diff options
244 files changed, 16200 insertions, 1469 deletions
diff --git a/.gitignore b/.gitignore index d1971967f6..a08c6c1ec4 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,8 @@ barebox.ubl barebox.zynq barebox.uimage barebox.map +barebox.kwb +barebox.kwbuart barebox-flash-image System.map Module.symvers diff --git a/Documentation/devicetree/bindings/README b/Documentation/devicetree/bindings/README new file mode 100644 index 0000000000..b818ee8243 --- /dev/null +++ b/Documentation/devicetree/bindings/README @@ -0,0 +1,6 @@ + +barebox uses the same devicetree bindings as the kernel. For +the bindings derived from the kernel look in the kernel sources +for reference. + +barebox specific bindings are documented here. diff --git a/Documentation/devicetree/bindings/misc/fsl,imx-iim.txt b/Documentation/devicetree/bindings/misc/fsl,imx-iim.txt new file mode 100644 index 0000000000..ed3efcc313 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/fsl,imx-iim.txt @@ -0,0 +1,20 @@ +Freescale i.MX IIM (Ic Identification Module) + +Required properties: + +- compatible: fsl,imx-iim +- reg: physical register base and size + +Optional properties: + +- barebox,provide-mac-address: Provide MAC addresses for ethernet devices. This + can be multiple entries in the form <&phandle bankno fuseofs> to specify a MAC + address to a ethernet device. + +Example: + +iim: iim@83f98000 { + compatible = "fsl,imx51-iim", "fsl,imx-iim"; + reg = <0x83f98000 0x4000>; + barebox,provide-mac-address = <&fec 1 9>; +}; @@ -1,5 +1,5 @@ VERSION = 2013 -PATCHLEVEL = 05 +PATCHLEVEL = 06 SUBLEVEL = 0 EXTRAVERSION = NAME = Amissive Actinocutious Kiwi @@ -970,7 +970,7 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \ .tmp_kallsyms* common/barebox_default_env* barebox.ldr \ scripts/bareboxenv-target barebox-flash-image \ Doxyfile.version barebox.srec barebox.s5p barebox.ubl \ - barebox.uimage barebox.spi + barebox.uimage barebox.spi barebox.kwb barebox.kwbuart # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include2 usr/include diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0a4f821814..cfb82b0515 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -79,6 +79,12 @@ config ARCH_IMX select WATCHDOG_IMX_RESET_SOURCE select HAS_DEBUG_LL +config ARCH_MVEBU + bool "Marvell EBU platforms" + select COMMON_CLK + select CLKDEV_LOOKUP + select HAS_DEBUG_LL + config ARCH_MXS bool "Freescale i.MX23/28 (mxs) based" select GENERIC_GPIO @@ -161,6 +167,7 @@ source arch/arm/mach-ep93xx/Kconfig source arch/arm/mach-highbank/Kconfig source arch/arm/mach-imx/Kconfig source arch/arm/mach-mxs/Kconfig +source arch/arm/mach-mvebu/Kconfig source arch/arm/mach-netx/Kconfig source arch/arm/mach-nomadik/Kconfig source arch/arm/mach-omap/Kconfig diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 8f0d23e92c..32bdd65a21 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -58,6 +58,7 @@ machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_HIGHBANK) := highbank machine-$(CONFIG_ARCH_IMX) := imx machine-$(CONFIG_ARCH_MXS) := mxs +machine-$(CONFIG_ARCH_MVEBU) := mvebu machine-$(CONFIG_ARCH_NOMADIK) := nomadik machine-$(CONFIG_ARCH_NETX) := netx machine-$(CONFIG_ARCH_OMAP) := omap @@ -70,101 +71,108 @@ machine-$(CONFIG_ARCH_ZYNQ) := zynq # Board directory name. This list is sorted alphanumerically # by CONFIG_* macro name. -board-$(CONFIG_MACH_A9M2410) := a9m2410 -board-$(CONFIG_MACH_A9M2440) := a9m2440 -board-$(CONFIG_MACH_ANIMEO_IP) := animeo_ip -board-$(CONFIG_MACH_AT91RM9200EK) := at91rm9200ek -board-$(CONFIG_MACH_AT91SAM9260EK) := at91sam9260ek -board-$(CONFIG_MACH_AT91SAM9261EK) := at91sam9261ek -board-$(CONFIG_MACH_AT91SAM9263EK) := at91sam9263ek -board-$(CONFIG_MACH_AT91SAM9G10EK) := at91sam9261ek -board-$(CONFIG_MACH_AT91SAM9G20EK) := at91sam9260ek -board-$(CONFIG_MACH_AT91SAM9N12EK) := at91sam9n12ek -board-$(CONFIG_MACH_AT91SAM9X5EK) := at91sam9x5ek -board-$(CONFIG_MACH_AT91SAM9M10IHD) := at91sam9m10ihd -board-$(CONFIG_MACH_AT91SAM9M10G45EK) := at91sam9m10g45ek -board-$(CONFIG_MACH_SAMA5D3XEK) := sama5d3xek -board-$(CONFIG_MACH_CLEP7212) := clep7212 -board-$(CONFIG_MACH_DSS11) := dss11 -board-$(CONFIG_MACH_EDB9301) := edb93xx -board-$(CONFIG_MACH_EDB9302) := edb93xx -board-$(CONFIG_MACH_EDB9302A) := edb93xx -board-$(CONFIG_MACH_EDB9307) := edb93xx -board-$(CONFIG_MACH_EDB9307A) := edb93xx -board-$(CONFIG_MACH_EDB93012) := edb93xx -board-$(CONFIG_MACH_EDB9315) := edb93xx -board-$(CONFIG_MACH_EDB9315A) := edb93xx -board-$(CONFIG_MACH_EUKREA_CPUIMX25) := eukrea_cpuimx25 -board-$(CONFIG_MACH_EUKREA_CPUIMX27) := eukrea_cpuimx27 -board-$(CONFIG_MACH_EUKREA_CPUIMX35) := eukrea_cpuimx35 -board-$(CONFIG_MACH_EUKREA_CPUIMX51SD) := eukrea_cpuimx51 -board-$(CONFIG_MACH_FREESCALE_MX25_3STACK) := freescale-mx25-3-stack -board-$(CONFIG_MACH_FREESCALE_MX35_3STACK) := freescale-mx35-3-stack -board-$(CONFIG_MACH_GE863) := telit-evk-pro3 -board-$(CONFIG_MACH_HIGHBANK) := highbank -board-$(CONFIG_MACH_IMX21ADS) := imx21ads -board-$(CONFIG_MACH_IMX27ADS) := imx27ads -board-$(CONFIG_MACH_IMX233_OLINUXINO) := imx233-olinuxino -board-$(CONFIG_MACH_MIOA701) := mioa701 -board-$(CONFIG_MACH_MMCCPU) := mmccpu -board-$(CONFIG_MACH_NOMADIK_8815NHK) := nhk8815 -board-$(CONFIG_MACH_NXDB500) := netx -board-$(CONFIG_MACH_OMAP343xSDP) := omap343xdsp -board-$(CONFIG_MACH_BEAGLE) := beagle -board-$(CONFIG_MACH_BEAGLEBONE) := beaglebone -board-$(CONFIG_MACH_OMAP3EVM) := omap3evm -board-$(CONFIG_MACH_PANDA) := panda -board-$(CONFIG_MACH_ARCHOSG9) := archosg9 -board-$(CONFIG_MACH_PCM049) := pcm049 -board-$(CONFIG_MACH_PCA100) := phycard-i.MX27 -board-$(CONFIG_MACH_PCAAL1) := phycard-a-l1 -board-$(CONFIG_MACH_PCAAXL2) := phycard-a-xl2 -board-$(CONFIG_MACH_PCM027) := pcm027 -board-$(CONFIG_MACH_PCM037) := pcm037 -board-$(CONFIG_MACH_PCM038) := pcm038 -board-$(CONFIG_MACH_PCM043) := pcm043 -board-$(CONFIG_MACH_PCM051) := pcm051 -board-$(CONFIG_MACH_PM9261) := pm9261 -board-$(CONFIG_MACH_PM9263) := pm9263 -board-$(CONFIG_MACH_PM9G45) := pm9g45 -board-$(CONFIG_MACH_RPI) := raspberry-pi -board-$(CONFIG_MACH_SCB9328) := scb9328 -board-$(CONFIG_MACH_NESO) := guf-neso -board-$(CONFIG_MACH_MX23EVK) := freescale-mx23-evk -board-$(CONFIG_MACH_CHUMBY) := chumby_falconwing -board-$(CONFIG_MACH_TX28) := karo-tx28 -board-$(CONFIG_MACH_MX28EVK) := freescale-mx28-evk -board-$(CONFIG_MACH_CFA10036) := crystalfontz-cfa10036 -board-$(CONFIG_MACH_FREESCALE_MX51_PDK) := freescale-mx51-pdk -board-$(CONFIG_MACH_FREESCALE_MX53_LOCO) := freescale-mx53-loco -board-$(CONFIG_MACH_FREESCALE_MX53_SMD) := freescale-mx53-smd -board-$(CONFIG_MACH_GUF_CUPID) := guf-cupid -board-$(CONFIG_MACH_MINI2440) := friendlyarm-mini2440 -board-$(CONFIG_MACH_MINI6410) := friendlyarm-mini6410 -board-$(CONFIG_MACH_TINY6410) := friendlyarm-tiny6410 -board-$(CONFIG_MACH_QIL_A9260) := qil-a9260 -board-$(CONFIG_MACH_TNY_A9260) := tny-a926x -board-$(CONFIG_MACH_TNY_A9263) := tny-a926x -board-$(CONFIG_MACH_TNY_A9G20) := tny-a926x -board-$(CONFIG_MACH_USB_A9260) := usb-a926x -board-$(CONFIG_MACH_USB_A9263) := usb-a926x -board-$(CONFIG_MACH_USB_A9G20) := usb-a926x -board-$(CONFIG_MACH_VERSATILEPB) := versatile -board-$(CONFIG_MACH_VEXPRESS) := vexpress -board-$(CONFIG_MACH_TX25) := karo-tx25 -board-$(CONFIG_MACH_TQMA53) := tqma53 -board-$(CONFIG_MACH_TX51) := karo-tx51 -board-$(CONFIG_MACH_MX6Q_ARM2) := freescale-mx6-arm2 -board-$(CONFIG_MACH_TOSHIBA_AC100) := toshiba-ac100 -board-$(CONFIG_MACH_CCMX51) := ccxmx51 -board-$(CONFIG_MACH_TINY210) := friendlyarm-tiny210 -board-$(CONFIG_MACH_SABRELITE) := freescale-mx6-sabrelite -board-$(CONFIG_MACH_TX53) := karo-tx53 -board-$(CONFIG_MACH_GUF_VINCELL) := guf-vincell -board-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) := efika-mx-smartbook -board-$(CONFIG_MACH_SABRESD) := freescale-mx6-sabresd -board-$(CONFIG_MACH_REALQ7) := dmo-mx6-realq7 -board-$(CONFIG_MACH_ZEDBOARD) := avnet-zedboard + +board-$(CONFIG_MACH_A9M2410) += a9m2410 +board-$(CONFIG_MACH_A9M2440) += a9m2440 +board-$(CONFIG_MACH_ANIMEO_IP) += animeo_ip +board-$(CONFIG_MACH_ARCHOSG9) += archosg9 +board-$(CONFIG_MACH_AT91RM9200EK) += at91rm9200ek +board-$(CONFIG_MACH_AT91SAM9260EK) += at91sam9260ek +board-$(CONFIG_MACH_AT91SAM9261EK) += at91sam9261ek +board-$(CONFIG_MACH_AT91SAM9263EK) += at91sam9263ek +board-$(CONFIG_MACH_AT91SAM9G10EK) += at91sam9261ek +board-$(CONFIG_MACH_AT91SAM9G20EK) += at91sam9260ek +board-$(CONFIG_MACH_AT91SAM9M10G45EK) += at91sam9m10g45ek +board-$(CONFIG_MACH_AT91SAM9M10IHD) += at91sam9m10ihd +board-$(CONFIG_MACH_AT91SAM9N12EK) += at91sam9n12ek +board-$(CONFIG_MACH_AT91SAM9X5EK) += at91sam9x5ek +board-$(CONFIG_MACH_BEAGLE) += beagle +board-$(CONFIG_MACH_BEAGLEBONE) += beaglebone +board-$(CONFIG_MACH_CCMX51) += ccxmx51 +board-$(CONFIG_MACH_CFA10036) += crystalfontz-cfa10036 +board-$(CONFIG_MACH_CHUMBY) += chumby_falconwing +board-$(CONFIG_MACH_CLEP7212) += clep7212 +board-$(CONFIG_MACH_DSS11) += dss11 +board-$(CONFIG_MACH_EDB93012) += edb93xx +board-$(CONFIG_MACH_EDB9301) += edb93xx +board-$(CONFIG_MACH_EDB9302A) += edb93xx +board-$(CONFIG_MACH_EDB9302) += edb93xx +board-$(CONFIG_MACH_EDB9307A) += edb93xx +board-$(CONFIG_MACH_EDB9307) += edb93xx +board-$(CONFIG_MACH_EDB9315A) += edb93xx +board-$(CONFIG_MACH_EDB9315) += edb93xx +board-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += efika-mx-smartbook +board-$(CONFIG_MACH_EUKREA_CPUIMX25) += eukrea_cpuimx25 +board-$(CONFIG_MACH_EUKREA_CPUIMX27) += eukrea_cpuimx27 +board-$(CONFIG_MACH_EUKREA_CPUIMX35) += eukrea_cpuimx35 +board-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += eukrea_cpuimx51 +board-$(CONFIG_MACH_FREESCALE_MX25_3STACK) += freescale-mx25-3-stack +board-$(CONFIG_MACH_FREESCALE_MX35_3STACK) += freescale-mx35-3-stack +board-$(CONFIG_MACH_FREESCALE_MX51_PDK) += freescale-mx51-pdk +board-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += freescale-mx53-loco +board-$(CONFIG_MACH_FREESCALE_MX53_SMD) += freescale-mx53-smd +board-$(CONFIG_MACH_GE863) += telit-evk-pro3 +board-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += globalscale-guruplug +board-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += globalscale-mirabox +board-$(CONFIG_MACH_GUF_CUPID) += guf-cupid +board-$(CONFIG_MACH_GUF_VINCELL) += guf-vincell +board-$(CONFIG_MACH_HIGHBANK) += highbank +board-$(CONFIG_MACH_IMX21ADS) += imx21ads +board-$(CONFIG_MACH_IMX233_OLINUXINO) += imx233-olinuxino +board-$(CONFIG_MACH_IMX27ADS) += imx27ads +board-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += marvell-armada-xp-gp +board-$(CONFIG_MACH_MINI2440) += friendlyarm-mini2440 +board-$(CONFIG_MACH_MINI6410) += friendlyarm-mini6410 +board-$(CONFIG_MACH_MIOA701) += mioa701 +board-$(CONFIG_MACH_MMCCPU) += mmccpu +board-$(CONFIG_MACH_MX23EVK) += freescale-mx23-evk +board-$(CONFIG_MACH_MX28EVK) += freescale-mx28-evk +board-$(CONFIG_MACH_MX6Q_ARM2) += freescale-mx6-arm2 +board-$(CONFIG_MACH_NESO) += guf-neso +board-$(CONFIG_MACH_NOMADIK_8815NHK) += nhk8815 +board-$(CONFIG_MACH_NXDB500) += netx +board-$(CONFIG_MACH_OMAP343xSDP) += omap343xdsp +board-$(CONFIG_MACH_OMAP3EVM) += omap3evm +board-$(CONFIG_MACH_PANDA) += panda +board-$(CONFIG_MACH_PCA100) += phycard-i.MX27 +board-$(CONFIG_MACH_PCAAL1) += phycard-a-l1 +board-$(CONFIG_MACH_PCAAXL2) += phycard-a-xl2 +board-$(CONFIG_MACH_PCM027) += pcm027 +board-$(CONFIG_MACH_PCM037) += pcm037 +board-$(CONFIG_MACH_PCM038) += pcm038 +board-$(CONFIG_MACH_PCM043) += pcm043 +board-$(CONFIG_MACH_PCM049) += pcm049 +board-$(CONFIG_MACH_PCM051) += pcm051 +board-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += plathome-openblocks-ax3 +board-$(CONFIG_MACH_PM9261) += pm9261 +board-$(CONFIG_MACH_PM9263) += pm9263 +board-$(CONFIG_MACH_PM9G45) += pm9g45 +board-$(CONFIG_MACH_QIL_A9260) += qil-a926x +board-$(CONFIG_MACH_QIL_A9G20) += qil-a926x +board-$(CONFIG_MACH_REALQ7) += dmo-mx6-realq7 +board-$(CONFIG_MACH_RPI) += raspberry-pi +board-$(CONFIG_MACH_SABRELITE) += freescale-mx6-sabrelite +board-$(CONFIG_MACH_SABRESD) += freescale-mx6-sabresd +board-$(CONFIG_MACH_SAMA5D3XEK) += sama5d3xek +board-$(CONFIG_MACH_SCB9328) += scb9328 +board-$(CONFIG_MACH_SOLIDRUN_CUBOX) += solidrun-cubox +board-$(CONFIG_MACH_TINY210) += friendlyarm-tiny210 +board-$(CONFIG_MACH_TINY6410) += friendlyarm-tiny6410 +board-$(CONFIG_MACH_TNY_A9260) += tny-a926x +board-$(CONFIG_MACH_TNY_A9263) += tny-a926x +board-$(CONFIG_MACH_TNY_A9G20) += tny-a926x +board-$(CONFIG_MACH_TOSHIBA_AC100) += toshiba-ac100 +board-$(CONFIG_MACH_TQMA53) += tqma53 +board-$(CONFIG_MACH_TX25) += karo-tx25 +board-$(CONFIG_MACH_TX28) += karo-tx28 +board-$(CONFIG_MACH_TX51) += karo-tx51 +board-$(CONFIG_MACH_TX53) += karo-tx53 +board-$(CONFIG_MACH_USB_A9260) += usb-a926x +board-$(CONFIG_MACH_USB_A9263) += usb-a926x +board-$(CONFIG_MACH_USB_A9G20) += usb-a926x +board-$(CONFIG_MACH_VERSATILEPB) += versatile +board-$(CONFIG_MACH_VEXPRESS) += vexpress +board-$(CONFIG_MACH_ZEDBOARD) += avnet-zedboard machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) @@ -256,6 +264,35 @@ ifeq ($(machine-y),zynq) KBUILD_IMAGE := barebox.zynq endif +CFG_barebox.imx := $(src)/arch/arm/boards/$(board-y)/flash-header.imxcfg +barebox.imx: $(KBUILD_BINARY) FORCE + $(call if_changed,imx_image) + +ifeq ($(CONFIG_ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE),y) +KBUILD_IMAGE := barebox.imx +endif + +KWBIMAGE_OPTS = \ + -c -i $(srctree)/$(BOARD)/kwbimage.cfg -d $(TEXT_BASE) -e $(TEXT_BASE) + +quiet_cmd_kwbimage = KWB $@ + cmd_kwbimage = scripts/kwbimage -p $< $(KWBIMAGE_OPTS) -o $@ || \ + echo "WARNING: Couldn't create KWB image due to previous errors." + +quiet_cmd_kwbimage_uart = KWBUART $@ + cmd_kwbimage_uart = scripts/kwbimage -m uart -p $< $(KWBIMAGE_OPTS) -o $@ || \ + echo "WARNING Couldn't create KWB image due to previous errors." + +barebox.kwb: $(KBUILD_BINARY) FORCE + $(call if_changed,kwbimage) + +barebox.kwbuart: $(KBUILD_BINARY) FORCE + $(call if_changed,kwbimage_uart) + +ifeq ($(CONFIG_ARCH_MVEBU),y) +KBUILD_IMAGE := barebox.kwb barebox.kwbuart +endif + pbl := arch/arm/pbl $(pbl)/zbarebox.S $(pbl)/zbarebox.bin $(pbl)/zbarebox: barebox.bin FORCE $(Q)$(MAKE) $(build)=$(pbl) $@ @@ -268,11 +305,6 @@ dts := arch/arm/dts %.dtb: scripts $(Q)$(MAKE) $(build)=$(dts) $(dts)/$@ -dtbs: scripts - $(Q)$(MAKE) $(build)=$(dts) dtbs - -KBUILD_DTBS := dtbs - KBUILD_IMAGE ?= $(KBUILD_BINARY) archprepare: maketools @@ -300,4 +332,6 @@ common-$(CONFIG_BUILTIN_DTB) += arch/arm/dts/ lds-y := arch/arm/lib/barebox.lds +common- += $(patsubst %,arch/arm/boards/%/,$(board-)) + CLEAN_FILES += include/generated/mach-types.h arch/arm/lib/barebox.lds barebox-flash-image diff --git a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c index 5eb3ca4cf7..21199d6433 100644 --- a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c +++ b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c @@ -29,6 +29,10 @@ enum board_type { BOARD_ID_CFA10036 = 0, BOARD_ID_CFA10037 = 1, BOARD_ID_CFA10049 = 2, + BOARD_ID_CFA10055 = 3, + BOARD_ID_CFA10056 = 4, + BOARD_ID_CFA10057 = 5, + BOARD_ID_CFA10058 = 6, }; struct cfa_eeprom_info { @@ -83,6 +87,18 @@ void cfa10036_detect_hw(void) case BOARD_ID_CFA10049: board_name = "cfa10049"; break; + case BOARD_ID_CFA10055: + board_name = "cfa10055"; + break; + case BOARD_ID_CFA10056: + board_name = "cfa10056"; + break; + case BOARD_ID_CFA10057: + board_name = "cfa10057"; + break; + case BOARD_ID_CFA10058: + board_name = "cfa10058"; + break; default: pr_err("Board ID not supported\n"); return; diff --git a/arch/arm/boards/freescale-mx51-pdk/Makefile b/arch/arm/boards/freescale-mx51-pdk/Makefile index d44f697718..f1baae24ff 100644 --- a/arch/arm/boards/freescale-mx51-pdk/Makefile +++ b/arch/arm/boards/freescale-mx51-pdk/Makefile @@ -1,3 +1,3 @@ -obj-y += board.o -lwl-y += flash_header.o +obj-y += board.o flash-header.o +extra-y += flash-header.S flash-header.dcd lwl-y += lowlevel.o diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c index db340564f9..6807796ab9 100644 --- a/arch/arm/boards/freescale-mx51-pdk/board.c +++ b/arch/arm/boards/freescale-mx51-pdk/board.c @@ -39,80 +39,8 @@ #include <mach/iomux-mx51.h> #include <mach/devices-imx51.h> #include <mach/revision.h> -#include <mach/iim.h> #include <mach/imx-flash-header.h> -static struct fec_platform_data fec_info = { - .xcv_type = PHY_INTERFACE_MODE_MII, -}; - -static iomux_v3_cfg_t f3s_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - /* FEC */ - MX51_PAD_EIM_EB2__FEC_MDIO, - MX51_PAD_EIM_EB3__FEC_RDATA1, - MX51_PAD_EIM_CS2__FEC_RDATA2, - MX51_PAD_EIM_CS3__FEC_RDATA3, - MX51_PAD_EIM_CS4__FEC_RX_ER, - MX51_PAD_EIM_CS5__FEC_CRS, - MX51_PAD_NANDF_RB2__FEC_COL, - MX51_PAD_NANDF_RB3__FEC_RX_CLK, - MX51_PAD_NANDF_CS2__FEC_TX_ER, - MX51_PAD_NANDF_CS3__FEC_MDC, - MX51_PAD_NANDF_CS4__FEC_TDATA1, - MX51_PAD_NANDF_CS5__FEC_TDATA2, - MX51_PAD_NANDF_CS6__FEC_TDATA3, - MX51_PAD_NANDF_CS7__FEC_TX_EN, - MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK, - MX51_PAD_NANDF_D11__FEC_RX_DV, - MX51_PAD_NANDF_D9__FEC_RDATA0, - MX51_PAD_NANDF_D8__FEC_TDATA0, - MX51_PAD_CSPI1_SS0__ECSPI1_SS0, - MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, - MX51_PAD_CSPI1_MISO__ECSPI1_MISO, - MX51_PAD_CSPI1_RDY__ECSPI1_RDY, - MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, - MX51_PAD_EIM_A20__GPIO2_14, /* LAN8700 reset pin */ - IOMUX_PAD(0x60C, 0x21C, 3, 0x0, 0, 0x85), /* FIXME: needed? */ - /* SD 1 */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - /* SD 2 */ - MX51_PAD_SD2_CMD__SD2_CMD, - MX51_PAD_SD2_CLK__SD2_CLK, - MX51_PAD_SD2_DATA0__SD2_DATA0, - MX51_PAD_SD2_DATA1__SD2_DATA1, - MX51_PAD_SD2_DATA2__SD2_DATA2, - MX51_PAD_SD2_DATA3__SD2_DATA3, - /* CD/WP gpio */ - MX51_PAD_GPIO1_6__GPIO1_6, - MX51_PAD_GPIO1_5__GPIO1_5, -}; - -#define BABBAGE_ECSPI1_CS0 (3 * 32 + 24) -static int spi_0_cs[] = {BABBAGE_ECSPI1_CS0}; - -static struct spi_imx_master spi_0_data = { - .chipselect = spi_0_cs, - .num_chipselect = ARRAY_SIZE(spi_0_cs), -}; - -static const struct spi_board_info mx51_babbage_spi_board_info[] = { - { - .name = "mc13xxx-spi", - .bus_num = 0, - .chip_select = 0, - }, -}; - #define MX51_CCM_CACRR 0x10 static void babbage_power_init(void) @@ -229,32 +157,22 @@ static void babbage_power_init(void) mdelay(50); } -#define DCD_NAME static struct imx_dcd_entry dcd_entry - -#include "dcd-data.h" +extern char flash_header_start[], flash_header_end[]; static int f3s_devices_init(void) { - spi_register_board_info(mx51_babbage_spi_board_info, - ARRAY_SIZE(mx51_babbage_spi_board_info)); - imx51_add_spi0(&spi_0_data); - babbage_power_init(); console_flush(); imx51_init_lowlevel(800); clock_notifier_call_chain(); - imx51_iim_register_fec_ethaddr(); - imx51_add_fec(&fec_info); - imx51_add_mmc0(NULL); - imx51_add_mmc1(NULL); - armlinux_set_bootparams((void *)0x90000100); armlinux_set_architecture(MACH_TYPE_MX51_BABBAGE); - imx51_bbu_internal_mmc_register_handler("mmc", "/dev/disk0", - BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry), 0); + imx51_bbu_internal_mmc_register_handler("mmc", "/dev/mmc0", + BBU_HANDLER_FLAG_DEFAULT, (void *)flash_header_start, + flash_header_end - flash_header_start, 0); return 0; } @@ -263,21 +181,9 @@ device_initcall(f3s_devices_init); static int f3s_part_init(void) { - devfs_add_partition("disk0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self0"); - devfs_add_partition("disk0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0"); + devfs_add_partition("mmc0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self0"); + devfs_add_partition("mmc0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0"); return 0; } late_initcall(f3s_part_init); - -static int f3s_console_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(f3s_pads, ARRAY_SIZE(f3s_pads)); - - imx51_add_uart0(); - - return 0; -} - -console_initcall(f3s_console_init); - diff --git a/arch/arm/boards/freescale-mx51-pdk/dcd-data.h b/arch/arm/boards/freescale-mx51-pdk/dcd-data.h deleted file mode 100644 index 4dd6c0d26c..0000000000 --- a/arch/arm/boards/freescale-mx51-pdk/dcd-data.h +++ /dev/null @@ -1,60 +0,0 @@ - -DCD_NAME[] = { - { .ptr_type = 4, .addr = 0x73fa88a0, .val = 0x00000200, }, - { .ptr_type = 4, .addr = 0x73fa850c, .val = 0x000020c5, }, - { .ptr_type = 4, .addr = 0x73fa8510, .val = 0x000020c5, }, - { .ptr_type = 4, .addr = 0x73fa883c, .val = 0x00000002, }, - { .ptr_type = 4, .addr = 0x73fa8848, .val = 0x00000002, }, - { .ptr_type = 4, .addr = 0x73fa84b8, .val = 0x000000e7, }, - { .ptr_type = 4, .addr = 0x73fa84bc, .val = 0x00000045, }, - { .ptr_type = 4, .addr = 0x73fa84c0, .val = 0x00000045, }, - { .ptr_type = 4, .addr = 0x73fa84c4, .val = 0x00000045, }, - { .ptr_type = 4, .addr = 0x73fa84c8, .val = 0x00000045, }, - { .ptr_type = 4, .addr = 0x73fa8820, .val = 0x00000000, }, - { .ptr_type = 4, .addr = 0x73fa84a4, .val = 0x00000003, }, - { .ptr_type = 4, .addr = 0x73fa84a8, .val = 0x00000003, }, - { .ptr_type = 4, .addr = 0x73fa84ac, .val = 0x000000e3, }, - { .ptr_type = 4, .addr = 0x73fa84b0, .val = 0x000000e3, }, - { .ptr_type = 4, .addr = 0x73fa84b4, .val = 0x000000e3, }, - { .ptr_type = 4, .addr = 0x73fa84cc, .val = 0x000000e3, }, - { .ptr_type = 4, .addr = 0x73fa84d0, .val = 0x000000e2, }, - { .ptr_type = 4, .addr = 0x73fa882c, .val = 0x00000004, }, - { .ptr_type = 4, .addr = 0x73fa88a4, .val = 0x00000004, }, - { .ptr_type = 4, .addr = 0x73fa88ac, .val = 0x00000004, }, - { .ptr_type = 4, .addr = 0x73fa88b8, .val = 0x00000004, }, - { .ptr_type = 4, .addr = 0x83fd9000, .val = 0x82a20000, }, - { .ptr_type = 4, .addr = 0x83fd9008, .val = 0x82a20000, }, - { .ptr_type = 4, .addr = 0x83fd9010, .val = 0x000ad0d0, }, - { .ptr_type = 4, .addr = 0x83fd9004, .val = 0x3f3584ab, }, - { .ptr_type = 4, .addr = 0x83fd900c, .val = 0x3f3584ab, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x04008008, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801a, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801b, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00448019, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x07328018, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x04008008, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008010, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008010, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x06328018, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x03808019, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00408019, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008000, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0400800c, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801e, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801f, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801d, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0732801c, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0400800c, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008014, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008014, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0632801c, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0380801d, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0040801d, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008004, }, - { .ptr_type = 4, .addr = 0x83fd9000, .val = 0xb2a20000, }, - { .ptr_type = 4, .addr = 0x83fd9008, .val = 0xb2a20000, }, - { .ptr_type = 4, .addr = 0x83fd9010, .val = 0x000ad6d0, }, - { .ptr_type = 4, .addr = 0x83fd9034, .val = 0x90000000, }, - { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00000000, }, -}; - diff --git a/arch/arm/boards/freescale-mx51-pdk/flash-header.imxcfg b/arch/arm/boards/freescale-mx51-pdk/flash-header.imxcfg new file mode 100644 index 0000000000..bac6816fee --- /dev/null +++ b/arch/arm/boards/freescale-mx51-pdk/flash-header.imxcfg @@ -0,0 +1,59 @@ +loadaddr 0x90000000 +soc imx51 +dcdofs 0x400 +wm 32 0x73fa88a0 0x00000200 +wm 32 0x73fa850c 0x000020c5 +wm 32 0x73fa8510 0x000020c5 +wm 32 0x73fa883c 0x00000002 +wm 32 0x73fa8848 0x00000002 +wm 32 0x73fa84b8 0x000000e7 +wm 32 0x73fa84bc 0x00000045 +wm 32 0x73fa84c0 0x00000045 +wm 32 0x73fa84c4 0x00000045 +wm 32 0x73fa84c8 0x00000045 +wm 32 0x73fa8820 0x00000000 +wm 32 0x73fa84a4 0x00000003 +wm 32 0x73fa84a8 0x00000003 +wm 32 0x73fa84ac 0x000000e3 +wm 32 0x73fa84b0 0x000000e3 +wm 32 0x73fa84b4 0x000000e3 +wm 32 0x73fa84cc 0x000000e3 +wm 32 0x73fa84d0 0x000000e2 +wm 32 0x73fa882c 0x00000004 +wm 32 0x73fa88a4 0x00000004 +wm 32 0x73fa88ac 0x00000004 +wm 32 0x73fa88b8 0x00000004 +wm 32 0x83fd9000 0x82a20000 +wm 32 0x83fd9008 0x82a20000 +wm 32 0x83fd9010 0x000ad0d0 +wm 32 0x83fd9004 0x3f3584ab +wm 32 0x83fd900c 0x3f3584ab +wm 32 0x83fd9014 0x04008008 +wm 32 0x83fd9014 0x0000801a +wm 32 0x83fd9014 0x0000801b +wm 32 0x83fd9014 0x00448019 +wm 32 0x83fd9014 0x07328018 +wm 32 0x83fd9014 0x04008008 +wm 32 0x83fd9014 0x00008010 +wm 32 0x83fd9014 0x00008010 +wm 32 0x83fd9014 0x06328018 +wm 32 0x83fd9014 0x03808019 +wm 32 0x83fd9014 0x00408019 +wm 32 0x83fd9014 0x00008000 +wm 32 0x83fd9014 0x0400800c +wm 32 0x83fd9014 0x0000801e +wm 32 0x83fd9014 0x0000801f +wm 32 0x83fd9014 0x0000801d +wm 32 0x83fd9014 0x0732801c +wm 32 0x83fd9014 0x0400800c +wm 32 0x83fd9014 0x00008014 +wm 32 0x83fd9014 0x00008014 +wm 32 0x83fd9014 0x0632801c +wm 32 0x83fd9014 0x0380801d +wm 32 0x83fd9014 0x0040801d +wm 32 0x83fd9014 0x00008004 +wm 32 0x83fd9000 0xb2a20000 +wm 32 0x83fd9008 0xb2a20000 +wm 32 0x83fd9010 0x000ad6d0 +wm 32 0x83fd9034 0x90000000 +wm 32 0x83fd9014 0x00000000 diff --git a/arch/arm/boards/freescale-mx51-pdk/flash_header.c b/arch/arm/boards/freescale-mx51-pdk/flash_header.c deleted file mode 100644 index f3f1e4bfd5..0000000000 --- a/arch/arm/boards/freescale-mx51-pdk/flash_header.c +++ /dev/null @@ -1,29 +0,0 @@ -#include <common.h> -#include <mach/imx-flash-header.h> -#include <asm/barebox-arm-head.h> - -void __naked __flash_header_start go(void) -{ - barebox_arm_head(); -} - -#define DCD_NAME struct imx_dcd_entry __dcd_entry_section dcd_entry - -#include "dcd-data.h" - -#define APP_DEST 0x90000000 - -struct imx_flash_header __flash_header_section flash_header = { - .app_code_jump_vector = APP_DEST + 0x1000, - .app_code_barker = APP_CODE_BARKER, - .app_code_csf = 0, - .dcd_ptr_ptr = APP_DEST + 0x400 + offsetof(struct imx_flash_header, dcd), - .super_root_key = 0, - .dcd = APP_DEST + 0x400 + offsetof(struct imx_flash_header, dcd_barker), - .app_dest = APP_DEST, - .dcd_barker = DCD_BARKER, - .dcd_block_len = sizeof (dcd_entry), -}; - -unsigned long __image_len_section barebox_len = DCD_BAREBOX_SIZE; - diff --git a/arch/arm/boards/freescale-mx6-sabrelite/board.c b/arch/arm/boards/freescale-mx6-sabrelite/board.c index 2afaae3007..ff27b05b14 100644 --- a/arch/arm/boards/freescale-mx6-sabrelite/board.c +++ b/arch/arm/boards/freescale-mx6-sabrelite/board.c @@ -29,6 +29,7 @@ #include <mach/generic.h> #include <sizes.h> #include <net.h> +#include <linux/micrel_phy.h> #include <mach/imx6.h> #include <mach/devices-imx6.h> #include <mach/iomux-mx6.h> @@ -37,73 +38,8 @@ #include <mach/spi.h> #include <mach/usb.h> -#define SABRELITE_SD3_WP IMX_GPIO_NR(7, 1) -#define SABRELITE_SD3_CD IMX_GPIO_NR(7, 0) - -#define SABRELITE_SD4_CD IMX_GPIO_NR(2, 6) - -static iomux_v3_cfg_t sabrelite_pads[] = { - /* UART1 */ - MX6Q_PAD_SD3_DAT6__UART1_RXD, - MX6Q_PAD_SD3_DAT7__UART1_TXD, - MX6Q_PAD_EIM_D26__UART2_TXD, - MX6Q_PAD_EIM_D27__UART2_RXD, - - /* SD3 (bottom) */ - MX6Q_PAD_SD3_CMD__USDHC3_CMD, - MX6Q_PAD_SD3_CLK__USDHC3_CLK, - MX6Q_PAD_SD3_DAT0__USDHC3_DAT0, - MX6Q_PAD_SD3_DAT1__USDHC3_DAT1, - MX6Q_PAD_SD3_DAT2__USDHC3_DAT2, - MX6Q_PAD_SD3_DAT3__USDHC3_DAT3, - MX6Q_PAD_SD3_DAT4__GPIO_7_1, /* WP */ - MX6Q_PAD_SD3_DAT5__GPIO_7_0, /* CD */ - - /* SD4 (top) */ - MX6Q_PAD_SD4_CLK__USDHC4_CLK, - MX6Q_PAD_SD4_CMD__USDHC4_CMD, - MX6Q_PAD_SD4_DAT0__USDHC4_DAT0, - MX6Q_PAD_SD4_DAT1__USDHC4_DAT1, - MX6Q_PAD_SD4_DAT2__USDHC4_DAT2, - MX6Q_PAD_SD4_DAT3__USDHC4_DAT3, - MX6Q_PAD_NANDF_D6__GPIO_2_6, /* CD */ - - /* ECSPI */ - MX6Q_PAD_EIM_D16__ECSPI1_SCLK, - MX6Q_PAD_EIM_D17__ECSPI1_MISO, - MX6Q_PAD_EIM_D18__ECSPI1_MOSI, - MX6Q_PAD_EIM_D19__GPIO_3_19, /* CS1 */ - - /* I2C0 */ - MX6Q_PAD_EIM_D21__I2C1_SCL, - MX6Q_PAD_EIM_D28__I2C1_SDA, - - /* I2C1 */ - MX6Q_PAD_KEY_COL3__I2C2_SCL, - MX6Q_PAD_KEY_ROW3__I2C2_SDA, - - /* I2C2 */ - MX6Q_PAD_GPIO_5__I2C3_SCL, - MX6Q_PAD_GPIO_16__I2C3_SDA, - - /* USB */ - MX6Q_PAD_GPIO_17__GPIO_7_12, - MX6Q_PAD_EIM_D22__GPIO_3_22, - MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC, -}; - -static iomux_v3_cfg_t sabrelite_enet_pads[] = { +static iomux_v3_cfg_t sabrelite_enet_gpio_pads[] = { /* Ethernet */ - MX6Q_PAD_ENET_MDC__ENET_MDC, - MX6Q_PAD_ENET_MDIO__ENET_MDIO, - MX6Q_PAD_ENET_REF_CLK__GPIO_1_23, // LED mode - MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, - MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC, - MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0, - MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1, - MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2, - MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3, - MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, MX6Q_PAD_EIM_D23__GPIO_3_23, /* RGMII_nRST */ MX6Q_PAD_RGMII_RXC__GPIO_6_30, /* PHYAD */ MX6Q_PAD_RGMII_RD0__GPIO_6_25, /* MODE0 */ @@ -113,16 +49,6 @@ static iomux_v3_cfg_t sabrelite_enet_pads[] = { MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24, }; -static iomux_v3_cfg_t sabrelite_enet2_pads[] = { - MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, - MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC, - MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0, - MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1, - MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2, - MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3, - MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, -}; - static int sabrelite_mem_init(void) { arm_add_mem_device("ram0", 0x10000000, SZ_1G); @@ -131,7 +57,7 @@ static int sabrelite_mem_init(void) } mem_initcall(sabrelite_mem_init); -static void mx6_rgmii_rework(struct phy_device *dev) +static int ksz9021rn_phy_fixup(struct phy_device *dev) { phy_write(dev, 0x09, 0x0f00); @@ -144,17 +70,14 @@ static void mx6_rgmii_rework(struct phy_device *dev) phy_write(dev, 0x0b, 0x8104); phy_write(dev, 0x0c, 0xf0f0); phy_write(dev, 0x0b, 0x104); -} -static struct fec_platform_data fec_info = { - .xcv_type = PHY_INTERFACE_MODE_RGMII, - .phy_init = mx6_rgmii_rework, - .phy_addr = 6, -}; + return 0; +} static int sabrelite_ksz9021rn_setup(void) { - mxc_iomux_v3_setup_multiple_pads(sabrelite_enet_pads, ARRAY_SIZE(sabrelite_enet_pads)); + mxc_iomux_v3_setup_multiple_pads(sabrelite_enet_gpio_pads, + ARRAY_SIZE(sabrelite_enet_gpio_pads)); gpio_direction_output(87, 0); /* GPIO 3-23 */ @@ -175,10 +98,13 @@ static int sabrelite_ksz9021rn_setup(void) mdelay(10); gpio_set_value(87, 1); - mxc_iomux_v3_setup_multiple_pads(sabrelite_enet2_pads, ARRAY_SIZE(sabrelite_enet2_pads)); - return 0; } +/* + * Do this before the fec initializes but after our + * gpios are available. + */ +fs_initcall(sabrelite_ksz9021rn_setup); static inline int imx6_iim_register_fec_ethaddr(void) { @@ -200,35 +126,6 @@ static inline int imx6_iim_register_fec_ethaddr(void) return 0; } -static int sabrelite_spi_cs[] = {IMX_GPIO_NR(3, 19)}; - -static struct spi_imx_master sabrelite_spi_0_data = { - .chipselect = sabrelite_spi_cs, - .num_chipselect = ARRAY_SIZE(sabrelite_spi_cs), -}; - -static const struct spi_board_info sabrelite_spi_board_info[] = { - { - .name = "m25p80", - .max_speed_hz = 40000000, - .bus_num = 0, - .chip_select = 0, - } -}; - -static struct esdhc_platform_data sabrelite_sd3_data = { - .cd_gpio = SABRELITE_SD3_CD, - .cd_type = ESDHC_CD_GPIO, - .wp_gpio = SABRELITE_SD3_WP, - .wp_type = ESDHC_WP_GPIO, -}; - -static struct esdhc_platform_data sabrelite_sd4_data = { - .cd_gpio = SABRELITE_SD4_CD, - .cd_type = ESDHC_CD_GPIO, - .wp_type = ESDHC_WP_NONE, -}; - static void sabrelite_ehci_init(void) { imx6_usb_phy2_disable_oc(); @@ -244,19 +141,8 @@ static void sabrelite_ehci_init(void) static int sabrelite_devices_init(void) { - imx6_add_mmc2(&sabrelite_sd3_data); - imx6_add_mmc3(&sabrelite_sd4_data); - - sabrelite_ksz9021rn_setup(); - imx6_iim_register_fec_ethaddr(); - imx6_add_fec(&fec_info); - sabrelite_ehci_init(); - spi_register_board_info(sabrelite_spi_board_info, - ARRAY_SIZE(sabrelite_spi_board_info)); - imx6_add_spi0(&sabrelite_spi_0_data); - armlinux_set_bootparams((void *)0x10000100); armlinux_set_architecture(3769); @@ -265,17 +151,23 @@ static int sabrelite_devices_init(void) return 0; } - device_initcall(sabrelite_devices_init); -static int sabrelite_console_init(void) +static int sabrelite_coredevices_init(void) { - mxc_iomux_v3_setup_multiple_pads(sabrelite_pads, ARRAY_SIZE(sabrelite_pads)); + phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, + ksz9021rn_phy_fixup); - imx6_init_lowlevel(); + imx6_iim_register_fec_ethaddr(); + + return 0; +} +coredevice_initcall(sabrelite_coredevices_init); - imx6_add_uart1(); +static int sabrelite_core_init(void) +{ + imx6_init_lowlevel(); return 0; } -console_initcall(sabrelite_console_init); +core_initcall(sabrelite_core_init); diff --git a/arch/arm/boards/freescale-mx6-sabresd/board.c b/arch/arm/boards/freescale-mx6-sabresd/board.c index e41dc77bf5..033a253a23 100644 --- a/arch/arm/boards/freescale-mx6-sabresd/board.c +++ b/arch/arm/boards/freescale-mx6-sabresd/board.c @@ -41,92 +41,6 @@ #define PHY_ID_AR8031 0x004dd074 #define AR_PHY_ID_MASK 0xffffffff -#define SABRESD_SD2_CD IMX_GPIO_NR(2, 2) -#define SABRESD_SD2_WP IMX_GPIO_NR(2, 3) - -#define SABRESD_SD3_CD IMX_GPIO_NR(2, 0) -#define SABRESD_SD3_WP IMX_GPIO_NR(2, 1) - -static iomux_v3_cfg_t sabresd_pads[] = { - /* UART1 */ - MX6Q_PAD_CSI0_DAT11__UART1_RXD, - MX6Q_PAD_CSI0_DAT10__UART1_TXD, - - /* Ethernet */ - MX6Q_PAD_ENET_MDC__ENET_MDC, - MX6Q_PAD_ENET_MDIO__ENET_MDIO, - MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, - - MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC, - MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0, - MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1, - MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2, - MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3, - MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, - - MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC, - MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0, - MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1, - MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2, - MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3, - MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, - - MX6Q_PAD_ENET_CRS_DV__GPIO_1_25, /* AR8031 PHY Reset */ - MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT, - - /* SD2 */ - MX6Q_PAD_SD2_CLK__USDHC2_CLK, - MX6Q_PAD_SD2_CMD__USDHC2_CMD, - MX6Q_PAD_SD2_DAT0__USDHC2_DAT0, - MX6Q_PAD_SD2_DAT1__USDHC2_DAT1, - MX6Q_PAD_SD2_DAT2__USDHC2_DAT2, - MX6Q_PAD_SD2_DAT3__USDHC2_DAT3, - MX6Q_PAD_NANDF_D4__USDHC2_DAT4, - MX6Q_PAD_NANDF_D5__USDHC2_DAT5, - MX6Q_PAD_NANDF_D6__USDHC2_DAT6, - MX6Q_PAD_NANDF_D7__USDHC2_DAT7, - MX6Q_PAD_NANDF_D2__GPIO_2_2, /* CD */ - MX6Q_PAD_NANDF_D3__GPIO_2_3, /* WP */ - - /* SD3 */ - MX6Q_PAD_SD3_CMD__USDHC3_CMD, - MX6Q_PAD_SD3_CLK__USDHC3_CLK, - MX6Q_PAD_SD3_DAT0__USDHC3_DAT0, - MX6Q_PAD_SD3_DAT1__USDHC3_DAT1, - MX6Q_PAD_SD3_DAT2__USDHC3_DAT2, - MX6Q_PAD_SD3_DAT3__USDHC3_DAT3, - MX6Q_PAD_SD3_DAT4__USDHC3_DAT4, - MX6Q_PAD_SD3_DAT5__USDHC3_DAT5, - MX6Q_PAD_SD3_DAT6__USDHC3_DAT6, - MX6Q_PAD_SD3_DAT7__USDHC3_DAT7, - MX6Q_PAD_NANDF_D0__GPIO_2_0, /* CD */ - MX6Q_PAD_NANDF_D1__GPIO_2_1, /* WP */ - - /* SD4 */ - MX6Q_PAD_SD4_CLK__USDHC4_CLK, - MX6Q_PAD_SD4_CMD__USDHC4_CMD, - MX6Q_PAD_SD4_DAT0__USDHC4_DAT0, - MX6Q_PAD_SD4_DAT1__USDHC4_DAT1, - MX6Q_PAD_SD4_DAT2__USDHC4_DAT2, - MX6Q_PAD_SD4_DAT3__USDHC4_DAT3, - MX6Q_PAD_SD4_DAT4__USDHC4_DAT4, - MX6Q_PAD_SD4_DAT5__USDHC4_DAT5, - MX6Q_PAD_SD4_DAT6__USDHC4_DAT6, - MX6Q_PAD_SD4_DAT7__USDHC4_DAT7, - - /* I2C0 */ - MX6Q_PAD_CSI0_DAT8__I2C1_SDA, - MX6Q_PAD_CSI0_DAT9__I2C1_SCL, - - /* I2C1 */ - MX6Q_PAD_KEY_COL3__I2C2_SCL, - MX6Q_PAD_KEY_ROW3__I2C2_SDA, - - /* I2C2 */ - MX6Q_PAD_GPIO_3__I2C3_SCL, - MX6Q_PAD_GPIO_6__I2C3_SDA, -}; - static int sabresd_mem_init(void) { arm_add_mem_device("ram0", 0x10000000, SZ_1G); @@ -158,11 +72,6 @@ static int ar8031_phy_fixup(struct phy_device *dev) return 0; } -static struct fec_platform_data fec_info = { - .xcv_type = PHY_INTERFACE_MODE_RGMII, - .phy_addr = 1, -}; - static void sabresd_phy_reset(void) { /* Reset AR8031 PHY */ @@ -191,37 +100,8 @@ static inline int imx6_iim_register_fec_ethaddr(void) return 0; } -static struct esdhc_platform_data sabresd_sd2_data = { - .cd_gpio = SABRESD_SD2_CD, - .cd_type = ESDHC_CD_GPIO, - .wp_gpio = SABRESD_SD2_WP, - .wp_type = ESDHC_WP_GPIO, -}; - -static struct esdhc_platform_data sabresd_sd3_data = { - .cd_gpio = SABRESD_SD3_CD, - .cd_type = ESDHC_CD_GPIO, - .wp_gpio = SABRESD_SD3_WP, - .wp_type = ESDHC_WP_GPIO, -}; - -static struct esdhc_platform_data sabresd_sd4_data = { - .cd_type = ESDHC_CD_PERMANENT, - .wp_type = ESDHC_WP_CONTROLLER, -}; - static int sabresd_devices_init(void) { - imx6_add_mmc3(&sabresd_sd4_data); - imx6_add_mmc1(&sabresd_sd2_data); - imx6_add_mmc2(&sabresd_sd3_data); - - phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, ar8031_phy_fixup); - - sabresd_phy_reset(); - imx6_iim_register_fec_ethaddr(); - imx6_add_fec(&fec_info); - armlinux_set_bootparams((void *)0x10000100); armlinux_set_architecture(3980); @@ -231,14 +111,27 @@ static int sabresd_devices_init(void) } device_initcall(sabresd_devices_init); -static int sabresd_console_init(void) +static int sabresd_coredevices_init(void) { - mxc_iomux_v3_setup_multiple_pads(sabresd_pads, ARRAY_SIZE(sabresd_pads)); + sabresd_phy_reset(); - imx6_init_lowlevel(); + phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, + ar8031_phy_fixup); - imx6_add_uart0(); + imx6_iim_register_fec_ethaddr(); + + return 0; +} +/* + * Do this before the fec initializes but after our + * gpios are available. + */ +fs_initcall(sabresd_coredevices_init); + +static int sabresd_core_init(void) +{ + imx6_init_lowlevel(); return 0; } -console_initcall(sabresd_console_init); +core_initcall(sabresd_core_init); diff --git a/arch/arm/boards/globalscale-guruplug/Makefile b/arch/arm/boards/globalscale-guruplug/Makefile new file mode 100644 index 0000000000..dcfc2937d3 --- /dev/null +++ b/arch/arm/boards/globalscale-guruplug/Makefile @@ -0,0 +1 @@ +obj-y += board.o diff --git a/arch/arm/boards/globalscale-guruplug/board.c b/arch/arm/boards/globalscale-guruplug/board.c new file mode 100644 index 0000000000..9c800c5410 --- /dev/null +++ b/arch/arm/boards/globalscale-guruplug/board.c @@ -0,0 +1,17 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +/* empty */ diff --git a/arch/arm/boards/globalscale-guruplug/config.h b/arch/arm/boards/globalscale-guruplug/config.h new file mode 100644 index 0000000000..ca15136817 --- /dev/null +++ b/arch/arm/boards/globalscale-guruplug/config.h @@ -0,0 +1,4 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/globalscale-guruplug/kwbimage.cfg b/arch/arm/boards/globalscale-guruplug/kwbimage.cfg new file mode 100644 index 0000000000..d0f3bdb01f --- /dev/null +++ b/arch/arm/boards/globalscale-guruplug/kwbimage.cfg @@ -0,0 +1,27 @@ +VERSION 0 +BOOT_FROM nand +NAND_ECCMODE default +NAND_PAGESZ 00000800 +DATA ffd100e0 1b1b9b9b +DATA ffd01400 43000c30 +DATA ffd01404 37543000 +DATA ffd01408 22125451 +DATA ffd0140c 00000a33 +DATA ffd01410 000000cc +DATA ffd01414 00000000 +DATA ffd01418 00000000 +DATA ffd0141c 00000c52 +DATA ffd01420 00000040 +DATA ffd01424 0000f17f +DATA ffd01428 00085520 +DATA ffd0147c 00008552 +DATA ffd01500 00000000 +DATA ffd01504 0ffffff1 +DATA ffd01508 10000000 +DATA ffd0150c 0ffffff5 +DATA ffd01514 00000000 +DATA ffd0151c 00000000 +DATA ffd01494 00030000 +DATA ffd01498 00000000 +DATA ffd0149c 0000e803 +DATA ffd01480 00000001 diff --git a/arch/arm/boards/globalscale-mirabox/Makefile b/arch/arm/boards/globalscale-mirabox/Makefile new file mode 100644 index 0000000000..9320510bab --- /dev/null +++ b/arch/arm/boards/globalscale-mirabox/Makefile @@ -0,0 +1 @@ +obj-y += board.c diff --git a/arch/arm/boards/globalscale-mirabox/board.c b/arch/arm/boards/globalscale-mirabox/board.c new file mode 100644 index 0000000000..9c800c5410 --- /dev/null +++ b/arch/arm/boards/globalscale-mirabox/board.c @@ -0,0 +1,17 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +/* empty */ diff --git a/arch/arm/boards/globalscale-mirabox/config.h b/arch/arm/boards/globalscale-mirabox/config.h new file mode 100644 index 0000000000..ca15136817 --- /dev/null +++ b/arch/arm/boards/globalscale-mirabox/config.h @@ -0,0 +1,4 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/globalscale-mirabox/kwbimage.cfg b/arch/arm/boards/globalscale-mirabox/kwbimage.cfg new file mode 100644 index 0000000000..72283d9b69 --- /dev/null +++ b/arch/arm/boards/globalscale-mirabox/kwbimage.cfg @@ -0,0 +1,5 @@ +VERSION 1 +BOOT_FROM nand +NAND_BLKSZ 00020000 +NAND_BADBLK_LOCATION 01 +BINARY globalscale-mirabox-binary.0 0000005b 00000068 diff --git a/arch/arm/boards/marvell-armada-xp-gp/Makefile b/arch/arm/boards/marvell-armada-xp-gp/Makefile new file mode 100644 index 0000000000..dcfc2937d3 --- /dev/null +++ b/arch/arm/boards/marvell-armada-xp-gp/Makefile @@ -0,0 +1 @@ +obj-y += board.o diff --git a/arch/arm/boards/marvell-armada-xp-gp/board.c b/arch/arm/boards/marvell-armada-xp-gp/board.c new file mode 100644 index 0000000000..9c800c5410 --- /dev/null +++ b/arch/arm/boards/marvell-armada-xp-gp/board.c @@ -0,0 +1,17 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +/* empty */ diff --git a/arch/arm/boards/marvell-armada-xp-gp/config.h b/arch/arm/boards/marvell-armada-xp-gp/config.h new file mode 100644 index 0000000000..ca15136817 --- /dev/null +++ b/arch/arm/boards/marvell-armada-xp-gp/config.h @@ -0,0 +1,4 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/marvell-armada-xp-gp/kwbimage.cfg b/arch/arm/boards/marvell-armada-xp-gp/kwbimage.cfg new file mode 100644 index 0000000000..db75969fe0 --- /dev/null +++ b/arch/arm/boards/marvell-armada-xp-gp/kwbimage.cfg @@ -0,0 +1,3 @@ +VERSION 1 +BOOT_FROM spi +BINARY marvell-armada-xp-gp-binary.0 0000005b 00000068 diff --git a/arch/arm/boards/pcm038/pcm038.c b/arch/arm/boards/pcm038/pcm038.c index 4b2fa6c6ca..372aea59d5 100644 --- a/arch/arm/boards/pcm038/pcm038.c +++ b/arch/arm/boards/pcm038/pcm038.c @@ -48,13 +48,20 @@ #define PCM038_GPIO_FEC_RST (GPIO_PORTC + 30) #define PCM038_GPIO_SPI_CS0 (GPIO_PORTD + 28) +#define PCM970_GPIO_SPI_CS1 (GPIO_PORTD + 27) +#define PCM038_GPIO_OTG_STP (GPIO_PORTE + 1) static struct fec_platform_data fec_info = { .xcv_type = PHY_INTERFACE_MODE_MII, .phy_addr = 1, }; -static int pcm038_spi_cs[] = { PCM038_GPIO_SPI_CS0 }; +static int pcm038_spi_cs[] = { + PCM038_GPIO_SPI_CS0, +#ifdef CONFIG_MACH_PCM970_BASEBOARD + PCM970_GPIO_SPI_CS1, +#endif +}; static struct spi_imx_master pcm038_spi_0_data = { .chipselect = pcm038_spi_cs, @@ -186,6 +193,11 @@ static int pcm038_power_init(void) return 0; } +struct imxusb_platformdata pcm038_otg_pdata = { + .mode = IMX_USB_MODE_DEVICE, + .flags = MXC_EHCI_MODE_ULPI | MXC_EHCI_INTERFACE_DIFF_UNI, +}; + static int pcm038_devices_init(void) { int i; @@ -221,10 +233,13 @@ static int pcm038_devices_init(void) PE15_PF_UART1_RTS, /* CSPI1 */ PD25_PF_CSPI1_RDY, - PCM038_GPIO_SPI_CS0 | GPIO_GPIO | GPIO_OUT, PD29_PF_CSPI1_SCLK, PD30_PF_CSPI1_MISO, PD31_PF_CSPI1_MOSI, + PCM038_GPIO_SPI_CS0 | GPIO_GPIO | GPIO_OUT, +#ifdef CONFIG_MACH_PCM970_BASEBOARD + PCM970_GPIO_SPI_CS1 | GPIO_GPIO | GPIO_OUT, +#endif /* Display */ PA5_PF_LSCLK, PA6_PF_LD0, @@ -253,7 +268,7 @@ static int pcm038_devices_init(void) PA29_PF_VSYNC, PA30_PF_CONTRAST, PA31_PF_OE_ACD, - /* OTG host */ + /* USB OTG */ PC7_PF_USBOTG_DATA5, PC8_PF_USBOTG_DATA6, PC9_PF_USBOTG_DATA0, @@ -262,7 +277,7 @@ static int pcm038_devices_init(void) PC12_PF_USBOTG_DATA4, PC13_PF_USBOTG_DATA3, PE0_PF_USBOTG_NXT, - PE1_PF_USBOTG_STP, + PCM038_GPIO_OTG_STP | GPIO_GPIO | GPIO_OUT, PE2_PF_USBOTG_DIR, PE24_PF_USBOTG_CLK, PE25_PF_USBOTG_DATA7, @@ -308,6 +323,13 @@ static int pcm038_devices_init(void) gpio_set_value(PCM038_GPIO_FEC_RST, 1); imx27_add_fec(&fec_info); + /* Apply delay for STP line to stop ULPI */ + gpio_direction_output(PCM038_GPIO_OTG_STP, 1); + mdelay(1); + imx_gpio_mode(PE1_PF_USBOTG_STP); + + imx27_add_usbotg(&pcm038_otg_pdata); + switch (bootsource_get()) { case BOOTSOURCE_NAND: devfs_add_partition("nand0", 0x00000, 0x80000, diff --git a/arch/arm/boards/pcm049/board.c b/arch/arm/boards/pcm049/board.c index b0d689bf02..3c4b1a7dbe 100644 --- a/arch/arm/boards/pcm049/board.c +++ b/arch/arm/boards/pcm049/board.c @@ -48,7 +48,11 @@ console_initcall(pcm049_console_init); static int pcm049_mem_init(void) { +#ifdef CONFIG_1024MB_DDR2RAM + omap_add_ram0(SZ_1G); +#else omap_add_ram0(SZ_512M); +#endif omap44xx_add_sram0(); return 0; diff --git a/arch/arm/boards/pcm049/lowlevel.c b/arch/arm/boards/pcm049/lowlevel.c index 5075bbba3b..8bcecb14b1 100644 --- a/arch/arm/boards/pcm049/lowlevel.c +++ b/arch/arm/boards/pcm049/lowlevel.c @@ -30,6 +30,7 @@ void set_muxconf_regs(void); +/* 512MB */ static const struct ddr_regs ddr_regs_mt42L64M64_25_400_mhz = { .tim1 = 0x0EEB0662, .tim2 = 0x20370DD2, @@ -43,6 +44,20 @@ static const struct ddr_regs ddr_regs_mt42L64M64_25_400_mhz = { .mr2 = 0x4 }; +/* 1GB */ +static const struct ddr_regs ddr_regs_mt42L128M64_25_400_mhz = { + .tim1 = 0x0EEB0663, + .tim2 = 0x205715D2, + .tim3 = 0x00BFC53F, + .phy_ctrl_1 = 0x849FF408, + .ref_ctrl = 0x00000618, + .config_init = 0x80001AB9, + .config_final = 0x80001AB9, + .zq_config = 0x50093215, + .mr1 = 0x83, + .mr2 = 0x4 +}; + static void noinline pcm049_init_lowlevel(void) { struct dpll_param core = OMAP4_CORE_DPLL_PARAM_19M2_DDR400; @@ -55,7 +70,11 @@ static void noinline pcm049_init_lowlevel(void) set_muxconf_regs(); - omap4_ddr_init(&ddr_regs_mt42L64M64_25_400_mhz, &core); +#ifdef CONFIG_1024MB_DDR2RAM + omap4_ddr_init(&ddr_regs_mt42L128M64_25_400_mhz, &core); +#else + omap4_ddr_init(&ddr_regs_mt42L64M64_25_400_mhz, &core); +#endif /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ omap4_scale_vcores(TPS62361_VSEL0_GPIO); @@ -76,11 +95,11 @@ static void noinline pcm049_init_lowlevel(void) /* Enable all clocks */ omap4_enable_all_clocks(); - sr32(0x4A30a31C, 8, 1, 0x1); /* enable software ioreq */ - sr32(0x4A30a31C, 1, 2, 0x0); /* set for sys_clk (19.2MHz) */ - sr32(0x4A30a31C, 16, 4, 0x0); /* set divisor to 1 */ - sr32(0x4A30a110, 0, 1, 0x1); /* set the clock source to active */ - sr32(0x4A30a110, 2, 2, 0x3); /* enable clocks */ + sr32(OMAP44XX_SCRM_AUXCLK3, 8, 1, 0x1); /* enable software ioreq */ + sr32(OMAP44XX_SCRM_AUXCLK3, 1, 2, 0x0); /* set for sys_clk (19.2MHz) */ + sr32(OMAP44XX_SCRM_AUXCLK3, 16, 4, 0x0); /* set divisor to 1 */ + sr32(OMAP44XX_SCRM_ALTCLKSRC, 0, 1, 0x1); /* activate clock source */ + sr32(OMAP44XX_SCRM_ALTCLKSRC, 2, 2, 0x3); /* enable clocks */ } void barebox_arm_reset_vector(void) diff --git a/arch/arm/boards/plathome-openblocks-ax3/Makefile b/arch/arm/boards/plathome-openblocks-ax3/Makefile new file mode 100644 index 0000000000..dcfc2937d3 --- /dev/null +++ b/arch/arm/boards/plathome-openblocks-ax3/Makefile @@ -0,0 +1 @@ +obj-y += board.o diff --git a/arch/arm/boards/plathome-openblocks-ax3/board.c b/arch/arm/boards/plathome-openblocks-ax3/board.c new file mode 100644 index 0000000000..9c800c5410 --- /dev/null +++ b/arch/arm/boards/plathome-openblocks-ax3/board.c @@ -0,0 +1,17 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +/* empty */ diff --git a/arch/arm/boards/plathome-openblocks-ax3/config.h b/arch/arm/boards/plathome-openblocks-ax3/config.h new file mode 100644 index 0000000000..ca15136817 --- /dev/null +++ b/arch/arm/boards/plathome-openblocks-ax3/config.h @@ -0,0 +1,4 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/plathome-openblocks-ax3/kwbimage.cfg b/arch/arm/boards/plathome-openblocks-ax3/kwbimage.cfg new file mode 100644 index 0000000000..69fd1fd1c1 --- /dev/null +++ b/arch/arm/boards/plathome-openblocks-ax3/kwbimage.cfg @@ -0,0 +1,3 @@ +VERSION 1 +BOOT_FROM spi +BINARY plathome-openblocks-ax3-binary.0 0000005b 00000068 diff --git a/arch/arm/boards/qil-a9260/Makefile b/arch/arm/boards/qil-a926x/Makefile index eb072c0161..eb072c0161 100644 --- a/arch/arm/boards/qil-a9260/Makefile +++ b/arch/arm/boards/qil-a926x/Makefile diff --git a/arch/arm/boards/qil-a9260/config.h b/arch/arm/boards/qil-a926x/config.h index d97181032f..d97181032f 100644 --- a/arch/arm/boards/qil-a9260/config.h +++ b/arch/arm/boards/qil-a926x/config.h diff --git a/arch/arm/boards/qil-a9260/env/bin/init_board b/arch/arm/boards/qil-a926x/env/bin/init_board index 0a6baf722b..0a6baf722b 100644 --- a/arch/arm/boards/qil-a9260/env/bin/init_board +++ b/arch/arm/boards/qil-a926x/env/bin/init_board diff --git a/arch/arm/boards/qil-a9260/env/config b/arch/arm/boards/qil-a926x/env/config index 99711062f8..793a73f11e 100644 --- a/arch/arm/boards/qil-a9260/env/config +++ b/arch/arm/boards/qil-a926x/env/config @@ -3,7 +3,8 @@ # use 'dhcp' to do dhcp in barebox and in kernel # use 'none' if you want to skip kernel ip autoconfiguration ip=dhcp-barebox -global.dhcp.vendor_id=barebox-qil-a9260 +[ x$armlinux_architecture = x1711 ] && global.dhcp.vendor_id=barebox-qil-a9260 +[ x$armlinux_architecture = x1844 ] && global.dhcp.vendor_id=barebox-qil-a9g20 # or set your networking parameters here #eth0.ipaddr=a.b.c.d diff --git a/arch/arm/boards/qil-a9260/init.c b/arch/arm/boards/qil-a926x/init.c index 56b51c245a..504abc6566 100644 --- a/arch/arm/boards/qil-a9260/init.c +++ b/arch/arm/boards/qil-a926x/init.c @@ -28,6 +28,14 @@ #include <mach/at91_pmc.h> #include <mach/at91_rstc.h> +static void qil_a9260_set_board_type(void) +{ + if (machine_is_qil_a9g20()) + armlinux_set_architecture(MACH_TYPE_QIL_A9G20); + else + armlinux_set_architecture(MACH_TYPE_QIL_A9260); +} + static struct atmel_nand_data nand_pdata = { .ale = 21, .cle = 22, @@ -37,7 +45,7 @@ static struct atmel_nand_data nand_pdata = { .on_flash_bbt = 1, }; -static struct sam9_smc_config nand_smc_config = { +static struct sam9_smc_config qil_a9260_nand_smc_config = { .ncs_read_setup = 0, .nrd_setup = 1, .ncs_write_setup = 0, @@ -55,10 +63,31 @@ static struct sam9_smc_config nand_smc_config = { .tdf_cycles = 2, }; +static struct sam9_smc_config qil_a9g20_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 4, + + .read_cycle = 7, + .write_cycle = 7, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 3, +}; + static void qil_a9260_add_device_nand(void) { /* configure chip-select 3 (NAND) */ - sam9_smc_configure(0, 3, &nand_smc_config); + if (machine_is_qil_a9g20()) + sam9_smc_configure(0, 3, &qil_a9g20_nand_smc_config); + else + sam9_smc_configure(0, 3, &qil_a9260_nand_smc_config); at91_add_device_nand(&nand_pdata); } @@ -174,7 +203,7 @@ static int qil_a9260_devices_init(void) qil_a9260_add_device_mb(); armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100)); - armlinux_set_architecture(MACH_TYPE_QIL_A9260); + qil_a9260_set_board_type(); devfs_add_partition("nand0", 0x00000, SZ_128K, DEVFS_PARTITION_FIXED, "at91bootstrap_raw"); dev_add_bb_dev("at91bootstrap_raw", "at91bootstrap"); diff --git a/arch/arm/boards/qil-a9260/qil-a9260.dox b/arch/arm/boards/qil-a926x/qil-a9260.dox index da5c197b34..da5c197b34 100644 --- a/arch/arm/boards/qil-a9260/qil-a9260.dox +++ b/arch/arm/boards/qil-a926x/qil-a9260.dox diff --git a/arch/arm/boards/solidrun-cubox/Makefile b/arch/arm/boards/solidrun-cubox/Makefile new file mode 100644 index 0000000000..9320510bab --- /dev/null +++ b/arch/arm/boards/solidrun-cubox/Makefile @@ -0,0 +1 @@ +obj-y += board.c diff --git a/arch/arm/boards/solidrun-cubox/board.c b/arch/arm/boards/solidrun-cubox/board.c new file mode 100644 index 0000000000..a28f4197df --- /dev/null +++ b/arch/arm/boards/solidrun-cubox/board.c @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2013 + * Sebastian Hesselbarth <sebastian.hesselbarth@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. + * + */ + +/* empty */ diff --git a/arch/arm/boards/solidrun-cubox/config.h b/arch/arm/boards/solidrun-cubox/config.h new file mode 100644 index 0000000000..ca15136817 --- /dev/null +++ b/arch/arm/boards/solidrun-cubox/config.h @@ -0,0 +1,4 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/solidrun-cubox/kwbimage.cfg b/arch/arm/boards/solidrun-cubox/kwbimage.cfg new file mode 100644 index 0000000000..db35acacd4 --- /dev/null +++ b/arch/arm/boards/solidrun-cubox/kwbimage.cfg @@ -0,0 +1,37 @@ +VERSION 0 +BOOT_FROM spi +DATA d0020104 00000000 +DATA d0800020 00022430 +DATA d0800030 00022430 +DATA d0800050 911500c3 +DATA d0800060 646602c4 +DATA d0800190 c2003053 +DATA d08001c0 34f4a187 +DATA d0800650 000f0121 +DATA d0800660 04040200 +DATA d0800080 00000000 +DATA d0800090 00080000 +DATA d08000f0 c0000000 +DATA d08001a0 20c0c009 +DATA d0800280 010e0202 +DATA d0800760 00000000 +DATA d0800770 0000000a +DATA d0800140 20004044 +DATA d08001d0 133c2339 +DATA d08001e0 07700330 +DATA d08001f0 00000033 +DATA d0800200 0011311c +DATA d0800210 00300000 +DATA d0800240 80000000 +DATA d0800510 010e0101 +DATA d0800230 2028006a +DATA d0800e10 00280062 +DATA d0800e20 00280062 +DATA d0800e30 00280062 +DATA d0800100 000d0001 +DATA d0800110 200d0001 +DATA d0020104 00000000 +DATA d0020104 00000000 +DATA d0020104 00000000 +DATA d0020104 00000000 +DATA d0020104 00000000 diff --git a/arch/arm/configs/freescale-mx6-sabrelite_defconfig b/arch/arm/configs/freescale-mx6-sabrelite_defconfig index be7919be4e..d4d6cf24a2 100644 --- a/arch/arm/configs/freescale-mx6-sabrelite_defconfig +++ b/arch/arm/configs/freescale-mx6-sabrelite_defconfig @@ -1,9 +1,10 @@ +CONFIG_BUILTIN_DTB=y +CONFIG_BUILTIN_DTB_NAME="imx6q-sabrelite" CONFIG_ARCH_IMX=y CONFIG_ARCH_IMX6=y CONFIG_MACH_SABRELITE=y CONFIG_IMX_IIM=y CONFIG_IMX_IIM_FUSE_BLOW=y -CONFIG_AEABI=y CONFIG_THUMB2_BAREBOX=y CONFIG_CMD_ARM_MMUINFO=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y @@ -17,8 +18,10 @@ CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y +CONFIG_CONSOLE_ACTIVATE_NONE=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/freescale-mx6-sabrelite/env" +CONFIG_RESET_SOURCE=y CONFIG_CMD_EDIT=y CONFIG_CMD_SLEEP=y CONFIG_CMD_MSLEEP=y @@ -28,8 +31,9 @@ CONFIG_CMD_READLINE=y CONFIG_CMD_MENU=y CONFIG_CMD_MENU_MANAGEMENT=y CONFIG_CMD_TIME=y -CONFIG_CMD_BASENAME=y -CONFIG_CMD_DIRNAME=y +CONFIG_CMD_LN=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_FILETYPE=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_IOMEM=y @@ -43,29 +47,37 @@ CONFIG_CMD_BOOTM_INITRD=y CONFIG_CMD_BOOTM_OFTREE=y CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y CONFIG_CMD_BOOTM_AIMAGE=y -# CONFIG_CMD_BOOTZ is not set # CONFIG_CMD_BOOTU is not set CONFIG_CMD_RESET=y CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_BAREBOX_UPDATE=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_MAGICVAR=y CONFIG_CMD_MAGICVAR_HELP=y CONFIG_CMD_GPIO=y CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_SPI=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_CLK=y CONFIG_NET=y CONFIG_NET_DHCP=y -CONFIG_NET_RESOLV=y CONFIG_NET_PING=y -CONFIG_CMD_TFTP=y CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_OFDEVICE=y CONFIG_DRIVER_NET_FEC_IMX=y CONFIG_DRIVER_SPI_IMX=y +CONFIG_MTD=y CONFIG_MTD_M25P80=y CONFIG_MTD_SST25L=y -CONFIG_MTD=y +CONFIG_USB=y +CONFIG_USB_EHCI=y +CONFIG_USB_STORAGE=y CONFIG_MCI=y -CONFIG_MCI_STARTUP=y CONFIG_MCI_IMX_ESDHC=y CONFIG_FS_TFTP=y CONFIG_FS_NFS=y diff --git a/arch/arm/configs/freescale_mx51_babbage_defconfig b/arch/arm/configs/freescale_mx51_babbage_defconfig index 97963c1dca..2c03c14212 100644 --- a/arch/arm/configs/freescale_mx51_babbage_defconfig +++ b/arch/arm/configs/freescale_mx51_babbage_defconfig @@ -1,13 +1,13 @@ +CONFIG_BUILTIN_DTB=y +CONFIG_BUILTIN_DTB_NAME="imx51-babbage" CONFIG_ARCH_IMX=y CONFIG_ARCH_IMX51=y CONFIG_IMX_IIM=y CONFIG_IMX_IIM_FUSE_BLOW=y -CONFIG_AEABI=y CONFIG_THUMB2_BAREBOX=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_ARM_UNWIND=y CONFIG_MMU=y -CONFIG_TEXT_BASE=0x97f00000 CONFIG_MALLOC_SIZE=0x2000000 CONFIG_MALLOC_TLSF=y CONFIG_KALLSYMS=y @@ -16,6 +16,7 @@ CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y +CONFIG_CONSOLE_ACTIVATE_NONE=y CONFIG_DEFAULT_ENVIRONMENT_COMPRESSED_LZO=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/freescale-mx51-pdk/env/" @@ -31,8 +32,10 @@ CONFIG_CMD_TIME=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_IOMEM=y +CONFIG_CMD_MM=y CONFIG_CMD_CRC=y CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MD5SUM=y CONFIG_CMD_FLASH=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y @@ -43,19 +46,28 @@ CONFIG_CMD_UIMAGE=y # CONFIG_CMD_BOOTU is not set CONFIG_CMD_RESET=y CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_BAREBOX_UPDATE=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_MAGICVAR=y CONFIG_CMD_MAGICVAR_HELP=y CONFIG_CMD_GPIO=y CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_SPI=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_CLK=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_PING=y CONFIG_NET_RESOLV=y +CONFIG_OFDEVICE=y CONFIG_DRIVER_NET_FEC_IMX=y CONFIG_DRIVER_SPI_IMX=y CONFIG_MTD=y +CONFIG_MTD_DATAFLASH=y CONFIG_DRIVER_CFI=y CONFIG_CFI_BUFFER_WRITE=y CONFIG_MCI=y diff --git a/arch/arm/configs/globalscale_guruplug_defconfig b/arch/arm/configs/globalscale_guruplug_defconfig new file mode 100644 index 0000000000..d21de45c5d --- /dev/null +++ b/arch/arm/configs/globalscale_guruplug_defconfig @@ -0,0 +1,6 @@ +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_KIRKWOOD=y +CONFIG_TEXT_BASE=0x2000000 +CONFIG_DEBUG_LL=y +CONFIG_CMD_RESET=y +CONFIG_DRIVER_SERIAL_NS16550=y diff --git a/arch/arm/configs/globalscale_mirabox_defconfig b/arch/arm/configs/globalscale_mirabox_defconfig new file mode 100644 index 0000000000..ed9d94d867 --- /dev/null +++ b/arch/arm/configs/globalscale_mirabox_defconfig @@ -0,0 +1,8 @@ +CONFIG_ARCH_MVEBU=y +CONFIG_AEABI=y +CONFIG_DEBUG_LL=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_RESET=y +CONFIG_CMD_CLK=y +CONFIG_DRIVER_SERIAL_NS16550=y diff --git a/arch/arm/configs/marvell_armada_xp_gp_defconfig b/arch/arm/configs/marvell_armada_xp_gp_defconfig new file mode 100644 index 0000000000..5a7ef52b5f --- /dev/null +++ b/arch/arm/configs/marvell_armada_xp_gp_defconfig @@ -0,0 +1,10 @@ +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_ARMADA_XP=y +CONFIG_MACH_MARVELL_ARMADA_XP_GP=y +CONFIG_AEABI=y +CONFIG_DEBUG_LL=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_RESET=y +CONFIG_CMD_CLK=y +CONFIG_DRIVER_SERIAL_NS16550=y diff --git a/arch/arm/configs/plathome_openblocks_ax3_defconfig b/arch/arm/configs/plathome_openblocks_ax3_defconfig new file mode 100644 index 0000000000..95449c9741 --- /dev/null +++ b/arch/arm/configs/plathome_openblocks_ax3_defconfig @@ -0,0 +1,9 @@ +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_ARMADA_XP=y +CONFIG_AEABI=y +CONFIG_DEBUG_LL=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_RESET=y +CONFIG_CMD_CLK=y +CONFIG_DRIVER_SERIAL_NS16550=y diff --git a/arch/arm/configs/qil_a9260_128mib_defconfig b/arch/arm/configs/qil_a9260_128mib_defconfig index 8cd28f42c0..a19e083628 100644 --- a/arch/arm/configs/qil_a9260_128mib_defconfig +++ b/arch/arm/configs/qil_a9260_128mib_defconfig @@ -2,12 +2,12 @@ CONFIG_ARCH_AT91SAM9260=y CONFIG_MACH_QIL_A9260=y CONFIG_AT91_HAVE_SRAM_128M=y CONFIG_CALAO_MB_QIL_A9260=y +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 CONFIG_AEABI=y # CONFIG_CMD_ARM_CPUINFO is not set CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_PBL_IMAGE=y CONFIG_MMU=y -CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 CONFIG_EXPERIMENTAL=y CONFIG_PROMPT="USB-9G20:" CONFIG_LONGHELP=y @@ -17,10 +17,9 @@ CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y -# CONFIG_CONSOLE_ACTIVATE_FIRST is not set CONFIG_CONSOLE_ACTIVATE_ALL=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y -CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/qil-a9260/env" +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/qil-a926x/env" CONFIG_CMD_EDIT=y CONFIG_CMD_SLEEP=y CONFIG_CMD_SAVEENV=y @@ -29,11 +28,10 @@ CONFIG_CMD_PRINTENV=y CONFIG_CMD_READLINE=y CONFIG_CMD_MENU=y CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_TFTP=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_LOADB=y CONFIG_CMD_MEMINFO=y -CONFIG_CMD_MTEST=y -CONFIG_CMD_MTEST_ALTERNATIVE=y CONFIG_CMD_FLASH=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y @@ -41,11 +39,12 @@ CONFIG_CMD_BOOTM_INITRD=y CONFIG_CMD_BOOTM_OFTREE=y CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y CONFIG_CMD_UIMAGE=y -# CONFIG_CMD_BOOTZ is not set # CONFIG_CMD_BOOTU is not set CONFIG_CMD_RESET=y CONFIG_CMD_GO=y CONFIG_CMD_OFTREE=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y @@ -55,8 +54,6 @@ CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y CONFIG_NET_PING=y -CONFIG_CMD_TFTP=y -CONFIG_FS_TFTP=y CONFIG_NET_NETCONSOLE=y CONFIG_NET_RESOLV=y CONFIG_DRIVER_NET_MACB=y @@ -77,3 +74,4 @@ CONFIG_MCI_ATMEL=y CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_LED_TRIGGERS=y +CONFIG_FS_TFTP=y diff --git a/arch/arm/configs/qil_a9260_defconfig b/arch/arm/configs/qil_a9260_defconfig index 13460e8e89..67ca804ea7 100644 --- a/arch/arm/configs/qil_a9260_defconfig +++ b/arch/arm/configs/qil_a9260_defconfig @@ -1,12 +1,12 @@ CONFIG_ARCH_AT91SAM9260=y CONFIG_MACH_QIL_A9260=y CONFIG_CALAO_MB_QIL_A9260=y +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 CONFIG_AEABI=y # CONFIG_CMD_ARM_CPUINFO is not set CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_PBL_IMAGE=y CONFIG_MMU=y -CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 CONFIG_EXPERIMENTAL=y CONFIG_PROMPT="USB-9G20:" CONFIG_LONGHELP=y @@ -16,10 +16,9 @@ CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y -# CONFIG_CONSOLE_ACTIVATE_FIRST is not set CONFIG_CONSOLE_ACTIVATE_ALL=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y -CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/qil-a9260/env" +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/qil-a926x/env" CONFIG_CMD_EDIT=y CONFIG_CMD_SLEEP=y CONFIG_CMD_SAVEENV=y @@ -28,11 +27,10 @@ CONFIG_CMD_PRINTENV=y CONFIG_CMD_READLINE=y CONFIG_CMD_MENU=y CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_TFTP=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_LOADB=y CONFIG_CMD_MEMINFO=y -CONFIG_CMD_MTEST=y -CONFIG_CMD_MTEST_ALTERNATIVE=y CONFIG_CMD_FLASH=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y @@ -40,11 +38,12 @@ CONFIG_CMD_BOOTM_INITRD=y CONFIG_CMD_BOOTM_OFTREE=y CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y CONFIG_CMD_UIMAGE=y -# CONFIG_CMD_BOOTZ is not set # CONFIG_CMD_BOOTU is not set CONFIG_CMD_RESET=y CONFIG_CMD_GO=y CONFIG_CMD_OFTREE=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y @@ -54,8 +53,6 @@ CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y CONFIG_NET_PING=y -CONFIG_CMD_TFTP=y -CONFIG_FS_TFTP=y CONFIG_NET_NETCONSOLE=y CONFIG_NET_RESOLV=y CONFIG_DRIVER_NET_MACB=y @@ -76,3 +73,4 @@ CONFIG_MCI_ATMEL=y CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_LED_TRIGGERS=y +CONFIG_FS_TFTP=y diff --git a/arch/arm/configs/qil_a9g20_128mib_defconfig b/arch/arm/configs/qil_a9g20_128mib_defconfig new file mode 100644 index 0000000000..2c4a1602aa --- /dev/null +++ b/arch/arm/configs/qil_a9g20_128mib_defconfig @@ -0,0 +1,77 @@ +CONFIG_ARCH_AT91SAM9G20=y +CONFIG_MACH_QIL_A9G20=y +CONFIG_AT91_HAVE_SRAM_128M=y +CONFIG_CALAO_MB_QIL_A9260=y +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 +CONFIG_AEABI=y +# CONFIG_CMD_ARM_CPUINFO is not set +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_PBL_IMAGE=y +CONFIG_MMU=y +CONFIG_EXPERIMENTAL=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/qil-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y +CONFIG_CMD_UIMAGE=y +# CONFIG_CMD_BOOTU is not set +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_LED=y +CONFIG_CMD_LED_TRIGGER=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +# CONFIG_MTD_OOB_DEVICE is not set +CONFIG_NAND=y +# CONFIG_NAND_ECC_HW is not set +# CONFIG_NAND_ECC_HW_SYNDROME is not set +# CONFIG_NAND_ECC_HW_NONE is not set +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DFU=y +CONFIG_USB_GADGET_SERIAL=y +CONFIG_MCI=y +CONFIG_MCI_ATMEL=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_TRIGGERS=y +CONFIG_FS_TFTP=y diff --git a/arch/arm/configs/qil_a9g20_defconfig b/arch/arm/configs/qil_a9g20_defconfig new file mode 100644 index 0000000000..5b2e9ef6e1 --- /dev/null +++ b/arch/arm/configs/qil_a9g20_defconfig @@ -0,0 +1,76 @@ +CONFIG_ARCH_AT91SAM9G20=y +CONFIG_MACH_QIL_A9G20=y +CONFIG_CALAO_MB_QIL_A9260=y +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 +CONFIG_AEABI=y +# CONFIG_CMD_ARM_CPUINFO is not set +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_PBL_IMAGE=y +CONFIG_MMU=y +CONFIG_EXPERIMENTAL=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/qil-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y +CONFIG_CMD_UIMAGE=y +# CONFIG_CMD_BOOTU is not set +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_LED=y +CONFIG_CMD_LED_TRIGGER=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +# CONFIG_MTD_OOB_DEVICE is not set +CONFIG_NAND=y +# CONFIG_NAND_ECC_HW is not set +# CONFIG_NAND_ECC_HW_SYNDROME is not set +# CONFIG_NAND_ECC_HW_NONE is not set +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DFU=y +CONFIG_USB_GADGET_SERIAL=y +CONFIG_MCI=y +CONFIG_MCI_ATMEL=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_TRIGGERS=y +CONFIG_FS_TFTP=y diff --git a/arch/arm/configs/solidrun_cubox_defconfig b/arch/arm/configs/solidrun_cubox_defconfig new file mode 100644 index 0000000000..1a27d815a6 --- /dev/null +++ b/arch/arm/configs/solidrun_cubox_defconfig @@ -0,0 +1,9 @@ +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_DOVE=y +CONFIG_AEABI=y +CONFIG_DEBUG_LL=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_RESET=y +CONFIG_CMD_CLK=y +CONFIG_DRIVER_SERIAL_NS16550=y diff --git a/arch/arm/configs/tegra20_colibri_iris_defconfig b/arch/arm/configs/tegra20_colibri_iris_defconfig new file mode 100644 index 0000000000..37a0e8ac51 --- /dev/null +++ b/arch/arm/configs/tegra20_colibri_iris_defconfig @@ -0,0 +1,24 @@ +CONFIG_BUILTIN_DTB_NAME="tegra20-colibri-iris" +CONFIG_ARCH_TEGRA=y +CONFIG_AEABI=y +CONFIG_CMD_ARM_MMUINFO=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_STACK_SIZE=0x10000 +CONFIG_MALLOC_SIZE=0x4000000 +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_GLOB_SORT=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_HUSH_GETOPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_RESET=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_CLK=y +CONFIG_DRIVER_SERIAL_NS16550=y diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig index 86bc174101..aed4cb7c63 100644 --- a/arch/arm/cpu/Kconfig +++ b/arch/arm/cpu/Kconfig @@ -39,6 +39,14 @@ config CPU_ARM926T Say Y if you want support for the ARM926T processor. Otherwise, say N. +# Feroceon +config CPU_FEROCEON + bool + select CPU_32v5 + help + This is a Marvell implementation of an ARMv5TE compatible + ARM core, used in the Marvell Kirkwood SoC family. + # ARMv6 config CPU_V6 bool diff --git a/arch/arm/cpu/cpuinfo.c b/arch/arm/cpu/cpuinfo.c index 3c8fe4147f..8aea4b472d 100644 --- a/arch/arm/cpu/cpuinfo.c +++ b/arch/arm/cpu/cpuinfo.c @@ -155,7 +155,7 @@ static int do_cpuinfo(int argc, char *argv[]) implementer, architecture); if (cache & (1 << 24)) { - /* seperate I/D cache */ + /* separate I/D cache */ printf("I-cache: "); decode_cache(cache & 0xfff); printf("D-cache: "); diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 3ee89247e0..fa6a330aa8 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1,10 +1,15 @@ +dtb-$(CONFIG_ARCH_IMX51) += imx51-babbage.dtb +dtb-$(CONFIG_ARCH_IMX6) += imx6q-sabrelite.dtb \ + imx6q-sabresd.dtb -BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME)).dtb.o -obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB) +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME)) +obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o + +.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S targets += dtbs targets += $(dtb-y) -dtbs: $(addprefix $(obj)/, $(dtb-y)) +extra-y += $(dtb-y) clean-files := *.dtb *.dtb.S diff --git a/arch/arm/dts/imx51-babbage.dts b/arch/arm/dts/imx51-babbage.dts new file mode 100644 index 0000000000..4950eef606 --- /dev/null +++ b/arch/arm/dts/imx51-babbage.dts @@ -0,0 +1,307 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +#include "imx51.dtsi" + +/ { + model = "Freescale i.MX51 Babbage Board"; + compatible = "fsl,imx51-babbage", "fsl,imx51"; + + chosen { + linux,stdout-path = "/soc/aips@70000000/serial@73fbc000"; + }; + + memory { + reg = <0x90000000 0x20000000>; + }; + + display@di0 { + compatible = "fsl,imx-parallel-display"; + crtcs = <&ipu 0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu_disp1_1>; + }; + + display@di1 { + compatible = "fsl,imx-parallel-display"; + crtcs = <&ipu 1>; + interface-pix-fmt = "rgb565"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu_disp2_1>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power Button"; + gpios = <&gpio2 21 0>; + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; + + sound { + compatible = "fsl,imx51-babbage-sgtl5000", + "fsl,imx-audio-sgtl5000"; + model = "imx51-babbage-sgtl5000"; + ssi-controller = <&ssi2>; + audio-codec = <&sgtl5000>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + mux-int-port = <2>; + mux-ext-port = <3>; + }; +}; + +&esdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc1_1>; + fsl,cd-controller; + fsl,wp-controller; + status = "okay"; +}; + +&esdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc2_1>; + cd-gpios = <&gpio1 6 0>; + wp-gpios = <&gpio1 5 0>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3_1>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&ecspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1_1>; + fsl,spi-num-chipselects = <2>; + cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>; + status = "okay"; + + pmic: mc13892@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mc13892"; + spi-max-frequency = <6000000>; + spi-cs-high; + reg = <0>; + interrupt-parent = <&gpio1>; + interrupts = <8 0x4>; + + regulators { + sw1_reg: sw1 { + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1375000>; + regulator-boot-on; + regulator-always-on; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1850000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3_reg: sw3 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1850000>; + regulator-boot-on; + regulator-always-on; + }; + + sw4_reg: sw4 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1850000>; + regulator-boot-on; + regulator-always-on; + }; + + vpll_reg: vpll { + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + vdig_reg: vdig { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1650000>; + regulator-boot-on; + }; + + vsd_reg: vsd { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3150000>; + }; + + vusb2_reg: vusb2 { + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <2775000>; + regulator-boot-on; + regulator-always-on; + }; + + vvideo_reg: vvideo { + regulator-min-microvolt = <2775000>; + regulator-max-microvolt = <2775000>; + }; + + vaudio_reg: vaudio { + regulator-min-microvolt = <2300000>; + regulator-max-microvolt = <3000000>; + }; + + vcam_reg: vcam { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3000000>; + }; + + vgen1_reg: vgen1 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vgen2_reg: vgen2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3150000>; + regulator-always-on; + }; + + vgen3_reg: vgen3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2900000>; + regulator-always-on; + }; + }; + }; + + flash: at45db321d@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash"; + spi-max-frequency = <25000000>; + reg = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "Kernel"; + reg = <0x40000 0x3c0000>; + }; + }; +}; + +&ssi2 { + fsl,mode = "i2s-slave"; + status = "okay"; +}; + +&iim { + barebox,provide-mac-address = <&fec 1 9>; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + hog { + pinctrl_hog: hoggrp { + fsl,pins = < + MX51_PAD_GPIO1_0__SD1_CD 0x20d5 + MX51_PAD_GPIO1_1__SD1_WP 0x20d5 + MX51_PAD_GPIO1_5__GPIO1_5 0x100 + MX51_PAD_GPIO1_6__GPIO1_6 0x100 + MX51_PAD_EIM_A27__GPIO2_21 0x5 + MX51_PAD_CSPI1_SS0__GPIO4_24 0x85 + MX51_PAD_CSPI1_SS1__GPIO4_25 0x85 + MX51_PAD_EIM_A20__GPIO2_14 0x85 + >; + }; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_1>; + fsl,uart-has-rtscts; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2_1>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2_1>; + status = "okay"; + + sgtl5000: codec@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + clock-frequency = <26000000>; + VDDA-supply = <&vdig_reg>; + VDDIO-supply = <&vvideo_reg>; + }; +}; + +&audmux { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux_1>; + status = "okay"; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec_1>; + phy-mode = "mii"; + status = "okay"; +}; + +&kpp { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_kpp_1>; + linux,keymap = <0x00000067 /* KEY_UP */ + 0x0001006c /* KEY_DOWN */ + 0x00020072 /* KEY_VOLUMEDOWN */ + 0x00030066 /* KEY_HOME */ + 0x0100006a /* KEY_RIGHT */ + 0x01010069 /* KEY_LEFT */ + 0x0102001c /* KEY_ENTER */ + 0x01030073 /* KEY_VOLUMEUP */ + 0x02000040 /* KEY_F6 */ + 0x02010042 /* KEY_F8 */ + 0x02020043 /* KEY_F9 */ + 0x02030044 /* KEY_F10 */ + 0x0300003b /* KEY_F1 */ + 0x0301003c /* KEY_F2 */ + 0x0302003d /* KEY_F3 */ + 0x03030074>; /* KEY_POWER */ + status = "okay"; +}; diff --git a/arch/arm/dts/imx51-pinfunc.h b/arch/arm/dts/imx51-pinfunc.h new file mode 100644 index 0000000000..9eb92abaeb --- /dev/null +++ b/arch/arm/dts/imx51-pinfunc.h @@ -0,0 +1,773 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __DTS_IMX51_PINFUNC_H +#define __DTS_IMX51_PINFUNC_H + +/* + * The pin function ID is a tuple of + * <mux_reg conf_reg input_reg mux_mode input_val> + */ +#define MX51_PAD_EIM_D16__AUD4_RXFS 0x05c 0x3f0 0x000 0x5 0x0 +#define MX51_PAD_EIM_D16__AUD5_TXD 0x05c 0x3f0 0x8d8 0x7 0x0 +#define MX51_PAD_EIM_D16__EIM_D16 0x05c 0x3f0 0x000 0x0 0x0 +#define MX51_PAD_EIM_D16__GPIO2_0 0x05c 0x3f0 0x000 0x1 0x0 +#define MX51_PAD_EIM_D16__I2C1_SDA 0x05c 0x3f0 0x9b4 0x4 0x0 +#define MX51_PAD_EIM_D16__UART2_CTS 0x05c 0x3f0 0x000 0x3 0x0 +#define MX51_PAD_EIM_D16__USBH2_DATA0 0x05c 0x3f0 0x000 0x2 0x0 +#define MX51_PAD_EIM_D17__AUD5_RXD 0x060 0x3f4 0x8d4 0x7 0x0 +#define MX51_PAD_EIM_D17__EIM_D17 0x060 0x3f4 0x000 0x0 0x0 +#define MX51_PAD_EIM_D17__GPIO2_1 0x060 0x3f4 0x000 0x1 0x0 +#define MX51_PAD_EIM_D17__UART2_RXD 0x060 0x3f4 0x9ec 0x3 0x0 +#define MX51_PAD_EIM_D17__UART3_CTS 0x060 0x3f4 0x000 0x4 0x0 +#define MX51_PAD_EIM_D17__USBH2_DATA1 0x060 0x3f4 0x000 0x2 0x0 +#define MX51_PAD_EIM_D18__AUD5_TXC 0x064 0x3f8 0x8e4 0x7 0x0 +#define MX51_PAD_EIM_D18__EIM_D18 0x064 0x3f8 0x000 0x0 0x0 +#define MX51_PAD_EIM_D18__GPIO2_2 0x064 0x3f8 0x000 0x1 0x0 +#define MX51_PAD_EIM_D18__UART2_TXD 0x064 0x3f8 0x000 0x3 0x0 +#define MX51_PAD_EIM_D18__UART3_RTS 0x064 0x3f8 0x9f0 0x4 0x1 +#define MX51_PAD_EIM_D18__USBH2_DATA2 0x064 0x3f8 0x000 0x2 0x0 +#define MX51_PAD_EIM_D19__AUD4_RXC 0x068 0x3fc 0x000 0x5 0x0 +#define MX51_PAD_EIM_D19__AUD5_TXFS 0x068 0x3fc 0x8e8 0x7 0x0 +#define MX51_PAD_EIM_D19__EIM_D19 0x068 0x3fc 0x000 0x0 0x0 +#define MX51_PAD_EIM_D19__GPIO2_3 0x068 0x3fc 0x000 0x1 0x0 +#define MX51_PAD_EIM_D19__I2C1_SCL 0x068 0x3fc 0x9b0 0x4 0x0 +#define MX51_PAD_EIM_D19__UART2_RTS 0x068 0x3fc 0x9e8 0x3 0x1 +#define MX51_PAD_EIM_D19__USBH2_DATA3 0x068 0x3fc 0x000 0x2 0x0 +#define MX51_PAD_EIM_D20__AUD4_TXD 0x06c 0x400 0x8c8 0x5 0x0 +#define MX51_PAD_EIM_D20__EIM_D20 0x06c 0x400 0x000 0x0 0x0 +#define MX51_PAD_EIM_D20__GPIO2_4 0x06c 0x400 0x000 0x1 0x0 +#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB 0x06c 0x400 0x000 0x4 0x0 +#define MX51_PAD_EIM_D20__USBH2_DATA4 0x06c 0x400 0x000 0x2 0x0 +#define MX51_PAD_EIM_D21__AUD4_RXD 0x070 0x404 0x8c4 0x5 0x0 +#define MX51_PAD_EIM_D21__EIM_D21 0x070 0x404 0x000 0x0 0x0 +#define MX51_PAD_EIM_D21__GPIO2_5 0x070 0x404 0x000 0x1 0x0 +#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB 0x070 0x404 0x000 0x3 0x0 +#define MX51_PAD_EIM_D21__USBH2_DATA5 0x070 0x404 0x000 0x2 0x0 +#define MX51_PAD_EIM_D22__AUD4_TXC 0x074 0x408 0x8cc 0x5 0x0 +#define MX51_PAD_EIM_D22__EIM_D22 0x074 0x408 0x000 0x0 0x0 +#define MX51_PAD_EIM_D22__GPIO2_6 0x074 0x408 0x000 0x1 0x0 +#define MX51_PAD_EIM_D22__USBH2_DATA6 0x074 0x408 0x000 0x2 0x0 +#define MX51_PAD_EIM_D23__AUD4_TXFS 0x078 0x40c 0x8d0 0x5 0x0 +#define MX51_PAD_EIM_D23__EIM_D23 0x078 0x40c 0x000 0x0 0x0 +#define MX51_PAD_EIM_D23__GPIO2_7 0x078 0x40c 0x000 0x1 0x0 +#define MX51_PAD_EIM_D23__SPDIF_OUT1 0x078 0x40c 0x000 0x4 0x0 +#define MX51_PAD_EIM_D23__USBH2_DATA7 0x078 0x40c 0x000 0x2 0x0 +#define MX51_PAD_EIM_D24__AUD6_RXFS 0x07c 0x410 0x8f8 0x5 0x0 +#define MX51_PAD_EIM_D24__EIM_D24 0x07c 0x410 0x000 0x0 0x0 +#define MX51_PAD_EIM_D24__GPIO2_8 0x07c 0x410 0x000 0x1 0x0 +#define MX51_PAD_EIM_D24__I2C2_SDA 0x07c 0x410 0x9bc 0x4 0x0 +#define MX51_PAD_EIM_D24__UART3_CTS 0x07c 0x410 0x000 0x3 0x0 +#define MX51_PAD_EIM_D24__USBOTG_DATA0 0x07c 0x410 0x000 0x2 0x0 +#define MX51_PAD_EIM_D25__EIM_D25 0x080 0x414 0x000 0x0 0x0 +#define MX51_PAD_EIM_D25__KEY_COL6 0x080 0x414 0x9c8 0x1 0x0 +#define MX51_PAD_EIM_D25__UART2_CTS 0x080 0x414 0x000 0x4 0x0 +#define MX51_PAD_EIM_D25__UART3_RXD 0x080 0x414 0x9f4 0x3 0x0 +#define MX51_PAD_EIM_D25__USBOTG_DATA1 0x080 0x414 0x000 0x2 0x0 +#define MX51_PAD_EIM_D26__EIM_D26 0x084 0x418 0x000 0x0 0x0 +#define MX51_PAD_EIM_D26__KEY_COL7 0x084 0x418 0x9cc 0x1 0x0 +#define MX51_PAD_EIM_D26__UART2_RTS 0x084 0x418 0x9e8 0x4 0x3 +#define MX51_PAD_EIM_D26__UART3_TXD 0x084 0x418 0x000 0x3 0x0 +#define MX51_PAD_EIM_D26__USBOTG_DATA2 0x084 0x418 0x000 0x2 0x0 +#define MX51_PAD_EIM_D27__AUD6_RXC 0x088 0x41c 0x8f4 0x5 0x0 +#define MX51_PAD_EIM_D27__EIM_D27 0x088 0x41c 0x000 0x0 0x0 +#define MX51_PAD_EIM_D27__GPIO2_9 0x088 0x41c 0x000 0x1 0x0 +#define MX51_PAD_EIM_D27__I2C2_SCL 0x088 0x41c 0x9b8 0x4 0x0 +#define MX51_PAD_EIM_D27__UART3_RTS 0x088 0x41c 0x9f0 0x3 0x3 +#define MX51_PAD_EIM_D27__USBOTG_DATA3 0x088 0x41c 0x000 0x2 0x0 +#define MX51_PAD_EIM_D28__AUD6_TXD 0x08c 0x420 0x8f0 0x5 0x0 +#define MX51_PAD_EIM_D28__EIM_D28 0x08c 0x420 0x000 0x0 0x0 +#define MX51_PAD_EIM_D28__KEY_ROW4 0x08c 0x420 0x9d0 0x1 0x0 +#define MX51_PAD_EIM_D28__USBOTG_DATA4 0x08c 0x420 0x000 0x2 0x0 +#define MX51_PAD_EIM_D29__AUD6_RXD 0x090 0x424 0x8ec 0x5 0x0 +#define MX51_PAD_EIM_D29__EIM_D29 0x090 0x424 0x000 0x0 0x0 +#define MX51_PAD_EIM_D29__KEY_ROW5 0x090 0x424 0x9d4 0x1 0x0 +#define MX51_PAD_EIM_D29__USBOTG_DATA5 0x090 0x424 0x000 0x2 0x0 +#define MX51_PAD_EIM_D30__AUD6_TXC 0x094 0x428 0x8fc 0x5 0x0 +#define MX51_PAD_EIM_D30__EIM_D30 0x094 0x428 0x000 0x0 0x0 +#define MX51_PAD_EIM_D30__KEY_ROW6 0x094 0x428 0x9d8 0x1 0x0 +#define MX51_PAD_EIM_D30__USBOTG_DATA6 0x094 0x428 0x000 0x2 0x0 +#define MX51_PAD_EIM_D31__AUD6_TXFS 0x098 0x42c 0x900 0x5 0x0 +#define MX51_PAD_EIM_D31__EIM_D31 0x098 0x42c 0x000 0x0 0x0 +#define MX51_PAD_EIM_D31__KEY_ROW7 0x098 0x42c 0x9dc 0x1 0x0 +#define MX51_PAD_EIM_D31__USBOTG_DATA7 0x098 0x42c 0x000 0x2 0x0 +#define MX51_PAD_EIM_A16__EIM_A16 0x09c 0x430 0x000 0x0 0x0 +#define MX51_PAD_EIM_A16__GPIO2_10 0x09c 0x430 0x000 0x1 0x0 +#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0 0x09c 0x430 0x000 0x7 0x0 +#define MX51_PAD_EIM_A17__EIM_A17 0x0a0 0x434 0x000 0x0 0x0 +#define MX51_PAD_EIM_A17__GPIO2_11 0x0a0 0x434 0x000 0x1 0x0 +#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1 0x0a0 0x434 0x000 0x7 0x0 +#define MX51_PAD_EIM_A18__BOOT_LPB0 0x0a4 0x438 0x000 0x7 0x0 +#define MX51_PAD_EIM_A18__EIM_A18 0x0a4 0x438 0x000 0x0 0x0 +#define MX51_PAD_EIM_A18__GPIO2_12 0x0a4 0x438 0x000 0x1 0x0 +#define MX51_PAD_EIM_A19__BOOT_LPB1 0x0a8 0x43c 0x000 0x7 0x0 +#define MX51_PAD_EIM_A19__EIM_A19 0x0a8 0x43c 0x000 0x0 0x0 +#define MX51_PAD_EIM_A19__GPIO2_13 0x0a8 0x43c 0x000 0x1 0x0 +#define MX51_PAD_EIM_A20__BOOT_UART_SRC0 0x0ac 0x440 0x000 0x7 0x0 +#define MX51_PAD_EIM_A20__EIM_A20 0x0ac 0x440 0x000 0x0 0x0 +#define MX51_PAD_EIM_A20__GPIO2_14 0x0ac 0x440 0x000 0x1 0x0 +#define MX51_PAD_EIM_A21__BOOT_UART_SRC1 0x0b0 0x444 0x000 0x7 0x0 +#define MX51_PAD_EIM_A21__EIM_A21 0x0b0 0x444 0x000 0x0 0x0 +#define MX51_PAD_EIM_A21__GPIO2_15 0x0b0 0x444 0x000 0x1 0x0 +#define MX51_PAD_EIM_A22__EIM_A22 0x0b4 0x448 0x000 0x0 0x0 +#define MX51_PAD_EIM_A22__GPIO2_16 0x0b4 0x448 0x000 0x1 0x0 +#define MX51_PAD_EIM_A23__BOOT_HPN_EN 0x0b8 0x44c 0x000 0x7 0x0 +#define MX51_PAD_EIM_A23__EIM_A23 0x0b8 0x44c 0x000 0x0 0x0 +#define MX51_PAD_EIM_A23__GPIO2_17 0x0b8 0x44c 0x000 0x1 0x0 +#define MX51_PAD_EIM_A24__EIM_A24 0x0bc 0x450 0x000 0x0 0x0 +#define MX51_PAD_EIM_A24__GPIO2_18 0x0bc 0x450 0x000 0x1 0x0 +#define MX51_PAD_EIM_A24__USBH2_CLK 0x0bc 0x450 0x000 0x2 0x0 +#define MX51_PAD_EIM_A25__DISP1_PIN4 0x0c0 0x454 0x000 0x6 0x0 +#define MX51_PAD_EIM_A25__EIM_A25 0x0c0 0x454 0x000 0x0 0x0 +#define MX51_PAD_EIM_A25__GPIO2_19 0x0c0 0x454 0x000 0x1 0x0 +#define MX51_PAD_EIM_A25__USBH2_DIR 0x0c0 0x454 0x000 0x2 0x0 +#define MX51_PAD_EIM_A26__CSI1_DATA_EN 0x0c4 0x458 0x9a0 0x5 0x0 +#define MX51_PAD_EIM_A26__DISP2_EXT_CLK 0x0c4 0x458 0x908 0x6 0x0 +#define MX51_PAD_EIM_A26__EIM_A26 0x0c4 0x458 0x000 0x0 0x0 +#define MX51_PAD_EIM_A26__GPIO2_20 0x0c4 0x458 0x000 0x1 0x0 +#define MX51_PAD_EIM_A26__USBH2_STP 0x0c4 0x458 0x000 0x2 0x0 +#define MX51_PAD_EIM_A27__CSI2_DATA_EN 0x0c8 0x45c 0x99c 0x5 0x0 +#define MX51_PAD_EIM_A27__DISP1_PIN1 0x0c8 0x45c 0x9a4 0x6 0x0 +#define MX51_PAD_EIM_A27__EIM_A27 0x0c8 0x45c 0x000 0x0 0x0 +#define MX51_PAD_EIM_A27__GPIO2_21 0x0c8 0x45c 0x000 0x1 0x0 +#define MX51_PAD_EIM_A27__USBH2_NXT 0x0c8 0x45c 0x000 0x2 0x0 +#define MX51_PAD_EIM_EB0__EIM_EB0 0x0cc 0x460 0x000 0x0 0x0 +#define MX51_PAD_EIM_EB1__EIM_EB1 0x0d0 0x464 0x000 0x0 0x0 +#define MX51_PAD_EIM_EB2__AUD5_RXFS 0x0d4 0x468 0x8e0 0x6 0x0 +#define MX51_PAD_EIM_EB2__CSI1_D2 0x0d4 0x468 0x000 0x5 0x0 +#define MX51_PAD_EIM_EB2__EIM_EB2 0x0d4 0x468 0x000 0x0 0x0 +#define MX51_PAD_EIM_EB2__FEC_MDIO 0x0d4 0x468 0x954 0x3 0x0 +#define MX51_PAD_EIM_EB2__GPIO2_22 0x0d4 0x468 0x000 0x1 0x0 +#define MX51_PAD_EIM_EB2__GPT_CMPOUT1 0x0d4 0x468 0x000 0x7 0x0 +#define MX51_PAD_EIM_EB3__AUD5_RXC 0x0d8 0x46c 0x8dc 0x6 0x0 +#define MX51_PAD_EIM_EB3__CSI1_D3 0x0d8 0x46c 0x000 0x5 0x0 +#define MX51_PAD_EIM_EB3__EIM_EB3 0x0d8 0x46c 0x000 0x0 0x0 +#define MX51_PAD_EIM_EB3__FEC_RDATA1 0x0d8 0x46c 0x95c 0x3 0x0 +#define MX51_PAD_EIM_EB3__GPIO2_23 0x0d8 0x46c 0x000 0x1 0x0 +#define MX51_PAD_EIM_EB3__GPT_CMPOUT2 0x0d8 0x46c 0x000 0x7 0x0 +#define MX51_PAD_EIM_OE__EIM_OE 0x0dc 0x470 0x000 0x0 0x0 +#define MX51_PAD_EIM_OE__GPIO2_24 0x0dc 0x470 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS0__EIM_CS0 0x0e0 0x474 0x000 0x0 0x0 +#define MX51_PAD_EIM_CS0__GPIO2_25 0x0e0 0x474 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS1__EIM_CS1 0x0e4 0x478 0x000 0x0 0x0 +#define MX51_PAD_EIM_CS1__GPIO2_26 0x0e4 0x478 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS2__AUD5_TXD 0x0e8 0x47c 0x8d8 0x6 0x1 +#define MX51_PAD_EIM_CS2__CSI1_D4 0x0e8 0x47c 0x000 0x5 0x0 +#define MX51_PAD_EIM_CS2__EIM_CS2 0x0e8 0x47c 0x000 0x0 0x0 +#define MX51_PAD_EIM_CS2__FEC_RDATA2 0x0e8 0x47c 0x960 0x3 0x0 +#define MX51_PAD_EIM_CS2__GPIO2_27 0x0e8 0x47c 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS2__USBOTG_STP 0x0e8 0x47c 0x000 0x2 0x0 +#define MX51_PAD_EIM_CS3__AUD5_RXD 0x0ec 0x480 0x8d4 0x6 0x1 +#define MX51_PAD_EIM_CS3__CSI1_D5 0x0ec 0x480 0x000 0x5 0x0 +#define MX51_PAD_EIM_CS3__EIM_CS3 0x0ec 0x480 0x000 0x0 0x0 +#define MX51_PAD_EIM_CS3__FEC_RDATA3 0x0ec 0x480 0x964 0x3 0x0 +#define MX51_PAD_EIM_CS3__GPIO2_28 0x0ec 0x480 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS3__USBOTG_NXT 0x0ec 0x480 0x000 0x2 0x0 +#define MX51_PAD_EIM_CS4__AUD5_TXC 0x0f0 0x484 0x8e4 0x6 0x1 +#define MX51_PAD_EIM_CS4__CSI1_D6 0x0f0 0x484 0x000 0x5 0x0 +#define MX51_PAD_EIM_CS4__EIM_CS4 0x0f0 0x484 0x000 0x0 0x0 +#define MX51_PAD_EIM_CS4__FEC_RX_ER 0x0f0 0x484 0x970 0x3 0x0 +#define MX51_PAD_EIM_CS4__GPIO2_29 0x0f0 0x484 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS4__USBOTG_CLK 0x0f0 0x484 0x000 0x2 0x0 +#define MX51_PAD_EIM_CS5__AUD5_TXFS 0x0f4 0x488 0x8e8 0x6 0x1 +#define MX51_PAD_EIM_CS5__CSI1_D7 0x0f4 0x488 0x000 0x5 0x0 +#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK 0x0f4 0x488 0x904 0x4 0x0 +#define MX51_PAD_EIM_CS5__EIM_CS5 0x0f4 0x488 0x000 0x0 0x0 +#define MX51_PAD_EIM_CS5__FEC_CRS 0x0f4 0x488 0x950 0x3 0x0 +#define MX51_PAD_EIM_CS5__GPIO2_30 0x0f4 0x488 0x000 0x1 0x0 +#define MX51_PAD_EIM_CS5__USBOTG_DIR 0x0f4 0x488 0x000 0x2 0x0 +#define MX51_PAD_EIM_DTACK__EIM_DTACK 0x0f8 0x48c 0x000 0x0 0x0 +#define MX51_PAD_EIM_DTACK__GPIO2_31 0x0f8 0x48c 0x000 0x1 0x0 +#define MX51_PAD_EIM_LBA__EIM_LBA 0x0fc 0x494 0x000 0x0 0x0 +#define MX51_PAD_EIM_LBA__GPIO3_1 0x0fc 0x494 0x978 0x1 0x0 +#define MX51_PAD_EIM_CRE__EIM_CRE 0x100 0x4a0 0x000 0x0 0x0 +#define MX51_PAD_EIM_CRE__GPIO3_2 0x100 0x4a0 0x97c 0x1 0x0 +#define MX51_PAD_DRAM_CS1__DRAM_CS1 0x104 0x4d0 0x000 0x0 0x0 +#define MX51_PAD_NANDF_WE_B__GPIO3_3 0x108 0x4e4 0x980 0x3 0x0 +#define MX51_PAD_NANDF_WE_B__NANDF_WE_B 0x108 0x4e4 0x000 0x0 0x0 +#define MX51_PAD_NANDF_WE_B__PATA_DIOW 0x108 0x4e4 0x000 0x1 0x0 +#define MX51_PAD_NANDF_WE_B__SD3_DATA0 0x108 0x4e4 0x93c 0x2 0x0 +#define MX51_PAD_NANDF_RE_B__GPIO3_4 0x10c 0x4e8 0x984 0x3 0x0 +#define MX51_PAD_NANDF_RE_B__NANDF_RE_B 0x10c 0x4e8 0x000 0x0 0x0 +#define MX51_PAD_NANDF_RE_B__PATA_DIOR 0x10c 0x4e8 0x000 0x1 0x0 +#define MX51_PAD_NANDF_RE_B__SD3_DATA1 0x10c 0x4e8 0x940 0x2 0x0 +#define MX51_PAD_NANDF_ALE__GPIO3_5 0x110 0x4ec 0x988 0x3 0x0 +#define MX51_PAD_NANDF_ALE__NANDF_ALE 0x110 0x4ec 0x000 0x0 0x0 +#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN 0x110 0x4ec 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CLE__GPIO3_6 0x114 0x4f0 0x98c 0x3 0x0 +#define MX51_PAD_NANDF_CLE__NANDF_CLE 0x114 0x4f0 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CLE__PATA_RESET_B 0x114 0x4f0 0x000 0x1 0x0 +#define MX51_PAD_NANDF_WP_B__GPIO3_7 0x118 0x4f4 0x990 0x3 0x0 +#define MX51_PAD_NANDF_WP_B__NANDF_WP_B 0x118 0x4f4 0x000 0x0 0x0 +#define MX51_PAD_NANDF_WP_B__PATA_DMACK 0x118 0x4f4 0x000 0x1 0x0 +#define MX51_PAD_NANDF_WP_B__SD3_DATA2 0x118 0x4f4 0x944 0x2 0x0 +#define MX51_PAD_NANDF_RB0__ECSPI2_SS1 0x11c 0x4f8 0x930 0x5 0x0 +#define MX51_PAD_NANDF_RB0__GPIO3_8 0x11c 0x4f8 0x994 0x3 0x0 +#define MX51_PAD_NANDF_RB0__NANDF_RB0 0x11c 0x4f8 0x000 0x0 0x0 +#define MX51_PAD_NANDF_RB0__PATA_DMARQ 0x11c 0x4f8 0x000 0x1 0x0 +#define MX51_PAD_NANDF_RB0__SD3_DATA3 0x11c 0x4f8 0x948 0x2 0x0 +#define MX51_PAD_NANDF_RB1__CSPI_MOSI 0x120 0x4fc 0x91c 0x6 0x0 +#define MX51_PAD_NANDF_RB1__ECSPI2_RDY 0x120 0x4fc 0x000 0x2 0x0 +#define MX51_PAD_NANDF_RB1__GPIO3_9 0x120 0x4fc 0x000 0x3 0x0 +#define MX51_PAD_NANDF_RB1__NANDF_RB1 0x120 0x4fc 0x000 0x0 0x0 +#define MX51_PAD_NANDF_RB1__PATA_IORDY 0x120 0x4fc 0x000 0x1 0x0 +#define MX51_PAD_NANDF_RB1__SD4_CMD 0x120 0x4fc 0x000 0x5 0x0 +#define MX51_PAD_NANDF_RB2__DISP2_WAIT 0x124 0x500 0x9a8 0x5 0x0 +#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x124 0x500 0x000 0x2 0x0 +#define MX51_PAD_NANDF_RB2__FEC_COL 0x124 0x500 0x94c 0x1 0x0 +#define MX51_PAD_NANDF_RB2__GPIO3_10 0x124 0x500 0x000 0x3 0x0 +#define MX51_PAD_NANDF_RB2__NANDF_RB2 0x124 0x500 0x000 0x0 0x0 +#define MX51_PAD_NANDF_RB2__USBH3_H3_DP 0x124 0x500 0x000 0x7 0x0 +#define MX51_PAD_NANDF_RB2__USBH3_NXT 0x124 0x500 0xa20 0x6 0x0 +#define MX51_PAD_NANDF_RB3__DISP1_WAIT 0x128 0x504 0x000 0x5 0x0 +#define MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x128 0x504 0x000 0x2 0x0 +#define MX51_PAD_NANDF_RB3__FEC_RX_CLK 0x128 0x504 0x968 0x1 0x0 +#define MX51_PAD_NANDF_RB3__GPIO3_11 0x128 0x504 0x000 0x3 0x0 +#define MX51_PAD_NANDF_RB3__NANDF_RB3 0x128 0x504 0x000 0x0 0x0 +#define MX51_PAD_NANDF_RB3__USBH3_CLK 0x128 0x504 0x9f8 0x6 0x0 +#define MX51_PAD_NANDF_RB3__USBH3_H3_DM 0x128 0x504 0x000 0x7 0x0 +#define MX51_PAD_GPIO_NAND__GPIO_NAND 0x12c 0x514 0x998 0x0 0x0 +#define MX51_PAD_GPIO_NAND__PATA_INTRQ 0x12c 0x514 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS0__GPIO3_16 0x130 0x518 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS0__NANDF_CS0 0x130 0x518 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS1__GPIO3_17 0x134 0x51c 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS1__NANDF_CS1 0x134 0x51c 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS2__CSPI_SCLK 0x138 0x520 0x914 0x6 0x0 +#define MX51_PAD_NANDF_CS2__FEC_TX_ER 0x138 0x520 0x000 0x2 0x0 +#define MX51_PAD_NANDF_CS2__GPIO3_18 0x138 0x520 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS2__NANDF_CS2 0x138 0x520 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS2__PATA_CS_0 0x138 0x520 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS2__SD4_CLK 0x138 0x520 0x000 0x5 0x0 +#define MX51_PAD_NANDF_CS2__USBH3_H1_DP 0x138 0x520 0x000 0x7 0x0 +#define MX51_PAD_NANDF_CS3__FEC_MDC 0x13c 0x524 0x000 0x2 0x0 +#define MX51_PAD_NANDF_CS3__GPIO3_19 0x13c 0x524 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS3__NANDF_CS3 0x13c 0x524 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS3__PATA_CS_1 0x13c 0x524 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS3__SD4_DAT0 0x13c 0x524 0x000 0x5 0x0 +#define MX51_PAD_NANDF_CS3__USBH3_H1_DM 0x13c 0x524 0x000 0x7 0x0 +#define MX51_PAD_NANDF_CS4__FEC_TDATA1 0x140 0x528 0x000 0x2 0x0 +#define MX51_PAD_NANDF_CS4__GPIO3_20 0x140 0x528 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS4__NANDF_CS4 0x140 0x528 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS4__PATA_DA_0 0x140 0x528 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS4__SD4_DAT1 0x140 0x528 0x000 0x5 0x0 +#define MX51_PAD_NANDF_CS4__USBH3_STP 0x140 0x528 0xa24 0x7 0x0 +#define MX51_PAD_NANDF_CS5__FEC_TDATA2 0x144 0x52c 0x000 0x2 0x0 +#define MX51_PAD_NANDF_CS5__GPIO3_21 0x144 0x52c 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS5__NANDF_CS5 0x144 0x52c 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS5__PATA_DA_1 0x144 0x52c 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS5__SD4_DAT2 0x144 0x52c 0x000 0x5 0x0 +#define MX51_PAD_NANDF_CS5__USBH3_DIR 0x144 0x52c 0xa1c 0x7 0x0 +#define MX51_PAD_NANDF_CS6__CSPI_SS3 0x148 0x530 0x928 0x7 0x0 +#define MX51_PAD_NANDF_CS6__FEC_TDATA3 0x148 0x530 0x000 0x2 0x0 +#define MX51_PAD_NANDF_CS6__GPIO3_22 0x148 0x530 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS6__NANDF_CS6 0x148 0x530 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS6__PATA_DA_2 0x148 0x530 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS6__SD4_DAT3 0x148 0x530 0x000 0x5 0x0 +#define MX51_PAD_NANDF_CS7__FEC_TX_EN 0x14c 0x534 0x000 0x1 0x0 +#define MX51_PAD_NANDF_CS7__GPIO3_23 0x14c 0x534 0x000 0x3 0x0 +#define MX51_PAD_NANDF_CS7__NANDF_CS7 0x14c 0x534 0x000 0x0 0x0 +#define MX51_PAD_NANDF_CS7__SD3_CLK 0x14c 0x534 0x000 0x5 0x0 +#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 0x150 0x538 0x000 0x2 0x0 +#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x150 0x538 0x974 0x1 0x0 +#define MX51_PAD_NANDF_RDY_INT__GPIO3_24 0x150 0x538 0x000 0x3 0x0 +#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT 0x150 0x538 0x938 0x0 0x0 +#define MX51_PAD_NANDF_RDY_INT__SD3_CMD 0x150 0x538 0x000 0x5 0x0 +#define MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x154 0x53c 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D15__GPIO3_25 0x154 0x53c 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D15__NANDF_D15 0x154 0x53c 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D15__PATA_DATA15 0x154 0x53c 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D15__SD3_DAT7 0x154 0x53c 0x000 0x5 0x0 +#define MX51_PAD_NANDF_D14__ECSPI2_SS3 0x158 0x540 0x934 0x2 0x0 +#define MX51_PAD_NANDF_D14__GPIO3_26 0x158 0x540 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D14__NANDF_D14 0x158 0x540 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D14__PATA_DATA14 0x158 0x540 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D14__SD3_DAT6 0x158 0x540 0x000 0x5 0x0 +#define MX51_PAD_NANDF_D13__ECSPI2_SS2 0x15c 0x544 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D13__GPIO3_27 0x15c 0x544 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D13__NANDF_D13 0x15c 0x544 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D13__PATA_DATA13 0x15c 0x544 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D13__SD3_DAT5 0x15c 0x544 0x000 0x5 0x0 +#define MX51_PAD_NANDF_D12__ECSPI2_SS1 0x160 0x548 0x930 0x2 0x1 +#define MX51_PAD_NANDF_D12__GPIO3_28 0x160 0x548 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D12__NANDF_D12 0x160 0x548 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D12__PATA_DATA12 0x160 0x548 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D12__SD3_DAT4 0x160 0x548 0x000 0x5 0x0 +#define MX51_PAD_NANDF_D11__FEC_RX_DV 0x164 0x54c 0x96c 0x2 0x0 +#define MX51_PAD_NANDF_D11__GPIO3_29 0x164 0x54c 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D11__NANDF_D11 0x164 0x54c 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D11__PATA_DATA11 0x164 0x54c 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D11__SD3_DATA3 0x164 0x54c 0x948 0x5 0x1 +#define MX51_PAD_NANDF_D10__GPIO3_30 0x168 0x550 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D10__NANDF_D10 0x168 0x550 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D10__PATA_DATA10 0x168 0x550 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D10__SD3_DATA2 0x168 0x550 0x944 0x5 0x1 +#define MX51_PAD_NANDF_D9__FEC_RDATA0 0x16c 0x554 0x958 0x2 0x0 +#define MX51_PAD_NANDF_D9__GPIO3_31 0x16c 0x554 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D9__NANDF_D9 0x16c 0x554 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D9__PATA_DATA9 0x16c 0x554 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D9__SD3_DATA1 0x16c 0x554 0x940 0x5 0x1 +#define MX51_PAD_NANDF_D8__FEC_TDATA0 0x170 0x558 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D8__GPIO4_0 0x170 0x558 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D8__NANDF_D8 0x170 0x558 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D8__PATA_DATA8 0x170 0x558 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D8__SD3_DATA0 0x170 0x558 0x93c 0x5 0x1 +#define MX51_PAD_NANDF_D7__GPIO4_1 0x174 0x55c 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D7__NANDF_D7 0x174 0x55c 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D7__PATA_DATA7 0x174 0x55c 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D7__USBH3_DATA0 0x174 0x55c 0x9fc 0x5 0x0 +#define MX51_PAD_NANDF_D6__GPIO4_2 0x178 0x560 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D6__NANDF_D6 0x178 0x560 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D6__PATA_DATA6 0x178 0x560 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D6__SD4_LCTL 0x178 0x560 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D6__USBH3_DATA1 0x178 0x560 0xa00 0x5 0x0 +#define MX51_PAD_NANDF_D5__GPIO4_3 0x17c 0x564 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D5__NANDF_D5 0x17c 0x564 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D5__PATA_DATA5 0x17c 0x564 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D5__SD4_WP 0x17c 0x564 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D5__USBH3_DATA2 0x17c 0x564 0xa04 0x5 0x0 +#define MX51_PAD_NANDF_D4__GPIO4_4 0x180 0x568 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D4__NANDF_D4 0x180 0x568 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D4__PATA_DATA4 0x180 0x568 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D4__SD4_CD 0x180 0x568 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D4__USBH3_DATA3 0x180 0x568 0xa08 0x5 0x0 +#define MX51_PAD_NANDF_D3__GPIO4_5 0x184 0x56c 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D3__NANDF_D3 0x184 0x56c 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D3__PATA_DATA3 0x184 0x56c 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D3__SD4_DAT4 0x184 0x56c 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D3__USBH3_DATA4 0x184 0x56c 0xa0c 0x5 0x0 +#define MX51_PAD_NANDF_D2__GPIO4_6 0x188 0x570 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D2__NANDF_D2 0x188 0x570 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D2__PATA_DATA2 0x188 0x570 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D2__SD4_DAT5 0x188 0x570 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D2__USBH3_DATA5 0x188 0x570 0xa10 0x5 0x0 +#define MX51_PAD_NANDF_D1__GPIO4_7 0x18c 0x574 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D1__NANDF_D1 0x18c 0x574 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D1__PATA_DATA1 0x18c 0x574 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D1__SD4_DAT6 0x18c 0x574 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D1__USBH3_DATA6 0x18c 0x574 0xa14 0x5 0x0 +#define MX51_PAD_NANDF_D0__GPIO4_8 0x190 0x578 0x000 0x3 0x0 +#define MX51_PAD_NANDF_D0__NANDF_D0 0x190 0x578 0x000 0x0 0x0 +#define MX51_PAD_NANDF_D0__PATA_DATA0 0x190 0x578 0x000 0x1 0x0 +#define MX51_PAD_NANDF_D0__SD4_DAT7 0x190 0x578 0x000 0x2 0x0 +#define MX51_PAD_NANDF_D0__USBH3_DATA7 0x190 0x578 0xa18 0x5 0x0 +#define MX51_PAD_CSI1_D8__CSI1_D8 0x194 0x57c 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D8__GPIO3_12 0x194 0x57c 0x998 0x3 0x1 +#define MX51_PAD_CSI1_D9__CSI1_D9 0x198 0x580 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D9__GPIO3_13 0x198 0x580 0x000 0x3 0x0 +#define MX51_PAD_CSI1_D10__CSI1_D10 0x19c 0x584 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D11__CSI1_D11 0x1a0 0x588 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D12__CSI1_D12 0x1a4 0x58c 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D13__CSI1_D13 0x1a8 0x590 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D14__CSI1_D14 0x1ac 0x594 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D15__CSI1_D15 0x1b0 0x598 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D16__CSI1_D16 0x1b4 0x59c 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D17__CSI1_D17 0x1b8 0x5a0 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D18__CSI1_D18 0x1bc 0x5a4 0x000 0x0 0x0 +#define MX51_PAD_CSI1_D19__CSI1_D19 0x1c0 0x5a8 0x000 0x0 0x0 +#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC 0x1c4 0x5ac 0x000 0x0 0x0 +#define MX51_PAD_CSI1_VSYNC__GPIO3_14 0x1c4 0x5ac 0x000 0x3 0x0 +#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC 0x1c8 0x5b0 0x000 0x0 0x0 +#define MX51_PAD_CSI1_HSYNC__GPIO3_15 0x1c8 0x5b0 0x000 0x3 0x0 +#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK 0x000 0x5b4 0x000 0x0 0x0 +#define MX51_PAD_CSI1_MCLK__CSI1_MCLK 0x000 0x5b8 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D12__CSI2_D12 0x1cc 0x5bc 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D12__GPIO4_9 0x1cc 0x5bc 0x000 0x3 0x0 +#define MX51_PAD_CSI2_D13__CSI2_D13 0x1d0 0x5c0 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D13__GPIO4_10 0x1d0 0x5c0 0x000 0x3 0x0 +#define MX51_PAD_CSI2_D14__CSI2_D14 0x1d4 0x5c4 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D15__CSI2_D15 0x1d8 0x5c8 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D16__CSI2_D16 0x1dc 0x5cc 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D17__CSI2_D17 0x1e0 0x5d0 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D18__CSI2_D18 0x1e4 0x5d4 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D18__GPIO4_11 0x1e4 0x5d4 0x000 0x3 0x0 +#define MX51_PAD_CSI2_D19__CSI2_D19 0x1e8 0x5d8 0x000 0x0 0x0 +#define MX51_PAD_CSI2_D19__GPIO4_12 0x1e8 0x5d8 0x000 0x3 0x0 +#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC 0x1ec 0x5dc 0x000 0x0 0x0 +#define MX51_PAD_CSI2_VSYNC__GPIO4_13 0x1ec 0x5dc 0x000 0x3 0x0 +#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC 0x1f0 0x5e0 0x000 0x0 0x0 +#define MX51_PAD_CSI2_HSYNC__GPIO4_14 0x1f0 0x5e0 0x000 0x3 0x0 +#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK 0x1f4 0x5e4 0x000 0x0 0x0 +#define MX51_PAD_CSI2_PIXCLK__GPIO4_15 0x1f4 0x5e4 0x000 0x3 0x0 +#define MX51_PAD_I2C1_CLK__GPIO4_16 0x1f8 0x5e8 0x000 0x3 0x0 +#define MX51_PAD_I2C1_CLK__I2C1_CLK 0x1f8 0x5e8 0x000 0x0 0x0 +#define MX51_PAD_I2C1_DAT__GPIO4_17 0x1fc 0x5ec 0x000 0x3 0x0 +#define MX51_PAD_I2C1_DAT__I2C1_DAT 0x1fc 0x5ec 0x000 0x0 0x0 +#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x200 0x5f0 0x000 0x0 0x0 +#define MX51_PAD_AUD3_BB_TXD__GPIO4_18 0x200 0x5f0 0x000 0x3 0x0 +#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x204 0x5f4 0x000 0x0 0x0 +#define MX51_PAD_AUD3_BB_RXD__GPIO4_19 0x204 0x5f4 0x000 0x3 0x0 +#define MX51_PAD_AUD3_BB_RXD__UART3_RXD 0x204 0x5f4 0x9f4 0x1 0x2 +#define MX51_PAD_AUD3_BB_CK__AUD3_TXC 0x208 0x5f8 0x000 0x0 0x0 +#define MX51_PAD_AUD3_BB_CK__GPIO4_20 0x208 0x5f8 0x000 0x3 0x0 +#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x20c 0x5fc 0x000 0x0 0x0 +#define MX51_PAD_AUD3_BB_FS__GPIO4_21 0x20c 0x5fc 0x000 0x3 0x0 +#define MX51_PAD_AUD3_BB_FS__UART3_TXD 0x20c 0x5fc 0x000 0x1 0x0 +#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x210 0x600 0x000 0x0 0x0 +#define MX51_PAD_CSPI1_MOSI__GPIO4_22 0x210 0x600 0x000 0x3 0x0 +#define MX51_PAD_CSPI1_MOSI__I2C1_SDA 0x210 0x600 0x9b4 0x1 0x1 +#define MX51_PAD_CSPI1_MISO__AUD4_RXD 0x214 0x604 0x8c4 0x1 0x1 +#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x214 0x604 0x000 0x0 0x0 +#define MX51_PAD_CSPI1_MISO__GPIO4_23 0x214 0x604 0x000 0x3 0x0 +#define MX51_PAD_CSPI1_SS0__AUD4_TXC 0x218 0x608 0x8cc 0x1 0x1 +#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0 0x218 0x608 0x000 0x0 0x0 +#define MX51_PAD_CSPI1_SS0__GPIO4_24 0x218 0x608 0x000 0x3 0x0 +#define MX51_PAD_CSPI1_SS1__AUD4_TXD 0x21c 0x60c 0x8c8 0x1 0x1 +#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1 0x21c 0x60c 0x000 0x0 0x0 +#define MX51_PAD_CSPI1_SS1__GPIO4_25 0x21c 0x60c 0x000 0x3 0x0 +#define MX51_PAD_CSPI1_RDY__AUD4_TXFS 0x220 0x610 0x8d0 0x1 0x1 +#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY 0x220 0x610 0x000 0x0 0x0 +#define MX51_PAD_CSPI1_RDY__GPIO4_26 0x220 0x610 0x000 0x3 0x0 +#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x224 0x614 0x000 0x0 0x0 +#define MX51_PAD_CSPI1_SCLK__GPIO4_27 0x224 0x614 0x000 0x3 0x0 +#define MX51_PAD_CSPI1_SCLK__I2C1_SCL 0x224 0x614 0x9b0 0x1 0x1 +#define MX51_PAD_UART1_RXD__GPIO4_28 0x228 0x618 0x000 0x3 0x0 +#define MX51_PAD_UART1_RXD__UART1_RXD 0x228 0x618 0x9e4 0x0 0x0 +#define MX51_PAD_UART1_TXD__GPIO4_29 0x22c 0x61c 0x000 0x3 0x0 +#define MX51_PAD_UART1_TXD__PWM2_PWMO 0x22c 0x61c 0x000 0x1 0x0 +#define MX51_PAD_UART1_TXD__UART1_TXD 0x22c 0x61c 0x000 0x0 0x0 +#define MX51_PAD_UART1_RTS__GPIO4_30 0x230 0x620 0x000 0x3 0x0 +#define MX51_PAD_UART1_RTS__UART1_RTS 0x230 0x620 0x9e0 0x0 0x0 +#define MX51_PAD_UART1_CTS__GPIO4_31 0x234 0x624 0x000 0x3 0x0 +#define MX51_PAD_UART1_CTS__UART1_CTS 0x234 0x624 0x000 0x0 0x0 +#define MX51_PAD_UART2_RXD__FIRI_TXD 0x238 0x628 0x000 0x1 0x0 +#define MX51_PAD_UART2_RXD__GPIO1_20 0x238 0x628 0x000 0x3 0x0 +#define MX51_PAD_UART2_RXD__UART2_RXD 0x238 0x628 0x9ec 0x0 0x2 +#define MX51_PAD_UART2_TXD__FIRI_RXD 0x23c 0x62c 0x000 0x1 0x0 +#define MX51_PAD_UART2_TXD__GPIO1_21 0x23c 0x62c 0x000 0x3 0x0 +#define MX51_PAD_UART2_TXD__UART2_TXD 0x23c 0x62c 0x000 0x0 0x0 +#define MX51_PAD_UART3_RXD__CSI1_D0 0x240 0x630 0x000 0x2 0x0 +#define MX51_PAD_UART3_RXD__GPIO1_22 0x240 0x630 0x000 0x3 0x0 +#define MX51_PAD_UART3_RXD__UART1_DTR 0x240 0x630 0x000 0x0 0x0 +#define MX51_PAD_UART3_RXD__UART3_RXD 0x240 0x630 0x9f4 0x1 0x4 +#define MX51_PAD_UART3_TXD__CSI1_D1 0x244 0x634 0x000 0x2 0x0 +#define MX51_PAD_UART3_TXD__GPIO1_23 0x244 0x634 0x000 0x3 0x0 +#define MX51_PAD_UART3_TXD__UART1_DSR 0x244 0x634 0x000 0x0 0x0 +#define MX51_PAD_UART3_TXD__UART3_TXD 0x244 0x634 0x000 0x1 0x0 +#define MX51_PAD_OWIRE_LINE__GPIO1_24 0x248 0x638 0x000 0x3 0x0 +#define MX51_PAD_OWIRE_LINE__OWIRE_LINE 0x248 0x638 0x000 0x0 0x0 +#define MX51_PAD_OWIRE_LINE__SPDIF_OUT 0x248 0x638 0x000 0x6 0x0 +#define MX51_PAD_KEY_ROW0__KEY_ROW0 0x24c 0x63c 0x000 0x0 0x0 +#define MX51_PAD_KEY_ROW1__KEY_ROW1 0x250 0x640 0x000 0x0 0x0 +#define MX51_PAD_KEY_ROW2__KEY_ROW2 0x254 0x644 0x000 0x0 0x0 +#define MX51_PAD_KEY_ROW3__KEY_ROW3 0x258 0x648 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL0__KEY_COL0 0x25c 0x64c 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL0__PLL1_BYP 0x25c 0x64c 0x90c 0x7 0x0 +#define MX51_PAD_KEY_COL1__KEY_COL1 0x260 0x650 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL1__PLL2_BYP 0x260 0x650 0x910 0x7 0x0 +#define MX51_PAD_KEY_COL2__KEY_COL2 0x264 0x654 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL2__PLL3_BYP 0x264 0x654 0x000 0x7 0x0 +#define MX51_PAD_KEY_COL3__KEY_COL3 0x268 0x658 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL4__I2C2_SCL 0x26c 0x65c 0x9b8 0x3 0x1 +#define MX51_PAD_KEY_COL4__KEY_COL4 0x26c 0x65c 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL4__SPDIF_OUT1 0x26c 0x65c 0x000 0x6 0x0 +#define MX51_PAD_KEY_COL4__UART1_RI 0x26c 0x65c 0x000 0x1 0x0 +#define MX51_PAD_KEY_COL4__UART3_RTS 0x26c 0x65c 0x9f0 0x2 0x4 +#define MX51_PAD_KEY_COL5__I2C2_SDA 0x270 0x660 0x9bc 0x3 0x1 +#define MX51_PAD_KEY_COL5__KEY_COL5 0x270 0x660 0x000 0x0 0x0 +#define MX51_PAD_KEY_COL5__UART1_DCD 0x270 0x660 0x000 0x1 0x0 +#define MX51_PAD_KEY_COL5__UART3_CTS 0x270 0x660 0x000 0x2 0x0 +#define MX51_PAD_USBH1_CLK__CSPI_SCLK 0x278 0x678 0x914 0x1 0x1 +#define MX51_PAD_USBH1_CLK__GPIO1_25 0x278 0x678 0x000 0x2 0x0 +#define MX51_PAD_USBH1_CLK__I2C2_SCL 0x278 0x678 0x9b8 0x5 0x2 +#define MX51_PAD_USBH1_CLK__USBH1_CLK 0x278 0x678 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DIR__CSPI_MOSI 0x27c 0x67c 0x91c 0x1 0x1 +#define MX51_PAD_USBH1_DIR__GPIO1_26 0x27c 0x67c 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DIR__I2C2_SDA 0x27c 0x67c 0x9bc 0x5 0x2 +#define MX51_PAD_USBH1_DIR__USBH1_DIR 0x27c 0x67c 0x000 0x0 0x0 +#define MX51_PAD_USBH1_STP__CSPI_RDY 0x280 0x680 0x000 0x1 0x0 +#define MX51_PAD_USBH1_STP__GPIO1_27 0x280 0x680 0x000 0x2 0x0 +#define MX51_PAD_USBH1_STP__UART3_RXD 0x280 0x680 0x9f4 0x5 0x6 +#define MX51_PAD_USBH1_STP__USBH1_STP 0x280 0x680 0x000 0x0 0x0 +#define MX51_PAD_USBH1_NXT__CSPI_MISO 0x284 0x684 0x918 0x1 0x0 +#define MX51_PAD_USBH1_NXT__GPIO1_28 0x284 0x684 0x000 0x2 0x0 +#define MX51_PAD_USBH1_NXT__UART3_TXD 0x284 0x684 0x000 0x5 0x0 +#define MX51_PAD_USBH1_NXT__USBH1_NXT 0x284 0x684 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA0__GPIO1_11 0x288 0x688 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA0__UART2_CTS 0x288 0x688 0x000 0x1 0x0 +#define MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x288 0x688 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA1__GPIO1_12 0x28c 0x68c 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA1__UART2_RXD 0x28c 0x68c 0x9ec 0x1 0x4 +#define MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x28c 0x68c 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA2__GPIO1_13 0x290 0x690 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA2__UART2_TXD 0x290 0x690 0x000 0x1 0x0 +#define MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x290 0x690 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA3__GPIO1_14 0x294 0x694 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA3__UART2_RTS 0x294 0x694 0x9e8 0x1 0x5 +#define MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x294 0x694 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA4__CSPI_SS0 0x298 0x698 0x000 0x1 0x0 +#define MX51_PAD_USBH1_DATA4__GPIO1_15 0x298 0x698 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x298 0x698 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA5__CSPI_SS1 0x29c 0x69c 0x920 0x1 0x0 +#define MX51_PAD_USBH1_DATA5__GPIO1_16 0x29c 0x69c 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x29c 0x69c 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA6__CSPI_SS3 0x2a0 0x6a0 0x928 0x1 0x1 +#define MX51_PAD_USBH1_DATA6__GPIO1_17 0x2a0 0x6a0 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x2a0 0x6a0 0x000 0x0 0x0 +#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3 0x2a4 0x6a4 0x000 0x1 0x0 +#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3 0x2a4 0x6a4 0x934 0x5 0x1 +#define MX51_PAD_USBH1_DATA7__GPIO1_18 0x2a4 0x6a4 0x000 0x2 0x0 +#define MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x2a4 0x6a4 0x000 0x0 0x0 +#define MX51_PAD_DI1_PIN11__DI1_PIN11 0x2a8 0x6a8 0x000 0x0 0x0 +#define MX51_PAD_DI1_PIN11__ECSPI1_SS2 0x2a8 0x6a8 0x000 0x7 0x0 +#define MX51_PAD_DI1_PIN11__GPIO3_0 0x2a8 0x6a8 0x000 0x4 0x0 +#define MX51_PAD_DI1_PIN12__DI1_PIN12 0x2ac 0x6ac 0x000 0x0 0x0 +#define MX51_PAD_DI1_PIN12__GPIO3_1 0x2ac 0x6ac 0x978 0x4 0x1 +#define MX51_PAD_DI1_PIN13__DI1_PIN13 0x2b0 0x6b0 0x000 0x0 0x0 +#define MX51_PAD_DI1_PIN13__GPIO3_2 0x2b0 0x6b0 0x97c 0x4 0x1 +#define MX51_PAD_DI1_D0_CS__DI1_D0_CS 0x2b4 0x6b4 0x000 0x0 0x0 +#define MX51_PAD_DI1_D0_CS__GPIO3_3 0x2b4 0x6b4 0x980 0x4 0x1 +#define MX51_PAD_DI1_D1_CS__DI1_D1_CS 0x2b8 0x6b8 0x000 0x0 0x0 +#define MX51_PAD_DI1_D1_CS__DISP1_PIN14 0x2b8 0x6b8 0x000 0x2 0x0 +#define MX51_PAD_DI1_D1_CS__DISP1_PIN5 0x2b8 0x6b8 0x000 0x3 0x0 +#define MX51_PAD_DI1_D1_CS__GPIO3_4 0x2b8 0x6b8 0x984 0x4 0x1 +#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 0x2bc 0x6bc 0x9a4 0x2 0x1 +#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN 0x2bc 0x6bc 0x9c4 0x0 0x0 +#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5 0x2bc 0x6bc 0x988 0x4 0x1 +#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 0x2c0 0x6c0 0x000 0x3 0x0 +#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO 0x2c0 0x6c0 0x9c4 0x0 0x1 +#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6 0x2c0 0x6c0 0x98c 0x4 0x1 +#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 0x2c4 0x6c4 0x000 0x2 0x0 +#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 0x2c4 0x6c4 0x000 0x3 0x0 +#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK 0x2c4 0x6c4 0x000 0x0 0x0 +#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7 0x2c4 0x6c4 0x990 0x4 0x1 +#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK 0x2c8 0x6c8 0x000 0x2 0x0 +#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 0x2c8 0x6c8 0x000 0x2 0x0 +#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 0x2c8 0x6c8 0x000 0x3 0x0 +#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS 0x2c8 0x6c8 0x000 0x0 0x0 +#define MX51_PAD_DISPB2_SER_RS__GPIO3_8 0x2c8 0x6c8 0x994 0x4 0x1 +#define MX51_PAD_DISP1_DAT0__DISP1_DAT0 0x2cc 0x6cc 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT1__DISP1_DAT1 0x2d0 0x6d0 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT2__DISP1_DAT2 0x2d4 0x6d4 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT3__DISP1_DAT3 0x2d8 0x6d8 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT4__DISP1_DAT4 0x2dc 0x6dc 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT5__DISP1_DAT5 0x2e0 0x6e0 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC 0x2e4 0x6e4 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT6__DISP1_DAT6 0x2e4 0x6e4 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG 0x2e8 0x6e8 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT7__DISP1_DAT7 0x2e8 0x6e8 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT8__BOOT_SRC0 0x2ec 0x6ec 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT8__DISP1_DAT8 0x2ec 0x6ec 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT9__BOOT_SRC1 0x2f0 0x6f0 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT9__DISP1_DAT9 0x2f0 0x6f0 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE 0x2f4 0x6f4 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x2f4 0x6f4 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 0x2f8 0x6f8 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x2f8 0x6f8 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL 0x2fc 0x6fc 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x2fc 0x6fc 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 0x300 0x700 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x300 0x700 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 0x304 0x704 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x304 0x704 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH 0x308 0x708 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x308 0x708 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 0x30c 0x70c 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x30c 0x70c 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 0x310 0x710 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x310 0x710 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 0x314 0x714 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x314 0x714 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT18__DISP2_PIN11 0x314 0x714 0x000 0x5 0x0 +#define MX51_PAD_DISP1_DAT18__DISP2_PIN5 0x314 0x714 0x000 0x4 0x0 +#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 0x318 0x718 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x318 0x718 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT19__DISP2_PIN12 0x318 0x718 0x000 0x5 0x0 +#define MX51_PAD_DISP1_DAT19__DISP2_PIN6 0x318 0x718 0x000 0x4 0x0 +#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 0x31c 0x71c 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x31c 0x71c 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT20__DISP2_PIN13 0x31c 0x71c 0x000 0x5 0x0 +#define MX51_PAD_DISP1_DAT20__DISP2_PIN7 0x31c 0x71c 0x000 0x4 0x0 +#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 0x320 0x720 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x320 0x720 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT21__DISP2_PIN14 0x320 0x720 0x000 0x5 0x0 +#define MX51_PAD_DISP1_DAT21__DISP2_PIN8 0x320 0x720 0x000 0x4 0x0 +#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 0x324 0x724 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x324 0x724 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS 0x324 0x724 0x000 0x6 0x0 +#define MX51_PAD_DISP1_DAT22__DISP2_DAT16 0x324 0x724 0x000 0x5 0x0 +#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 0x328 0x728 0x000 0x7 0x0 +#define MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x328 0x728 0x000 0x0 0x0 +#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS 0x328 0x728 0x000 0x6 0x0 +#define MX51_PAD_DISP1_DAT23__DISP2_DAT17 0x328 0x728 0x000 0x5 0x0 +#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS 0x328 0x728 0x000 0x4 0x0 +#define MX51_PAD_DI1_PIN3__DI1_PIN3 0x32c 0x72c 0x000 0x0 0x0 +#define MX51_PAD_DI1_PIN2__DI1_PIN2 0x330 0x734 0x000 0x0 0x0 +#define MX51_PAD_DI_GP2__DISP1_SER_CLK 0x338 0x740 0x000 0x0 0x0 +#define MX51_PAD_DI_GP2__DISP2_WAIT 0x338 0x740 0x9a8 0x2 0x1 +#define MX51_PAD_DI_GP3__CSI1_DATA_EN 0x33c 0x744 0x9a0 0x3 0x1 +#define MX51_PAD_DI_GP3__DISP1_SER_DIO 0x33c 0x744 0x9c0 0x0 0x0 +#define MX51_PAD_DI_GP3__FEC_TX_ER 0x33c 0x744 0x000 0x2 0x0 +#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN 0x340 0x748 0x99c 0x3 0x1 +#define MX51_PAD_DI2_PIN4__DI2_PIN4 0x340 0x748 0x000 0x0 0x0 +#define MX51_PAD_DI2_PIN4__FEC_CRS 0x340 0x748 0x950 0x2 0x1 +#define MX51_PAD_DI2_PIN2__DI2_PIN2 0x344 0x74c 0x000 0x0 0x0 +#define MX51_PAD_DI2_PIN2__FEC_MDC 0x344 0x74c 0x000 0x2 0x0 +#define MX51_PAD_DI2_PIN3__DI2_PIN3 0x348 0x750 0x000 0x0 0x0 +#define MX51_PAD_DI2_PIN3__FEC_MDIO 0x348 0x750 0x954 0x2 0x1 +#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x34c 0x754 0x000 0x0 0x0 +#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x34c 0x754 0x95c 0x2 0x1 +#define MX51_PAD_DI_GP4__DI2_PIN15 0x350 0x758 0x000 0x4 0x0 +#define MX51_PAD_DI_GP4__DISP1_SER_DIN 0x350 0x758 0x9c0 0x0 0x1 +#define MX51_PAD_DI_GP4__DISP2_PIN1 0x350 0x758 0x000 0x3 0x0 +#define MX51_PAD_DI_GP4__FEC_RDATA2 0x350 0x758 0x960 0x2 0x1 +#define MX51_PAD_DISP2_DAT0__DISP2_DAT0 0x354 0x75c 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x354 0x75c 0x964 0x2 0x1 +#define MX51_PAD_DISP2_DAT0__KEY_COL6 0x354 0x75c 0x9c8 0x4 0x1 +#define MX51_PAD_DISP2_DAT0__UART3_RXD 0x354 0x75c 0x9f4 0x5 0x8 +#define MX51_PAD_DISP2_DAT0__USBH3_CLK 0x354 0x75c 0x9f8 0x3 0x1 +#define MX51_PAD_DISP2_DAT1__DISP2_DAT1 0x358 0x760 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x358 0x760 0x970 0x2 0x1 +#define MX51_PAD_DISP2_DAT1__KEY_COL7 0x358 0x760 0x9cc 0x4 0x1 +#define MX51_PAD_DISP2_DAT1__UART3_TXD 0x358 0x760 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT1__USBH3_DIR 0x358 0x760 0xa1c 0x3 0x1 +#define MX51_PAD_DISP2_DAT2__DISP2_DAT2 0x35c 0x764 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT3__DISP2_DAT3 0x360 0x768 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT4__DISP2_DAT4 0x364 0x76c 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT5__DISP2_DAT5 0x368 0x770 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT6__DISP2_DAT6 0x36c 0x774 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x36c 0x774 0x000 0x2 0x0 +#define MX51_PAD_DISP2_DAT6__GPIO1_19 0x36c 0x774 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT6__KEY_ROW4 0x36c 0x774 0x9d0 0x4 0x1 +#define MX51_PAD_DISP2_DAT6__USBH3_STP 0x36c 0x774 0xa24 0x3 0x1 +#define MX51_PAD_DISP2_DAT7__DISP2_DAT7 0x370 0x778 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x370 0x778 0x000 0x2 0x0 +#define MX51_PAD_DISP2_DAT7__GPIO1_29 0x370 0x778 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT7__KEY_ROW5 0x370 0x778 0x9d4 0x4 0x1 +#define MX51_PAD_DISP2_DAT7__USBH3_NXT 0x370 0x778 0xa20 0x3 0x1 +#define MX51_PAD_DISP2_DAT8__DISP2_DAT8 0x374 0x77c 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x374 0x77c 0x000 0x2 0x0 +#define MX51_PAD_DISP2_DAT8__GPIO1_30 0x374 0x77c 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT8__KEY_ROW6 0x374 0x77c 0x9d8 0x4 0x1 +#define MX51_PAD_DISP2_DAT8__USBH3_DATA0 0x374 0x77c 0x9fc 0x3 0x1 +#define MX51_PAD_DISP2_DAT9__AUD6_RXC 0x378 0x780 0x8f4 0x4 0x1 +#define MX51_PAD_DISP2_DAT9__DISP2_DAT9 0x378 0x780 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x378 0x780 0x000 0x2 0x0 +#define MX51_PAD_DISP2_DAT9__GPIO1_31 0x378 0x780 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT9__USBH3_DATA1 0x378 0x780 0xa00 0x3 0x1 +#define MX51_PAD_DISP2_DAT10__DISP2_DAT10 0x37c 0x784 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS 0x37c 0x784 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT10__FEC_COL 0x37c 0x784 0x94c 0x2 0x1 +#define MX51_PAD_DISP2_DAT10__KEY_ROW7 0x37c 0x784 0x9dc 0x4 0x1 +#define MX51_PAD_DISP2_DAT10__USBH3_DATA2 0x37c 0x784 0xa04 0x3 0x1 +#define MX51_PAD_DISP2_DAT11__AUD6_TXD 0x380 0x788 0x8f0 0x4 0x1 +#define MX51_PAD_DISP2_DAT11__DISP2_DAT11 0x380 0x788 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x380 0x788 0x968 0x2 0x1 +#define MX51_PAD_DISP2_DAT11__GPIO1_10 0x380 0x788 0x000 0x7 0x0 +#define MX51_PAD_DISP2_DAT11__USBH3_DATA3 0x380 0x788 0xa08 0x3 0x1 +#define MX51_PAD_DISP2_DAT12__AUD6_RXD 0x384 0x78c 0x8ec 0x4 0x1 +#define MX51_PAD_DISP2_DAT12__DISP2_DAT12 0x384 0x78c 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x384 0x78c 0x96c 0x2 0x1 +#define MX51_PAD_DISP2_DAT12__USBH3_DATA4 0x384 0x78c 0xa0c 0x3 0x1 +#define MX51_PAD_DISP2_DAT13__AUD6_TXC 0x388 0x790 0x8fc 0x4 0x1 +#define MX51_PAD_DISP2_DAT13__DISP2_DAT13 0x388 0x790 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x388 0x790 0x974 0x2 0x1 +#define MX51_PAD_DISP2_DAT13__USBH3_DATA5 0x388 0x790 0xa10 0x3 0x1 +#define MX51_PAD_DISP2_DAT14__AUD6_TXFS 0x38c 0x794 0x900 0x4 0x1 +#define MX51_PAD_DISP2_DAT14__DISP2_DAT14 0x38c 0x794 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x38c 0x794 0x958 0x2 0x1 +#define MX51_PAD_DISP2_DAT14__USBH3_DATA6 0x38c 0x794 0xa14 0x3 0x1 +#define MX51_PAD_DISP2_DAT15__AUD6_RXFS 0x390 0x798 0x8f8 0x4 0x1 +#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS 0x390 0x798 0x000 0x5 0x0 +#define MX51_PAD_DISP2_DAT15__DISP2_DAT15 0x390 0x798 0x000 0x0 0x0 +#define MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x390 0x798 0x000 0x2 0x0 +#define MX51_PAD_DISP2_DAT15__USBH3_DATA7 0x390 0x798 0xa18 0x3 0x1 +#define MX51_PAD_SD1_CMD__AUD5_RXFS 0x394 0x79c 0x8e0 0x1 0x1 +#define MX51_PAD_SD1_CMD__CSPI_MOSI 0x394 0x79c 0x91c 0x2 0x2 +#define MX51_PAD_SD1_CMD__SD1_CMD 0x394 0x79c 0x000 0x0 0x0 +#define MX51_PAD_SD1_CLK__AUD5_RXC 0x398 0x7a0 0x8dc 0x1 0x1 +#define MX51_PAD_SD1_CLK__CSPI_SCLK 0x398 0x7a0 0x914 0x2 0x2 +#define MX51_PAD_SD1_CLK__SD1_CLK 0x398 0x7a0 0x000 0x0 0x0 +#define MX51_PAD_SD1_DATA0__AUD5_TXD 0x39c 0x7a4 0x8d8 0x1 0x2 +#define MX51_PAD_SD1_DATA0__CSPI_MISO 0x39c 0x7a4 0x918 0x2 0x1 +#define MX51_PAD_SD1_DATA0__SD1_DATA0 0x39c 0x7a4 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA0__EIM_DA0 0x01c 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA1__EIM_DA1 0x020 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA2__EIM_DA2 0x024 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA3__EIM_DA3 0x028 0x000 0x000 0x0 0x0 +#define MX51_PAD_SD1_DATA1__AUD5_RXD 0x3a0 0x7a8 0x8d4 0x1 0x2 +#define MX51_PAD_SD1_DATA1__SD1_DATA1 0x3a0 0x7a8 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA4__EIM_DA4 0x02c 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA5__EIM_DA5 0x030 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA6__EIM_DA6 0x034 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA7__EIM_DA7 0x038 0x000 0x000 0x0 0x0 +#define MX51_PAD_SD1_DATA2__AUD5_TXC 0x3a4 0x7ac 0x8e4 0x1 0x2 +#define MX51_PAD_SD1_DATA2__SD1_DATA2 0x3a4 0x7ac 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA10__EIM_DA10 0x044 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA11__EIM_DA11 0x048 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA8__EIM_DA8 0x03c 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA9__EIM_DA9 0x040 0x000 0x000 0x0 0x0 +#define MX51_PAD_SD1_DATA3__AUD5_TXFS 0x3a8 0x7b0 0x8e8 0x1 0x2 +#define MX51_PAD_SD1_DATA3__CSPI_SS1 0x3a8 0x7b0 0x920 0x2 0x1 +#define MX51_PAD_SD1_DATA3__SD1_DATA3 0x3a8 0x7b0 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_0__CSPI_SS2 0x3ac 0x7b4 0x924 0x2 0x0 +#define MX51_PAD_GPIO1_0__GPIO1_0 0x3ac 0x7b4 0x000 0x1 0x0 +#define MX51_PAD_GPIO1_0__SD1_CD 0x3ac 0x7b4 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_1__CSPI_MISO 0x3b0 0x7b8 0x918 0x2 0x2 +#define MX51_PAD_GPIO1_1__GPIO1_1 0x3b0 0x7b8 0x000 0x1 0x0 +#define MX51_PAD_GPIO1_1__SD1_WP 0x3b0 0x7b8 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA12__EIM_DA12 0x04c 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA13__EIM_DA13 0x050 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA14__EIM_DA14 0x054 0x000 0x000 0x0 0x0 +#define MX51_PAD_EIM_DA15__EIM_DA15 0x058 0x000 0x000 0x0 0x0 +#define MX51_PAD_SD2_CMD__CSPI_MOSI 0x3b4 0x7bc 0x91c 0x2 0x3 +#define MX51_PAD_SD2_CMD__I2C1_SCL 0x3b4 0x7bc 0x9b0 0x1 0x2 +#define MX51_PAD_SD2_CMD__SD2_CMD 0x3b4 0x7bc 0x000 0x0 0x0 +#define MX51_PAD_SD2_CLK__CSPI_SCLK 0x3b8 0x7c0 0x914 0x2 0x3 +#define MX51_PAD_SD2_CLK__I2C1_SDA 0x3b8 0x7c0 0x9b4 0x1 0x2 +#define MX51_PAD_SD2_CLK__SD2_CLK 0x3b8 0x7c0 0x000 0x0 0x0 +#define MX51_PAD_SD2_DATA0__CSPI_MISO 0x3bc 0x7c4 0x918 0x2 0x3 +#define MX51_PAD_SD2_DATA0__SD1_DAT4 0x3bc 0x7c4 0x000 0x1 0x0 +#define MX51_PAD_SD2_DATA0__SD2_DATA0 0x3bc 0x7c4 0x000 0x0 0x0 +#define MX51_PAD_SD2_DATA1__SD1_DAT5 0x3c0 0x7c8 0x000 0x1 0x0 +#define MX51_PAD_SD2_DATA1__SD2_DATA1 0x3c0 0x7c8 0x000 0x0 0x0 +#define MX51_PAD_SD2_DATA1__USBH3_H2_DP 0x3c0 0x7c8 0x000 0x2 0x0 +#define MX51_PAD_SD2_DATA2__SD1_DAT6 0x3c4 0x7cc 0x000 0x1 0x0 +#define MX51_PAD_SD2_DATA2__SD2_DATA2 0x3c4 0x7cc 0x000 0x0 0x0 +#define MX51_PAD_SD2_DATA2__USBH3_H2_DM 0x3c4 0x7cc 0x000 0x2 0x0 +#define MX51_PAD_SD2_DATA3__CSPI_SS2 0x3c8 0x7d0 0x924 0x2 0x1 +#define MX51_PAD_SD2_DATA3__SD1_DAT7 0x3c8 0x7d0 0x000 0x1 0x0 +#define MX51_PAD_SD2_DATA3__SD2_DATA3 0x3c8 0x7d0 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_2__CCM_OUT_2 0x3cc 0x7d4 0x000 0x5 0x0 +#define MX51_PAD_GPIO1_2__GPIO1_2 0x3cc 0x7d4 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_2__I2C2_SCL 0x3cc 0x7d4 0x9b8 0x2 0x3 +#define MX51_PAD_GPIO1_2__PLL1_BYP 0x3cc 0x7d4 0x90c 0x7 0x1 +#define MX51_PAD_GPIO1_2__PWM1_PWMO 0x3cc 0x7d4 0x000 0x1 0x0 +#define MX51_PAD_GPIO1_3__GPIO1_3 0x3d0 0x7d8 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_3__I2C2_SDA 0x3d0 0x7d8 0x9bc 0x2 0x3 +#define MX51_PAD_GPIO1_3__PLL2_BYP 0x3d0 0x7d8 0x910 0x7 0x1 +#define MX51_PAD_GPIO1_3__PWM2_PWMO 0x3d0 0x7d8 0x000 0x1 0x0 +#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ 0x3d4 0x7fc 0x000 0x0 0x0 +#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B 0x3d4 0x7fc 0x000 0x1 0x0 +#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK 0x3d8 0x804 0x908 0x4 0x1 +#define MX51_PAD_GPIO1_4__EIM_RDY 0x3d8 0x804 0x938 0x3 0x1 +#define MX51_PAD_GPIO1_4__GPIO1_4 0x3d8 0x804 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B 0x3d8 0x804 0x000 0x2 0x0 +#define MX51_PAD_GPIO1_5__CSI2_MCLK 0x3dc 0x808 0x000 0x6 0x0 +#define MX51_PAD_GPIO1_5__DISP2_PIN16 0x3dc 0x808 0x000 0x3 0x0 +#define MX51_PAD_GPIO1_5__GPIO1_5 0x3dc 0x808 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B 0x3dc 0x808 0x000 0x2 0x0 +#define MX51_PAD_GPIO1_6__DISP2_PIN17 0x3e0 0x80c 0x000 0x4 0x0 +#define MX51_PAD_GPIO1_6__GPIO1_6 0x3e0 0x80c 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_6__REF_EN_B 0x3e0 0x80c 0x000 0x3 0x0 +#define MX51_PAD_GPIO1_7__CCM_OUT_0 0x3e4 0x810 0x000 0x3 0x0 +#define MX51_PAD_GPIO1_7__GPIO1_7 0x3e4 0x810 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_7__SD2_WP 0x3e4 0x810 0x000 0x6 0x0 +#define MX51_PAD_GPIO1_7__SPDIF_OUT1 0x3e4 0x810 0x000 0x2 0x0 +#define MX51_PAD_GPIO1_8__CSI2_DATA_EN 0x3e8 0x814 0x99c 0x2 0x2 +#define MX51_PAD_GPIO1_8__GPIO1_8 0x3e8 0x814 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_8__SD2_CD 0x3e8 0x814 0x000 0x6 0x0 +#define MX51_PAD_GPIO1_8__USBH3_PWR 0x3e8 0x814 0x000 0x1 0x0 +#define MX51_PAD_GPIO1_9__CCM_OUT_1 0x3ec 0x818 0x000 0x3 0x0 +#define MX51_PAD_GPIO1_9__DISP2_D1_CS 0x3ec 0x818 0x000 0x2 0x0 +#define MX51_PAD_GPIO1_9__DISP2_SER_CS 0x3ec 0x818 0x000 0x7 0x0 +#define MX51_PAD_GPIO1_9__GPIO1_9 0x3ec 0x818 0x000 0x0 0x0 +#define MX51_PAD_GPIO1_9__SD2_LCTL 0x3ec 0x818 0x000 0x6 0x0 +#define MX51_PAD_GPIO1_9__USBH3_OC 0x3ec 0x818 0x000 0x1 0x0 + +#endif /* __DTS_IMX51_PINFUNC_H */ diff --git a/arch/arm/dts/imx51.dtsi b/arch/arm/dts/imx51.dtsi new file mode 100644 index 0000000000..a9002878ba --- /dev/null +++ b/arch/arm/dts/imx51.dtsi @@ -0,0 +1,723 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "skeleton.dtsi" +#include "imx51-pinfunc.h" + +/ { + aliases { + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + mmc0 = &esdhc1; + mmc1 = &esdhc2; + mmc2 = &esdhc3; + mmc3 = &esdhc4; + }; + + tzic: tz-interrupt-controller@e0000000 { + compatible = "fsl,imx51-tzic", "fsl,tzic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0xe0000000 0x4000>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + ckil { + compatible = "fsl,imx-ckil", "fixed-clock"; + clock-frequency = <32768>; + }; + + ckih1 { + compatible = "fsl,imx-ckih1", "fixed-clock"; + clock-frequency = <22579200>; + }; + + ckih2 { + compatible = "fsl,imx-ckih2", "fixed-clock"; + clock-frequency = <0>; + }; + + osc { + compatible = "fsl,imx-osc", "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a8"; + reg = <0>; + clock-latency = <61036>; /* two CLK32 periods */ + clocks = <&clks 24>; + clock-names = "cpu"; + operating-points = < + /* kHz uV (No regulator support) */ + 160000 0 + 800000 0 + >; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&tzic>; + ranges; + + ipu: ipu@40000000 { + #crtc-cells = <1>; + compatible = "fsl,imx51-ipu"; + reg = <0x40000000 0x20000000>; + interrupts = <11 10>; + clocks = <&clks 59>, <&clks 110>, <&clks 61>; + clock-names = "bus", "di0", "di1"; + resets = <&src 2>; + }; + + aips@70000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x70000000 0x10000000>; + ranges; + + spba@70000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x70000000 0x40000>; + ranges; + + esdhc1: esdhc@70004000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70004000 0x4000>; + interrupts = <1>; + clocks = <&clks 44>, <&clks 0>, <&clks 71>; + clock-names = "ipg", "ahb", "per"; + status = "disabled"; + }; + + esdhc2: esdhc@70008000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70008000 0x4000>; + interrupts = <2>; + clocks = <&clks 45>, <&clks 0>, <&clks 72>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + + uart3: serial@7000c000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; + reg = <0x7000c000 0x4000>; + interrupts = <33>; + clocks = <&clks 32>, <&clks 33>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + ecspi1: ecspi@70010000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-ecspi"; + reg = <0x70010000 0x4000>; + interrupts = <36>; + clocks = <&clks 51>, <&clks 52>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + ssi2: ssi@70014000 { + compatible = "fsl,imx51-ssi", "fsl,imx21-ssi"; + reg = <0x70014000 0x4000>; + interrupts = <30>; + clocks = <&clks 49>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */ + status = "disabled"; + }; + + esdhc3: esdhc@70020000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70020000 0x4000>; + interrupts = <3>; + clocks = <&clks 46>, <&clks 0>, <&clks 73>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + + esdhc4: esdhc@70024000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70024000 0x4000>; + interrupts = <4>; + clocks = <&clks 47>, <&clks 0>, <&clks 74>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + }; + + usbotg: usb@73f80000 { + compatible = "fsl,imx51-usb", "fsl,imx27-usb"; + reg = <0x73f80000 0x0200>; + interrupts = <18>; + status = "disabled"; + }; + + usbh1: usb@73f80200 { + compatible = "fsl,imx51-usb", "fsl,imx27-usb"; + reg = <0x73f80200 0x0200>; + interrupts = <14>; + status = "disabled"; + }; + + usbh2: usb@73f80400 { + compatible = "fsl,imx51-usb", "fsl,imx27-usb"; + reg = <0x73f80400 0x0200>; + interrupts = <16>; + status = "disabled"; + }; + + usbh3: usb@73f80600 { + compatible = "fsl,imx51-usb", "fsl,imx27-usb"; + reg = <0x73f80600 0x0200>; + interrupts = <17>; + status = "disabled"; + }; + + gpio1: gpio@73f84000 { + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; + reg = <0x73f84000 0x4000>; + interrupts = <50 51>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@73f88000 { + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; + reg = <0x73f88000 0x4000>; + interrupts = <52 53>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@73f8c000 { + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; + reg = <0x73f8c000 0x4000>; + interrupts = <54 55>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio4: gpio@73f90000 { + compatible = "fsl,imx51-gpio", "fsl,imx35-gpio"; + reg = <0x73f90000 0x4000>; + interrupts = <56 57>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + kpp: kpp@73f94000 { + compatible = "fsl,imx51-kpp", "fsl,imx21-kpp"; + reg = <0x73f94000 0x4000>; + interrupts = <60>; + clocks = <&clks 0>; + status = "disabled"; + }; + + wdog1: wdog@73f98000 { + compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; + reg = <0x73f98000 0x4000>; + interrupts = <58>; + clocks = <&clks 0>; + }; + + wdog2: wdog@73f9c000 { + compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; + reg = <0x73f9c000 0x4000>; + interrupts = <59>; + clocks = <&clks 0>; + status = "disabled"; + }; + + gpt: timer@73fa0000 { + compatible = "fsl,imx51-gpt", "fsl,imx31-gpt"; + reg = <0x73fa0000 0x4000>; + interrupts = <39>; + clocks = <&clks 36>, <&clks 41>; + clock-names = "ipg", "per"; + }; + + iomuxc: iomuxc@73fa8000 { + compatible = "fsl,imx51-iomuxc"; + reg = <0x73fa8000 0x4000>; + + audmux { + pinctrl_audmux_1: audmuxgrp-1 { + fsl,pins = < + MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000 + MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000 + MX51_PAD_AUD3_BB_CK__AUD3_TXC 0x80000000 + MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000 + >; + }; + }; + + fec { + pinctrl_fec_1: fecgrp-1 { + fsl,pins = < + MX51_PAD_EIM_EB2__FEC_MDIO 0x000001f5 + MX51_PAD_EIM_EB3__FEC_RDATA1 0x00000085 + MX51_PAD_EIM_CS2__FEC_RDATA2 0x00000085 + MX51_PAD_EIM_CS3__FEC_RDATA3 0x00000085 + MX51_PAD_EIM_CS4__FEC_RX_ER 0x00000180 + MX51_PAD_EIM_CS5__FEC_CRS 0x00000180 + MX51_PAD_NANDF_RB2__FEC_COL 0x00000180 + MX51_PAD_NANDF_RB3__FEC_RX_CLK 0x00000180 + MX51_PAD_NANDF_D9__FEC_RDATA0 0x00002180 + MX51_PAD_NANDF_D8__FEC_TDATA0 0x00002004 + MX51_PAD_NANDF_CS2__FEC_TX_ER 0x00002004 + MX51_PAD_NANDF_CS3__FEC_MDC 0x00002004 + MX51_PAD_NANDF_CS4__FEC_TDATA1 0x00002004 + MX51_PAD_NANDF_CS5__FEC_TDATA2 0x00002004 + MX51_PAD_NANDF_CS6__FEC_TDATA3 0x00002004 + MX51_PAD_NANDF_CS7__FEC_TX_EN 0x00002004 + MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x00002180 + MX51_PAD_NANDF_D11__FEC_RX_DV 0x000020a4 + >; + }; + + pinctrl_fec_2: fecgrp-2 { + fsl,pins = < + MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000 + MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000 + MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000 + MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000 + MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000 + MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000 + MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000 + MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000 + MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000 + MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000 + MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000 + MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000 + MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000 + MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000 + MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000 + MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000 + MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000 + MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000 + >; + }; + }; + + ecspi1 { + pinctrl_ecspi1_1: ecspi1grp-1 { + fsl,pins = < + MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185 + MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185 + MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185 + >; + }; + }; + + ecspi2 { + pinctrl_ecspi2_1: ecspi2grp-1 { + fsl,pins = < + MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x185 + MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x185 + MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x185 + >; + }; + }; + + esdhc1 { + pinctrl_esdhc1_1: esdhc1grp-1 { + fsl,pins = < + MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5 + MX51_PAD_SD1_CLK__SD1_CLK 0x20d5 + MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5 + MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5 + MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5 + MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5 + >; + }; + }; + + esdhc2 { + pinctrl_esdhc2_1: esdhc2grp-1 { + fsl,pins = < + MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5 + MX51_PAD_SD2_CLK__SD2_CLK 0x20d5 + MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5 + MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5 + MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5 + MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5 + >; + }; + }; + + i2c2 { + pinctrl_i2c2_1: i2c2grp-1 { + fsl,pins = < + MX51_PAD_KEY_COL4__I2C2_SCL 0x400001ed + MX51_PAD_KEY_COL5__I2C2_SDA 0x400001ed + >; + }; + + pinctrl_i2c2_2: i2c2grp-2 { + fsl,pins = < + MX51_PAD_EIM_D27__I2C2_SCL 0x400001ed + MX51_PAD_EIM_D24__I2C2_SDA 0x400001ed + >; + }; + }; + + ipu_disp1 { + pinctrl_ipu_disp1_1: ipudisp1grp-1 { + fsl,pins = < + MX51_PAD_DISP1_DAT0__DISP1_DAT0 0x5 + MX51_PAD_DISP1_DAT1__DISP1_DAT1 0x5 + MX51_PAD_DISP1_DAT2__DISP1_DAT2 0x5 + MX51_PAD_DISP1_DAT3__DISP1_DAT3 0x5 + MX51_PAD_DISP1_DAT4__DISP1_DAT4 0x5 + MX51_PAD_DISP1_DAT5__DISP1_DAT5 0x5 + MX51_PAD_DISP1_DAT6__DISP1_DAT6 0x5 + MX51_PAD_DISP1_DAT7__DISP1_DAT7 0x5 + MX51_PAD_DISP1_DAT8__DISP1_DAT8 0x5 + MX51_PAD_DISP1_DAT9__DISP1_DAT9 0x5 + MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5 + MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5 + MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5 + MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5 + MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5 + MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5 + MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5 + MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5 + MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5 + MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5 + MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5 + MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5 + MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5 + MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5 + MX51_PAD_DI1_PIN2__DI1_PIN2 0x5 /* hsync */ + MX51_PAD_DI1_PIN3__DI1_PIN3 0x5 /* vsync */ + >; + }; + }; + + ipu_disp2 { + pinctrl_ipu_disp2_1: ipudisp2grp-1 { + fsl,pins = < + MX51_PAD_DISP2_DAT0__DISP2_DAT0 0x5 + MX51_PAD_DISP2_DAT1__DISP2_DAT1 0x5 + MX51_PAD_DISP2_DAT2__DISP2_DAT2 0x5 + MX51_PAD_DISP2_DAT3__DISP2_DAT3 0x5 + MX51_PAD_DISP2_DAT4__DISP2_DAT4 0x5 + MX51_PAD_DISP2_DAT5__DISP2_DAT5 0x5 + MX51_PAD_DISP2_DAT6__DISP2_DAT6 0x5 + MX51_PAD_DISP2_DAT7__DISP2_DAT7 0x5 + MX51_PAD_DISP2_DAT8__DISP2_DAT8 0x5 + MX51_PAD_DISP2_DAT9__DISP2_DAT9 0x5 + MX51_PAD_DISP2_DAT10__DISP2_DAT10 0x5 + MX51_PAD_DISP2_DAT11__DISP2_DAT11 0x5 + MX51_PAD_DISP2_DAT12__DISP2_DAT12 0x5 + MX51_PAD_DISP2_DAT13__DISP2_DAT13 0x5 + MX51_PAD_DISP2_DAT14__DISP2_DAT14 0x5 + MX51_PAD_DISP2_DAT15__DISP2_DAT15 0x5 + MX51_PAD_DI2_PIN2__DI2_PIN2 0x5 /* hsync */ + MX51_PAD_DI2_PIN3__DI2_PIN3 0x5 /* vsync */ + MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5 + MX51_PAD_DI_GP4__DI2_PIN15 0x5 + >; + }; + }; + + pata { + pinctrl_pata_1: patagrp-1 { + fsl,pins = < + MX51_PAD_NANDF_WE_B__PATA_DIOW 0x2004 + MX51_PAD_NANDF_RE_B__PATA_DIOR 0x2004 + MX51_PAD_NANDF_ALE__PATA_BUFFER_EN 0x2004 + MX51_PAD_NANDF_CLE__PATA_RESET_B 0x2004 + MX51_PAD_NANDF_WP_B__PATA_DMACK 0x2004 + MX51_PAD_NANDF_RB0__PATA_DMARQ 0x2004 + MX51_PAD_NANDF_RB1__PATA_IORDY 0x2004 + MX51_PAD_GPIO_NAND__PATA_INTRQ 0x2004 + MX51_PAD_NANDF_CS2__PATA_CS_0 0x2004 + MX51_PAD_NANDF_CS3__PATA_CS_1 0x2004 + MX51_PAD_NANDF_CS4__PATA_DA_0 0x2004 + MX51_PAD_NANDF_CS5__PATA_DA_1 0x2004 + MX51_PAD_NANDF_CS6__PATA_DA_2 0x2004 + MX51_PAD_NANDF_D15__PATA_DATA15 0x2004 + MX51_PAD_NANDF_D14__PATA_DATA14 0x2004 + MX51_PAD_NANDF_D13__PATA_DATA13 0x2004 + MX51_PAD_NANDF_D12__PATA_DATA12 0x2004 + MX51_PAD_NANDF_D11__PATA_DATA11 0x2004 + MX51_PAD_NANDF_D10__PATA_DATA10 0x2004 + MX51_PAD_NANDF_D9__PATA_DATA9 0x2004 + MX51_PAD_NANDF_D8__PATA_DATA8 0x2004 + MX51_PAD_NANDF_D7__PATA_DATA7 0x2004 + MX51_PAD_NANDF_D6__PATA_DATA6 0x2004 + MX51_PAD_NANDF_D5__PATA_DATA5 0x2004 + MX51_PAD_NANDF_D4__PATA_DATA4 0x2004 + MX51_PAD_NANDF_D3__PATA_DATA3 0x2004 + MX51_PAD_NANDF_D2__PATA_DATA2 0x2004 + MX51_PAD_NANDF_D1__PATA_DATA1 0x2004 + MX51_PAD_NANDF_D0__PATA_DATA0 0x2004 + >; + }; + }; + + uart1 { + pinctrl_uart1_1: uart1grp-1 { + fsl,pins = < + MX51_PAD_UART1_RXD__UART1_RXD 0x1c5 + MX51_PAD_UART1_TXD__UART1_TXD 0x1c5 + MX51_PAD_UART1_RTS__UART1_RTS 0x1c5 + MX51_PAD_UART1_CTS__UART1_CTS 0x1c5 + >; + }; + }; + + uart2 { + pinctrl_uart2_1: uart2grp-1 { + fsl,pins = < + MX51_PAD_UART2_RXD__UART2_RXD 0x1c5 + MX51_PAD_UART2_TXD__UART2_TXD 0x1c5 + >; + }; + }; + + uart3 { + pinctrl_uart3_1: uart3grp-1 { + fsl,pins = < + MX51_PAD_EIM_D25__UART3_RXD 0x1c5 + MX51_PAD_EIM_D26__UART3_TXD 0x1c5 + MX51_PAD_EIM_D27__UART3_RTS 0x1c5 + MX51_PAD_EIM_D24__UART3_CTS 0x1c5 + >; + }; + + pinctrl_uart3_2: uart3grp-2 { + fsl,pins = < + MX51_PAD_UART3_RXD__UART3_RXD 0x1c5 + MX51_PAD_UART3_TXD__UART3_TXD 0x1c5 + >; + }; + }; + + kpp { + pinctrl_kpp_1: kppgrp-1 { + fsl,pins = < + MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0 + MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0 + MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0 + MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0 + MX51_PAD_KEY_COL0__KEY_COL0 0xe8 + MX51_PAD_KEY_COL1__KEY_COL1 0xe8 + MX51_PAD_KEY_COL2__KEY_COL2 0xe8 + MX51_PAD_KEY_COL3__KEY_COL3 0xe8 + >; + }; + }; + }; + + pwm1: pwm@73fb4000 { + #pwm-cells = <2>; + compatible = "fsl,imx51-pwm", "fsl,imx27-pwm"; + reg = <0x73fb4000 0x4000>; + clocks = <&clks 37>, <&clks 38>; + clock-names = "ipg", "per"; + interrupts = <61>; + }; + + pwm2: pwm@73fb8000 { + #pwm-cells = <2>; + compatible = "fsl,imx51-pwm", "fsl,imx27-pwm"; + reg = <0x73fb8000 0x4000>; + clocks = <&clks 39>, <&clks 40>; + clock-names = "ipg", "per"; + interrupts = <94>; + }; + + uart1: serial@73fbc000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; + reg = <0x73fbc000 0x4000>; + interrupts = <31>; + clocks = <&clks 28>, <&clks 29>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + uart2: serial@73fc0000 { + compatible = "fsl,imx51-uart", "fsl,imx21-uart"; + reg = <0x73fc0000 0x4000>; + interrupts = <32>; + clocks = <&clks 30>, <&clks 31>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + src: src@73fd0000 { + compatible = "fsl,imx51-src"; + reg = <0x73fd0000 0x4000>; + #reset-cells = <1>; + }; + + clks: ccm@73fd4000{ + compatible = "fsl,imx51-ccm"; + reg = <0x73fd4000 0x4000>; + interrupts = <0 71 0x04 0 72 0x04>; + #clock-cells = <1>; + }; + }; + + aips@80000000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80000000 0x10000000>; + ranges; + + iim: iim@83f98000 { + compatible = "fsl,imx51-iim", "fsl,imx-iim"; + reg = <0x83f98000 0x4000>; + interrupts = <69>; + clocks = <&clks 107>; + }; + + ecspi2: ecspi@83fac000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-ecspi"; + reg = <0x83fac000 0x4000>; + interrupts = <37>; + clocks = <&clks 53>, <&clks 54>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + sdma: sdma@83fb0000 { + compatible = "fsl,imx51-sdma", "fsl,imx35-sdma"; + reg = <0x83fb0000 0x4000>; + interrupts = <6>; + clocks = <&clks 56>, <&clks 56>; + clock-names = "ipg", "ahb"; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin"; + }; + + cspi: cspi@83fc0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-cspi", "fsl,imx35-cspi"; + reg = <0x83fc0000 0x4000>; + interrupts = <38>; + clocks = <&clks 55>, <&clks 0>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + i2c2: i2c@83fc4000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-i2c", "fsl,imx21-i2c"; + reg = <0x83fc4000 0x4000>; + interrupts = <63>; + clocks = <&clks 35>; + status = "disabled"; + }; + + i2c1: i2c@83fc8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-i2c", "fsl,imx21-i2c"; + reg = <0x83fc8000 0x4000>; + interrupts = <62>; + clocks = <&clks 34>; + status = "disabled"; + }; + + ssi1: ssi@83fcc000 { + compatible = "fsl,imx51-ssi", "fsl,imx21-ssi"; + reg = <0x83fcc000 0x4000>; + interrupts = <29>; + clocks = <&clks 48>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */ + status = "disabled"; + }; + + audmux: audmux@83fd0000 { + compatible = "fsl,imx51-audmux", "fsl,imx31-audmux"; + reg = <0x83fd0000 0x4000>; + status = "disabled"; + }; + + nfc: nand@83fdb000 { + compatible = "fsl,imx51-nand"; + reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>; + interrupts = <8>; + clocks = <&clks 60>; + status = "disabled"; + }; + + pata: pata@83fe0000 { + compatible = "fsl,imx51-pata", "fsl,imx27-pata"; + reg = <0x83fe0000 0x4000>; + interrupts = <70>; + clocks = <&clks 161>; + status = "disabled"; + }; + + ssi3: ssi@83fe8000 { + compatible = "fsl,imx51-ssi", "fsl,imx21-ssi"; + reg = <0x83fe8000 0x4000>; + interrupts = <96>; + clocks = <&clks 50>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */ + status = "disabled"; + }; + + fec: ethernet@83fec000 { + compatible = "fsl,imx51-fec", "fsl,imx27-fec"; + reg = <0x83fec000 0x4000>; + interrupts = <87>; + clocks = <&clks 42>, <&clks 42>, <&clks 42>; + clock-names = "ipg", "ahb", "ptp"; + status = "disabled"; + }; + }; + }; +}; diff --git a/arch/arm/dts/imx6q-pinfunc.h b/arch/arm/dts/imx6q-pinfunc.h new file mode 100644 index 0000000000..faea6e1ada --- /dev/null +++ b/arch/arm/dts/imx6q-pinfunc.h @@ -0,0 +1,1041 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __DTS_IMX6Q_PINFUNC_H +#define __DTS_IMX6Q_PINFUNC_H + +/* + * The pin function ID is a tuple of + * <mux_reg conf_reg input_reg mux_mode input_val> + */ +#define MX6Q_PAD_SD2_DAT1__SD2_DATA1 0x04c 0x360 0x000 0x0 0x0 +#define MX6Q_PAD_SD2_DAT1__ECSPI5_SS0 0x04c 0x360 0x834 0x1 0x0 +#define MX6Q_PAD_SD2_DAT1__EIM_CS2_B 0x04c 0x360 0x000 0x2 0x0 +#define MX6Q_PAD_SD2_DAT1__AUD4_TXFS 0x04c 0x360 0x7c8 0x3 0x0 +#define MX6Q_PAD_SD2_DAT1__KEY_COL7 0x04c 0x360 0x8f0 0x4 0x0 +#define MX6Q_PAD_SD2_DAT1__GPIO1_IO14 0x04c 0x360 0x000 0x5 0x0 +#define MX6Q_PAD_SD2_DAT2__SD2_DATA2 0x050 0x364 0x000 0x0 0x0 +#define MX6Q_PAD_SD2_DAT2__ECSPI5_SS1 0x050 0x364 0x838 0x1 0x0 +#define MX6Q_PAD_SD2_DAT2__EIM_CS3_B 0x050 0x364 0x000 0x2 0x0 +#define MX6Q_PAD_SD2_DAT2__AUD4_TXD 0x050 0x364 0x7b8 0x3 0x0 +#define MX6Q_PAD_SD2_DAT2__KEY_ROW6 0x050 0x364 0x8f8 0x4 0x0 +#define MX6Q_PAD_SD2_DAT2__GPIO1_IO13 0x050 0x364 0x000 0x5 0x0 +#define MX6Q_PAD_SD2_DAT0__SD2_DATA0 0x054 0x368 0x000 0x0 0x0 +#define MX6Q_PAD_SD2_DAT0__ECSPI5_MISO 0x054 0x368 0x82c 0x1 0x0 +#define MX6Q_PAD_SD2_DAT0__AUD4_RXD 0x054 0x368 0x7b4 0x3 0x0 +#define MX6Q_PAD_SD2_DAT0__KEY_ROW7 0x054 0x368 0x8fc 0x4 0x0 +#define MX6Q_PAD_SD2_DAT0__GPIO1_IO15 0x054 0x368 0x000 0x5 0x0 +#define MX6Q_PAD_SD2_DAT0__DCIC2_OUT 0x054 0x368 0x000 0x6 0x0 +#define MX6Q_PAD_RGMII_TXC__USB_H2_DATA 0x058 0x36c 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_TXC__RGMII_TXC 0x058 0x36c 0x000 0x1 0x0 +#define MX6Q_PAD_RGMII_TXC__SPDIF_EXT_CLK 0x058 0x36c 0x918 0x2 0x0 +#define MX6Q_PAD_RGMII_TXC__GPIO6_IO19 0x058 0x36c 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M 0x058 0x36c 0x000 0x7 0x0 +#define MX6Q_PAD_RGMII_TD0__HSI_TX_READY 0x05c 0x370 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_TD0__RGMII_TD0 0x05c 0x370 0x000 0x1 0x0 +#define MX6Q_PAD_RGMII_TD0__GPIO6_IO20 0x05c 0x370 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_TD1__HSI_RX_FLAG 0x060 0x374 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_TD1__RGMII_TD1 0x060 0x374 0x000 0x1 0x0 +#define MX6Q_PAD_RGMII_TD1__GPIO6_IO21 0x060 0x374 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_TD2__HSI_RX_DATA 0x064 0x378 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_TD2__RGMII_TD2 0x064 0x378 0x000 0x1 0x0 +#define MX6Q_PAD_RGMII_TD2__GPIO6_IO22 0x064 0x378 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_TD3__HSI_RX_WAKE 0x068 0x37c 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_TD3__RGMII_TD3 0x068 0x37c 0x000 0x1 0x0 +#define MX6Q_PAD_RGMII_TD3__GPIO6_IO23 0x068 0x37c 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_RX_CTL__USB_H3_DATA 0x06c 0x380 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x06c 0x380 0x858 0x1 0x0 +#define MX6Q_PAD_RGMII_RX_CTL__GPIO6_IO24 0x06c 0x380 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_RD0__HSI_RX_READY 0x070 0x384 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_RD0__RGMII_RD0 0x070 0x384 0x848 0x1 0x0 +#define MX6Q_PAD_RGMII_RD0__GPIO6_IO25 0x070 0x384 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x074 0x388 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x074 0x388 0x000 0x1 0x0 +#define MX6Q_PAD_RGMII_TX_CTL__GPIO6_IO26 0x074 0x388 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_TX_CTL__ENET_REF_CLK 0x074 0x388 0x83c 0x7 0x0 +#define MX6Q_PAD_RGMII_RD1__HSI_TX_FLAG 0x078 0x38c 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_RD1__RGMII_RD1 0x078 0x38c 0x84c 0x1 0x0 +#define MX6Q_PAD_RGMII_RD1__GPIO6_IO27 0x078 0x38c 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_RD2__HSI_TX_DATA 0x07c 0x390 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_RD2__RGMII_RD2 0x07c 0x390 0x850 0x1 0x0 +#define MX6Q_PAD_RGMII_RD2__GPIO6_IO28 0x07c 0x390 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_RD3__HSI_TX_WAKE 0x080 0x394 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_RD3__RGMII_RD3 0x080 0x394 0x854 0x1 0x0 +#define MX6Q_PAD_RGMII_RD3__GPIO6_IO29 0x080 0x394 0x000 0x5 0x0 +#define MX6Q_PAD_RGMII_RXC__USB_H3_STROBE 0x084 0x398 0x000 0x0 0x0 +#define MX6Q_PAD_RGMII_RXC__RGMII_RXC 0x084 0x398 0x844 0x1 0x0 +#define MX6Q_PAD_RGMII_RXC__GPIO6_IO30 0x084 0x398 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A25__EIM_ADDR25 0x088 0x39c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A25__ECSPI4_SS1 0x088 0x39c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A25__ECSPI2_RDY 0x088 0x39c 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12 0x088 0x39c 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS 0x088 0x39c 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_A25__GPIO5_IO02 0x088 0x39c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x088 0x39c 0x88c 0x6 0x0 +#define MX6Q_PAD_EIM_EB2__EIM_EB2_B 0x08c 0x3a0 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_EB2__ECSPI1_SS0 0x08c 0x3a0 0x800 0x1 0x0 +#define MX6Q_PAD_EIM_EB2__IPU2_CSI1_DATA19 0x08c 0x3a0 0x8d4 0x3 0x0 +#define MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x08c 0x3a0 0x890 0x4 0x0 +#define MX6Q_PAD_EIM_EB2__GPIO2_IO30 0x08c 0x3a0 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_EB2__I2C2_SCL 0x08c 0x3a0 0x8a0 0x6 0x0 +#define MX6Q_PAD_EIM_EB2__SRC_BOOT_CFG30 0x08c 0x3a0 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D16__EIM_DATA16 0x090 0x3a4 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D16__ECSPI1_SCLK 0x090 0x3a4 0x7f4 0x1 0x0 +#define MX6Q_PAD_EIM_D16__IPU1_DI0_PIN05 0x090 0x3a4 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D16__IPU2_CSI1_DATA18 0x090 0x3a4 0x8d0 0x3 0x0 +#define MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x090 0x3a4 0x894 0x4 0x0 +#define MX6Q_PAD_EIM_D16__GPIO3_IO16 0x090 0x3a4 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D16__I2C2_SDA 0x090 0x3a4 0x8a4 0x6 0x0 +#define MX6Q_PAD_EIM_D17__EIM_DATA17 0x094 0x3a8 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D17__ECSPI1_MISO 0x094 0x3a8 0x7f8 0x1 0x0 +#define MX6Q_PAD_EIM_D17__IPU1_DI0_PIN06 0x094 0x3a8 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK 0x094 0x3a8 0x8e0 0x3 0x0 +#define MX6Q_PAD_EIM_D17__DCIC1_OUT 0x094 0x3a8 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D17__GPIO3_IO17 0x094 0x3a8 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D17__I2C3_SCL 0x094 0x3a8 0x8a8 0x6 0x0 +#define MX6Q_PAD_EIM_D18__EIM_DATA18 0x098 0x3ac 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D18__ECSPI1_MOSI 0x098 0x3ac 0x7fc 0x1 0x0 +#define MX6Q_PAD_EIM_D18__IPU1_DI0_PIN07 0x098 0x3ac 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D18__IPU2_CSI1_DATA17 0x098 0x3ac 0x8cc 0x3 0x0 +#define MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS 0x098 0x3ac 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D18__GPIO3_IO18 0x098 0x3ac 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D18__I2C3_SDA 0x098 0x3ac 0x8ac 0x6 0x0 +#define MX6Q_PAD_EIM_D19__EIM_DATA19 0x09c 0x3b0 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D19__ECSPI1_SS1 0x09c 0x3b0 0x804 0x1 0x0 +#define MX6Q_PAD_EIM_D19__IPU1_DI0_PIN08 0x09c 0x3b0 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D19__IPU2_CSI1_DATA16 0x09c 0x3b0 0x8c8 0x3 0x0 +#define MX6Q_PAD_EIM_D19__UART1_CTS_B 0x09c 0x3b0 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D19__UART1_RTS_B 0x09c 0x3b0 0x91c 0x4 0x0 +#define MX6Q_PAD_EIM_D19__GPIO3_IO19 0x09c 0x3b0 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D19__EPIT1_OUT 0x09c 0x3b0 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D20__EIM_DATA20 0x0a0 0x3b4 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D20__ECSPI4_SS0 0x0a0 0x3b4 0x824 0x1 0x0 +#define MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16 0x0a0 0x3b4 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D20__IPU2_CSI1_DATA15 0x0a0 0x3b4 0x8c4 0x3 0x0 +#define MX6Q_PAD_EIM_D20__UART1_RTS_B 0x0a0 0x3b4 0x91c 0x4 0x1 +#define MX6Q_PAD_EIM_D20__UART1_CTS_B 0x0a0 0x3b4 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D20__GPIO3_IO20 0x0a0 0x3b4 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D20__EPIT2_OUT 0x0a0 0x3b4 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D21__EIM_DATA21 0x0a4 0x3b8 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D21__ECSPI4_SCLK 0x0a4 0x3b8 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17 0x0a4 0x3b8 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D21__IPU2_CSI1_DATA11 0x0a4 0x3b8 0x8b4 0x3 0x0 +#define MX6Q_PAD_EIM_D21__USB_OTG_OC 0x0a4 0x3b8 0x944 0x4 0x0 +#define MX6Q_PAD_EIM_D21__GPIO3_IO21 0x0a4 0x3b8 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D21__I2C1_SCL 0x0a4 0x3b8 0x898 0x6 0x0 +#define MX6Q_PAD_EIM_D21__SPDIF_IN 0x0a4 0x3b8 0x914 0x7 0x0 +#define MX6Q_PAD_EIM_D22__EIM_DATA22 0x0a8 0x3bc 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D22__ECSPI4_MISO 0x0a8 0x3bc 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D22__IPU1_DI0_PIN01 0x0a8 0x3bc 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D22__IPU2_CSI1_DATA10 0x0a8 0x3bc 0x8b0 0x3 0x0 +#define MX6Q_PAD_EIM_D22__USB_OTG_PWR 0x0a8 0x3bc 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D22__GPIO3_IO22 0x0a8 0x3bc 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D22__SPDIF_OUT 0x0a8 0x3bc 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D23__EIM_DATA23 0x0ac 0x3c0 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS 0x0ac 0x3c0 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D23__UART3_CTS_B 0x0ac 0x3c0 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D23__UART3_RTS_B 0x0ac 0x3c0 0x92c 0x2 0x0 +#define MX6Q_PAD_EIM_D23__UART1_DCD_B 0x0ac 0x3c0 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN 0x0ac 0x3c0 0x8d8 0x4 0x0 +#define MX6Q_PAD_EIM_D23__GPIO3_IO23 0x0ac 0x3c0 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D23__IPU1_DI1_PIN02 0x0ac 0x3c0 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14 0x0ac 0x3c0 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_EB3__EIM_EB3_B 0x0b0 0x3c4 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_EB3__ECSPI4_RDY 0x0b0 0x3c4 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_EB3__UART3_RTS_B 0x0b0 0x3c4 0x92c 0x2 0x1 +#define MX6Q_PAD_EIM_EB3__UART3_CTS_B 0x0b0 0x3c4 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_EB3__UART1_RI_B 0x0b0 0x3c4 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC 0x0b0 0x3c4 0x8dc 0x4 0x0 +#define MX6Q_PAD_EIM_EB3__GPIO2_IO31 0x0b0 0x3c4 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN03 0x0b0 0x3c4 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_EB3__SRC_BOOT_CFG31 0x0b0 0x3c4 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D24__EIM_DATA24 0x0b4 0x3c8 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D24__ECSPI4_SS2 0x0b4 0x3c8 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D24__UART3_TX_DATA 0x0b4 0x3c8 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D24__UART3_RX_DATA 0x0b4 0x3c8 0x930 0x2 0x0 +#define MX6Q_PAD_EIM_D24__ECSPI1_SS2 0x0b4 0x3c8 0x808 0x3 0x0 +#define MX6Q_PAD_EIM_D24__ECSPI2_SS2 0x0b4 0x3c8 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D24__GPIO3_IO24 0x0b4 0x3c8 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D24__AUD5_RXFS 0x0b4 0x3c8 0x7d8 0x6 0x0 +#define MX6Q_PAD_EIM_D24__UART1_DTR_B 0x0b4 0x3c8 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D25__EIM_DATA25 0x0b8 0x3cc 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D25__ECSPI4_SS3 0x0b8 0x3cc 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D25__UART3_RX_DATA 0x0b8 0x3cc 0x930 0x2 0x1 +#define MX6Q_PAD_EIM_D25__UART3_TX_DATA 0x0b8 0x3cc 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D25__ECSPI1_SS3 0x0b8 0x3cc 0x80c 0x3 0x0 +#define MX6Q_PAD_EIM_D25__ECSPI2_SS3 0x0b8 0x3cc 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D25__GPIO3_IO25 0x0b8 0x3cc 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D25__AUD5_RXC 0x0b8 0x3cc 0x7d4 0x6 0x0 +#define MX6Q_PAD_EIM_D25__UART1_DSR_B 0x0b8 0x3cc 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D26__EIM_DATA26 0x0bc 0x3d0 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11 0x0bc 0x3d0 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D26__IPU1_CSI0_DATA01 0x0bc 0x3d0 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D26__IPU2_CSI1_DATA14 0x0bc 0x3d0 0x8c0 0x3 0x0 +#define MX6Q_PAD_EIM_D26__UART2_TX_DATA 0x0bc 0x3d0 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D26__UART2_RX_DATA 0x0bc 0x3d0 0x928 0x4 0x0 +#define MX6Q_PAD_EIM_D26__GPIO3_IO26 0x0bc 0x3d0 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D26__IPU1_SISG2 0x0bc 0x3d0 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D26__IPU1_DISP1_DATA22 0x0bc 0x3d0 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D27__EIM_DATA27 0x0c0 0x3d4 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13 0x0c0 0x3d4 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D27__IPU1_CSI0_DATA00 0x0c0 0x3d4 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D27__IPU2_CSI1_DATA13 0x0c0 0x3d4 0x8bc 0x3 0x0 +#define MX6Q_PAD_EIM_D27__UART2_RX_DATA 0x0c0 0x3d4 0x928 0x4 0x1 +#define MX6Q_PAD_EIM_D27__UART2_TX_DATA 0x0c0 0x3d4 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D27__GPIO3_IO27 0x0c0 0x3d4 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D27__IPU1_SISG3 0x0c0 0x3d4 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D27__IPU1_DISP1_DATA23 0x0c0 0x3d4 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D28__EIM_DATA28 0x0c4 0x3d8 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D28__I2C1_SDA 0x0c4 0x3d8 0x89c 0x1 0x0 +#define MX6Q_PAD_EIM_D28__ECSPI4_MOSI 0x0c4 0x3d8 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D28__IPU2_CSI1_DATA12 0x0c4 0x3d8 0x8b8 0x3 0x0 +#define MX6Q_PAD_EIM_D28__UART2_CTS_B 0x0c4 0x3d8 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D28__UART2_RTS_B 0x0c4 0x3d8 0x924 0x4 0x0 +#define MX6Q_PAD_EIM_D28__GPIO3_IO28 0x0c4 0x3d8 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG 0x0c4 0x3d8 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13 0x0c4 0x3d8 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D29__EIM_DATA29 0x0c8 0x3dc 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15 0x0c8 0x3dc 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D29__ECSPI4_SS0 0x0c8 0x3dc 0x824 0x2 0x1 +#define MX6Q_PAD_EIM_D29__UART2_RTS_B 0x0c8 0x3dc 0x924 0x4 0x1 +#define MX6Q_PAD_EIM_D29__UART2_CTS_B 0x0c8 0x3dc 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D29__GPIO3_IO29 0x0c8 0x3dc 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC 0x0c8 0x3dc 0x8e4 0x6 0x0 +#define MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14 0x0c8 0x3dc 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_D30__EIM_DATA30 0x0cc 0x3e0 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D30__IPU1_DISP1_DATA21 0x0cc 0x3e0 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11 0x0cc 0x3e0 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D30__IPU1_CSI0_DATA03 0x0cc 0x3e0 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_D30__UART3_CTS_B 0x0cc 0x3e0 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D30__UART3_RTS_B 0x0cc 0x3e0 0x92c 0x4 0x2 +#define MX6Q_PAD_EIM_D30__GPIO3_IO30 0x0cc 0x3e0 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D30__USB_H1_OC 0x0cc 0x3e0 0x948 0x6 0x0 +#define MX6Q_PAD_EIM_D31__EIM_DATA31 0x0d0 0x3e4 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_D31__IPU1_DISP1_DATA20 0x0d0 0x3e4 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12 0x0d0 0x3e4 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_D31__IPU1_CSI0_DATA02 0x0d0 0x3e4 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_D31__UART3_RTS_B 0x0d0 0x3e4 0x92c 0x4 0x3 +#define MX6Q_PAD_EIM_D31__UART3_CTS_B 0x0d0 0x3e4 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_D31__GPIO3_IO31 0x0d0 0x3e4 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_D31__USB_H1_PWR 0x0d0 0x3e4 0x000 0x6 0x0 +#define MX6Q_PAD_EIM_A24__EIM_ADDR24 0x0d4 0x3e8 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A24__IPU1_DISP1_DATA19 0x0d4 0x3e8 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A24__IPU2_CSI1_DATA19 0x0d4 0x3e8 0x8d4 0x2 0x1 +#define MX6Q_PAD_EIM_A24__IPU2_SISG2 0x0d4 0x3e8 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_A24__IPU1_SISG2 0x0d4 0x3e8 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_A24__GPIO5_IO04 0x0d4 0x3e8 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A24__SRC_BOOT_CFG24 0x0d4 0x3e8 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A23__EIM_ADDR23 0x0d8 0x3ec 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A23__IPU1_DISP1_DATA18 0x0d8 0x3ec 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A23__IPU2_CSI1_DATA18 0x0d8 0x3ec 0x8d0 0x2 0x1 +#define MX6Q_PAD_EIM_A23__IPU2_SISG3 0x0d8 0x3ec 0x000 0x3 0x0 +#define MX6Q_PAD_EIM_A23__IPU1_SISG3 0x0d8 0x3ec 0x000 0x4 0x0 +#define MX6Q_PAD_EIM_A23__GPIO6_IO06 0x0d8 0x3ec 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A23__SRC_BOOT_CFG23 0x0d8 0x3ec 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A22__EIM_ADDR22 0x0dc 0x3f0 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A22__IPU1_DISP1_DATA17 0x0dc 0x3f0 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A22__IPU2_CSI1_DATA17 0x0dc 0x3f0 0x8cc 0x2 0x1 +#define MX6Q_PAD_EIM_A22__GPIO2_IO16 0x0dc 0x3f0 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A22__SRC_BOOT_CFG22 0x0dc 0x3f0 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A21__EIM_ADDR21 0x0e0 0x3f4 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A21__IPU1_DISP1_DATA16 0x0e0 0x3f4 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A21__IPU2_CSI1_DATA16 0x0e0 0x3f4 0x8c8 0x2 0x1 +#define MX6Q_PAD_EIM_A21__GPIO2_IO17 0x0e0 0x3f4 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A21__SRC_BOOT_CFG21 0x0e0 0x3f4 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A20__EIM_ADDR20 0x0e4 0x3f8 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A20__IPU1_DISP1_DATA15 0x0e4 0x3f8 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A20__IPU2_CSI1_DATA15 0x0e4 0x3f8 0x8c4 0x2 0x1 +#define MX6Q_PAD_EIM_A20__GPIO2_IO18 0x0e4 0x3f8 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A20__SRC_BOOT_CFG20 0x0e4 0x3f8 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A19__EIM_ADDR19 0x0e8 0x3fc 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A19__IPU1_DISP1_DATA14 0x0e8 0x3fc 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A19__IPU2_CSI1_DATA14 0x0e8 0x3fc 0x8c0 0x2 0x1 +#define MX6Q_PAD_EIM_A19__GPIO2_IO19 0x0e8 0x3fc 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A19__SRC_BOOT_CFG19 0x0e8 0x3fc 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A18__EIM_ADDR18 0x0ec 0x400 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A18__IPU1_DISP1_DATA13 0x0ec 0x400 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A18__IPU2_CSI1_DATA13 0x0ec 0x400 0x8bc 0x2 0x1 +#define MX6Q_PAD_EIM_A18__GPIO2_IO20 0x0ec 0x400 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A18__SRC_BOOT_CFG18 0x0ec 0x400 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A17__EIM_ADDR17 0x0f0 0x404 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A17__IPU1_DISP1_DATA12 0x0f0 0x404 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A17__IPU2_CSI1_DATA12 0x0f0 0x404 0x8b8 0x2 0x1 +#define MX6Q_PAD_EIM_A17__GPIO2_IO21 0x0f0 0x404 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A17__SRC_BOOT_CFG17 0x0f0 0x404 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_A16__EIM_ADDR16 0x0f4 0x408 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK 0x0f4 0x408 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK 0x0f4 0x408 0x8e0 0x2 0x1 +#define MX6Q_PAD_EIM_A16__GPIO2_IO22 0x0f4 0x408 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_A16__SRC_BOOT_CFG16 0x0f4 0x408 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_CS0__EIM_CS0_B 0x0f8 0x40c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN05 0x0f8 0x40c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_CS0__ECSPI2_SCLK 0x0f8 0x40c 0x810 0x2 0x0 +#define MX6Q_PAD_EIM_CS0__GPIO2_IO23 0x0f8 0x40c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_CS1__EIM_CS1_B 0x0fc 0x410 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN06 0x0fc 0x410 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_CS1__ECSPI2_MOSI 0x0fc 0x410 0x818 0x2 0x0 +#define MX6Q_PAD_EIM_CS1__GPIO2_IO24 0x0fc 0x410 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_OE__EIM_OE_B 0x100 0x414 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_OE__IPU1_DI1_PIN07 0x100 0x414 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_OE__ECSPI2_MISO 0x100 0x414 0x814 0x2 0x0 +#define MX6Q_PAD_EIM_OE__GPIO2_IO25 0x100 0x414 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_RW__EIM_RW 0x104 0x418 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_RW__IPU1_DI1_PIN08 0x104 0x418 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_RW__ECSPI2_SS0 0x104 0x418 0x81c 0x2 0x0 +#define MX6Q_PAD_EIM_RW__GPIO2_IO26 0x104 0x418 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_RW__SRC_BOOT_CFG29 0x104 0x418 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_LBA__EIM_LBA_B 0x108 0x41c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17 0x108 0x41c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_LBA__ECSPI2_SS1 0x108 0x41c 0x820 0x2 0x0 +#define MX6Q_PAD_EIM_LBA__GPIO2_IO27 0x108 0x41c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_LBA__SRC_BOOT_CFG26 0x108 0x41c 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_EB0__EIM_EB0_B 0x10c 0x420 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_EB0__IPU1_DISP1_DATA11 0x10c 0x420 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_EB0__IPU2_CSI1_DATA11 0x10c 0x420 0x8b4 0x2 0x1 +#define MX6Q_PAD_EIM_EB0__CCM_PMIC_READY 0x10c 0x420 0x7f0 0x4 0x0 +#define MX6Q_PAD_EIM_EB0__GPIO2_IO28 0x10c 0x420 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_EB0__SRC_BOOT_CFG27 0x10c 0x420 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_EB1__EIM_EB1_B 0x110 0x424 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_EB1__IPU1_DISP1_DATA10 0x110 0x424 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_EB1__IPU2_CSI1_DATA10 0x110 0x424 0x8b0 0x2 0x1 +#define MX6Q_PAD_EIM_EB1__GPIO2_IO29 0x110 0x424 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_EB1__SRC_BOOT_CFG28 0x110 0x424 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA0__EIM_AD00 0x114 0x428 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA0__IPU1_DISP1_DATA09 0x114 0x428 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA0__IPU2_CSI1_DATA09 0x114 0x428 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA0__GPIO3_IO00 0x114 0x428 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA0__SRC_BOOT_CFG00 0x114 0x428 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA1__EIM_AD01 0x118 0x42c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA1__IPU1_DISP1_DATA08 0x118 0x42c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA1__IPU2_CSI1_DATA08 0x118 0x42c 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA1__GPIO3_IO01 0x118 0x42c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA1__SRC_BOOT_CFG01 0x118 0x42c 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA2__EIM_AD02 0x11c 0x430 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA2__IPU1_DISP1_DATA07 0x11c 0x430 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA2__IPU2_CSI1_DATA07 0x11c 0x430 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA2__GPIO3_IO02 0x11c 0x430 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA2__SRC_BOOT_CFG02 0x11c 0x430 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA3__EIM_AD03 0x120 0x434 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA3__IPU1_DISP1_DATA06 0x120 0x434 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA3__IPU2_CSI1_DATA06 0x120 0x434 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA3__GPIO3_IO03 0x120 0x434 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA3__SRC_BOOT_CFG03 0x120 0x434 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA4__EIM_AD04 0x124 0x438 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA4__IPU1_DISP1_DATA05 0x124 0x438 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA4__IPU2_CSI1_DATA05 0x124 0x438 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA4__GPIO3_IO04 0x124 0x438 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA4__SRC_BOOT_CFG04 0x124 0x438 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA5__EIM_AD05 0x128 0x43c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA5__IPU1_DISP1_DATA04 0x128 0x43c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA5__IPU2_CSI1_DATA04 0x128 0x43c 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA5__GPIO3_IO05 0x128 0x43c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA5__SRC_BOOT_CFG05 0x128 0x43c 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA6__EIM_AD06 0x12c 0x440 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA6__IPU1_DISP1_DATA03 0x12c 0x440 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA6__IPU2_CSI1_DATA03 0x12c 0x440 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA6__GPIO3_IO06 0x12c 0x440 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA6__SRC_BOOT_CFG06 0x12c 0x440 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA7__EIM_AD07 0x130 0x444 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA7__IPU1_DISP1_DATA02 0x130 0x444 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA7__IPU2_CSI1_DATA02 0x130 0x444 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA7__GPIO3_IO07 0x130 0x444 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA7__SRC_BOOT_CFG07 0x130 0x444 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA8__EIM_AD08 0x134 0x448 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA8__IPU1_DISP1_DATA01 0x134 0x448 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA8__IPU2_CSI1_DATA01 0x134 0x448 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA8__GPIO3_IO08 0x134 0x448 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA8__SRC_BOOT_CFG08 0x134 0x448 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA9__EIM_AD09 0x138 0x44c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA9__IPU1_DISP1_DATA00 0x138 0x44c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA9__IPU2_CSI1_DATA00 0x138 0x44c 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA9__GPIO3_IO09 0x138 0x44c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA9__SRC_BOOT_CFG09 0x138 0x44c 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA10__EIM_AD10 0x13c 0x450 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15 0x13c 0x450 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN 0x13c 0x450 0x8d8 0x2 0x1 +#define MX6Q_PAD_EIM_DA10__GPIO3_IO10 0x13c 0x450 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA10__SRC_BOOT_CFG10 0x13c 0x450 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA11__EIM_AD11 0x140 0x454 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN02 0x140 0x454 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC 0x140 0x454 0x8dc 0x2 0x1 +#define MX6Q_PAD_EIM_DA11__GPIO3_IO11 0x140 0x454 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA11__SRC_BOOT_CFG11 0x140 0x454 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA12__EIM_AD12 0x144 0x458 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN03 0x144 0x458 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC 0x144 0x458 0x8e4 0x2 0x1 +#define MX6Q_PAD_EIM_DA12__GPIO3_IO12 0x144 0x458 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA12__SRC_BOOT_CFG12 0x144 0x458 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA13__EIM_AD13 0x148 0x45c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS 0x148 0x45c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA13__GPIO3_IO13 0x148 0x45c 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA13__SRC_BOOT_CFG13 0x148 0x45c 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA14__EIM_AD14 0x14c 0x460 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS 0x14c 0x460 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA14__GPIO3_IO14 0x14c 0x460 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA14__SRC_BOOT_CFG14 0x14c 0x460 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_DA15__EIM_AD15 0x150 0x464 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN01 0x150 0x464 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN04 0x150 0x464 0x000 0x2 0x0 +#define MX6Q_PAD_EIM_DA15__GPIO3_IO15 0x150 0x464 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_DA15__SRC_BOOT_CFG15 0x150 0x464 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_WAIT__EIM_WAIT_B 0x154 0x468 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_WAIT__EIM_DTACK_B 0x154 0x468 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_WAIT__GPIO5_IO00 0x154 0x468 0x000 0x5 0x0 +#define MX6Q_PAD_EIM_WAIT__SRC_BOOT_CFG25 0x154 0x468 0x000 0x7 0x0 +#define MX6Q_PAD_EIM_BCLK__EIM_BCLK 0x158 0x46c 0x000 0x0 0x0 +#define MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16 0x158 0x46c 0x000 0x1 0x0 +#define MX6Q_PAD_EIM_BCLK__GPIO6_IO31 0x158 0x46c 0x000 0x5 0x0 +#define MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x15c 0x470 0x000 0x0 0x0 +#define MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DISP_CLK 0x15c 0x470 0x000 0x1 0x0 +#define MX6Q_PAD_DI0_DISP_CLK__GPIO4_IO16 0x15c 0x470 0x000 0x5 0x0 +#define MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x160 0x474 0x000 0x0 0x0 +#define MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15 0x160 0x474 0x000 0x1 0x0 +#define MX6Q_PAD_DI0_PIN15__AUD6_TXC 0x160 0x474 0x000 0x2 0x0 +#define MX6Q_PAD_DI0_PIN15__GPIO4_IO17 0x160 0x474 0x000 0x5 0x0 +#define MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x164 0x478 0x000 0x0 0x0 +#define MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN02 0x164 0x478 0x000 0x1 0x0 +#define MX6Q_PAD_DI0_PIN2__AUD6_TXD 0x164 0x478 0x000 0x2 0x0 +#define MX6Q_PAD_DI0_PIN2__GPIO4_IO18 0x164 0x478 0x000 0x5 0x0 +#define MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x168 0x47c 0x000 0x0 0x0 +#define MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN03 0x168 0x47c 0x000 0x1 0x0 +#define MX6Q_PAD_DI0_PIN3__AUD6_TXFS 0x168 0x47c 0x000 0x2 0x0 +#define MX6Q_PAD_DI0_PIN3__GPIO4_IO19 0x168 0x47c 0x000 0x5 0x0 +#define MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x16c 0x480 0x000 0x0 0x0 +#define MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN04 0x16c 0x480 0x000 0x1 0x0 +#define MX6Q_PAD_DI0_PIN4__AUD6_RXD 0x16c 0x480 0x000 0x2 0x0 +#define MX6Q_PAD_DI0_PIN4__SD1_WP 0x16c 0x480 0x94c 0x3 0x0 +#define MX6Q_PAD_DI0_PIN4__GPIO4_IO20 0x16c 0x480 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x170 0x484 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DATA00 0x170 0x484 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK 0x170 0x484 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT0__GPIO4_IO21 0x170 0x484 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x174 0x488 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DATA01 0x174 0x488 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI 0x174 0x488 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT1__GPIO4_IO22 0x174 0x488 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x178 0x48c 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DATA02 0x178 0x48c 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO 0x178 0x48c 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT2__GPIO4_IO23 0x178 0x48c 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x17c 0x490 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DATA03 0x17c 0x490 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0 0x17c 0x490 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT3__GPIO4_IO24 0x17c 0x490 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x180 0x494 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DATA04 0x180 0x494 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1 0x180 0x494 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT4__GPIO4_IO25 0x180 0x494 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x184 0x498 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DATA05 0x184 0x498 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2 0x184 0x498 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT5__AUD6_RXFS 0x184 0x498 0x000 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT5__GPIO4_IO26 0x184 0x498 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x188 0x49c 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DATA06 0x188 0x49c 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3 0x188 0x49c 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT6__AUD6_RXC 0x188 0x49c 0x000 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT6__GPIO4_IO27 0x188 0x49c 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x18c 0x4a0 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DATA07 0x18c 0x4a0 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY 0x18c 0x4a0 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT7__GPIO4_IO28 0x18c 0x4a0 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x190 0x4a4 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DATA08 0x190 0x4a4 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT8__PWM1_OUT 0x190 0x4a4 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT8__WDOG1_B 0x190 0x4a4 0x000 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT8__GPIO4_IO29 0x190 0x4a4 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x194 0x4a8 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DATA09 0x194 0x4a8 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT9__PWM2_OUT 0x194 0x4a8 0x000 0x2 0x0 +#define MX6Q_PAD_DISP0_DAT9__WDOG2_B 0x194 0x4a8 0x000 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT9__GPIO4_IO30 0x194 0x4a8 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x198 0x4ac 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DATA10 0x198 0x4ac 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT10__GPIO4_IO31 0x198 0x4ac 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x19c 0x4b0 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DATA11 0x19c 0x4b0 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT11__GPIO5_IO05 0x19c 0x4b0 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x1a0 0x4b4 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DATA12 0x1a0 0x4b4 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT12__GPIO5_IO06 0x1a0 0x4b4 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x1a4 0x4b8 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DATA13 0x1a4 0x4b8 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT13__AUD5_RXFS 0x1a4 0x4b8 0x7d8 0x3 0x1 +#define MX6Q_PAD_DISP0_DAT13__GPIO5_IO07 0x1a4 0x4b8 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x1a8 0x4bc 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DATA14 0x1a8 0x4bc 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT14__AUD5_RXC 0x1a8 0x4bc 0x7d4 0x3 0x1 +#define MX6Q_PAD_DISP0_DAT14__GPIO5_IO08 0x1a8 0x4bc 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x1ac 0x4c0 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DATA15 0x1ac 0x4c0 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1 0x1ac 0x4c0 0x804 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1 0x1ac 0x4c0 0x820 0x3 0x1 +#define MX6Q_PAD_DISP0_DAT15__GPIO5_IO09 0x1ac 0x4c0 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x1b0 0x4c4 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DATA16 0x1b0 0x4c4 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI 0x1b0 0x4c4 0x818 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT16__AUD5_TXC 0x1b0 0x4c4 0x7dc 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT0 0x1b0 0x4c4 0x90c 0x4 0x0 +#define MX6Q_PAD_DISP0_DAT16__GPIO5_IO10 0x1b0 0x4c4 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x1b4 0x4c8 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DATA17 0x1b4 0x4c8 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO 0x1b4 0x4c8 0x814 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT17__AUD5_TXD 0x1b4 0x4c8 0x7d0 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT1 0x1b4 0x4c8 0x910 0x4 0x0 +#define MX6Q_PAD_DISP0_DAT17__GPIO5_IO11 0x1b4 0x4c8 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x1b8 0x4cc 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DATA18 0x1b8 0x4cc 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0 0x1b8 0x4cc 0x81c 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT18__AUD5_TXFS 0x1b8 0x4cc 0x7e0 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT18__AUD4_RXFS 0x1b8 0x4cc 0x7c0 0x4 0x0 +#define MX6Q_PAD_DISP0_DAT18__GPIO5_IO12 0x1b8 0x4cc 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT18__EIM_CS2_B 0x1b8 0x4cc 0x000 0x7 0x0 +#define MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x1bc 0x4d0 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DATA19 0x1bc 0x4d0 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK 0x1bc 0x4d0 0x810 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT19__AUD5_RXD 0x1bc 0x4d0 0x7cc 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT19__AUD4_RXC 0x1bc 0x4d0 0x7bc 0x4 0x0 +#define MX6Q_PAD_DISP0_DAT19__GPIO5_IO13 0x1bc 0x4d0 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT19__EIM_CS3_B 0x1bc 0x4d0 0x000 0x7 0x0 +#define MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x1c0 0x4d4 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DATA20 0x1c0 0x4d4 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK 0x1c0 0x4d4 0x7f4 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT20__AUD4_TXC 0x1c0 0x4d4 0x7c4 0x3 0x0 +#define MX6Q_PAD_DISP0_DAT20__GPIO5_IO14 0x1c0 0x4d4 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x1c4 0x4d8 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DATA21 0x1c4 0x4d8 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI 0x1c4 0x4d8 0x7fc 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT21__AUD4_TXD 0x1c4 0x4d8 0x7b8 0x3 0x1 +#define MX6Q_PAD_DISP0_DAT21__GPIO5_IO15 0x1c4 0x4d8 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x1c8 0x4dc 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DATA22 0x1c8 0x4dc 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO 0x1c8 0x4dc 0x7f8 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT22__AUD4_TXFS 0x1c8 0x4dc 0x7c8 0x3 0x1 +#define MX6Q_PAD_DISP0_DAT22__GPIO5_IO16 0x1c8 0x4dc 0x000 0x5 0x0 +#define MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x1cc 0x4e0 0x000 0x0 0x0 +#define MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DATA23 0x1cc 0x4e0 0x000 0x1 0x0 +#define MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0 0x1cc 0x4e0 0x800 0x2 0x1 +#define MX6Q_PAD_DISP0_DAT23__AUD4_RXD 0x1cc 0x4e0 0x7b4 0x3 0x1 +#define MX6Q_PAD_DISP0_DAT23__GPIO5_IO17 0x1cc 0x4e0 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_MDIO__ENET_MDIO 0x1d0 0x4e4 0x840 0x1 0x0 +#define MX6Q_PAD_ENET_MDIO__ESAI_RX_CLK 0x1d0 0x4e4 0x86c 0x2 0x0 +#define MX6Q_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT 0x1d0 0x4e4 0x000 0x4 0x0 +#define MX6Q_PAD_ENET_MDIO__GPIO1_IO22 0x1d0 0x4e4 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_MDIO__SPDIF_LOCK 0x1d0 0x4e4 0x000 0x6 0x0 +#define MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1d4 0x4e8 0x000 0x1 0x0 +#define MX6Q_PAD_ENET_REF_CLK__ESAI_RX_FS 0x1d4 0x4e8 0x85c 0x2 0x0 +#define MX6Q_PAD_ENET_REF_CLK__GPIO1_IO23 0x1d4 0x4e8 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_REF_CLK__SPDIF_SR_CLK 0x1d4 0x4e8 0x000 0x6 0x0 +#define MX6Q_PAD_ENET_RX_ER__USB_OTG_ID 0x1d8 0x4ec 0x000 0x0 0x0 +#define MX6Q_PAD_ENET_RX_ER__ENET_RX_ER 0x1d8 0x4ec 0x000 0x1 0x0 +#define MX6Q_PAD_ENET_RX_ER__ESAI_RX_HF_CLK 0x1d8 0x4ec 0x864 0x2 0x0 +#define MX6Q_PAD_ENET_RX_ER__SPDIF_IN 0x1d8 0x4ec 0x914 0x3 0x1 +#define MX6Q_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT 0x1d8 0x4ec 0x000 0x4 0x0 +#define MX6Q_PAD_ENET_RX_ER__GPIO1_IO24 0x1d8 0x4ec 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN 0x1dc 0x4f0 0x858 0x1 0x1 +#define MX6Q_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1dc 0x4f0 0x870 0x2 0x0 +#define MX6Q_PAD_ENET_CRS_DV__SPDIF_EXT_CLK 0x1dc 0x4f0 0x918 0x3 0x1 +#define MX6Q_PAD_ENET_CRS_DV__GPIO1_IO25 0x1dc 0x4f0 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_RXD1__MLB_SIG 0x1e0 0x4f4 0x908 0x0 0x0 +#define MX6Q_PAD_ENET_RXD1__ENET_RX_DATA1 0x1e0 0x4f4 0x84c 0x1 0x1 +#define MX6Q_PAD_ENET_RXD1__ESAI_TX_FS 0x1e0 0x4f4 0x860 0x2 0x0 +#define MX6Q_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT 0x1e0 0x4f4 0x000 0x4 0x0 +#define MX6Q_PAD_ENET_RXD1__GPIO1_IO26 0x1e0 0x4f4 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_RXD0__ENET_RX_DATA0 0x1e4 0x4f8 0x848 0x1 0x1 +#define MX6Q_PAD_ENET_RXD0__ESAI_TX_HF_CLK 0x1e4 0x4f8 0x868 0x2 0x0 +#define MX6Q_PAD_ENET_RXD0__SPDIF_OUT 0x1e4 0x4f8 0x000 0x3 0x0 +#define MX6Q_PAD_ENET_RXD0__GPIO1_IO27 0x1e4 0x4f8 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_TX_EN__ENET_TX_EN 0x1e8 0x4fc 0x000 0x1 0x0 +#define MX6Q_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1e8 0x4fc 0x880 0x2 0x0 +#define MX6Q_PAD_ENET_TX_EN__GPIO1_IO28 0x1e8 0x4fc 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_TXD1__MLB_CLK 0x1ec 0x500 0x900 0x0 0x0 +#define MX6Q_PAD_ENET_TXD1__ENET_TX_DATA1 0x1ec 0x500 0x000 0x1 0x0 +#define MX6Q_PAD_ENET_TXD1__ESAI_TX2_RX3 0x1ec 0x500 0x87c 0x2 0x0 +#define MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN 0x1ec 0x500 0x000 0x4 0x0 +#define MX6Q_PAD_ENET_TXD1__GPIO1_IO29 0x1ec 0x500 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_TXD0__ENET_TX_DATA0 0x1f0 0x504 0x000 0x1 0x0 +#define MX6Q_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1f0 0x504 0x884 0x2 0x0 +#define MX6Q_PAD_ENET_TXD0__GPIO1_IO30 0x1f0 0x504 0x000 0x5 0x0 +#define MX6Q_PAD_ENET_MDC__MLB_DATA 0x1f4 0x508 0x904 0x0 0x0 +#define MX6Q_PAD_ENET_MDC__ENET_MDC 0x1f4 0x508 0x000 0x1 0x0 +#define MX6Q_PAD_ENET_MDC__ESAI_TX5_RX0 0x1f4 0x508 0x888 0x2 0x0 +#define MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN 0x1f4 0x508 0x000 0x4 0x0 +#define MX6Q_PAD_ENET_MDC__GPIO1_IO31 0x1f4 0x508 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_COL0__ECSPI1_SCLK 0x1f8 0x5c8 0x7f4 0x0 0x2 +#define MX6Q_PAD_KEY_COL0__ENET_RX_DATA3 0x1f8 0x5c8 0x854 0x1 0x1 +#define MX6Q_PAD_KEY_COL0__AUD5_TXC 0x1f8 0x5c8 0x7dc 0x2 0x1 +#define MX6Q_PAD_KEY_COL0__KEY_COL0 0x1f8 0x5c8 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_COL0__UART4_TX_DATA 0x1f8 0x5c8 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_COL0__UART4_RX_DATA 0x1f8 0x5c8 0x938 0x4 0x0 +#define MX6Q_PAD_KEY_COL0__GPIO4_IO06 0x1f8 0x5c8 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_COL0__DCIC1_OUT 0x1f8 0x5c8 0x000 0x6 0x0 +#define MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI 0x1fc 0x5cc 0x7fc 0x0 0x2 +#define MX6Q_PAD_KEY_ROW0__ENET_TX_DATA3 0x1fc 0x5cc 0x000 0x1 0x0 +#define MX6Q_PAD_KEY_ROW0__AUD5_TXD 0x1fc 0x5cc 0x7d0 0x2 0x1 +#define MX6Q_PAD_KEY_ROW0__KEY_ROW0 0x1fc 0x5cc 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_ROW0__UART4_RX_DATA 0x1fc 0x5cc 0x938 0x4 0x1 +#define MX6Q_PAD_KEY_ROW0__UART4_TX_DATA 0x1fc 0x5cc 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_ROW0__GPIO4_IO07 0x1fc 0x5cc 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_ROW0__DCIC2_OUT 0x1fc 0x5cc 0x000 0x6 0x0 +#define MX6Q_PAD_KEY_COL1__ECSPI1_MISO 0x200 0x5d0 0x7f8 0x0 0x2 +#define MX6Q_PAD_KEY_COL1__ENET_MDIO 0x200 0x5d0 0x840 0x1 0x1 +#define MX6Q_PAD_KEY_COL1__AUD5_TXFS 0x200 0x5d0 0x7e0 0x2 0x1 +#define MX6Q_PAD_KEY_COL1__KEY_COL1 0x200 0x5d0 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_COL1__UART5_TX_DATA 0x200 0x5d0 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_COL1__UART5_RX_DATA 0x200 0x5d0 0x940 0x4 0x0 +#define MX6Q_PAD_KEY_COL1__GPIO4_IO08 0x200 0x5d0 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_COL1__SD1_VSELECT 0x200 0x5d0 0x000 0x6 0x0 +#define MX6Q_PAD_KEY_ROW1__ECSPI1_SS0 0x204 0x5d4 0x800 0x0 0x2 +#define MX6Q_PAD_KEY_ROW1__ENET_COL 0x204 0x5d4 0x000 0x1 0x0 +#define MX6Q_PAD_KEY_ROW1__AUD5_RXD 0x204 0x5d4 0x7cc 0x2 0x1 +#define MX6Q_PAD_KEY_ROW1__KEY_ROW1 0x204 0x5d4 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_ROW1__UART5_RX_DATA 0x204 0x5d4 0x940 0x4 0x1 +#define MX6Q_PAD_KEY_ROW1__UART5_TX_DATA 0x204 0x5d4 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_ROW1__GPIO4_IO09 0x204 0x5d4 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_ROW1__SD2_VSELECT 0x204 0x5d4 0x000 0x6 0x0 +#define MX6Q_PAD_KEY_COL2__ECSPI1_SS1 0x208 0x5d8 0x804 0x0 0x2 +#define MX6Q_PAD_KEY_COL2__ENET_RX_DATA2 0x208 0x5d8 0x850 0x1 0x1 +#define MX6Q_PAD_KEY_COL2__FLEXCAN1_TX 0x208 0x5d8 0x000 0x2 0x0 +#define MX6Q_PAD_KEY_COL2__KEY_COL2 0x208 0x5d8 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_COL2__ENET_MDC 0x208 0x5d8 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_COL2__GPIO4_IO10 0x208 0x5d8 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_COL2__USB_H1_PWR_CTL_WAKE 0x208 0x5d8 0x000 0x6 0x0 +#define MX6Q_PAD_KEY_ROW2__ECSPI1_SS2 0x20c 0x5dc 0x808 0x0 0x1 +#define MX6Q_PAD_KEY_ROW2__ENET_TX_DATA2 0x20c 0x5dc 0x000 0x1 0x0 +#define MX6Q_PAD_KEY_ROW2__FLEXCAN1_RX 0x20c 0x5dc 0x7e4 0x2 0x0 +#define MX6Q_PAD_KEY_ROW2__KEY_ROW2 0x20c 0x5dc 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_ROW2__SD2_VSELECT 0x20c 0x5dc 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_ROW2__GPIO4_IO11 0x20c 0x5dc 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x20c 0x5dc 0x88c 0x6 0x1 +#define MX6Q_PAD_KEY_COL3__ECSPI1_SS3 0x210 0x5e0 0x80c 0x0 0x1 +#define MX6Q_PAD_KEY_COL3__ENET_CRS 0x210 0x5e0 0x000 0x1 0x0 +#define MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x210 0x5e0 0x890 0x2 0x1 +#define MX6Q_PAD_KEY_COL3__KEY_COL3 0x210 0x5e0 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_COL3__I2C2_SCL 0x210 0x5e0 0x8a0 0x4 0x1 +#define MX6Q_PAD_KEY_COL3__GPIO4_IO12 0x210 0x5e0 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_COL3__SPDIF_IN 0x210 0x5e0 0x914 0x6 0x2 +#define MX6Q_PAD_KEY_ROW3__ASRC_EXT_CLK 0x214 0x5e4 0x7b0 0x1 0x0 +#define MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x214 0x5e4 0x894 0x2 0x1 +#define MX6Q_PAD_KEY_ROW3__KEY_ROW3 0x214 0x5e4 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_ROW3__I2C2_SDA 0x214 0x5e4 0x8a4 0x4 0x1 +#define MX6Q_PAD_KEY_ROW3__GPIO4_IO13 0x214 0x5e4 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_ROW3__SD1_VSELECT 0x214 0x5e4 0x000 0x6 0x0 +#define MX6Q_PAD_KEY_COL4__FLEXCAN2_TX 0x218 0x5e8 0x000 0x0 0x0 +#define MX6Q_PAD_KEY_COL4__IPU1_SISG4 0x218 0x5e8 0x000 0x1 0x0 +#define MX6Q_PAD_KEY_COL4__USB_OTG_OC 0x218 0x5e8 0x944 0x2 0x1 +#define MX6Q_PAD_KEY_COL4__KEY_COL4 0x218 0x5e8 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_COL4__UART5_RTS_B 0x218 0x5e8 0x93c 0x4 0x0 +#define MX6Q_PAD_KEY_COL4__UART5_CTS_B 0x218 0x5e8 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_COL4__GPIO4_IO14 0x218 0x5e8 0x000 0x5 0x0 +#define MX6Q_PAD_KEY_ROW4__FLEXCAN2_RX 0x21c 0x5ec 0x7e8 0x0 0x0 +#define MX6Q_PAD_KEY_ROW4__IPU1_SISG5 0x21c 0x5ec 0x000 0x1 0x0 +#define MX6Q_PAD_KEY_ROW4__USB_OTG_PWR 0x21c 0x5ec 0x000 0x2 0x0 +#define MX6Q_PAD_KEY_ROW4__KEY_ROW4 0x21c 0x5ec 0x000 0x3 0x0 +#define MX6Q_PAD_KEY_ROW4__UART5_CTS_B 0x21c 0x5ec 0x000 0x4 0x0 +#define MX6Q_PAD_KEY_ROW4__UART5_RTS_B 0x21c 0x5ec 0x93c 0x4 0x1 +#define MX6Q_PAD_KEY_ROW4__GPIO4_IO15 0x21c 0x5ec 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_0__CCM_CLKO1 0x220 0x5f0 0x000 0x0 0x0 +#define MX6Q_PAD_GPIO_0__KEY_COL5 0x220 0x5f0 0x8e8 0x2 0x0 +#define MX6Q_PAD_GPIO_0__ASRC_EXT_CLK 0x220 0x5f0 0x7b0 0x3 0x1 +#define MX6Q_PAD_GPIO_0__EPIT1_OUT 0x220 0x5f0 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_0__GPIO1_IO00 0x220 0x5f0 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_0__USB_H1_PWR 0x220 0x5f0 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_0__SNVS_VIO_5 0x220 0x5f0 0x000 0x7 0x0 +#define MX6Q_PAD_GPIO_1__ESAI_RX_CLK 0x224 0x5f4 0x86c 0x0 0x1 +#define MX6Q_PAD_GPIO_1__WDOG2_B 0x224 0x5f4 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_1__KEY_ROW5 0x224 0x5f4 0x8f4 0x2 0x0 +#define MX6Q_PAD_GPIO_1__USB_OTG_ID 0x224 0x5f4 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_1__PWM2_OUT 0x224 0x5f4 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_1__GPIO1_IO01 0x224 0x5f4 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_1__SD1_CD_B 0x224 0x5f4 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_9__ESAI_RX_FS 0x228 0x5f8 0x85c 0x0 0x1 +#define MX6Q_PAD_GPIO_9__WDOG1_B 0x228 0x5f8 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_9__KEY_COL6 0x228 0x5f8 0x8ec 0x2 0x0 +#define MX6Q_PAD_GPIO_9__CCM_REF_EN_B 0x228 0x5f8 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_9__PWM1_OUT 0x228 0x5f8 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_9__GPIO1_IO09 0x228 0x5f8 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_9__SD1_WP 0x228 0x5f8 0x94c 0x6 0x1 +#define MX6Q_PAD_GPIO_3__ESAI_RX_HF_CLK 0x22c 0x5fc 0x864 0x0 0x1 +#define MX6Q_PAD_GPIO_3__I2C3_SCL 0x22c 0x5fc 0x8a8 0x2 0x1 +#define MX6Q_PAD_GPIO_3__XTALOSC_REF_CLK_24M 0x22c 0x5fc 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_3__CCM_CLKO2 0x22c 0x5fc 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_3__GPIO1_IO03 0x22c 0x5fc 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_3__USB_H1_OC 0x22c 0x5fc 0x948 0x6 0x1 +#define MX6Q_PAD_GPIO_3__MLB_CLK 0x22c 0x5fc 0x900 0x7 0x1 +#define MX6Q_PAD_GPIO_6__ESAI_TX_CLK 0x230 0x600 0x870 0x0 0x1 +#define MX6Q_PAD_GPIO_6__I2C3_SDA 0x230 0x600 0x8ac 0x2 0x1 +#define MX6Q_PAD_GPIO_6__GPIO1_IO06 0x230 0x600 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_6__SD2_LCTL 0x230 0x600 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_6__MLB_SIG 0x230 0x600 0x908 0x7 0x1 +#define MX6Q_PAD_GPIO_2__ESAI_TX_FS 0x234 0x604 0x860 0x0 0x1 +#define MX6Q_PAD_GPIO_2__KEY_ROW6 0x234 0x604 0x8f8 0x2 0x1 +#define MX6Q_PAD_GPIO_2__GPIO1_IO02 0x234 0x604 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_2__SD2_WP 0x234 0x604 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_2__MLB_DATA 0x234 0x604 0x904 0x7 0x1 +#define MX6Q_PAD_GPIO_4__ESAI_TX_HF_CLK 0x238 0x608 0x868 0x0 0x1 +#define MX6Q_PAD_GPIO_4__KEY_COL7 0x238 0x608 0x8f0 0x2 0x1 +#define MX6Q_PAD_GPIO_4__GPIO1_IO04 0x238 0x608 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_4__SD2_CD_B 0x238 0x608 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_5__ESAI_TX2_RX3 0x23c 0x60c 0x87c 0x0 0x1 +#define MX6Q_PAD_GPIO_5__KEY_ROW7 0x23c 0x60c 0x8fc 0x2 0x1 +#define MX6Q_PAD_GPIO_5__CCM_CLKO1 0x23c 0x60c 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_5__GPIO1_IO05 0x23c 0x60c 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_5__I2C3_SCL 0x23c 0x60c 0x8a8 0x6 0x2 +#define MX6Q_PAD_GPIO_5__ARM_EVENTI 0x23c 0x60c 0x000 0x7 0x0 +#define MX6Q_PAD_GPIO_7__ESAI_TX4_RX1 0x240 0x610 0x884 0x0 0x1 +#define MX6Q_PAD_GPIO_7__ECSPI5_RDY 0x240 0x610 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_7__EPIT1_OUT 0x240 0x610 0x000 0x2 0x0 +#define MX6Q_PAD_GPIO_7__FLEXCAN1_TX 0x240 0x610 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_7__UART2_TX_DATA 0x240 0x610 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_7__UART2_RX_DATA 0x240 0x610 0x928 0x4 0x2 +#define MX6Q_PAD_GPIO_7__GPIO1_IO07 0x240 0x610 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_7__SPDIF_LOCK 0x240 0x610 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_7__USB_OTG_HOST_MODE 0x240 0x610 0x000 0x7 0x0 +#define MX6Q_PAD_GPIO_8__ESAI_TX5_RX0 0x244 0x614 0x888 0x0 0x1 +#define MX6Q_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x244 0x614 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_8__EPIT2_OUT 0x244 0x614 0x000 0x2 0x0 +#define MX6Q_PAD_GPIO_8__FLEXCAN1_RX 0x244 0x614 0x7e4 0x3 0x1 +#define MX6Q_PAD_GPIO_8__UART2_RX_DATA 0x244 0x614 0x928 0x4 0x3 +#define MX6Q_PAD_GPIO_8__UART2_TX_DATA 0x244 0x614 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_8__GPIO1_IO08 0x244 0x614 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_8__SPDIF_SR_CLK 0x244 0x614 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_8__USB_OTG_PWR_CTL_WAKE 0x244 0x614 0x000 0x7 0x0 +#define MX6Q_PAD_GPIO_16__ESAI_TX3_RX2 0x248 0x618 0x880 0x0 0x1 +#define MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN 0x248 0x618 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_16__ENET_REF_CLK 0x248 0x618 0x83c 0x2 0x1 +#define MX6Q_PAD_GPIO_16__SD1_LCTL 0x248 0x618 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_16__SPDIF_IN 0x248 0x618 0x914 0x4 0x3 +#define MX6Q_PAD_GPIO_16__GPIO7_IO11 0x248 0x618 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_16__I2C3_SDA 0x248 0x618 0x8ac 0x6 0x2 +#define MX6Q_PAD_GPIO_16__JTAG_DE_B 0x248 0x618 0x000 0x7 0x0 +#define MX6Q_PAD_GPIO_17__ESAI_TX0 0x24c 0x61c 0x874 0x0 0x0 +#define MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN 0x24c 0x61c 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_17__CCM_PMIC_READY 0x24c 0x61c 0x7f0 0x2 0x1 +#define MX6Q_PAD_GPIO_17__SDMA_EXT_EVENT0 0x24c 0x61c 0x90c 0x3 0x1 +#define MX6Q_PAD_GPIO_17__SPDIF_OUT 0x24c 0x61c 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_17__GPIO7_IO12 0x24c 0x61c 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_18__ESAI_TX1 0x250 0x620 0x878 0x0 0x0 +#define MX6Q_PAD_GPIO_18__ENET_RX_CLK 0x250 0x620 0x844 0x1 0x1 +#define MX6Q_PAD_GPIO_18__SD3_VSELECT 0x250 0x620 0x000 0x2 0x0 +#define MX6Q_PAD_GPIO_18__SDMA_EXT_EVENT1 0x250 0x620 0x910 0x3 0x1 +#define MX6Q_PAD_GPIO_18__ASRC_EXT_CLK 0x250 0x620 0x7b0 0x4 0x2 +#define MX6Q_PAD_GPIO_18__GPIO7_IO13 0x250 0x620 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_18__SNVS_VIO_5_CTL 0x250 0x620 0x000 0x6 0x0 +#define MX6Q_PAD_GPIO_19__KEY_COL5 0x254 0x624 0x8e8 0x0 0x1 +#define MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT 0x254 0x624 0x000 0x1 0x0 +#define MX6Q_PAD_GPIO_19__SPDIF_OUT 0x254 0x624 0x000 0x2 0x0 +#define MX6Q_PAD_GPIO_19__CCM_CLKO1 0x254 0x624 0x000 0x3 0x0 +#define MX6Q_PAD_GPIO_19__ECSPI1_RDY 0x254 0x624 0x000 0x4 0x0 +#define MX6Q_PAD_GPIO_19__GPIO4_IO05 0x254 0x624 0x000 0x5 0x0 +#define MX6Q_PAD_GPIO_19__ENET_TX_ER 0x254 0x624 0x000 0x6 0x0 +#define MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x258 0x628 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_PIXCLK__GPIO5_IO18 0x258 0x628 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_PIXCLK__ARM_EVENTO 0x258 0x628 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x25c 0x62c 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_MCLK__CCM_CLKO1 0x25c 0x62c 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_MCLK__GPIO5_IO19 0x25c 0x62c 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_MCLK__ARM_TRACE_CTL 0x25c 0x62c 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x260 0x630 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DATA_EN__EIM_DATA00 0x260 0x630 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DATA_EN__GPIO5_IO20 0x260 0x630 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DATA_EN__ARM_TRACE_CLK 0x260 0x630 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x264 0x634 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_VSYNC__EIM_DATA01 0x264 0x634 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_VSYNC__GPIO5_IO21 0x264 0x634 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_VSYNC__ARM_TRACE00 0x264 0x634 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_DATA04 0x268 0x638 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT4__EIM_DATA02 0x268 0x638 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK 0x268 0x638 0x7f4 0x2 0x3 +#define MX6Q_PAD_CSI0_DAT4__KEY_COL5 0x268 0x638 0x8e8 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT4__AUD3_TXC 0x268 0x638 0x000 0x4 0x0 +#define MX6Q_PAD_CSI0_DAT4__GPIO5_IO22 0x268 0x638 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT4__ARM_TRACE01 0x268 0x638 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_DATA05 0x26c 0x63c 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT5__EIM_DATA03 0x26c 0x63c 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI 0x26c 0x63c 0x7fc 0x2 0x3 +#define MX6Q_PAD_CSI0_DAT5__KEY_ROW5 0x26c 0x63c 0x8f4 0x3 0x1 +#define MX6Q_PAD_CSI0_DAT5__AUD3_TXD 0x26c 0x63c 0x000 0x4 0x0 +#define MX6Q_PAD_CSI0_DAT5__GPIO5_IO23 0x26c 0x63c 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT5__ARM_TRACE02 0x26c 0x63c 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_DATA06 0x270 0x640 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT6__EIM_DATA04 0x270 0x640 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO 0x270 0x640 0x7f8 0x2 0x3 +#define MX6Q_PAD_CSI0_DAT6__KEY_COL6 0x270 0x640 0x8ec 0x3 0x1 +#define MX6Q_PAD_CSI0_DAT6__AUD3_TXFS 0x270 0x640 0x000 0x4 0x0 +#define MX6Q_PAD_CSI0_DAT6__GPIO5_IO24 0x270 0x640 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT6__ARM_TRACE03 0x270 0x640 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_DATA07 0x274 0x644 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT7__EIM_DATA05 0x274 0x644 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0 0x274 0x644 0x800 0x2 0x3 +#define MX6Q_PAD_CSI0_DAT7__KEY_ROW6 0x274 0x644 0x8f8 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT7__AUD3_RXD 0x274 0x644 0x000 0x4 0x0 +#define MX6Q_PAD_CSI0_DAT7__GPIO5_IO25 0x274 0x644 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT7__ARM_TRACE04 0x274 0x644 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_DATA08 0x278 0x648 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT8__EIM_DATA06 0x278 0x648 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK 0x278 0x648 0x810 0x2 0x2 +#define MX6Q_PAD_CSI0_DAT8__KEY_COL7 0x278 0x648 0x8f0 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT8__I2C1_SDA 0x278 0x648 0x89c 0x4 0x1 +#define MX6Q_PAD_CSI0_DAT8__GPIO5_IO26 0x278 0x648 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT8__ARM_TRACE05 0x278 0x648 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_DATA09 0x27c 0x64c 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT9__EIM_DATA07 0x27c 0x64c 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI 0x27c 0x64c 0x818 0x2 0x2 +#define MX6Q_PAD_CSI0_DAT9__KEY_ROW7 0x27c 0x64c 0x8fc 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT9__I2C1_SCL 0x27c 0x64c 0x898 0x4 0x1 +#define MX6Q_PAD_CSI0_DAT9__GPIO5_IO27 0x27c 0x64c 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT9__ARM_TRACE06 0x27c 0x64c 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_DATA10 0x280 0x650 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT10__AUD3_RXC 0x280 0x650 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO 0x280 0x650 0x814 0x2 0x2 +#define MX6Q_PAD_CSI0_DAT10__UART1_TX_DATA 0x280 0x650 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT10__UART1_RX_DATA 0x280 0x650 0x920 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT10__GPIO5_IO28 0x280 0x650 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT10__ARM_TRACE07 0x280 0x650 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_DATA11 0x284 0x654 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT11__AUD3_RXFS 0x284 0x654 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0 0x284 0x654 0x81c 0x2 0x2 +#define MX6Q_PAD_CSI0_DAT11__UART1_RX_DATA 0x284 0x654 0x920 0x3 0x1 +#define MX6Q_PAD_CSI0_DAT11__UART1_TX_DATA 0x284 0x654 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT11__GPIO5_IO29 0x284 0x654 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT11__ARM_TRACE08 0x284 0x654 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x288 0x658 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT12__EIM_DATA08 0x288 0x658 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT12__UART4_TX_DATA 0x288 0x658 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT12__UART4_RX_DATA 0x288 0x658 0x938 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT12__GPIO5_IO30 0x288 0x658 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT12__ARM_TRACE09 0x288 0x658 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x28c 0x65c 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT13__EIM_DATA09 0x28c 0x65c 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT13__UART4_RX_DATA 0x28c 0x65c 0x938 0x3 0x3 +#define MX6Q_PAD_CSI0_DAT13__UART4_TX_DATA 0x28c 0x65c 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT13__GPIO5_IO31 0x28c 0x65c 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT13__ARM_TRACE10 0x28c 0x65c 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x290 0x660 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT14__EIM_DATA10 0x290 0x660 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT14__UART5_TX_DATA 0x290 0x660 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT14__UART5_RX_DATA 0x290 0x660 0x940 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT14__GPIO6_IO00 0x290 0x660 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT14__ARM_TRACE11 0x290 0x660 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x294 0x664 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT15__EIM_DATA11 0x294 0x664 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT15__UART5_RX_DATA 0x294 0x664 0x940 0x3 0x3 +#define MX6Q_PAD_CSI0_DAT15__UART5_TX_DATA 0x294 0x664 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT15__GPIO6_IO01 0x294 0x664 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT15__ARM_TRACE12 0x294 0x664 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x298 0x668 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT16__EIM_DATA12 0x298 0x668 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT16__UART4_RTS_B 0x298 0x668 0x934 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT16__UART4_CTS_B 0x298 0x668 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT16__GPIO6_IO02 0x298 0x668 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT16__ARM_TRACE13 0x298 0x668 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x29c 0x66c 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT17__EIM_DATA13 0x29c 0x66c 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT17__UART4_CTS_B 0x29c 0x66c 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT17__UART4_RTS_B 0x29c 0x66c 0x934 0x3 0x1 +#define MX6Q_PAD_CSI0_DAT17__GPIO6_IO03 0x29c 0x66c 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT17__ARM_TRACE14 0x29c 0x66c 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x2a0 0x670 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT18__EIM_DATA14 0x2a0 0x670 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT18__UART5_RTS_B 0x2a0 0x670 0x93c 0x3 0x2 +#define MX6Q_PAD_CSI0_DAT18__UART5_CTS_B 0x2a0 0x670 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT18__GPIO6_IO04 0x2a0 0x670 0x000 0x5 0x0 +#define MX6Q_PAD_CSI0_DAT18__ARM_TRACE15 0x2a0 0x670 0x000 0x7 0x0 +#define MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x2a4 0x674 0x000 0x0 0x0 +#define MX6Q_PAD_CSI0_DAT19__EIM_DATA15 0x2a4 0x674 0x000 0x1 0x0 +#define MX6Q_PAD_CSI0_DAT19__UART5_CTS_B 0x2a4 0x674 0x000 0x3 0x0 +#define MX6Q_PAD_CSI0_DAT19__UART5_RTS_B 0x2a4 0x674 0x93c 0x3 0x3 +#define MX6Q_PAD_CSI0_DAT19__GPIO6_IO05 0x2a4 0x674 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT7__SD3_DATA7 0x2a8 0x690 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT7__UART1_TX_DATA 0x2a8 0x690 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT7__UART1_RX_DATA 0x2a8 0x690 0x920 0x1 0x2 +#define MX6Q_PAD_SD3_DAT7__GPIO6_IO17 0x2a8 0x690 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT6__SD3_DATA6 0x2ac 0x694 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT6__UART1_RX_DATA 0x2ac 0x694 0x920 0x1 0x3 +#define MX6Q_PAD_SD3_DAT6__UART1_TX_DATA 0x2ac 0x694 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT6__GPIO6_IO18 0x2ac 0x694 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT5__SD3_DATA5 0x2b0 0x698 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT5__UART2_TX_DATA 0x2b0 0x698 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT5__UART2_RX_DATA 0x2b0 0x698 0x928 0x1 0x4 +#define MX6Q_PAD_SD3_DAT5__GPIO7_IO00 0x2b0 0x698 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT4__SD3_DATA4 0x2b4 0x69c 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT4__UART2_RX_DATA 0x2b4 0x69c 0x928 0x1 0x5 +#define MX6Q_PAD_SD3_DAT4__UART2_TX_DATA 0x2b4 0x69c 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT4__GPIO7_IO01 0x2b4 0x69c 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_CMD__SD3_CMD 0x2b8 0x6a0 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_CMD__UART2_CTS_B 0x2b8 0x6a0 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_CMD__UART2_RTS_B 0x2b8 0x6a0 0x924 0x1 0x2 +#define MX6Q_PAD_SD3_CMD__FLEXCAN1_TX 0x2b8 0x6a0 0x000 0x2 0x0 +#define MX6Q_PAD_SD3_CMD__GPIO7_IO02 0x2b8 0x6a0 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_CLK__SD3_CLK 0x2bc 0x6a4 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_CLK__UART2_RTS_B 0x2bc 0x6a4 0x924 0x1 0x3 +#define MX6Q_PAD_SD3_CLK__UART2_CTS_B 0x2bc 0x6a4 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_CLK__FLEXCAN1_RX 0x2bc 0x6a4 0x7e4 0x2 0x2 +#define MX6Q_PAD_SD3_CLK__GPIO7_IO03 0x2bc 0x6a4 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT0__SD3_DATA0 0x2c0 0x6a8 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT0__UART1_CTS_B 0x2c0 0x6a8 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT0__UART1_RTS_B 0x2c0 0x6a8 0x91c 0x1 0x2 +#define MX6Q_PAD_SD3_DAT0__FLEXCAN2_TX 0x2c0 0x6a8 0x000 0x2 0x0 +#define MX6Q_PAD_SD3_DAT0__GPIO7_IO04 0x2c0 0x6a8 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT1__SD3_DATA1 0x2c4 0x6ac 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT1__UART1_RTS_B 0x2c4 0x6ac 0x91c 0x1 0x3 +#define MX6Q_PAD_SD3_DAT1__UART1_CTS_B 0x2c4 0x6ac 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT1__FLEXCAN2_RX 0x2c4 0x6ac 0x7e8 0x2 0x1 +#define MX6Q_PAD_SD3_DAT1__GPIO7_IO05 0x2c4 0x6ac 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT2__SD3_DATA2 0x2c8 0x6b0 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT2__GPIO7_IO06 0x2c8 0x6b0 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_DAT3__SD3_DATA3 0x2cc 0x6b4 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_DAT3__UART3_CTS_B 0x2cc 0x6b4 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_DAT3__UART3_RTS_B 0x2cc 0x6b4 0x92c 0x1 0x4 +#define MX6Q_PAD_SD3_DAT3__GPIO7_IO07 0x2cc 0x6b4 0x000 0x5 0x0 +#define MX6Q_PAD_SD3_RST__SD3_RESET 0x2d0 0x6b8 0x000 0x0 0x0 +#define MX6Q_PAD_SD3_RST__UART3_RTS_B 0x2d0 0x6b8 0x92c 0x1 0x5 +#define MX6Q_PAD_SD3_RST__UART3_CTS_B 0x2d0 0x6b8 0x000 0x1 0x0 +#define MX6Q_PAD_SD3_RST__GPIO7_IO08 0x2d0 0x6b8 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_CLE__NAND_CLE 0x2d4 0x6bc 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_CLE__IPU2_SISG4 0x2d4 0x6bc 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_CLE__GPIO6_IO07 0x2d4 0x6bc 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_ALE__NAND_ALE 0x2d8 0x6c0 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_ALE__SD4_RESET 0x2d8 0x6c0 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_ALE__GPIO6_IO08 0x2d8 0x6c0 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_WP_B__NAND_WP_B 0x2dc 0x6c4 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_WP_B__IPU2_SISG5 0x2dc 0x6c4 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_WP_B__GPIO6_IO09 0x2dc 0x6c4 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_RB0__NAND_READY_B 0x2e0 0x6c8 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN01 0x2e0 0x6c8 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_RB0__GPIO6_IO10 0x2e0 0x6c8 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_CS0__NAND_CE0_B 0x2e4 0x6cc 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_CS0__GPIO6_IO11 0x2e4 0x6cc 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_CS1__NAND_CE1_B 0x2e8 0x6d0 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_CS1__SD4_VSELECT 0x2e8 0x6d0 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_CS1__SD3_VSELECT 0x2e8 0x6d0 0x000 0x2 0x0 +#define MX6Q_PAD_NANDF_CS1__GPIO6_IO14 0x2e8 0x6d0 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_CS2__NAND_CE2_B 0x2ec 0x6d4 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_CS2__IPU1_SISG0 0x2ec 0x6d4 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_CS2__ESAI_TX0 0x2ec 0x6d4 0x874 0x2 0x1 +#define MX6Q_PAD_NANDF_CS2__EIM_CRE 0x2ec 0x6d4 0x000 0x3 0x0 +#define MX6Q_PAD_NANDF_CS2__CCM_CLKO2 0x2ec 0x6d4 0x000 0x4 0x0 +#define MX6Q_PAD_NANDF_CS2__GPIO6_IO15 0x2ec 0x6d4 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_CS2__IPU2_SISG0 0x2ec 0x6d4 0x000 0x6 0x0 +#define MX6Q_PAD_NANDF_CS3__NAND_CE3_B 0x2f0 0x6d8 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_CS3__IPU1_SISG1 0x2f0 0x6d8 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_CS3__ESAI_TX1 0x2f0 0x6d8 0x878 0x2 0x1 +#define MX6Q_PAD_NANDF_CS3__EIM_ADDR26 0x2f0 0x6d8 0x000 0x3 0x0 +#define MX6Q_PAD_NANDF_CS3__GPIO6_IO16 0x2f0 0x6d8 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_CS3__IPU2_SISG1 0x2f0 0x6d8 0x000 0x6 0x0 +#define MX6Q_PAD_SD4_CMD__SD4_CMD 0x2f4 0x6dc 0x000 0x0 0x0 +#define MX6Q_PAD_SD4_CMD__NAND_RE_B 0x2f4 0x6dc 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_CMD__UART3_TX_DATA 0x2f4 0x6dc 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_CMD__UART3_RX_DATA 0x2f4 0x6dc 0x930 0x2 0x2 +#define MX6Q_PAD_SD4_CMD__GPIO7_IO09 0x2f4 0x6dc 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_CLK__SD4_CLK 0x2f8 0x6e0 0x000 0x0 0x0 +#define MX6Q_PAD_SD4_CLK__NAND_WE_B 0x2f8 0x6e0 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_CLK__UART3_RX_DATA 0x2f8 0x6e0 0x930 0x2 0x3 +#define MX6Q_PAD_SD4_CLK__UART3_TX_DATA 0x2f8 0x6e0 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_CLK__GPIO7_IO10 0x2f8 0x6e0 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D0__NAND_DATA00 0x2fc 0x6e4 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D0__SD1_DATA4 0x2fc 0x6e4 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D0__GPIO2_IO00 0x2fc 0x6e4 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D1__NAND_DATA01 0x300 0x6e8 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D1__SD1_DATA5 0x300 0x6e8 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D1__GPIO2_IO01 0x300 0x6e8 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D2__NAND_DATA02 0x304 0x6ec 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D2__SD1_DATA6 0x304 0x6ec 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D2__GPIO2_IO02 0x304 0x6ec 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D3__NAND_DATA03 0x308 0x6f0 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D3__SD1_DATA7 0x308 0x6f0 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D3__GPIO2_IO03 0x308 0x6f0 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D4__NAND_DATA04 0x30c 0x6f4 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D4__SD2_DATA4 0x30c 0x6f4 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D4__GPIO2_IO04 0x30c 0x6f4 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D5__NAND_DATA05 0x310 0x6f8 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D5__SD2_DATA5 0x310 0x6f8 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D5__GPIO2_IO05 0x310 0x6f8 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D6__NAND_DATA06 0x314 0x6fc 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D6__SD2_DATA6 0x314 0x6fc 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D6__GPIO2_IO06 0x314 0x6fc 0x000 0x5 0x0 +#define MX6Q_PAD_NANDF_D7__NAND_DATA07 0x318 0x700 0x000 0x0 0x0 +#define MX6Q_PAD_NANDF_D7__SD2_DATA7 0x318 0x700 0x000 0x1 0x0 +#define MX6Q_PAD_NANDF_D7__GPIO2_IO07 0x318 0x700 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT0__SD4_DATA0 0x31c 0x704 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT0__NAND_DQS 0x31c 0x704 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT0__GPIO2_IO08 0x31c 0x704 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT1__SD4_DATA1 0x320 0x708 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT1__PWM3_OUT 0x320 0x708 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT1__GPIO2_IO09 0x320 0x708 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT2__SD4_DATA2 0x324 0x70c 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT2__PWM4_OUT 0x324 0x70c 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT2__GPIO2_IO10 0x324 0x70c 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT3__SD4_DATA3 0x328 0x710 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT3__GPIO2_IO11 0x328 0x710 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT4__SD4_DATA4 0x32c 0x714 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT4__UART2_RX_DATA 0x32c 0x714 0x928 0x2 0x6 +#define MX6Q_PAD_SD4_DAT4__UART2_TX_DATA 0x32c 0x714 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT4__GPIO2_IO12 0x32c 0x714 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT5__SD4_DATA5 0x330 0x718 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT5__UART2_RTS_B 0x330 0x718 0x924 0x2 0x4 +#define MX6Q_PAD_SD4_DAT5__UART2_CTS_B 0x330 0x718 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT5__GPIO2_IO13 0x330 0x718 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT6__SD4_DATA6 0x334 0x71c 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT6__UART2_CTS_B 0x334 0x71c 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT6__UART2_RTS_B 0x334 0x71c 0x924 0x2 0x5 +#define MX6Q_PAD_SD4_DAT6__GPIO2_IO14 0x334 0x71c 0x000 0x5 0x0 +#define MX6Q_PAD_SD4_DAT7__SD4_DATA7 0x338 0x720 0x000 0x1 0x0 +#define MX6Q_PAD_SD4_DAT7__UART2_TX_DATA 0x338 0x720 0x000 0x2 0x0 +#define MX6Q_PAD_SD4_DAT7__UART2_RX_DATA 0x338 0x720 0x928 0x2 0x7 +#define MX6Q_PAD_SD4_DAT7__GPIO2_IO15 0x338 0x720 0x000 0x5 0x0 +#define MX6Q_PAD_SD1_DAT1__SD1_DATA1 0x33c 0x724 0x000 0x0 0x0 +#define MX6Q_PAD_SD1_DAT1__ECSPI5_SS0 0x33c 0x724 0x834 0x1 0x1 +#define MX6Q_PAD_SD1_DAT1__PWM3_OUT 0x33c 0x724 0x000 0x2 0x0 +#define MX6Q_PAD_SD1_DAT1__GPT_CAPTURE2 0x33c 0x724 0x000 0x3 0x0 +#define MX6Q_PAD_SD1_DAT1__GPIO1_IO17 0x33c 0x724 0x000 0x5 0x0 +#define MX6Q_PAD_SD1_DAT0__SD1_DATA0 0x340 0x728 0x000 0x0 0x0 +#define MX6Q_PAD_SD1_DAT0__ECSPI5_MISO 0x340 0x728 0x82c 0x1 0x1 +#define MX6Q_PAD_SD1_DAT0__GPT_CAPTURE1 0x340 0x728 0x000 0x3 0x0 +#define MX6Q_PAD_SD1_DAT0__GPIO1_IO16 0x340 0x728 0x000 0x5 0x0 +#define MX6Q_PAD_SD1_DAT3__SD1_DATA3 0x344 0x72c 0x000 0x0 0x0 +#define MX6Q_PAD_SD1_DAT3__ECSPI5_SS2 0x344 0x72c 0x000 0x1 0x0 +#define MX6Q_PAD_SD1_DAT3__GPT_COMPARE3 0x344 0x72c 0x000 0x2 0x0 +#define MX6Q_PAD_SD1_DAT3__PWM1_OUT 0x344 0x72c 0x000 0x3 0x0 +#define MX6Q_PAD_SD1_DAT3__WDOG2_B 0x344 0x72c 0x000 0x4 0x0 +#define MX6Q_PAD_SD1_DAT3__GPIO1_IO21 0x344 0x72c 0x000 0x5 0x0 +#define MX6Q_PAD_SD1_DAT3__WDOG2_RESET_B_DEB 0x344 0x72c 0x000 0x6 0x0 +#define MX6Q_PAD_SD1_CMD__SD1_CMD 0x348 0x730 0x000 0x0 0x0 +#define MX6Q_PAD_SD1_CMD__ECSPI5_MOSI 0x348 0x730 0x830 0x1 0x0 +#define MX6Q_PAD_SD1_CMD__PWM4_OUT 0x348 0x730 0x000 0x2 0x0 +#define MX6Q_PAD_SD1_CMD__GPT_COMPARE1 0x348 0x730 0x000 0x3 0x0 +#define MX6Q_PAD_SD1_CMD__GPIO1_IO18 0x348 0x730 0x000 0x5 0x0 +#define MX6Q_PAD_SD1_DAT2__SD1_DATA2 0x34c 0x734 0x000 0x0 0x0 +#define MX6Q_PAD_SD1_DAT2__ECSPI5_SS1 0x34c 0x734 0x838 0x1 0x1 +#define MX6Q_PAD_SD1_DAT2__GPT_COMPARE2 0x34c 0x734 0x000 0x2 0x0 +#define MX6Q_PAD_SD1_DAT2__PWM2_OUT 0x34c 0x734 0x000 0x3 0x0 +#define MX6Q_PAD_SD1_DAT2__WDOG1_B 0x34c 0x734 0x000 0x4 0x0 +#define MX6Q_PAD_SD1_DAT2__GPIO1_IO19 0x34c 0x734 0x000 0x5 0x0 +#define MX6Q_PAD_SD1_DAT2__WDOG1_RESET_B_DEB 0x34c 0x734 0x000 0x6 0x0 +#define MX6Q_PAD_SD1_CLK__SD1_CLK 0x350 0x738 0x000 0x0 0x0 +#define MX6Q_PAD_SD1_CLK__ECSPI5_SCLK 0x350 0x738 0x828 0x1 0x0 +#define MX6Q_PAD_SD1_CLK__GPT_CLKIN 0x350 0x738 0x000 0x3 0x0 +#define MX6Q_PAD_SD1_CLK__GPIO1_IO20 0x350 0x738 0x000 0x5 0x0 +#define MX6Q_PAD_SD2_CLK__SD2_CLK 0x354 0x73c 0x000 0x0 0x0 +#define MX6Q_PAD_SD2_CLK__ECSPI5_SCLK 0x354 0x73c 0x828 0x1 0x1 +#define MX6Q_PAD_SD2_CLK__KEY_COL5 0x354 0x73c 0x8e8 0x2 0x3 +#define MX6Q_PAD_SD2_CLK__AUD4_RXFS 0x354 0x73c 0x7c0 0x3 0x1 +#define MX6Q_PAD_SD2_CLK__GPIO1_IO10 0x354 0x73c 0x000 0x5 0x0 +#define MX6Q_PAD_SD2_CMD__SD2_CMD 0x358 0x740 0x000 0x0 0x0 +#define MX6Q_PAD_SD2_CMD__ECSPI5_MOSI 0x358 0x740 0x830 0x1 0x1 +#define MX6Q_PAD_SD2_CMD__KEY_ROW5 0x358 0x740 0x8f4 0x2 0x2 +#define MX6Q_PAD_SD2_CMD__AUD4_RXC 0x358 0x740 0x7bc 0x3 0x1 +#define MX6Q_PAD_SD2_CMD__GPIO1_IO11 0x358 0x740 0x000 0x5 0x0 +#define MX6Q_PAD_SD2_DAT3__SD2_DATA3 0x35c 0x744 0x000 0x0 0x0 +#define MX6Q_PAD_SD2_DAT3__ECSPI5_SS3 0x35c 0x744 0x000 0x1 0x0 +#define MX6Q_PAD_SD2_DAT3__KEY_COL6 0x35c 0x744 0x8ec 0x2 0x2 +#define MX6Q_PAD_SD2_DAT3__AUD4_TXC 0x35c 0x744 0x7c4 0x3 0x1 +#define MX6Q_PAD_SD2_DAT3__GPIO1_IO12 0x35c 0x744 0x000 0x5 0x0 + +#endif /* __DTS_IMX6Q_PINFUNC_H */ diff --git a/arch/arm/dts/imx6q-sabrelite.dts b/arch/arm/dts/imx6q-sabrelite.dts new file mode 100644 index 0000000000..483a39d9a1 --- /dev/null +++ b/arch/arm/dts/imx6q-sabrelite.dts @@ -0,0 +1,174 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +#include "imx6q.dtsi" + +/ { + model = "Freescale i.MX6 Quad SABRE Lite Board"; + compatible = "fsl,imx6q-sabrelite", "fsl,imx6q"; + + chosen { + linux,stdout-path = "/soc/aips-bus@02100000/serial@021e8000"; + }; + + memory { + reg = <0x10000000 0x40000000>; + }; + + regulators { + compatible = "simple-bus"; + + reg_2p5v: 2p5v { + compatible = "regulator-fixed"; + regulator-name = "2P5V"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3p3v: 3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_usb_otg_vbus: usb_otg_vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 22 0>; + enable-active-high; + }; + }; + + sound { + compatible = "fsl,imx6q-sabrelite-sgtl5000", + "fsl,imx-audio-sgtl5000"; + model = "imx6q-sabrelite-sgtl5000"; + ssi-controller = <&ssi1>; + audio-codec = <&codec>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <4>; + }; +}; + +&ecspi1 { + fsl,spi-num-chipselects = <1>; + cs-gpios = <&gpio3 19 0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1_1>; + status = "okay"; + + flash: m25p80@0 { + compatible = "sst,sst25vf016b", "m25p80"; + spi-max-frequency = <20000000>; + reg = <0>; + }; +}; + +&ssi1 { + fsl,mode = "i2s-slave"; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + hog { + pinctrl_hog: hoggrp { + fsl,pins = < + MX6Q_PAD_NANDF_D6__GPIO2_IO06 0x80000000 + MX6Q_PAD_NANDF_D7__GPIO2_IO07 0x80000000 + MX6Q_PAD_EIM_D19__GPIO3_IO19 0x80000000 + MX6Q_PAD_EIM_D22__GPIO3_IO22 0x80000000 + MX6Q_PAD_EIM_D23__GPIO3_IO23 0x80000000 + MX6Q_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 + MX6Q_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 + MX6Q_PAD_GPIO_0__CCM_CLKO1 0x80000000 + >; + }; + }; +}; + +&usbotg { + vbus-supply = <®_usb_otg_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg_1>; + disable-over-current; + status = "okay"; +}; + +&usbh1 { + status = "okay"; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet_1>; + phy-mode = "rgmii"; + phy-reset-gpios = <&gpio3 23 0>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3_2>; + cd-gpios = <&gpio7 0 0>; + wp-gpios = <&gpio7 1 0>; + vmmc-supply = <®_3p3v>; + status = "okay"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4_2>; + cd-gpios = <&gpio2 6 0>; + wp-gpios = <&gpio2 7 0>; + vmmc-supply = <®_3p3v>; + status = "okay"; +}; + +&audmux { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux_1>; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2_1>; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_1>; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + clocks = <&clks 169>; + VDDA-supply = <®_2p5v>; + VDDIO-supply = <®_3p3v>; + }; +}; diff --git a/arch/arm/dts/imx6q-sabresd.dts b/arch/arm/dts/imx6q-sabresd.dts new file mode 100644 index 0000000000..1b64ad1c31 --- /dev/null +++ b/arch/arm/dts/imx6q-sabresd.dts @@ -0,0 +1,43 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-sabresd.dtsi" + +/ { + model = "Freescale i.MX6 Quad SABRE Smart Device Board"; + compatible = "fsl,imx6q-sabresd", "fsl,imx6q"; + + chosen { + linux,stdout-path = "/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000"; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + hog { + pinctrl_hog: hoggrp { + fsl,pins = < + MX6Q_PAD_GPIO_4__GPIO1_IO04 0x80000000 + MX6Q_PAD_GPIO_5__GPIO1_IO05 0x80000000 + MX6Q_PAD_NANDF_D0__GPIO2_IO00 0x80000000 + MX6Q_PAD_NANDF_D1__GPIO2_IO01 0x80000000 + MX6Q_PAD_NANDF_D2__GPIO2_IO02 0x80000000 + MX6Q_PAD_NANDF_D3__GPIO2_IO03 0x80000000 + >; + }; + }; +}; diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi new file mode 100644 index 0000000000..21e675848b --- /dev/null +++ b/arch/arm/dts/imx6q.dtsi @@ -0,0 +1,358 @@ + +/* + * Copyright 2013 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 "imx6qdl.dtsi" +#include "imx6q-pinfunc.h" + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a9"; + reg = <0>; + next-level-cache = <&L2>; + operating-points = < + /* kHz uV */ + 1200000 1275000 + 996000 1250000 + 792000 1150000 + 396000 950000 + >; + clock-latency = <61036>; /* two CLK32 periods */ + clocks = <&clks 104>, <&clks 6>, <&clks 16>, + <&clks 17>, <&clks 170>; + clock-names = "arm", "pll2_pfd2_396m", "step", + "pll1_sw", "pll1_sys"; + arm-supply = <®_arm>; + pu-supply = <®_pu>; + soc-supply = <®_soc>; + }; + + cpu@1 { + compatible = "arm,cortex-a9"; + reg = <1>; + next-level-cache = <&L2>; + }; + + cpu@2 { + compatible = "arm,cortex-a9"; + reg = <2>; + next-level-cache = <&L2>; + }; + + cpu@3 { + compatible = "arm,cortex-a9"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; + + soc { + aips-bus@02000000 { /* AIPS1 */ + spba-bus@02000000 { + ecspi5: ecspi@02018000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02018000 0x4000>; + interrupts = <0 35 0x04>; + clocks = <&clks 116>, <&clks 116>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + }; + + iomuxc: iomuxc@020e0000 { + compatible = "fsl,imx6q-iomuxc"; + reg = <0x020e0000 0x4000>; + + /* shared pinctrl settings */ + audmux { + pinctrl_audmux_1: audmux-1 { + fsl,pins = < + MX6Q_PAD_SD2_DAT0__AUD4_RXD 0x80000000 + MX6Q_PAD_SD2_DAT3__AUD4_TXC 0x80000000 + MX6Q_PAD_SD2_DAT2__AUD4_TXD 0x80000000 + MX6Q_PAD_SD2_DAT1__AUD4_TXFS 0x80000000 + >; + }; + + pinctrl_audmux_2: audmux-2 { + fsl,pins = < + MX6Q_PAD_CSI0_DAT7__AUD3_RXD 0x80000000 + MX6Q_PAD_CSI0_DAT4__AUD3_TXC 0x80000000 + MX6Q_PAD_CSI0_DAT5__AUD3_TXD 0x80000000 + MX6Q_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000 + >; + }; + }; + + ecspi1 { + pinctrl_ecspi1_1: ecspi1grp-1 { + fsl,pins = < + MX6Q_PAD_EIM_D17__ECSPI1_MISO 0x100b1 + MX6Q_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 + MX6Q_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 + >; + }; + }; + + ecspi3 { + pinctrl_ecspi3_1: ecspi3grp-1 { + fsl,pins = < + MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1 + MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1 + MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1 + >; + }; + }; + + enet { + pinctrl_enet_1: enetgrp-1 { + fsl,pins = < + MX6Q_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6Q_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6Q_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6Q_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6Q_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6Q_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6Q_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6Q_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6Q_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 + MX6Q_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 + MX6Q_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6Q_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 + MX6Q_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 + >; + }; + + pinctrl_enet_2: enetgrp-2 { + fsl,pins = < + MX6Q_PAD_KEY_COL1__ENET_MDIO 0x1b0b0 + MX6Q_PAD_KEY_COL2__ENET_MDC 0x1b0b0 + MX6Q_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6Q_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6Q_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6Q_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6Q_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6Q_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6Q_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 + MX6Q_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 + MX6Q_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6Q_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 + >; + }; + }; + + gpmi-nand { + pinctrl_gpmi_nand_1: gpmi-nand-1 { + fsl,pins = < + MX6Q_PAD_NANDF_CLE__NAND_CLE 0xb0b1 + MX6Q_PAD_NANDF_ALE__NAND_ALE 0xb0b1 + MX6Q_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 + MX6Q_PAD_NANDF_RB0__NAND_READY_B 0xb000 + MX6Q_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 + MX6Q_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 + MX6Q_PAD_NANDF_CS2__NAND_CE2_B 0xb0b1 + MX6Q_PAD_NANDF_CS3__NAND_CE3_B 0xb0b1 + MX6Q_PAD_SD4_CMD__NAND_RE_B 0xb0b1 + MX6Q_PAD_SD4_CLK__NAND_WE_B 0xb0b1 + MX6Q_PAD_NANDF_D0__NAND_DATA00 0xb0b1 + MX6Q_PAD_NANDF_D1__NAND_DATA01 0xb0b1 + MX6Q_PAD_NANDF_D2__NAND_DATA02 0xb0b1 + MX6Q_PAD_NANDF_D3__NAND_DATA03 0xb0b1 + MX6Q_PAD_NANDF_D4__NAND_DATA04 0xb0b1 + MX6Q_PAD_NANDF_D5__NAND_DATA05 0xb0b1 + MX6Q_PAD_NANDF_D6__NAND_DATA06 0xb0b1 + MX6Q_PAD_NANDF_D7__NAND_DATA07 0xb0b1 + MX6Q_PAD_SD4_DAT0__NAND_DQS 0x00b1 + >; + }; + }; + + i2c1 { + pinctrl_i2c1_1: i2c1grp-1 { + fsl,pins = < + MX6Q_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 + MX6Q_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 + >; + }; + }; + + i2c2 { + pinctrl_i2c2_1: i2c2grp-1 { + fsl,pins = < + MX6Q_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 + MX6Q_PAD_EIM_D16__I2C2_SDA 0x4001b8b1 + >; + }; + }; + + i2c3 { + pinctrl_i2c3_1: i2c3grp-1 { + fsl,pins = < + MX6Q_PAD_EIM_D17__I2C3_SCL 0x4001b8b1 + MX6Q_PAD_EIM_D18__I2C3_SDA 0x4001b8b1 + >; + }; + }; + + uart1 { + pinctrl_uart1_1: uart1grp-1 { + fsl,pins = < + MX6Q_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 + MX6Q_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 + >; + }; + }; + + uart2 { + pinctrl_uart2_1: uart2grp-1 { + fsl,pins = < + MX6Q_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 + MX6Q_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 + >; + }; + }; + + uart4 { + pinctrl_uart4_1: uart4grp-1 { + fsl,pins = < + MX6Q_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 + MX6Q_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 + >; + }; + }; + + usbotg { + pinctrl_usbotg_1: usbotggrp-1 { + fsl,pins = < + MX6Q_PAD_GPIO_1__USB_OTG_ID 0x17059 + >; + }; + + pinctrl_usbotg_2: usbotggrp-2 { + fsl,pins = < + MX6Q_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 + >; + }; + }; + + usdhc2 { + pinctrl_usdhc2_1: usdhc2grp-1 { + fsl,pins = < + MX6Q_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6Q_PAD_SD2_CLK__SD2_CLK 0x10059 + MX6Q_PAD_SD2_DAT0__SD2_DATA0 0x17059 + MX6Q_PAD_SD2_DAT1__SD2_DATA1 0x17059 + MX6Q_PAD_SD2_DAT2__SD2_DATA2 0x17059 + MX6Q_PAD_SD2_DAT3__SD2_DATA3 0x17059 + MX6Q_PAD_NANDF_D4__SD2_DATA4 0x17059 + MX6Q_PAD_NANDF_D5__SD2_DATA5 0x17059 + MX6Q_PAD_NANDF_D6__SD2_DATA6 0x17059 + MX6Q_PAD_NANDF_D7__SD2_DATA7 0x17059 + >; + }; + }; + + usdhc3 { + pinctrl_usdhc3_1: usdhc3grp-1 { + fsl,pins = < + MX6Q_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6Q_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6Q_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6Q_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6Q_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6Q_PAD_SD3_DAT3__SD3_DATA3 0x17059 + MX6Q_PAD_SD3_DAT4__SD3_DATA4 0x17059 + MX6Q_PAD_SD3_DAT5__SD3_DATA5 0x17059 + MX6Q_PAD_SD3_DAT6__SD3_DATA6 0x17059 + MX6Q_PAD_SD3_DAT7__SD3_DATA7 0x17059 + >; + }; + + pinctrl_usdhc3_2: usdhc3grp-2 { + fsl,pins = < + MX6Q_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6Q_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6Q_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6Q_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6Q_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6Q_PAD_SD3_DAT3__SD3_DATA3 0x17059 + >; + }; + }; + + usdhc4 { + pinctrl_usdhc4_1: usdhc4grp-1 { + fsl,pins = < + MX6Q_PAD_SD4_CMD__SD4_CMD 0x17059 + MX6Q_PAD_SD4_CLK__SD4_CLK 0x10059 + MX6Q_PAD_SD4_DAT0__SD4_DATA0 0x17059 + MX6Q_PAD_SD4_DAT1__SD4_DATA1 0x17059 + MX6Q_PAD_SD4_DAT2__SD4_DATA2 0x17059 + MX6Q_PAD_SD4_DAT3__SD4_DATA3 0x17059 + MX6Q_PAD_SD4_DAT4__SD4_DATA4 0x17059 + MX6Q_PAD_SD4_DAT5__SD4_DATA5 0x17059 + MX6Q_PAD_SD4_DAT6__SD4_DATA6 0x17059 + MX6Q_PAD_SD4_DAT7__SD4_DATA7 0x17059 + >; + }; + + pinctrl_usdhc4_2: usdhc4grp-2 { + fsl,pins = < + MX6Q_PAD_SD4_CMD__SD4_CMD 0x17059 + MX6Q_PAD_SD4_CLK__SD4_CLK 0x10059 + MX6Q_PAD_SD4_DAT0__SD4_DATA0 0x17059 + MX6Q_PAD_SD4_DAT1__SD4_DATA1 0x17059 + MX6Q_PAD_SD4_DAT2__SD4_DATA2 0x17059 + MX6Q_PAD_SD4_DAT3__SD4_DATA3 0x17059 + >; + }; + }; + }; + }; + + ipu2: ipu@02800000 { + #crtc-cells = <1>; + compatible = "fsl,imx6q-ipu"; + reg = <0x02800000 0x400000>; + interrupts = <0 8 0x4 0 7 0x4>; + clocks = <&clks 133>, <&clks 134>, <&clks 137>; + clock-names = "bus", "di0", "di1"; + resets = <&src 4>; + }; + }; +}; + +&ldb { + clocks = <&clks 33>, <&clks 34>, + <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>, + <&clks 135>, <&clks 136>; + clock-names = "di0_pll", "di1_pll", + "di0_sel", "di1_sel", "di2_sel", "di3_sel", + "di0", "di1"; + + lvds-channel@0 { + crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>; + }; + + lvds-channel@1 { + crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>; + }; +}; diff --git a/arch/arm/dts/imx6qdl-sabresd.dtsi b/arch/arm/dts/imx6qdl-sabresd.dtsi new file mode 100644 index 0000000000..e21f6a89cf --- /dev/null +++ b/arch/arm/dts/imx6qdl-sabresd.dtsi @@ -0,0 +1,87 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/ { + memory { + reg = <0x10000000 0x40000000>; + }; + + regulators { + compatible = "simple-bus"; + + reg_usb_otg_vbus: usb_otg_vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 22 0>; + enable-active-high; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + volume-up { + label = "Volume Up"; + gpios = <&gpio1 4 0>; + linux,code = <115>; /* KEY_VOLUMEUP */ + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio1 5 0>; + linux,code = <114>; /* KEY_VOLUMEDOWN */ + }; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet_1>; + phy-mode = "rgmii"; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_1>; + status = "okay"; +}; + +&usbh1 { + status = "okay"; +}; + +&usbotg { + vbus-supply = <®_usb_otg_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg_2>; + disable-over-current; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2_1>; + cd-gpios = <&gpio2 2 0>; + wp-gpios = <&gpio2 3 0>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3_1>; + cd-gpios = <&gpio2 0 0>; + wp-gpios = <&gpio2 1 0>; + status = "okay"; +}; diff --git a/arch/arm/dts/imx6qdl.dtsi b/arch/arm/dts/imx6qdl.dtsi new file mode 100644 index 0000000000..b6360027b3 --- /dev/null +++ b/arch/arm/dts/imx6qdl.dtsi @@ -0,0 +1,840 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "skeleton.dtsi" + +/ { + aliases { + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; + serial3 = &uart4; + serial4 = &uart5; + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + gpio4 = &gpio5; + gpio5 = &gpio6; + gpio6 = &gpio7; + mmc0 = &usdhc1; + mmc1 = &usdhc2; + mmc2 = &usdhc3; + mmc3 = &usdhc4; + }; + + intc: interrupt-controller@00a01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + interrupt-controller; + reg = <0x00a01000 0x1000>, + <0x00a00100 0x100>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + ckil { + compatible = "fsl,imx-ckil", "fixed-clock"; + clock-frequency = <32768>; + }; + + ckih1 { + compatible = "fsl,imx-ckih1", "fixed-clock"; + clock-frequency = <0>; + }; + + osc { + compatible = "fsl,imx-osc", "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&intc>; + ranges; + + dma_apbh: dma-apbh@00110000 { + compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; + reg = <0x00110000 0x2000>; + interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>; + interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3"; + #dma-cells = <1>; + dma-channels = <4>; + clocks = <&clks 106>; + }; + + gpmi: gpmi-nand@00112000 { + compatible = "fsl,imx6q-gpmi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x00112000 0x2000>, <0x00114000 0x2000>; + reg-names = "gpmi-nand", "bch"; + interrupts = <0 13 0x04>, <0 15 0x04>; + interrupt-names = "gpmi-dma", "bch"; + clocks = <&clks 152>, <&clks 153>, <&clks 151>, + <&clks 150>, <&clks 149>; + clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch", + "gpmi_bch_apb", "per1_bch"; + dmas = <&dma_apbh 0>; + dma-names = "rx-tx"; + fsl,gpmi-dma-channel = <0>; + status = "disabled"; + }; + + timer@00a00600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x00a00600 0x20>; + interrupts = <1 13 0xf01>; + clocks = <&clks 15>; + }; + + L2: l2-cache@00a02000 { + compatible = "arm,pl310-cache"; + reg = <0x00a02000 0x1000>; + interrupts = <0 92 0x04>; + cache-unified; + cache-level = <2>; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts = <0 94 0x04>; + }; + + aips-bus@02000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x02000000 0x100000>; + ranges; + + spba-bus@02000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x02000000 0x40000>; + ranges; + + spdif: spdif@02004000 { + reg = <0x02004000 0x4000>; + interrupts = <0 52 0x04>; + }; + + ecspi1: ecspi@02008000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02008000 0x4000>; + interrupts = <0 31 0x04>; + clocks = <&clks 112>, <&clks 112>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + ecspi2: ecspi@0200c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x0200c000 0x4000>; + interrupts = <0 32 0x04>; + clocks = <&clks 113>, <&clks 113>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + ecspi3: ecspi@02010000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02010000 0x4000>; + interrupts = <0 33 0x04>; + clocks = <&clks 114>, <&clks 114>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + ecspi4: ecspi@02014000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; + reg = <0x02014000 0x4000>; + interrupts = <0 34 0x04>; + clocks = <&clks 115>, <&clks 115>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + uart1: serial@02020000 { + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02020000 0x4000>; + interrupts = <0 26 0x04>; + clocks = <&clks 160>, <&clks 161>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + esai: esai@02024000 { + reg = <0x02024000 0x4000>; + interrupts = <0 51 0x04>; + }; + + ssi1: ssi@02028000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; + reg = <0x02028000 0x4000>; + interrupts = <0 46 0x04>; + clocks = <&clks 178>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <38 37>; + status = "disabled"; + }; + + ssi2: ssi@0202c000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; + reg = <0x0202c000 0x4000>; + interrupts = <0 47 0x04>; + clocks = <&clks 179>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <42 41>; + status = "disabled"; + }; + + ssi3: ssi@02030000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; + reg = <0x02030000 0x4000>; + interrupts = <0 48 0x04>; + clocks = <&clks 180>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <46 45>; + status = "disabled"; + }; + + asrc: asrc@02034000 { + reg = <0x02034000 0x4000>; + interrupts = <0 50 0x04>; + }; + + spba@0203c000 { + reg = <0x0203c000 0x4000>; + }; + }; + + vpu: vpu@02040000 { + reg = <0x02040000 0x3c000>; + interrupts = <0 3 0x04 0 12 0x04>; + }; + + aipstz@0207c000 { /* AIPSTZ1 */ + reg = <0x0207c000 0x4000>; + }; + + pwm1: pwm@02080000 { + #pwm-cells = <2>; + compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; + reg = <0x02080000 0x4000>; + interrupts = <0 83 0x04>; + clocks = <&clks 62>, <&clks 145>; + clock-names = "ipg", "per"; + }; + + pwm2: pwm@02084000 { + #pwm-cells = <2>; + compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; + reg = <0x02084000 0x4000>; + interrupts = <0 84 0x04>; + clocks = <&clks 62>, <&clks 146>; + clock-names = "ipg", "per"; + }; + + pwm3: pwm@02088000 { + #pwm-cells = <2>; + compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; + reg = <0x02088000 0x4000>; + interrupts = <0 85 0x04>; + clocks = <&clks 62>, <&clks 147>; + clock-names = "ipg", "per"; + }; + + pwm4: pwm@0208c000 { + #pwm-cells = <2>; + compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; + reg = <0x0208c000 0x4000>; + interrupts = <0 86 0x04>; + clocks = <&clks 62>, <&clks 148>; + clock-names = "ipg", "per"; + }; + + can1: flexcan@02090000 { + reg = <0x02090000 0x4000>; + interrupts = <0 110 0x04>; + }; + + can2: flexcan@02094000 { + reg = <0x02094000 0x4000>; + interrupts = <0 111 0x04>; + }; + + gpt: gpt@02098000 { + compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt"; + reg = <0x02098000 0x4000>; + interrupts = <0 55 0x04>; + clocks = <&clks 119>, <&clks 120>; + clock-names = "ipg", "per"; + }; + + gpio1: gpio@0209c000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x0209c000 0x4000>; + interrupts = <0 66 0x04 0 67 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@020a0000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x020a0000 0x4000>; + interrupts = <0 68 0x04 0 69 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@020a4000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x020a4000 0x4000>; + interrupts = <0 70 0x04 0 71 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio4: gpio@020a8000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x020a8000 0x4000>; + interrupts = <0 72 0x04 0 73 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio5: gpio@020ac000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x020ac000 0x4000>; + interrupts = <0 74 0x04 0 75 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio6: gpio@020b0000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x020b0000 0x4000>; + interrupts = <0 76 0x04 0 77 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio7: gpio@020b4000 { + compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; + reg = <0x020b4000 0x4000>; + interrupts = <0 78 0x04 0 79 0x04>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + kpp: kpp@020b8000 { + reg = <0x020b8000 0x4000>; + interrupts = <0 82 0x04>; + }; + + wdog1: wdog@020bc000 { + compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; + reg = <0x020bc000 0x4000>; + interrupts = <0 80 0x04>; + clocks = <&clks 0>; + }; + + wdog2: wdog@020c0000 { + compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; + reg = <0x020c0000 0x4000>; + interrupts = <0 81 0x04>; + clocks = <&clks 0>; + status = "disabled"; + }; + + clks: ccm@020c4000 { + compatible = "fsl,imx6q-ccm"; + reg = <0x020c4000 0x4000>; + interrupts = <0 87 0x04 0 88 0x04>; + #clock-cells = <1>; + }; + + anatop: anatop@020c8000 { + compatible = "fsl,imx6q-anatop", "syscon", "simple-bus"; + reg = <0x020c8000 0x1000>; + interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>; + + regulator-1p1@110 { + compatible = "fsl,anatop-regulator"; + regulator-name = "vdd1p1"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1375000>; + regulator-always-on; + anatop-reg-offset = <0x110>; + anatop-vol-bit-shift = <8>; + anatop-vol-bit-width = <5>; + anatop-min-bit-val = <4>; + anatop-min-voltage = <800000>; + anatop-max-voltage = <1375000>; + }; + + regulator-3p0@120 { + compatible = "fsl,anatop-regulator"; + regulator-name = "vdd3p0"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3150000>; + regulator-always-on; + anatop-reg-offset = <0x120>; + anatop-vol-bit-shift = <8>; + anatop-vol-bit-width = <5>; + anatop-min-bit-val = <0>; + anatop-min-voltage = <2625000>; + anatop-max-voltage = <3400000>; + }; + + regulator-2p5@130 { + compatible = "fsl,anatop-regulator"; + regulator-name = "vdd2p5"; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2750000>; + regulator-always-on; + anatop-reg-offset = <0x130>; + anatop-vol-bit-shift = <8>; + anatop-vol-bit-width = <5>; + anatop-min-bit-val = <0>; + anatop-min-voltage = <2000000>; + anatop-max-voltage = <2750000>; + }; + + reg_arm: regulator-vddcore@140 { + compatible = "fsl,anatop-regulator"; + regulator-name = "cpu"; + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1450000>; + regulator-always-on; + anatop-reg-offset = <0x140>; + anatop-vol-bit-shift = <0>; + anatop-vol-bit-width = <5>; + anatop-delay-reg-offset = <0x170>; + anatop-delay-bit-shift = <24>; + anatop-delay-bit-width = <2>; + anatop-min-bit-val = <1>; + anatop-min-voltage = <725000>; + anatop-max-voltage = <1450000>; + }; + + reg_pu: regulator-vddpu@140 { + compatible = "fsl,anatop-regulator"; + regulator-name = "vddpu"; + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1450000>; + regulator-always-on; + anatop-reg-offset = <0x140>; + anatop-vol-bit-shift = <9>; + anatop-vol-bit-width = <5>; + anatop-delay-reg-offset = <0x170>; + anatop-delay-bit-shift = <26>; + anatop-delay-bit-width = <2>; + anatop-min-bit-val = <1>; + anatop-min-voltage = <725000>; + anatop-max-voltage = <1450000>; + }; + + reg_soc: regulator-vddsoc@140 { + compatible = "fsl,anatop-regulator"; + regulator-name = "vddsoc"; + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1450000>; + regulator-always-on; + anatop-reg-offset = <0x140>; + anatop-vol-bit-shift = <18>; + anatop-vol-bit-width = <5>; + anatop-delay-reg-offset = <0x170>; + anatop-delay-bit-shift = <28>; + anatop-delay-bit-width = <2>; + anatop-min-bit-val = <1>; + anatop-min-voltage = <725000>; + anatop-max-voltage = <1450000>; + }; + }; + + usbphy1: usbphy@020c9000 { + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; + reg = <0x020c9000 0x1000>; + interrupts = <0 44 0x04>; + clocks = <&clks 182>; + }; + + usbphy2: usbphy@020ca000 { + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; + reg = <0x020ca000 0x1000>; + interrupts = <0 45 0x04>; + clocks = <&clks 183>; + }; + + snvs@020cc000 { + compatible = "fsl,sec-v4.0-mon", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x020cc000 0x4000>; + + snvs-rtc-lp@34 { + compatible = "fsl,sec-v4.0-mon-rtc-lp"; + reg = <0x34 0x58>; + interrupts = <0 19 0x04 0 20 0x04>; + }; + }; + + epit1: epit@020d0000 { /* EPIT1 */ + reg = <0x020d0000 0x4000>; + interrupts = <0 56 0x04>; + }; + + epit2: epit@020d4000 { /* EPIT2 */ + reg = <0x020d4000 0x4000>; + interrupts = <0 57 0x04>; + }; + + src: src@020d8000 { + compatible = "fsl,imx6q-src", "fsl,imx51-src"; + reg = <0x020d8000 0x4000>; + interrupts = <0 91 0x04 0 96 0x04>; + #reset-cells = <1>; + }; + + gpc: gpc@020dc000 { + compatible = "fsl,imx6q-gpc"; + reg = <0x020dc000 0x4000>; + interrupts = <0 89 0x04 0 90 0x04>; + }; + + gpr: iomuxc-gpr@020e0000 { + compatible = "fsl,imx6q-iomuxc-gpr", "syscon"; + reg = <0x020e0000 0x38>; + }; + + ldb: ldb@020e0008 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb"; + gpr = <&gpr>; + status = "disabled"; + + lvds-channel@0 { + reg = <0>; + crtcs = <&ipu1 0>; + status = "disabled"; + }; + + lvds-channel@1 { + reg = <1>; + crtcs = <&ipu1 1>; + status = "disabled"; + }; + }; + + dcic1: dcic@020e4000 { + reg = <0x020e4000 0x4000>; + interrupts = <0 124 0x04>; + }; + + dcic2: dcic@020e8000 { + reg = <0x020e8000 0x4000>; + interrupts = <0 125 0x04>; + }; + + sdma: sdma@020ec000 { + compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; + reg = <0x020ec000 0x4000>; + interrupts = <0 2 0x04>; + clocks = <&clks 155>, <&clks 155>; + clock-names = "ipg", "ahb"; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin"; + }; + }; + + aips-bus@02100000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x02100000 0x100000>; + ranges; + + caam@02100000 { + reg = <0x02100000 0x40000>; + interrupts = <0 105 0x04 0 106 0x04>; + }; + + aipstz@0217c000 { /* AIPSTZ2 */ + reg = <0x0217c000 0x4000>; + }; + + usbotg: usb@02184000 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; + reg = <0x02184000 0x200>; + interrupts = <0 43 0x04>; + clocks = <&clks 162>; + fsl,usbphy = <&usbphy1>; + fsl,usbmisc = <&usbmisc 0>; + status = "disabled"; + }; + + usbh1: usb@02184200 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; + reg = <0x02184200 0x200>; + interrupts = <0 40 0x04>; + clocks = <&clks 162>; + fsl,usbphy = <&usbphy2>; + fsl,usbmisc = <&usbmisc 1>; + status = "disabled"; + }; + + usbh2: usb@02184400 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; + reg = <0x02184400 0x200>; + interrupts = <0 41 0x04>; + clocks = <&clks 162>; + fsl,usbmisc = <&usbmisc 2>; + status = "disabled"; + }; + + usbh3: usb@02184600 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; + reg = <0x02184600 0x200>; + interrupts = <0 42 0x04>; + clocks = <&clks 162>; + fsl,usbmisc = <&usbmisc 3>; + status = "disabled"; + }; + + usbmisc: usbmisc: usbmisc@02184800 { + #index-cells = <1>; + compatible = "fsl,imx6q-usbmisc"; + reg = <0x02184800 0x200>; + clocks = <&clks 162>; + }; + + fec: ethernet@02188000 { + compatible = "fsl,imx6q-fec"; + reg = <0x02188000 0x4000>; + interrupts = <0 118 0x04 0 119 0x04>; + clocks = <&clks 117>, <&clks 117>, <&clks 190>; + clock-names = "ipg", "ahb", "ptp"; + status = "disabled"; + }; + + mlb@0218c000 { + reg = <0x0218c000 0x4000>; + interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>; + }; + + usdhc1: usdhc@02190000 { + compatible = "fsl,imx6q-usdhc"; + reg = <0x02190000 0x4000>; + interrupts = <0 22 0x04>; + clocks = <&clks 163>, <&clks 163>, <&clks 163>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + + usdhc2: usdhc@02194000 { + compatible = "fsl,imx6q-usdhc"; + reg = <0x02194000 0x4000>; + interrupts = <0 23 0x04>; + clocks = <&clks 164>, <&clks 164>, <&clks 164>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + + usdhc3: usdhc@02198000 { + compatible = "fsl,imx6q-usdhc"; + reg = <0x02198000 0x4000>; + interrupts = <0 24 0x04>; + clocks = <&clks 165>, <&clks 165>, <&clks 165>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + + usdhc4: usdhc@0219c000 { + compatible = "fsl,imx6q-usdhc"; + reg = <0x0219c000 0x4000>; + interrupts = <0 25 0x04>; + clocks = <&clks 166>, <&clks 166>, <&clks 166>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; + status = "disabled"; + }; + + i2c1: i2c@021a0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; + reg = <0x021a0000 0x4000>; + interrupts = <0 36 0x04>; + clocks = <&clks 125>; + status = "disabled"; + }; + + i2c2: i2c@021a4000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; + reg = <0x021a4000 0x4000>; + interrupts = <0 37 0x04>; + clocks = <&clks 126>; + status = "disabled"; + }; + + i2c3: i2c@021a8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; + reg = <0x021a8000 0x4000>; + interrupts = <0 38 0x04>; + clocks = <&clks 127>; + status = "disabled"; + }; + + romcp@021ac000 { + reg = <0x021ac000 0x4000>; + }; + + mmdc0: mmdc@021b0000 { /* MMDC0 */ + compatible = "fsl,imx6q-mmdc"; + reg = <0x021b0000 0x4000>; + }; + + mmdc1: mmdc@021b4000 { /* MMDC1 */ + reg = <0x021b4000 0x4000>; + }; + + weim@021b8000 { + reg = <0x021b8000 0x4000>; + interrupts = <0 14 0x04>; + }; + + ocotp@021bc000 { + compatible = "fsl,imx6q-ocotp"; + reg = <0x021bc000 0x4000>; + }; + + ocotp@021c0000 { + reg = <0x021c0000 0x4000>; + interrupts = <0 21 0x04>; + }; + + tzasc@021d0000 { /* TZASC1 */ + reg = <0x021d0000 0x4000>; + interrupts = <0 108 0x04>; + }; + + tzasc@021d4000 { /* TZASC2 */ + reg = <0x021d4000 0x4000>; + interrupts = <0 109 0x04>; + }; + + audmux: audmux@021d8000 { + compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux"; + reg = <0x021d8000 0x4000>; + status = "disabled"; + }; + + mipi@021dc000 { /* MIPI-CSI */ + reg = <0x021dc000 0x4000>; + }; + + mipi@021e0000 { /* MIPI-DSI */ + reg = <0x021e0000 0x4000>; + }; + + vdoa@021e4000 { + reg = <0x021e4000 0x4000>; + interrupts = <0 18 0x04>; + }; + + uart2: serial@021e8000 { + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021e8000 0x4000>; + interrupts = <0 27 0x04>; + clocks = <&clks 160>, <&clks 161>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + uart3: serial@021ec000 { + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021ec000 0x4000>; + interrupts = <0 28 0x04>; + clocks = <&clks 160>, <&clks 161>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + uart4: serial@021f0000 { + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021f0000 0x4000>; + interrupts = <0 29 0x04>; + clocks = <&clks 160>, <&clks 161>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + uart5: serial@021f4000 { + compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x021f4000 0x4000>; + interrupts = <0 30 0x04>; + clocks = <&clks 160>, <&clks 161>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + }; + + ipu1: ipu@02400000 { + #crtc-cells = <1>; + compatible = "fsl,imx6q-ipu"; + reg = <0x02400000 0x400000>; + interrupts = <0 6 0x4 0 5 0x4>; + clocks = <&clks 130>, <&clks 131>, <&clks 132>; + clock-names = "bus", "di0", "di1"; + resets = <&src 2>; + }; + }; +}; diff --git a/arch/arm/dts/tegra20-colibri-iris.dts b/arch/arm/dts/tegra20-colibri-iris.dts new file mode 100644 index 0000000000..804750e421 --- /dev/null +++ b/arch/arm/dts/tegra20-colibri-iris.dts @@ -0,0 +1,32 @@ +/dts-v1/; + +/include/ "tegra20-colibri.dtsi" + +/ { + model = "Toradex Colibri T20 on Iris"; + compatible = "toradex,iris", "toradex,colibri-t20", "nvidia,tegra20"; + + pinmux { + state_default: pinmux { + hdint { + nvidia,tristate = <0>; + }; + + i2cddc { + nvidia,tristate = <0>; + }; + + sdio4 { + nvidia,tristate = <0>; + }; + + uarta { + nvidia,tristate = <0>; + }; + + uartd { + nvidia,tristate = <0>; + }; + }; + }; +}; diff --git a/arch/arm/dts/tegra20-colibri.dtsi b/arch/arm/dts/tegra20-colibri.dtsi new file mode 100644 index 0000000000..3644e7de4e --- /dev/null +++ b/arch/arm/dts/tegra20-colibri.dtsi @@ -0,0 +1,190 @@ +/include/ "tegra20.dtsi" + +/ { + model = "Toradex Colibri T20"; + compatible = "toradex,colibri_t20", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x20000000>; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + audio_refclk { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + crt { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + displaya { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", + "ld4", "ld5", "ld6", "ld7", "ld8", + "ld9", "ld10", "ld11", "ld12", "ld13", + "ld14", "ld15", "ld16", "ld17", + "lhs", "lpw0", "lpw2", "lsc0", + "lsc1", "lsck", "lsda", "lspi", "lvs"; + nvidia,function = "displaya"; + nvidia,tristate = <1>; + }; + gpio_dte { + nvidia,pins = "dte"; + nvidia,function = "rsvd1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + gpio_gmi { + nvidia,pins = "ata", "atc", "atd", "ate", + "dap1", "dap2", "dap4", "gpu", "irrx", + "irtx", "spia", "spib", "spic"; + nvidia,function = "gmi"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + gpio_pta { + nvidia,pins = "pta"; + nvidia,function = "rsvd4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + gpio_uac { + nvidia,pins = "uac"; + nvidia,function = "rsvd2"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + hdint { + nvidia,pins = "hdint"; + nvidia,function = "hdmi"; + nvidia,tristate = <1>; + }; + i2c1 { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + i2c3 { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + i2cddc { + nvidia,pins = "ddc"; + nvidia,function = "i2c2"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + irda { + nvidia,pins = "uad"; + nvidia,function = "irda"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + nand { + nvidia,pins = "kbca", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "nand"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + owc { + nvidia,pins = "owc"; + nvidia,function = "owr"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + nvidia,tristate = <0>; + }; + pwm { + nvidia,pins = "sdb", "sdc", "sdd"; + nvidia,function = "pwm"; + nvidia,tristate = <1>; + }; + sdio4 { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + spi1 { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + spi4 { + nvidia,pins = "slxa", "slxc", "slxd", "slxk"; + nvidia,function = "spi4"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + uarta { + nvidia,pins = "sdio1"; + nvidia,function = "uarta"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + uartd { + nvidia,pins = "gmc"; + nvidia,function = "uartd"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + ulpi { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + ulpi_refclk { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + usb_gpio { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + vi { + nvidia,pins = "dta", "dtb", "dtc", "dtd"; + nvidia,function = "vi"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + vi_sc { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + }; + }; +}; diff --git a/arch/arm/dts/tegra20-paz00.dts b/arch/arm/dts/tegra20-paz00.dts index 09ccb8ba3a..e8486aae49 100644 --- a/arch/arm/dts/tegra20-paz00.dts +++ b/arch/arm/dts/tegra20-paz00.dts @@ -9,4 +9,220 @@ memory { reg = <0x00000000 0x20000000>; }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata", "atc", "atd", "ate", + "dap2", "gmb", "gmc", "gmd", "spia", + "spib", "spic", "spid", "spie"; + nvidia,function = "gmi"; + }; + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "pllc_out1"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + ddc { + nvidia,pins = "ddc"; + nvidia,function = "i2c2"; + }; + dta { + nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte"; + nvidia,function = "rsvd1"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gpu { + nvidia,pins = "gpu", "sdb", "sdd"; + nvidia,function = "pwm"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint", "pta"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uarta"; + }; + kbca { + nvidia,pins = "kbca", "kbcc", "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + kbcb { + nvidia,pins = "kbcb", "kbcd"; + nvidia,function = "sdio2"; + }; + lcsn { + nvidia,pins = "lcsn", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhp0", "lhp1", "lhp2", + "lhs", "lm0", "lm1", "lpp", "lpw0", + "lpw1", "lpw2", "lsc0", "lsc1", "lsck", + "lsda", "lsdi", "lspi", "lvp0", "lvp1", + "lvs"; + nvidia,function = "displaya"; + }; + owc { + nvidia,pins = "owc"; + nvidia,function = "owr"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdc { + nvidia,pins = "sdc"; + nvidia,function = "twc"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "spi4"; + }; + spdi { + nvidia,pins = "spdi", "spdo"; + nvidia,function = "rsvd2"; + }; + spif { + nvidia,pins = "spif", "uac"; + nvidia,function = "rsvd4"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "spdif"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atb", "atc", "atd", "ate", + "cdev1", "cdev2", "dap1", "dap2", "dtf", + "gma", "gmb", "gmc", "gmd", "gme", + "gpu", "gpu7", "gpv", "i2cp", "pta", + "rm", "sdio1", "slxk", "spdo", "uac", + "uda"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_crtp { + nvidia,pins = "crtp", "dap3", "dap4", "dtb", + "dtc", "dte", "slxa", "slxc", "slxd", + "spdi"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_csus { + nvidia,pins = "csus", "spia", "spib", "spid", + "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_ddc { + nvidia,pins = "ddc", "irrx", "irtx", "kbca", + "kbcb", "kbcc", "kbcd", "kbce", "kbcf", + "spic", "spig", "uaa", "uab"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_dta { + nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd", + "spie", "spih", "uad", "uca", "ucb"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_hdint { + nvidia,pins = "hdint", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhs", "lsc0", "lspi", + "lvs", "pmc"; + nvidia,tristate = <0>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_lcsn { + nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2", + "lm0", "lm1", "lpp", "lpw0", "lpw1", + "lpw2", "lsc1", "lsck", "lsda", "lsdi", + "lvp0", "lvp1", "sdb"; + nvidia,tristate = <1>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + }; + }; }; diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi index b7d1e27de2..f63ead89db 100644 --- a/arch/arm/dts/tegra20.dtsi +++ b/arch/arm/dts/tegra20.dtsi @@ -34,6 +34,14 @@ interrupt-controller; }; + pinmux: pinmux { + compatible = "nvidia,tegra20-pinmux"; + reg = <0x70000014 0x10 /* Tri-state registers */ + 0x70000080 0x20 /* Mux registers */ + 0x700000a0 0x14 /* Pull-up/down registers */ + 0x70000868 0xa8>; /* Pad control registers */ + }; + pmc { compatible = "nvidia,tegra20-pmc"; reg = <0x7000e400 0x400>; diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e7a0625d3b..0786e22d3d 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -91,6 +91,10 @@ static int __do_bootm_linux(struct image_data *data, int swap) of_add_reserve_entry(initrd_start, initrd_end); data->oftree = of_get_fixed_tree(data->of_root_node); fdt_add_reserve_map(data->oftree); + if (bootm_verbose(data)) + of_print_cmdline(data->of_root_node); + if (bootm_verbose(data) > 1) + of_print_nodes(data->of_root_node, 0); } if (bootm_verbose(data)) { @@ -326,7 +330,7 @@ static int aimage_load_resource(int fd, struct resource *r, void* buf, int ps) ret = read_full(fd, buf, to_read); if (ret < 0) - printf("could not read dummy %d\n", to_read); + printf("could not read dummy %u\n", to_read); return ret; } diff --git a/arch/arm/lib/module.c b/arch/arm/lib/module.c index 643a8bed0e..be7965d59c 100644 --- a/arch/arm/lib/module.c +++ b/arch/arm/lib/module.c @@ -34,7 +34,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset = ELF32_R_SYM(rel->r_info); if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { - printf("%s: bad relocation, section %d reloc %d\n", + printf("%s: bad relocation, section %u reloc %u\n", module->name, relindex, i); return -ENOEXEC; } @@ -43,7 +43,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { printf("%s: out of bounds relocation, " - "section %d reloc %d offset %d size %d\n", + "section %u reloc %u offset %d size %d\n", module->name, relindex, i, rel->r_offset, dstsec->sh_size); return -ENOEXEC; @@ -68,7 +68,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset <= (s32)0xfe000000 || offset >= (s32)0x02000000) { printf("%s: relocation out of range, section " - "%d reloc %d sym '%s'\n", module->name, + "%u reloc %u sym '%s'\n", module->name, relindex, i, strtab + sym->st_name); return -ENOEXEC; } diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b8528d0616..8116b62f24 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -59,6 +59,7 @@ config BOARDINFO default "Calao TNY-A9263" if MACH_TNY_A9263 default "Calao TNY-A9G20" if MACH_TNY_A9G20 default "Calao QIL-A9260" if MACH_QIL_A9260 + default "Calao QIL-A9G20" if MACH_QIL_A9G20 default "Somfy Animeo IP" if MACH_ANIMEO_IP default "Telit EVK-PRO3" if MACH_GE863 @@ -363,6 +364,13 @@ config MACH_DSS11 Select this if you are using aizo dSS11 that embeds only one SD/MMC slot. +config MACH_QIL_A9G20 + bool "CALAO QIL-A9G20 board" + help + Select this if you are using a Calao Systems QIL-A9G20 Board. + <http://www.calao-systems.com> + + endchoice endif @@ -513,7 +521,7 @@ config AT91_HAVE_2MMC config AT91_HAVE_SRAM_128M bool "Have 128 of ram" - depends on MACH_USB_A9G20 || MACH_USB_A9263 || MACH_QIL_A9260 + depends on MACH_USB_A9G20 || MACH_USB_A9263 || MACH_QIL_A9260 || MACH_QIL_A9G20 help Select this if you board have 128 MiB of Ram (as USB_A9G20 C11) @@ -543,7 +551,7 @@ config CALAO_MOB_TNY_MD2 config CALAO_MB_QIL_A9260 bool "MB-QIL A9260 Motherboard Board support" - depends on MACH_QIL_A9260 + depends on MACH_QIL_A9260 || MACH_QIL_A9G20 if COMMAND_SUPPORT diff --git a/arch/arm/mach-bcm2835/core.c b/arch/arm/mach-bcm2835/core.c index f44ecd5bf3..906e4344dd 100644 --- a/arch/arm/mach-bcm2835/core.c +++ b/arch/arm/mach-bcm2835/core.c @@ -70,6 +70,7 @@ static int bcm2835_dev_init(void) { add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL); add_generic_device("bcm2835-cs", DEVICE_ID_SINGLE, NULL, BCM2835_ST_BASE, 0x1C, IORESOURCE_MEM, NULL); + add_generic_device("bcm2835_mci", 0, NULL, BCM2835_EMMC_BASE, 0xFC, IORESOURCE_MEM, NULL); return 0; } coredevice_initcall(bcm2835_dev_init); diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 359b5cd091..a66395cb06 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -66,6 +66,7 @@ config BOARDINFO choice prompt "Select boot mode" + depends on !ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE help i.MX processors support two different boot modes. With the internal boot mode the boot medium contains a header describing the image to @@ -93,6 +94,21 @@ config ARCH_IMX_EXTERNAL_BOOT endchoice +config ARCH_IMX_IMXIMAGE + bool + help + if enabled the imx-image tool is compiled + +config ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE + select ARCH_IMX_IMXIMAGE + bool + help + Traditionally the i.MX specific format for internal bootmode + was generated using C structs inside the binary. Now there is + a tool available to generate the imx-image format. Boards using + this tool must select this option. This is recommended for new + boards. + choice depends on ARCH_IMX_INTERNAL_BOOT prompt "Internal boot source" @@ -407,6 +423,7 @@ choice config MACH_FREESCALE_MX51_PDK select HAVE_DEFAULT_ENVIRONMENT_NEW + select ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE bool "Freescale i.MX51 PDK" config MACH_EUKREA_CPUIMX51SD @@ -508,6 +525,7 @@ config MACH_MX6Q_ARM2 bool "Freescale i.MX6q Armadillo2" config MACH_SABRELITE + select HAVE_DEFAULT_ENVIRONMENT_NEW bool "Freescale i.MX6 Sabre Lite" config MACH_SABRESD @@ -596,6 +614,13 @@ endmenu menu "i.MX specific settings" +config ARCH_IMX_USBLOADER + bool "compile imx-usb-loader" + help + imx-usb-loader is a tool to upload and start imximages to an i.MX SoC + in ROM boot mode. It requires libusb, so make sure you have the libusb + devel package installed on your machine. + config IMX_IIM tristate "IIM fusebox device" depends on !ARCH_IMX21 && !ARCH_IMX21 diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c index f1b167aac5..5c84df264a 100644 --- a/arch/arm/mach-imx/clk-imx6.c +++ b/arch/arm/mach-imx/clk-imx6.c @@ -321,7 +321,7 @@ static int imx6_ccm_probe(struct device_d *dev) static __maybe_unused struct of_device_id imx6_ccm_dt_ids[] = { { - .compatible = "fsl,imx6-ccm", + .compatible = "fsl,imx6q-ccm", }, { /* sentinel */ } diff --git a/arch/arm/mach-imx/iim.c b/arch/arm/mach-imx/iim.c index ce2bbafc90..956811cc6d 100644 --- a/arch/arm/mach-imx/iim.c +++ b/arch/arm/mach-imx/iim.c @@ -31,8 +31,6 @@ #define DRIVERNAME "imx_iim" -static unsigned long mac_addr_base; - static int iim_write_enable; static int iim_sense_enable; @@ -225,21 +223,66 @@ static int imx_iim_add_bank(struct device_d *dev, void __iomem *base, int num) return devfs_create(cdev); } +#if IS_ENABLED(CONFIG_OFDEVICE) + +/* + * a single MAC address reference has the form + * <&phandle iim-bank-no offset>, so three cells + */ +#define MAC_ADDRESS_PROPLEN (3 * sizeof(__be32)) + +static void imx_iim_init_dt(struct device_d *dev) +{ + char mac[6]; + const __be32 *prop; + struct device_node *node = dev->device_node; + int len, ret; + + if (!node) + return; + + prop = of_get_property(node, "barebox,provide-mac-address", &len); + if (!prop) + return; + + while (len >= MAC_ADDRESS_PROPLEN) { + struct device_node *rnode; + uint32_t phandle, bank, offset; + + phandle = be32_to_cpup(prop++); + + rnode = of_find_node_by_phandle(phandle); + bank = be32_to_cpup(prop++); + offset = be32_to_cpup(prop++); + + ret = imx_iim_read(bank, offset, mac, 6); + if (ret == 6) { + of_eth_register_ethaddr(rnode, mac); + } else { + dev_err(dev, "cannot read: %s\n", strerror(-ret)); + } + + len -= MAC_ADDRESS_PROPLEN; + } +} +#else +static inline void imx_iim_init_dt(struct device_d *dev) +{ +} +#endif + static int imx_iim_probe(struct device_d *dev) { - struct imx_iim_platform_data *pdata = dev->platform_data; int i; void __iomem *base; base = dev_request_mem_region(dev, 0); - if (pdata) - mac_addr_base = pdata->mac_addr_base; - for (i = 0; i < 8; i++) { imx_iim_add_bank(dev, base, i); } + imx_iim_init_dt(dev); if (IS_ENABLED(CONFIG_IMX_IIM_FUSE_BLOW)) dev_add_param_bool(dev, "permanent_write_enable", @@ -251,9 +294,18 @@ static int imx_iim_probe(struct device_d *dev) return 0; } +static __maybe_unused struct of_device_id imx_iim_dt_ids[] = { + { + .compatible = "fsl,imx-iim", + }, { + /* sentinel */ + } +}; + static struct driver_d imx_iim_driver = { .name = DRIVERNAME, .probe = imx_iim_probe, + .of_compatible = DRV_OF_COMPAT(imx_iim_dt_ids), }; static int imx_iim_init(void) diff --git a/arch/arm/mach-imx/imx25.c b/arch/arm/mach-imx/imx25.c index 501191874f..63e91a51f0 100644 --- a/arch/arm/mach-imx/imx25.c +++ b/arch/arm/mach-imx/imx25.c @@ -53,16 +53,12 @@ u64 imx_uid(void) return uid; } -static struct imx_iim_platform_data imx25_iim_pdata = { - .mac_addr_base = IIM_MAC_ADDR, -}; - static int imx25_init(void) { imx25_boot_save_loc((void *)MX25_CCM_BASE_ADDR); add_generic_device("imx_iim", 0, NULL, MX25_IIM_BASE_ADDR, SZ_4K, - IORESOURCE_MEM, &imx25_iim_pdata); + IORESOURCE_MEM, NULL); add_generic_device("imx-iomuxv3", 0, NULL, MX25_IOMUXC_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx25-ccm", 0, NULL, MX25_CCM_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index 54d99a4c19..fdf2374402 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -58,6 +58,9 @@ static int imx51_init(void) imx51_silicon_revision(); imx51_boot_save_loc((void *)MX51_SRC_BASE_ADDR); + if (of_get_root_node()) + return 0; + add_generic_device("imx_iim", 0, NULL, MX51_IIM_BASE_ADDR, SZ_4K, IORESOURCE_MEM, NULL); @@ -95,15 +98,63 @@ postcore_initcall(imx51_init); * power up. */ +#define DP_MFN_800_DIT 60 /* PL Dither mode */ + +/* + * Workaround for i.MX51 PLL errata. This is needed by all boards using the + * i.MX51 silicon version up until (including) 3.0 running at 800MHz. + * The PLL's in the i.MX51 processor can go out of lock due to a metastable + * condition in an analog flip-flop when used at high frequencies. + * This workaround implements an undocumented feature in the PLL (dither + * mode), which causes the effect of this failure to be much lower (in terms + * of frequency deviation), avoiding system failure, or at least decreasing + * the likelihood of system failure. + */ +static void imx51_setup_pll800_bug(void) +{ + void __iomem *base = (void *)MX51_PLL1_BASE_ADDR; + u32 dp_config; + volatile int i; + + imx5_setup_pll_864(base); + + dp_config = readl(base + MX5_PLL_DP_CONFIG); + dp_config &= ~MX5_PLL_DP_CONFIG_AREN; + writel(dp_config, base + MX5_PLL_DP_CONFIG); + + /* Restart PLL with PLM = 1 */ + writel(0x00001236, base + MX5_PLL_DP_CTL); + + /* Wait for lock */ + while (!(readl(base + MX5_PLL_DP_CTL) & 1)); + + /* Modify MFN value */ + writel(DP_MFN_800_DIT, base + MX5_PLL_DP_MFN); + writel(DP_MFN_800_DIT, base + MX5_PLL_DP_HFS_MFN); + + /* Reload MFN value */ + writel(0x1, base + MX5_PLL_DP_CONFIG); + + while (readl(base + MX5_PLL_DP_CONFIG) & 1); + + /* Wait at least 4 us */ + for (i = 0; i < 100; i++); + + /* Enable auto-restart AREN bit */ + dp_config |= MX5_PLL_DP_CONFIG_AREN; + writel(dp_config, base + MX5_PLL_DP_CONFIG); +} + void imx51_init_lowlevel(unsigned int cpufreq_mhz) { void __iomem *ccm = (void __iomem *)MX51_CCM_BASE_ADDR; u32 r; + int rev = imx_silicon_revision(); imx5_init_lowlevel(); /* disable write combine for TO 2 and lower revs */ - if (imx_silicon_revision() < IMX_CHIP_REV_3_0) { + if (rev < IMX_CHIP_REV_3_0) { __asm__ __volatile__("mrc 15, 1, %0, c9, c0, 1":"=r"(r)); r |= (1 << 25); __asm__ __volatile__("mcr 15, 1, %0, c9, c0, 1" : : "r"(r)); @@ -135,7 +186,10 @@ void imx51_init_lowlevel(unsigned int cpufreq_mhz) break; default: /* Default maximum 800MHz */ - imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR); + if (rev <= IMX_CHIP_REV_3_0) + imx51_setup_pll800_bug(); + else + imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR); break; } diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index 7a7ce15c46..5c20aa1841 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -57,6 +57,9 @@ static int imx6_init(void) { imx6_boot_save_loc((void *)MX6_SRC_BASE_ADDR); + if (of_get_root_node()) + return 0; + add_generic_device("imx-iomuxv3", 0, NULL, MX6_IOMUXC_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx6-ccm", 0, NULL, MX6_CCM_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); add_generic_device("imx31-gpt", 0, NULL, MX6_GPT_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); diff --git a/arch/arm/mach-imx/include/mach/devices-imx1.h b/arch/arm/mach-imx/include/mach/devices-imx1.h index 391c1a9c8e..e4185bc281 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx1.h +++ b/arch/arm/mach-imx/include/mach/devices-imx1.h @@ -1,4 +1,5 @@ #include <mach/devices.h> +#include <mach/imx1-regs.h> static inline struct device_d *imx1_add_uart0(void) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx21.h b/arch/arm/mach-imx/include/mach/devices-imx21.h index ad7ee5ed02..5b2dfd7505 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx21.h +++ b/arch/arm/mach-imx/include/mach/devices-imx21.h @@ -1,5 +1,6 @@ #include <mach/devices.h> +#include <mach/imx21-regs.h> static inline struct device_d *imx21_add_uart0(void) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx25.h b/arch/arm/mach-imx/include/mach/devices-imx25.h index a655be9564..5b582b88cd 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx25.h +++ b/arch/arm/mach-imx/include/mach/devices-imx25.h @@ -1,5 +1,6 @@ #include <mach/devices.h> +#include <mach/imx25-regs.h> static inline struct device_d *imx25_add_i2c0(struct i2c_platform_data *pdata) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx27.h b/arch/arm/mach-imx/include/mach/devices-imx27.h index d6c884a30a..87a3a7cc1c 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx27.h +++ b/arch/arm/mach-imx/include/mach/devices-imx27.h @@ -1,5 +1,6 @@ #include <mach/devices.h> +#include <mach/imx27-regs.h> static inline struct device_d *imx27_add_spi0(struct spi_imx_master *pdata) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx35.h b/arch/arm/mach-imx/include/mach/devices-imx35.h index 912c41872e..766610de9d 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx35.h +++ b/arch/arm/mach-imx/include/mach/devices-imx35.h @@ -1,5 +1,6 @@ #include <mach/devices.h> +#include <mach/imx35-regs.h> static inline struct device_d *imx35_add_i2c0(struct i2c_platform_data *pdata) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h index ec8467ae9c..00644788a7 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx51.h +++ b/arch/arm/mach-imx/include/mach/devices-imx51.h @@ -1,6 +1,7 @@ -#include <mach/devices.h> #include <sizes.h> +#include <mach/devices.h> +#include <mach/imx51-regs.h> static inline struct device_d *imx51_add_spi0(struct spi_imx_master *pdata) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h index 5bdcf32291..df14654865 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx53.h +++ b/arch/arm/mach-imx/include/mach/devices-imx53.h @@ -1,5 +1,6 @@ #include <mach/devices.h> +#include <mach/imx53-regs.h> static inline struct device_d *imx53_add_spi0(struct spi_imx_master *pdata) { diff --git a/arch/arm/mach-imx/include/mach/devices-imx6.h b/arch/arm/mach-imx/include/mach/devices-imx6.h index b6b538a95b..7d41d7f02b 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx6.h +++ b/arch/arm/mach-imx/include/mach/devices-imx6.h @@ -1,4 +1,5 @@ #include <mach/devices.h> +#include <mach/imx6-regs.h> static inline struct device_d *imx6_add_uart0(void) { diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index 189b32f2c3..9958cb2f3f 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -1,6 +1,9 @@ #ifndef __MACH_GENERIC_H #define __MACH_GENERIC_H +#include <linux/compiler.h> +#include <linux/types.h> + u64 imx_uid(void); void imx25_boot_save_loc(void __iomem *ccm_base); diff --git a/arch/arm/mach-imx/include/mach/iim.h b/arch/arm/mach-imx/include/mach/iim.h index 713f0de057..1d2814919b 100644 --- a/arch/arm/mach-imx/include/mach/iim.h +++ b/arch/arm/mach-imx/include/mach/iim.h @@ -38,10 +38,6 @@ #define IIM_SCS2 0x0034 #define IIM_SCS3 0x0038 -struct imx_iim_platform_data { - unsigned long mac_addr_base; -}; - #ifdef CONFIG_IMX_IIM int imx_iim_read(unsigned int bank, int offset, void *buf, int count); #else diff --git a/arch/arm/mach-imx/include/mach/imx5.h b/arch/arm/mach-imx/include/mach/imx5.h index 7f5c2eff50..5d1a7d7d40 100644 --- a/arch/arm/mach-imx/include/mach/imx5.h +++ b/arch/arm/mach-imx/include/mach/imx5.h @@ -9,6 +9,7 @@ void imx5_init_lowlevel(void); void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn); #define imx5_setup_pll_1000(base) imx5_setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5) +#define imx5_setup_pll_864(base) imx5_setup_pll((base), 864, (( 8 << 4) + ((1 - 1) << 0)), (180 - 1), 180) #define imx5_setup_pll_800(base) imx5_setup_pll((base), 800, (( 8 << 4) + ((1 - 1) << 0)), (3 - 1), 1) #define imx5_setup_pll_665(base) imx5_setup_pll((base), 665, (( 6 << 4) + ((1 - 1) << 0)), (96 - 1), 89) #define imx5_setup_pll_600(base) imx5_setup_pll((base), 600, (( 6 << 4) + ((1 - 1) << 0)), ( 4 - 1), 1) diff --git a/arch/arm/mach-imx/include/mach/iomux-v1.h b/arch/arm/mach-imx/include/mach/iomux-v1.h index 55fbcdb94e..49dcecd1de 100644 --- a/arch/arm/mach-imx/include/mach/iomux-v1.h +++ b/arch/arm/mach-imx/include/mach/iomux-v1.h @@ -1,6 +1,8 @@ #ifndef __MACH_IOMUX_V1_H__ #define __MACH_IOMUX_V1_H__ +#include <linux/compiler.h> + #define GPIO_PIN_MASK 0x1f #define GPIO_PORT_SHIFT 5 diff --git a/arch/arm/mach-imx/include/mach/weim.h b/arch/arm/mach-imx/include/mach/weim.h index 8d572dc0bf..3fbbb6ba8e 100644 --- a/arch/arm/mach-imx/include/mach/weim.h +++ b/arch/arm/mach-imx/include/mach/weim.h @@ -1,6 +1,8 @@ #ifndef __MACH_WEIM_H #define __MACH_WEIM_H +#include <linux/types.h> + void imx27_setup_weimcs(size_t cs, unsigned upper, unsigned lower, unsigned additional); diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig new file mode 100644 index 0000000000..11e4550ec5 --- /dev/null +++ b/arch/arm/mach-mvebu/Kconfig @@ -0,0 +1,124 @@ +if ARCH_MVEBU + +config ARCH_TEXT_BASE + hex + default 0x2000000 if MACH_PLATHOME_OPENBLOCKS_AX3 + default 0x2000000 if MACH_GLOBALSCALE_MIRABOX + default 0x2000000 if MACH_GLOBALSCALE_GURUPLUG + default 0x2000000 if MACH_MARVELL_ARMADA_XP_GP + default 0x2000000 if MACH_SOLIDRUN_CUBOX + +config BOARDINFO + default "PlatHome OpenBlocks AX3" if MACH_PLATHOME_OPENBLOCKS_AX3 + default "Globalscale Mirabox" if MACH_GLOBALSCALE_MIRABOX + default "Globalscale Guruplug" if MACH_GLOBALSCALE_GURUPLUG + default "Marvell Armada XP GP" if MACH_MARVELL_ARMADA_XP_GP + default "SolidRun CuBox" if MACH_SOLIDRUN_CUBOX + +choice + prompt "Marvell EBU Processor" + +config ARCH_ARMADA_370 + bool "Armada 370" + select CPU_V7 + select CLOCKSOURCE_MVEBU + +config ARCH_ARMADA_XP + bool "Armada XP" + select CPU_V7 + select CLOCKSOURCE_MVEBU + +config ARCH_DOVE + bool "Dove 88AP510" + select CPU_V7 + select CLOCKSOURCE_ORION + +config ARCH_KIRKWOOD + bool "Kirkwood" + select CPU_FEROCEON + select CLOCKSOURCE_ORION + +endchoice + +# +# Armada 370 SoC boards +# + +if ARCH_ARMADA_370 + +choice + prompt "Armada 370 Board Type" + +config MACH_GLOBALSCALE_MIRABOX + bool "Globalscale Mirabox" + +endchoice + +endif # ARCH_ARMADA_370 + +# +# Armada XP SoC boards +# + +if ARCH_ARMADA_XP + +choice + prompt "Armada XP Board Type" + +config MACH_PLATHOME_OPENBLOCKS_AX3 + bool "PlatHome OpenBlocks AX3" + +config MACH_MARVELL_ARMADA_XP_GP + bool "Marvell Armada XP GP" + +endchoice + +endif # ARCH_ARMADA_XP + +# +# Dove 88AP510 SoC boards +# + +if ARCH_DOVE + +choice + prompt "Dove 88AP510 Board Type" + +config MACH_SOLIDRUN_CUBOX + bool "SolidRun CuBox" + +endchoice + +endif # ARCH_DOVE + +# +# Kirkwood SoC boards +# + +if ARCH_KIRKWOOD + +choice + prompt "Kirkwood Board Type" + +config MACH_GLOBALSCALE_GURUPLUG + bool "Guruplug" + +endchoice + +endif # ARCH_KIRKWOOD + +# +# Common options +# + +config MVEBU_CONSOLE_UART + int "UART number for console" + default 0 + range 0 1 if ARCH_ARMADA_370 + range 0 1 if ARCH_ARMADA_XP + range 0 3 if ARCH_DOVE + range 0 1 if ARCH_KIRKWOOD + help + Select the UART number the barebox console will sit on. + +endif # ARCH_MVEBU diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile new file mode 100644 index 0000000000..80b3947cc8 --- /dev/null +++ b/arch/arm/mach-mvebu/Makefile @@ -0,0 +1,6 @@ +lwl-y += lowlevel.o +obj-y += common.o +obj-$(CONFIG_ARCH_ARMADA_370) += armada-370-xp.o +obj-$(CONFIG_ARCH_ARMADA_XP) += armada-370-xp.o +obj-$(CONFIG_ARCH_DOVE) += dove.o +obj-$(CONFIG_ARCH_KIRKWOOD) += kirkwood.o diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c new file mode 100644 index 0000000000..2cdc3b0cbc --- /dev/null +++ b/arch/arm/mach-mvebu/armada-370-xp.c @@ -0,0 +1,121 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <ns16550.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <asm/memory.h> +#include <mach/armada-370-xp-regs.h> + +#define CONSOLE_UART_BASE \ + ARMADA_370_XP_UARTn_BASE(CONFIG_MVEBU_CONSOLE_UART) + +static struct clk *tclk; + +static inline void armada_370_xp_memory_find(unsigned long *phys_base, + unsigned long *phys_size) +{ + int cs; + + *phys_base = ~0; + *phys_size = 0; + + for (cs = 0; cs < 4; cs++) { + u32 base = readl(ARMADA_370_XP_SDRAM_BASE + DDR_BASE_CSn(cs)); + u32 ctrl = readl(ARMADA_370_XP_SDRAM_BASE + DDR_SIZE_CSn(cs)); + + /* Skip non-enabled CS */ + if ((ctrl & DDR_SIZE_ENABLED) != DDR_SIZE_ENABLED) + continue; + + base &= DDR_BASE_CS_LOW_MASK; + if (base < *phys_base) + *phys_base = base; + *phys_size += (ctrl | ~DDR_SIZE_MASK) + 1; + } +} + +static struct NS16550_plat uart_plat = { + .shift = 2, +}; + +static int armada_370_xp_add_uart(void) +{ + uart_plat.clock = clk_get_rate(tclk); + if (!add_ns16550_device(DEVICE_ID_DYNAMIC, + (unsigned int)CONSOLE_UART_BASE, 32, + IORESOURCE_MEM_32BIT, &uart_plat)) + return -ENODEV; + return 0; +} + +#if defined(CONFIG_ARCH_ARMADA_370) +static int armada_370_init_clocks(void) +{ + u32 val = readl(ARMADA_370_XP_SAR_BASE + SAR_LOW); + unsigned int rate; + + /* + * On Armada 370, the TCLK frequency can be either + * 166 Mhz or 200 Mhz + */ + if ((val & SAR_TCLK_FREQ) == SAR_TCLK_FREQ) + rate = 200000000; + else + rate = 166000000; + + tclk = clk_fixed("tclk", rate); + return clk_register_clkdev(tclk, NULL, "mvebu-timer"); +} +#define armada_370_xp_init_clocks() armada_370_init_clocks() +#endif + +#if defined(CONFIG_ARCH_ARMADA_XP) +static int armada_xp_init_clocks(void) +{ + /* On Armada XP, the TCLK frequency is always 250 Mhz */ + tclk = clk_fixed("tclk", 250000000); + return clk_register_clkdev(tclk, NULL, "mvebu-timer"); +} +#define armada_370_xp_init_clocks() armada_xp_init_clocks() +#endif + +static int armada_370_xp_init_soc(void) +{ + unsigned long phys_base, phys_size; + + armada_370_xp_init_clocks(); + add_generic_device("mvebu-timer", DEVICE_ID_SINGLE, NULL, + (unsigned int)ARMADA_370_XP_TIMER_BASE, 0x30, + IORESOURCE_MEM, NULL); + armada_370_xp_memory_find(&phys_base, &phys_size); + arm_add_mem_device("ram0", phys_base, phys_size); + armada_370_xp_add_uart(); + return 0; +} +postcore_initcall(armada_370_xp_init_soc); + +void __noreturn reset_cpu(unsigned long addr) +{ + writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x60); + writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x64); + while (1) + ; +} +EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c new file mode 100644 index 0000000000..e2092c8705 --- /dev/null +++ b/arch/arm/mach-mvebu/common.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * Sebastian Hesselbarth <sebastian.hesselbarth@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. + * + */ + +#include <common.h> +#include <io.h> +#include <sizes.h> +#include <asm/barebox-arm.h> +#include <mach/common.h> + +/* + * All MVEBU SoCs start with internal registers at 0xd0000000. + * To get more contiguous address space and as Linux expects them + * there, we remap them early to 0xf1000000. + * + * There is no way to determine internal registers base address + * safely later on, as the remap register itself is within the + * internal registers. + */ +#define MVEBU_BOOTUP_INT_REG_BASE 0xd0000000 +#define MVEBU_BRIDGE_REG_BASE 0x20000 +#define DEVICE_INTERNAL_BASE_ADDR (MVEBU_BRIDGE_REG_BASE + 0x80) + +static void mvebu_remap_registers(void) +{ + writel(MVEBU_REMAP_INT_REG_BASE, + IOMEM(MVEBU_BOOTUP_INT_REG_BASE) + DEVICE_INTERNAL_BASE_ADDR); +} + +/* + * Determining the actual memory size is highly SoC dependent, + * but for all SoCs RAM starts at 0x00000000. Therefore, we start + * with a minimal memory setup of 64M and probe correct memory size + * later. + */ +#define MVEBU_BOOTUP_MEMORY_BASE 0x00000000 +#define MVEBU_BOOTUP_MEMORY_SIZE SZ_64M + +void __naked __noreturn mvebu_barebox_entry(void) +{ + mvebu_remap_registers(); + barebox_arm_entry(MVEBU_BOOTUP_MEMORY_BASE, + MVEBU_BOOTUP_MEMORY_SIZE, 0); +} diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c new file mode 100644 index 0000000000..6e8e1130ec --- /dev/null +++ b/arch/arm/mach-mvebu/dove.c @@ -0,0 +1,145 @@ +/* + * Copyright + * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@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. + * + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <ns16550.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <asm/memory.h> +#include <mach/dove-regs.h> + +#define CONSOLE_UART_BASE DOVE_UARTn_BASE(CONFIG_MVEBU_CONSOLE_UART) + +static struct clk *tclk; + +static inline void dove_remap_mc_regs(void) +{ + void __iomem *mcboot = IOMEM(DOVE_BOOTUP_MC_REGS); + uint32_t val; + + /* remap ahb slave base */ + val = readl(DOVE_CPU_CTRL) & 0xffff0000; + val |= (DOVE_REMAP_MC_REGS & 0xffff0000) >> 16; + writel(val, DOVE_CPU_CTRL); + + /* remap axi bridge address */ + val = readl(DOVE_AXI_CTRL) & 0x007fffff; + val |= DOVE_REMAP_MC_REGS & 0xff800000; + writel(val, DOVE_AXI_CTRL); + + /* remap memory controller base address */ + val = readl(mcboot + SDRAM_REGS_BASE_DECODE) & 0x0000ffff; + val |= DOVE_REMAP_MC_REGS & 0xffff0000; + writel(val, mcboot + SDRAM_REGS_BASE_DECODE); +} + +static inline void dove_memory_find(unsigned long *phys_base, + unsigned long *phys_size) +{ + int n; + + *phys_base = ~0; + *phys_size = 0; + + for (n = 0; n < 2; n++) { + uint32_t map = readl(DOVE_SDRAM_BASE + SDRAM_MAPn(n)); + uint32_t base, size; + + /* skip disabled areas */ + if ((map & SDRAM_MAP_VALID) != SDRAM_MAP_VALID) + continue; + + base = map & SDRAM_START_MASK; + if (base < *phys_base) + *phys_base = base; + + /* real size is encoded as ld(2^(16+length)) */ + size = (map & SDRAM_LENGTH_MASK) >> SDRAM_LENGTH_SHIFT; + *phys_size += 1 << (16 + size); + } +} + +static struct NS16550_plat uart_plat = { + .shift = 2, +}; + +static int dove_add_uart(void) +{ + uart_plat.clock = clk_get_rate(tclk); + if (!add_ns16550_device(DEVICE_ID_DYNAMIC, + (unsigned int)CONSOLE_UART_BASE, 32, + IORESOURCE_MEM_32BIT, &uart_plat)) + return -ENODEV; + return 0; +} + +/* + * Dove TCLK sample-at-reset configuation + * + * SAR0[24:23] : TCLK frequency + * 0 = 166 MHz + * 1 = 125 MHz + * others reserved. + */ +static int dove_init_clocks(void) +{ + uint32_t strap, sar = readl(DOVE_SAR_BASE + SAR0); + unsigned int rate; + + strap = (sar & TCLK_FREQ_MASK) >> TCLK_FREQ_SHIFT; + switch (strap) { + case 0: + rate = 166666667; + break; + case 1: + rate = 125000000; + break; + default: + panic("Unknown TCLK strapping %d\n", strap); + } + + tclk = clk_fixed("tclk", rate); + return clk_register_clkdev(tclk, NULL, "orion-timer"); +} + +static int dove_init_soc(void) +{ + unsigned long phys_base, phys_size; + + dove_remap_mc_regs(); + dove_init_clocks(); + add_generic_device("orion-timer", DEVICE_ID_SINGLE, NULL, + (unsigned int)DOVE_TIMER_BASE, 0x30, + IORESOURCE_MEM, NULL); + dove_memory_find(&phys_base, &phys_size); + arm_add_mem_device("ram0", phys_base, phys_size); + dove_add_uart(); + + return 0; +} +postcore_initcall(dove_init_soc); + +void __noreturn reset_cpu(unsigned long addr) +{ + /* enable and assert RSTOUTn */ + writel(SOFT_RESET_OUT_EN, DOVE_BRIDGE_BASE + BRIDGE_RSTOUT_MASK); + writel(SOFT_RESET_EN, DOVE_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET); + while (1) + ; +} +EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h b/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h new file mode 100644 index 0000000000..5fd16e5733 --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h @@ -0,0 +1,47 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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 __MACH_MVEBU_ARMADA_370_XP_REGS_H +#define __MACH_MVEBU_ARMADA_370_XP_REGS_H + +#include <mach/common.h> + +#define ARMADA_370_XP_INT_REGS_BASE IOMEM(MVEBU_REMAP_INT_REG_BASE) +#define ARMADA_370_XP_UART_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x12000) +#define ARMADA_370_XP_UARTn_BASE(n) \ + (ARMADA_370_XP_UART_BASE + ((n) * 0x100)) + +#define ARMADA_370_XP_SYSCTL_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x18200) +#define ARMADA_370_XP_SAR_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x18230) +#define SAR_LOW 0x00 +#define SAR_TCLK_FREQ BIT(20) +#define SAR_HIGH 0x04 + +#define ARMADA_370_XP_SDRAM_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x20000) +#define DDR_BASE_CS 0x180 +#define DDR_BASE_CSn(n) (DDR_BASE_CS + ((n) * 0x8)) +#define DDR_BASE_CS_HIGH_MASK 0x0000000f +#define DDR_BASE_CS_LOW_MASK 0xff000000 +#define DDR_SIZE_CS 0x184 +#define DDR_SIZE_CSn(n) (DDR_SIZE_CS + ((n) * 0x8)) +#define DDR_SIZE_ENABLED BIT(0) +#define DDR_SIZE_CS_MASK 0x0000001c +#define DDR_SIZE_CS_SHIFT 2 +#define DDR_SIZE_MASK 0xff000000 + +#define ARMADA_370_XP_TIMER_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x20300) + +#endif /* __MACH_MVEBU_DOVE_REGS_H */ diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h new file mode 100644 index 0000000000..3cc1bf71c0 --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/common.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2013 + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * Sebastian Hesselbarth <sebastian.hesselbarth@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 __MACH_COMMON_H__ +#define __MACH_COMMON_H__ + +#define MVEBU_REMAP_INT_REG_BASE 0xf1000000 + +#endif diff --git a/arch/arm/mach-mvebu/include/mach/debug_ll.h b/arch/arm/mach-mvebu/include/mach/debug_ll.h new file mode 100644 index 0000000000..1cf821ee2a --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/debug_ll.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 + * Thomas Petazzoni <thomas.petazzoni@free-electrons.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 __MACH_DEBUG_LL_H__ +#define __MACH_DEBUG_LL_H__ + +#include <io.h> + +#define UART_BASE 0xf1012000 +#define UARTn_BASE(n) (UART_BASE + ((n) * 0x100)) +#define UART_THR 0x00 +#define UART_LSR 0x14 +#define LSR_THRE BIT(5) + +#define EARLY_UART UARTn_BASE(CONFIG_MVEBU_CONSOLE_UART) + +static inline void PUTC_LL(char c) +{ + /* Wait until there is space in the FIFO */ + while (!(readl(EARLY_UART + UART_LSR) & LSR_THRE)) + ; + + /* Send the character */ + writel(c, EARLY_UART + UART_THR); + + /* Wait to make sure it hits the line */ + while (!(readl(EARLY_UART + UART_LSR) & LSR_THRE)) + ; +} +#endif diff --git a/arch/arm/mach-mvebu/include/mach/dove-regs.h b/arch/arm/mach-mvebu/include/mach/dove-regs.h new file mode 100644 index 0000000000..519457e3d4 --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/dove-regs.h @@ -0,0 +1,62 @@ +/* + * Copyright + * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@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 __MACH_MVEBU_DOVE_REGS_H +#define __MACH_MVEBU_DOVE_REGS_H + +#include <mach/common.h> + +/* + * Even after MVEBU SoC internal register base remap. Dove MC + * registers are still at 0xd0800000. We remap it right after + * internal registers to 0xf1800000. +*/ +#define DOVE_BOOTUP_MC_REGS 0xd0800000 +#define DOVE_REMAP_MC_REGS 0xf1800000 + +#define DOVE_INT_REGS_BASE IOMEM(MVEBU_REMAP_INT_REG_BASE) +#define DOVE_MC_REGS_BASE IOMEM(DOVE_REMAP_MC_REGS) + +#define DOVE_UART_BASE (DOVE_INT_REGS_BASE + 0x12000) +#define DOVE_UARTn_BASE(n) (DOVE_UART_BASE + ((n) * 0x100)) + +#define DOVE_BRIDGE_BASE (DOVE_INT_REGS_BASE + 0x20000) +#define INT_REGS_BASE_MAP 0x080 +#define BRIDGE_RSTOUT_MASK 0x108 +#define SOFT_RESET_OUT_EN BIT(2) +#define BRIDGE_SYS_SOFT_RESET 0x10c +#define SOFT_RESET_EN BIT(0) +#define DOVE_TIMER_BASE (DOVE_INT_REGS_BASE + 0x20300) + +#define DOVE_SAR_BASE (DOVE_INT_REGS_BASE + 0xd0214) +#define SAR0 0x000 +#define TCLK_FREQ_SHIFT 23 +#define TCLK_FREQ_MASK (0x3 << TCLK_FREQ_SHIFT) +#define SAR1 0x004 + +#define DOVE_AXI_CTRL (DOVE_INT_REGS_BASE + 0xd0224) +#define DOVE_CPU_CTRL (DOVE_INT_REGS_BASE + 0xd025c) + +#define DOVE_SDRAM_BASE (DOVE_MC_REGS_BASE) +#define SDRAM_REGS_BASE_DECODE 0x010 +#define SDRAM_MAPn(n) (0x100 + ((n) * 0x10)) +#define SDRAM_START_MASK (0x1ff << 23) +#define SDRAM_LENGTH_SHIFT 16 +#define SDRAM_LENGTH_MASK (0x00f << SDRAM_LENGTH_SHIFT) +#define SDRAM_ADDRESS_MASK (0x1ff << 7) +#define SDRAM_MAP_VALID BIT(0) + +#endif /* __MACH_MVEBU_DOVE_REGS_H */ diff --git a/arch/arm/mach-mvebu/include/mach/dove.h b/arch/arm/mach-mvebu/include/mach/dove.h new file mode 100644 index 0000000000..1712fa7a1d --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/dove.h @@ -0,0 +1,23 @@ +/* + * Copyright + * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@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 __MACH_MVEBU_DOVE_H +#define __MACH_MVEBU_DOVE_H + +int dove_add_uart(int num); +void __naked __noreturn dove_barebox_entry(void); + +#endif /* __MACH_MVEBU_DOVE_H */ diff --git a/arch/arm/mach-mvebu/include/mach/kirkwood-regs.h b/arch/arm/mach-mvebu/include/mach/kirkwood-regs.h new file mode 100644 index 0000000000..39fa37900b --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/kirkwood-regs.h @@ -0,0 +1,50 @@ +/* + * Copyright + * (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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 __MACH_MVEBU_KIRKWOOD_REGS_H +#define __MACH_MVEBU_KIRKWOOD_REGS_H + +#include <mach/common.h> + +#define KIRKWOOD_INT_REGS_BASE IOMEM(MVEBU_REMAP_INT_REG_BASE) + +#define KIRKWOOD_SDRAM_BASE (KIRKWOOD_INT_REGS_BASE + 0x00000) +#define DDR_BASE_CS 0x1500 +#define DDR_BASE_CSn(n) (DDR_BASE_CS + ((n) * 0x8)) +#define DDR_BASE_CS_HIGH_MASK 0x0000000f +#define DDR_BASE_CS_LOW_MASK 0xff000000 +#define DDR_SIZE_CS 0x1504 +#define DDR_SIZE_CSn(n) (DDR_SIZE_CS + ((n) * 0x8)) +#define DDR_SIZE_ENABLED BIT(0) +#define DDR_SIZE_CS_MASK 0x1c +#define DDR_SIZE_CS_SHIFT 2 +#define DDR_SIZE_MASK 0xff000000 + +#define KIRKWOOD_SAR_BASE (KIRKWOOD_INT_REGS_BASE + 0x10030) +#define SAR_TCLK_FREQ BIT(21) + +#define KIRKWOOD_UART_BASE (KIRKWOOD_INT_REGS_BASE + 0x12000) +#define KIRKWOOD_UARTn_BASE(n) (KIRKWOOD_UART_BASE + ((n) * 0x100)) + +#define KIRKWOOD_BRIDGE_BASE (KIRKWOOD_INT_REGS_BASE + 0x20000) +#define BRIDGE_RSTOUT_MASK 0x108 +#define SOFT_RESET_OUT_EN BIT(2) +#define BRIDGE_SYS_SOFT_RESET 0x10c +#define SOFT_RESET_EN BIT(0) + +#define KIRKWOOD_TIMER_BASE (KIRKWOOD_INT_REGS_BASE + 0x20300) + +#endif /* __MACH_MVEBU_KIRKWOOD_REGS_H */ diff --git a/arch/arm/mach-mvebu/include/mach/kirkwood.h b/arch/arm/mach-mvebu/include/mach/kirkwood.h new file mode 100644 index 0000000000..7fe002d44d --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/kirkwood.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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 __MACH_KIRKWOOD_H +#define __MACH_KIRKWOOD_H + +int kirkwood_add_uart0(void); +void __naked __noreturn kirkwood_barebox_entry(void); + +#endif /* __MACH_KIRKWOOD_H */ diff --git a/arch/arm/mach-mvebu/include/mach/lowlevel.h b/arch/arm/mach-mvebu/include/mach/lowlevel.h new file mode 100644 index 0000000000..e86d928f63 --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/lowlevel.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2013 + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * Sebastian Hesselbarth <sebastian.hesselbarth@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 __MACH_LOWLEVEL_H__ +#define __MACH_LOWLEVEL_H__ + +void mvebu_barebox_entry(void); + +#endif diff --git a/arch/arm/mach-mvebu/include/mach/mvebu.h b/arch/arm/mach-mvebu/include/mach/mvebu.h new file mode 100644 index 0000000000..e13a446fca --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/mvebu.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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 __MACH_MVEBU_H +#define __MACH_MVEBU_H + +int mvebu_add_uart0(void); +void __naked __noreturn mvebu_barebox_entry(void); + +#endif /* __MACH_MVEBU_H */ diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c new file mode 100644 index 0000000000..3e16f410be --- /dev/null +++ b/arch/arm/mach-mvebu/kirkwood.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <ns16550.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <asm/memory.h> +#include <mach/kirkwood-regs.h> + +#define CONSOLE_UART_BASE KIRKWOOD_UARTn_BASE(CONFIG_MVEBU_CONSOLE_UART) + +static struct clk *tclk; + +static inline void kirkwood_memory_find(unsigned long *phys_base, + unsigned long *phys_size) +{ + int cs; + + *phys_base = ~0; + *phys_size = 0; + + for (cs = 0; cs < 4; cs++) { + u32 base = readl(KIRKWOOD_SDRAM_BASE + DDR_BASE_CSn(cs)); + u32 ctrl = readl(KIRKWOOD_SDRAM_BASE + DDR_SIZE_CSn(cs)); + + /* Skip non-enabled CS */ + if ((ctrl & DDR_SIZE_ENABLED) != DDR_SIZE_ENABLED) + continue; + + base &= DDR_BASE_CS_LOW_MASK; + if (base < *phys_base) + *phys_base = base; + *phys_size += (ctrl | ~DDR_SIZE_MASK) + 1; + } +} + +static struct NS16550_plat uart_plat = { + .shift = 2, +}; + +static int kirkwood_add_uart(void) +{ + uart_plat.clock = clk_get_rate(tclk); + if (!add_ns16550_device(DEVICE_ID_DYNAMIC, + (unsigned int)CONSOLE_UART_BASE, 32, + IORESOURCE_MEM_32BIT, &uart_plat)) + return -ENODEV; + return 0; +} + +static int kirkwood_init_clocks(void) +{ + u32 val = readl(KIRKWOOD_SAR_BASE); + unsigned int rate; + + /* + * On Kirkwood, the TCLK frequency can be either + * 166 Mhz or 200 Mhz + */ + if ((val & SAR_TCLK_FREQ) == SAR_TCLK_FREQ) + rate = 166666667; + else + rate = 200000000; + + tclk = clk_fixed("tclk", rate); + return clk_register_clkdev(tclk, NULL, "orion-timer"); +} + +static int kirkwood_init_soc(void) +{ + unsigned long phys_base, phys_size; + + kirkwood_init_clocks(); + add_generic_device("orion-timer", DEVICE_ID_SINGLE, NULL, + (unsigned int)KIRKWOOD_TIMER_BASE, 0x30, + IORESOURCE_MEM, NULL); + kirkwood_memory_find(&phys_base, &phys_size); + arm_add_mem_device("ram0", phys_base, phys_size); + kirkwood_add_uart(); + + return 0; +} +postcore_initcall(kirkwood_init_soc); + +void __noreturn reset_cpu(unsigned long addr) +{ + writel(SOFT_RESET_OUT_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_RSTOUT_MASK); + writel(SOFT_RESET_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET); + for(;;) + ; +} +EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-mvebu/lowlevel.c b/arch/arm/mach-mvebu/lowlevel.c new file mode 100644 index 0000000000..3f64c4a5b4 --- /dev/null +++ b/arch/arm/mach-mvebu/lowlevel.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * Sebastian Hesselbarth <sebastian.hesselbarth@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. + * + */ + +#include <common.h> +#include <sizes.h> +#include <asm/barebox-arm.h> +#include <asm/barebox-arm-head.h> +#include <mach/lowlevel.h> + +void __naked barebox_arm_reset_vector(void) +{ + arm_cpu_lowlevel_init(); + mvebu_barebox_entry(); +} diff --git a/arch/arm/mach-mxs/imx.c b/arch/arm/mach-mxs/imx.c index fcb26f73b3..5acce9376a 100644 --- a/arch/arm/mach-mxs/imx.c +++ b/arch/arm/mach-mxs/imx.c @@ -112,6 +112,48 @@ static void mxs_silicon_revision(void) silicon_revision_set(product, revision); } +#define HW_PINCTRL_MUXSEL2 0x120 +#define HW_PINCTRL_MUXSEL3 0x130 +#define HW_PINCTRL_DOE1 0x710 +#define HW_PINCTRL_DIN1 0x610 + +/* + * we are interested in the setting of: + * - GPIO BANK1/19: 1 = the ROM has used the following pins for boot source selection + * - GPIO BANK1/5: ETM enable + * - GPIO BANK1/3: BM3 + * - GPIO BANK1/2: BM2 + * - GPIO BANK1/1: BM1 + * - GPIO BANK1/0: BM0 + */ +static uint32_t mx23_detect_bootsource(void) +{ + uint32_t mux2, mux3, dir, mode; + + mux3 = readl(IMX_IOMUXC_BASE + HW_PINCTRL_MUXSEL3); + mux2 = readl(IMX_IOMUXC_BASE + HW_PINCTRL_MUXSEL2); + dir = readl(IMX_IOMUXC_BASE + HW_PINCTRL_DOE1); + + /* force the GPIO lines of interest to input */ + writel(0x0008002f, IMX_IOMUXC_BASE + HW_PINCTRL_DOE1 + 8); + /* force the GPIO lines of interest to act as GPIO */ + writel(0x00000cff, IMX_IOMUXC_BASE + HW_PINCTRL_MUXSEL2 + 4); + writel(0x000000c0, IMX_IOMUXC_BASE + HW_PINCTRL_MUXSEL3 + 4); + + /* read the bootstrapping */ + mode = readl(IMX_IOMUXC_BASE + HW_PINCTRL_DIN1) & 0x8002f; + + /* restore previous settings */ + writel(mux3, IMX_IOMUXC_BASE + HW_PINCTRL_MUXSEL3); + writel(mux2, IMX_IOMUXC_BASE + HW_PINCTRL_MUXSEL2); + writel(dir, IMX_IOMUXC_BASE + HW_PINCTRL_DOE1); + + if (!(mode & (1 << 19))) + return 0xff; /* invalid marker */ + + return (mode & 0xf) | ((mode & 0x20) >> 1); +} + #define MX28_REV_1_0_MODE (0x0001a7f0) #define MX28_REV_1_2_MODE (0x00019bf0) @@ -122,7 +164,7 @@ static void mxs_boot_save_loc(void) uint32_t mode = 0xff; if (cpu_is_mx23()) { - /* not implemented yet */ + mode = mx23_detect_bootsource(); } else if (cpu_is_mx28()) { enum silicon_revision rev = silicon_revision_get(); diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig index f7aa8c5a28..3ec18f0c4d 100644 --- a/arch/arm/mach-omap/Kconfig +++ b/arch/arm/mach-omap/Kconfig @@ -214,6 +214,18 @@ endchoice endif +if MACH_PCM049 + choice + prompt "Select DDR2-RAM Size" + + config 512MB_DDR2RAM + bool "512MB" + config 1024MB_DDR2RAM + bool "1024MB" + + endchoice +endif + config MACH_OMAP_ADVANCED_MUX bool "Enable advanced pin muxing" depends on MACH_OMAP343xSDP diff --git a/arch/arm/mach-omap/am33xx_clock.c b/arch/arm/mach-omap/am33xx_clock.c index a28540c919..4451d62268 100644 --- a/arch/arm/mach-omap/am33xx_clock.c +++ b/arch/arm/mach-omap/am33xx_clock.c @@ -89,6 +89,14 @@ static void per_clocks_enable(void) __raw_writel(PRCM_MOD_EN, CM_WKUP_UART0_CLKCTRL); while (__raw_readl(CM_WKUP_UART0_CLKCTRL) != PRCM_MOD_EN); + /* UART1 */ + __raw_writel(PRCM_MOD_EN, CM_PER_UART1_CLKCTRL); + while (__raw_readl(CM_PER_UART1_CLKCTRL) != PRCM_MOD_EN); + + /* UART2 */ + __raw_writel(PRCM_MOD_EN, CM_PER_UART2_CLKCTRL); + while (__raw_readl(CM_PER_UART2_CLKCTRL) != PRCM_MOD_EN); + /* UART3 */ __raw_writel(PRCM_MOD_EN, CM_PER_UART3_CLKCTRL); while (__raw_readl(CM_PER_UART3_CLKCTRL) != PRCM_MOD_EN); diff --git a/arch/arm/mach-omap/am33xx_mux.c b/arch/arm/mach-omap/am33xx_mux.c index 36fe3792d1..424d120125 100644 --- a/arch/arm/mach-omap/am33xx_mux.c +++ b/arch/arm/mach-omap/am33xx_mux.c @@ -27,6 +27,12 @@ static const __maybe_unused struct module_pin_mux uart0_pin_mux[] = { {-1}, }; +static const __maybe_unused struct module_pin_mux uart2_pin_mux[] = { + {OFFSET(mii1_txclk), (MODE(1) | PULLUDEN | RXACTIVE)}, /* UART2_RXD */ + {OFFSET(mii1_rxclk), (MODE(1) | PULLUDEN)}, /* UART2_TXD */ + {-1}, +}; + static const __maybe_unused struct module_pin_mux uart3_pin_mux[] = { {OFFSET(spi0_cs1), (MODE(1) | PULLUDEN | RXACTIVE)}, /* UART3_RXD */ {OFFSET(ecap0_in_pwm0_out), (MODE(1) | PULLUDEN)}, /* UART3_TXD */ @@ -142,6 +148,20 @@ static const __maybe_unused struct module_pin_mux rmii1_pin_mux[] = { {-1}, }; +static const __maybe_unused struct module_pin_mux rmii2_pin_mux[] = { + {OFFSET(gpmc_a0), MODE(3)}, /* RMII2_TXEN */ + {OFFSET(gpmc_a4), MODE(3)}, /* RMII2_TXD1 */ + {OFFSET(gpmc_a5), MODE(3)}, /* RMII2_TXD0 */ + {OFFSET(gpmc_a10), MODE(3) | RXACTIVE}, /* RMII2_RXD1 */ + {OFFSET(gpmc_a11), MODE(3) | RXACTIVE}, /* RMII2_RXD0 */ + {OFFSET(gpmc_wait0), MODE(3) | RXACTIVE}, /* RMII2_CRS */ + {OFFSET(gpmc_wpn), MODE(3) | RXACTIVE}, /* RMII2_RXERR */ + {OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN}, /* MDIO_DATA */ + {OFFSET(mdio_clk), MODE(0) | PULLUP_EN}, /* MDIO_CLK */ + {OFFSET(mii1_col), MODE(1) | RXACTIVE}, /* RMII2_REFCLK */ + {-1}, +}; + #ifdef CONFIG_NOR static const __maybe_unused struct module_pin_mux nor_pin_mux[] = { {OFFSET(lcd_data0), MODE(1) | PULLUDEN}, /* NOR_A0 */ @@ -255,6 +275,16 @@ void am33xx_enable_mii1_pin_mux(void) configure_module_pin_mux(mii1_pin_mux); } +void am33xx_enable_rmii1_pin_mux(void) +{ + configure_module_pin_mux(rmii1_pin_mux); +} + +void am33xx_enable_rmii2_pin_mux(void) +{ + configure_module_pin_mux(rmii2_pin_mux); +} + void am33xx_enable_i2c0_pin_mux(void) { configure_module_pin_mux(i2c0_pin_mux); @@ -275,6 +305,11 @@ void am33xx_enable_uart0_pin_mux(void) configure_module_pin_mux(uart0_pin_mux); } +void am33xx_enable_uart2_pin_mux(void) +{ + configure_module_pin_mux(uart2_pin_mux); +} + void am33xx_enable_mmc0_pin_mux(void) { configure_module_pin_mux(mmc0_pin_mux); diff --git a/arch/arm/mach-omap/include/mach/am33xx-clock.h b/arch/arm/mach-omap/include/mach/am33xx-clock.h index 2ecfc5fc8d..3d1f074da9 100644 --- a/arch/arm/mach-omap/include/mach/am33xx-clock.h +++ b/arch/arm/mach-omap/include/mach/am33xx-clock.h @@ -136,7 +136,10 @@ #define CM_PER_GPIO1_CLKCTRL (CM_PER + 0xAC) /* GPIO1 */ #define CM_PER_GPIO2_CLKCTRL (CM_PER + 0xB0) /* GPIO2 */ #define CM_PER_GPIO3_CLKCTRL (CM_PER + 0xB4) /* GPIO3 */ +#define CM_PER_UART1_CLKCTRL (CM_PER + 0x6C) /* UART1 */ +#define CM_PER_UART2_CLKCTRL (CM_PER + 0x70) /* UART2 */ #define CM_PER_UART3_CLKCTRL (CM_PER + 0x74) /* UART3 */ +#define CM_PER_UART4_CLKCTRL (CM_PER + 0x78) /* UART4 */ #define CM_PER_I2C1_CLKCTRL (CM_PER + 0x48) /* I2C1 */ #define CM_PER_I2C2_CLKCTRL (CM_PER + 0x44) /* I2C2 */ #define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x8) /* GPIO0 */ diff --git a/arch/arm/mach-omap/include/mach/am33xx-mux.h b/arch/arm/mach-omap/include/mach/am33xx-mux.h index 896e9588eb..44b93bd25c 100644 --- a/arch/arm/mach-omap/include/mach/am33xx-mux.h +++ b/arch/arm/mach-omap/include/mach/am33xx-mux.h @@ -248,10 +248,13 @@ extern void configure_module_pin_mux(const struct module_pin_mux *mod_pin_mux); /* Standard mux settings */ extern void am33xx_enable_mii1_pin_mux(void); +extern void am33xx_enable_rmii1_pin_mux(void); +extern void am33xx_enable_rmii2_pin_mux(void); extern void am33xx_enable_i2c0_pin_mux(void); extern void am33xx_enable_i2c1_pin_mux(void); extern void am33xx_enable_i2c2_pin_mux(void); extern void am33xx_enable_uart0_pin_mux(void); +extern void am33xx_enable_uart2_pin_mux(void); extern void am33xx_enable_mmc0_pin_mux(void); #endif /*__AM33XX_MUX_H__ */ diff --git a/arch/arm/mach-omap/omap4_twl6030_mmc.c b/arch/arm/mach-omap/omap4_twl6030_mmc.c index 7d71eb868a..155add6ea1 100644 --- a/arch/arm/mach-omap/omap4_twl6030_mmc.c +++ b/arch/arm/mach-omap/omap4_twl6030_mmc.c @@ -16,7 +16,7 @@ #include <common.h> #include <io.h> -#include <mci/twl6030.h> +#include <mfd/twl6030.h> /* MMC voltage */ #define OMAP4_CONTROL_PBIASLITE 0x4A100600 @@ -24,6 +24,16 @@ #define OMAP4_MMC1_PBIASLITE_PWRDNZ (1<<22) #define OMAP4_MMC1_PWRDNZ (1<<26) +static void twl6030_mci_write(u8 address, u8 data) +{ + int ret; + struct twl6030 *twl6030 = twl6030_get(); + + ret = twl6030_reg_write(twl6030, address, data); + if (ret != 0) + printf("TWL6030 Write[0x%x] Error %d\n", address, ret); +} + void set_up_mmc_voltage_omap4(void) { u32 value; @@ -32,7 +42,12 @@ void set_up_mmc_voltage_omap4(void) value &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ); writel(value, OMAP4_CONTROL_PBIASLITE); - twl6030_mci_power_init(); + twl6030_mci_write(TWL6030_PMCS_VMMC_CFG_VOLTAGE, + TWL6030_VMMC_WR_S | + TWL6030_VMMC_VSEL_0 | TWL6030_VMMC_VSEL_2 | + TWL6030_VMMC_VSEL_4); + twl6030_mci_write(TWL6030_PMCS_VMMC_CFG_STATE, + TWL6030_VMMC_STATE0 | TWL6030_VMMC_GRP_APP); value = readl(OMAP4_CONTROL_PBIASLITE); value |= (OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PBIASLITE_PWRDNZ | diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 965e7ab6ba..9224e628cb 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -5,6 +5,7 @@ choice config ARCH_TEGRA_2x_SOC bool "Tegra 20" + select PINCTRL_TEGRA20 endchoice @@ -52,6 +53,11 @@ config ARCH_TEXT_BASE choice prompt "Tegra 20 Board Type" +config MACH_TEGRA20_GENERIC + bool "Generic DT based board" + help + Say Y here if you are building for a generic DT based board. + config MACH_TOSHIBA_AC100 bool "Toshiba AC100" help @@ -59,6 +65,13 @@ config MACH_TOSHIBA_AC100 endchoice +if MACH_TEGRA20_GENERIC + +config BOARDINFO + default "Generic Tegra20 board" + +endif #MACH_TEGRA20_GENERIC + source arch/arm/boards/toshiba-ac100/Kconfig endif #ARCH_TEGRA_2x_SOC diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 947edcf6f8..2e44619a0e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -23,6 +23,14 @@ config GENERIC_LINKER_SCRIPT menu "Machine selection" +config BUILTIN_DTB + bool "link a DTB into the barebox image" + depends on OFTREE + +config BUILTIN_DTB_NAME + string "DTB to build into the barebox image" + depends on BUILTIN_DTB + choice prompt "System type" default MACH_MIPS_MALTA @@ -37,6 +45,14 @@ config MACH_MIPS_MALTA select SYS_SUPPORTS_BIG_ENDIAN select HAS_DEBUG_LL +config MACH_MIPS_AR231X + bool "Atheros ar231x-based boards" + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select CSRC_R4K_LIB + select DRIVER_SERIAL_NS16550 + config MACH_MIPS_BCM47XX bool "Broadcom BCM47xx-based boards" select CSRC_R4K_LIB @@ -53,9 +69,12 @@ config MACH_MIPS_XBURST select SYS_SUPPORTS_32BIT_KERNEL select DRIVER_SERIAL_NS16550 select HAS_DEBUG_LL + select HAVE_PBL_IMAGE + select HAVE_IMAGE_COMPRESSION endchoice source arch/mips/mach-malta/Kconfig +source arch/mips/mach-ar231x/Kconfig source arch/mips/mach-bcm47xx/Kconfig source arch/mips/mach-xburst/Kconfig diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 3c565a48af..dc0fe56d68 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -72,6 +72,9 @@ LDFLAGS_barebox += -nostdlib machine-$(CONFIG_MACH_MIPS_MALTA) := malta board-$(CONFIG_BOARD_QEMU_MALTA) := qemu-malta +machine-$(CONFIG_MACH_MIPS_AR231X) := ar231x +board-$(CONFIG_BOARD_NETGEAR_WG102) := netgear-wg102 + machine-$(CONFIG_MACH_MIPS_BCM47XX) := bcm47xx board-$(CONFIG_BOARD_DLINK_DIR320) := dlink-dir-320 @@ -113,6 +116,8 @@ common-y += $(BOARD) $(MACH) common-y += arch/mips/lib/ common-y += arch/mips/boot/ +common-$(CONFIG_BUILTIN_DTB) += arch/mips/dts/ + CPPFLAGS += $(cflags-y) CFLAGS += $(cflags-y) @@ -127,4 +132,14 @@ zbarebox.S zbarebox.bin zbarebox: barebox.bin archclean: $(MAKE) $(clean)=$(pbl) +dts := arch/mips/dts + +%.dtb: scripts + $(Q)$(MAKE) $(build)=$(dts) $(dts)/$@ + +dtbs: scripts + $(Q)$(MAKE) $(build)=$(dts) dtbs + +KBUILD_DTBS := dtbs + KBUILD_IMAGE ?= $(KBUILD_BINARY) diff --git a/arch/mips/boards/netgear-wg102/Kconfig b/arch/mips/boards/netgear-wg102/Kconfig new file mode 100644 index 0000000000..ceca6de820 --- /dev/null +++ b/arch/mips/boards/netgear-wg102/Kconfig @@ -0,0 +1,6 @@ +if BOARD_NETGEAR_WG102 + +config BOARDINFO + default "Netgear WG102" + +endif diff --git a/arch/mips/boards/netgear-wg102/Makefile b/arch/mips/boards/netgear-wg102/Makefile new file mode 100644 index 0000000000..0899b66c5f --- /dev/null +++ b/arch/mips/boards/netgear-wg102/Makefile @@ -0,0 +1 @@ +obj-y += ram.o diff --git a/arch/mips/boards/netgear-wg102/ram.c b/arch/mips/boards/netgear-wg102/ram.c new file mode 100644 index 0000000000..00a008a1ee --- /dev/null +++ b/arch/mips/boards/netgear-wg102/ram.c @@ -0,0 +1,11 @@ +#include <common.h> +#include <init.h> +#include <sizes.h> +#include <asm/memory.h> + +static int mem_init(void) +{ + mips_add_ram0(SZ_16M); + return 0; +} +mem_initcall(mem_init); diff --git a/arch/mips/boards/qemu-malta/init.c b/arch/mips/boards/qemu-malta/init.c index fb4472fe86..db26b3b5c9 100644 --- a/arch/mips/boards/qemu-malta/init.c +++ b/arch/mips/boards/qemu-malta/init.c @@ -20,21 +20,10 @@ #include <types.h> #include <driver.h> #include <init.h> -#include <asm/memory.h> #include <ns16550.h> #include <mach/hardware.h> -#include <io.h> #include <partition.h> #include <sizes.h> -#include <asm/common.h> - -static int malta_mem_init(void) -{ - mips_add_ram0(SZ_256M); - - return 0; -} -mem_initcall(malta_mem_init); static int malta_devices_init(void) { diff --git a/arch/mips/boards/rzx50/include/board/board_pbl_start.h b/arch/mips/boards/rzx50/include/board/board_pbl_start.h new file mode 100644 index 0000000000..cba3e7f470 --- /dev/null +++ b/arch/mips/boards/rzx50/include/board/board_pbl_start.h @@ -0,0 +1,34 @@ +/* + * Startup Code for Ritmix RZX-50 board + * + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * 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. + * + */ + +#include <asm/pbl_macros.h> + + .macro board_pbl_start + .set push + .set noreorder + + mips_disable_interrupts + + /* CPU/SoC specific setup ... */ + /* ... absent */ + + copy_to_link_location pbl_start + + .set pop + .endm diff --git a/arch/mips/boards/rzx50/include/board/debug_ll.h b/arch/mips/boards/rzx50/include/board/debug_ll.h index 3d183b0a1c..7ae0e2a4fd 100644 --- a/arch/mips/boards/rzx50/include/board/debug_ll.h +++ b/arch/mips/boards/rzx50/include/board/debug_ll.h @@ -18,9 +18,6 @@ #ifndef __INCLUDE_RZX50_BOARD_DEBUG_LL_H__ #define __INCLUDE_RZX50_BOARD_DEBUG_LL_H__ -#include <mach/jz4750d_regs.h> - -#define DEBUG_LL_UART_ADDR UART1_BASE -#define DEBUG_LL_UART_SHIFT 2 +#include <mach/debug_ll_jz4750d.h> #endif /* __INCLUDE_RZX50_BOARD_DEBUG_LL_H__ */ diff --git a/arch/mips/boards/rzx50/serial.c b/arch/mips/boards/rzx50/serial.c index 5230aaa8c8..129806d5a1 100644 --- a/arch/mips/boards/rzx50/serial.c +++ b/arch/mips/boards/rzx50/serial.c @@ -16,47 +16,14 @@ */ #include <common.h> -#include <types.h> -#include <driver.h> #include <init.h> -#include <ns16550.h> +#include <mach/devices.h> #include <mach/jz4750d_regs.h> -#include <io.h> -#include <asm/common.h> - -#define JZ4750D_UART_SHIFT 2 - -#define ier (1 << JZ4750D_UART_SHIFT) -#define fcr (2 << JZ4750D_UART_SHIFT) - -static void jz4750d_serial_reg_write(unsigned int val, unsigned long base, - unsigned char reg_offset) -{ - switch (reg_offset) { - case fcr: - val |= 0x10; /* Enable uart module */ - break; - case ier: - val |= (val & 0x4) << 2; - break; - default: - break; - } - - writeb(val & 0xff, (void *)(base + reg_offset)); -} - -static struct NS16550_plat serial_plat = { - .clock = 12000000, - .shift = JZ4750D_UART_SHIFT, - .reg_write = &jz4750d_serial_reg_write, -}; static int rzx50_console_init(void) { /* Register the serial port */ - add_ns16550_device(DEVICE_ID_DYNAMIC, UART1_BASE, 8 << JZ4750D_UART_SHIFT, - IORESOURCE_MEM_8BIT, &serial_plat); + jz_add_uart(DEVICE_ID_DYNAMIC, UART1_BASE, 12000000); return 0; } diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index 6b093f1e0e..b865b10f8b 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -1,4 +1,6 @@ obj-y += start.o obj-y += main_entry.o +obj-$(CONFIG_BUILTIN_DTB) += dtb.o + pbl-y += start-pbl.o main_entry-pbl.o diff --git a/arch/mips/boot/dtb.c b/arch/mips/boot/dtb.c new file mode 100644 index 0000000000..c1962bfd0c --- /dev/null +++ b/arch/mips/boot/dtb.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * Based on arch/arm/cpu/dtb.c: + * Copyright (C) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + */ +#include <common.h> +#include <init.h> +#include <of.h> +#include <memory.h> +#include <asm/addrspace.h> + +void of_add_memory_bank(struct device_node *node, bool dump, int r, + u64 base, u64 size) +{ + static char str[12]; + + sprintf(str, "kseg0_ram%d", r); + barebox_add_memory_bank(str, KSEG0 | base, size); + + sprintf(str, "kseg1_ram%d", r); + barebox_add_memory_bank(str, KSEG1 | base, size); + + if (dump) + pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); +} + +extern char __dtb_start[]; + +static int of_mips_init(void) +{ + struct device_node *root; + + root = of_get_root_node(); + if (root) + return 0; + + root = of_unflatten_dtb(NULL, __dtb_start); + if (root) { + pr_debug("using internal DTB\n"); + of_set_root_node(root); + if (IS_ENABLED(CONFIG_OFDEVICE)) + of_probe(); + } + + return 0; +} +core_initcall(of_mips_init); diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig index 7dab969931..18c840d7c3 100644 --- a/arch/mips/configs/qemu-malta_defconfig +++ b/arch/mips/configs/qemu-malta_defconfig @@ -1,3 +1,5 @@ +CONFIG_BUILTIN_DTB=y +CONFIG_BUILTIN_DTB_NAME="qemu-malta" CONFIG_PBL_IMAGE=y CONFIG_STACK_SIZE=0x7000 CONFIG_BROKEN=y @@ -23,22 +25,25 @@ CONFIG_CMD_MENU=y CONFIG_CMD_MENU_MANAGEMENT=y CONFIG_CMD_PASSWD=y CONFIG_CMD_TIME=y +CONFIG_CMD_TFTP=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_LOADB=y CONFIG_CMD_LOADY=y CONFIG_CMD_MEMINFO=y +CONFIG_CMD_IOMEM=y CONFIG_CMD_CRC=y CONFIG_CMD_CRC_CMP=y CONFIG_CMD_MD5SUM=y CONFIG_CMD_SHA1SUM=y CONFIG_CMD_SHA256SUM=y -CONFIG_CMD_MTEST=y CONFIG_CMD_FLASH=y -CONFIG_CMD_BOOTM_ZLIB=y -CONFIG_CMD_BOOTM_BZLIB=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_RESET=y CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_MTEST=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_UNCOMPRESS=y @@ -46,18 +51,18 @@ CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y CONFIG_NET_PING=y -CONFIG_CMD_TFTP=y -CONFIG_FS_TFTP=y CONFIG_NET_NETCONSOLE=y CONFIG_NET_RESOLV=y +CONFIG_OFDEVICE=y # CONFIG_SPI is not set +CONFIG_MTD=y CONFIG_DRIVER_CFI=y # CONFIG_DRIVER_CFI_AMD is not set # CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set # CONFIG_DRIVER_CFI_BANK_WIDTH_2 is not set CONFIG_CFI_BUFFER_WRITE=y -CONFIG_MTD=y CONFIG_FS_CRAMFS=y +CONFIG_FS_TFTP=y CONFIG_FS_FAT=y CONFIG_FS_FAT_WRITE=y CONFIG_FS_FAT_LFN=y diff --git a/arch/mips/configs/rzx50_defconfig b/arch/mips/configs/rzx50_defconfig index 722d977f50..5d994c76e1 100644 --- a/arch/mips/configs/rzx50_defconfig +++ b/arch/mips/configs/rzx50_defconfig @@ -1,4 +1,5 @@ CONFIG_MACH_MIPS_XBURST=y +CONFIG_PBL_IMAGE=y CONFIG_BAUDRATE=57600 CONFIG_GLOB=y CONFIG_HUSH_FANCY_PROMPT=y @@ -14,6 +15,7 @@ CONFIG_CMD_LOADY=y CONFIG_CMD_LOADS=y CONFIG_CMD_SAVES=y CONFIG_CMD_MEMINFO=y +CONFIG_CMD_IOMEM=y CONFIG_CMD_MD5SUM=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y @@ -22,6 +24,7 @@ CONFIG_CMD_BOOTM_OFTREE=y CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y CONFIG_CMD_UIMAGE=y CONFIG_CMD_RESET=y +CONFIG_CMD_POWEROFF=y CONFIG_CMD_GO=y # CONFIG_SPI is not set CONFIG_SHA1=y diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile new file mode 100644 index 0000000000..3ee89247e0 --- /dev/null +++ b/arch/mips/dts/Makefile @@ -0,0 +1,10 @@ + +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME)).dtb.o +obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB) + +targets += dtbs +targets += $(dtb-y) + +dtbs: $(addprefix $(obj)/, $(dtb-y)) + +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/dts/qemu-malta.dts b/arch/mips/dts/qemu-malta.dts new file mode 100644 index 0000000000..c4dcf056c1 --- /dev/null +++ b/arch/mips/dts/qemu-malta.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/include/ "skeleton.dtsi" + +/ { + model = "qemu malta"; + compatible = "qemu,malta"; + + memory { + reg = <0x00000000 0x10000000>; + }; +}; diff --git a/arch/mips/dts/skeleton.dtsi b/arch/mips/dts/skeleton.dtsi new file mode 100644 index 0000000000..b41d241de2 --- /dev/null +++ b/arch/mips/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/mips/include/asm/debug_ll_ns16550.h b/arch/mips/include/asm/debug_ll_ns16550.h new file mode 100644 index 0000000000..5dd1b39041 --- /dev/null +++ b/arch/mips/include/asm/debug_ll_ns16550.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012, 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * 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. + * + */ + +/** @file + * This file contains declaration for early output support + */ +#ifndef __INCLUDE_MIPS_ASM_DEBUG_LL_NS16550_H__ +#define __INCLUDE_MIPS_ASM_DEBUG_LL_NS16550_H__ + +#ifdef CONFIG_DEBUG_LL + +#ifndef DEBUG_LL_UART_ADDR +#error DEBUG_LL_UART_ADDR is undefined! +#endif + +#ifndef DEBUG_LL_UART_SHIFT +#error DEBUG_LL_UART_SHIFT is undefined! +#endif + +#ifndef DEBUG_LL_UART_DIVISOR +#error DEBUG_LL_UART_DIVISOR is undefined! +#endif + +#endif /* CONFIG_DEBUG_LL */ + +#define UART_THR (0x0 << DEBUG_LL_UART_SHIFT) +#define UART_DLL (0x0 << DEBUG_LL_UART_SHIFT) +#define UART_DLM (0x1 << DEBUG_LL_UART_SHIFT) +#define UART_LCR (0x3 << DEBUG_LL_UART_SHIFT) +#define UART_LSR (0x5 << DEBUG_LL_UART_SHIFT) + +#define UART_LCR_W 0x07 /* Set UART to 8,N,2 & DLAB = 0 */ +#define UART_LCR_DLAB 0x87 /* Set UART to 8,N,2 & DLAB = 1 */ + +#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ + +/* + * Macros for use in assembly language code + */ + +.macro debug_ll_ns16550_init +#ifdef CONFIG_DEBUG_LL + la t0, DEBUG_LL_UART_ADDR + + li t1, UART_LCR_DLAB /* DLAB on */ + sb t1, UART_LCR(t0) /* Write it out */ + + li t1, DEBUG_LL_UART_DIVISOR + sb t1, UART_DLL(t0) /* write low order byte */ + srl t1, t1, 8 + sb t1, UART_DLM(t0) /* write high order byte */ + + li t1, UART_LCR_W /* DLAB off */ + sb t1, UART_LCR(t0) /* Write it out */ +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * output a character in a0 + */ +.macro debug_ll_ns16550_outc chr +#ifdef CONFIG_DEBUG_LL + li a0, \chr + la t0, DEBUG_LL_UART_ADDR + +1: lbu t1, UART_LSR(t0) /* get line status */ + nop + andi t1, t1, UART_LSR_THRE /* check for transmitter empty */ + beqz t1, 1b /* try again */ + nop + + sb a0, UART_THR(t0) /* write the character */ +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * output CR + NL + */ +.macro debug_ll_ns16550_outnl +#ifdef CONFIG_DEBUG_LL + debug_ll_ns16550_outc '\r' + debug_ll_ns16550_outc '\n' +#endif /* CONFIG_DEBUG_LL */ +.endm + +#endif /* __INCLUDE_MIPS_ASM_DEBUG_LL_NS16550_H__ */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 608f19bda1..f9238607ab 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -673,19 +673,11 @@ do { \ #define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) #define read_c0_status() __read_32bit_c0_register($12, 0) -#ifdef CONFIG_MIPS_MT_SMTC -#define write_c0_status(val) \ -do { \ - __write_32bit_c0_register($12, 0, val); \ - __ehb(); \ -} while (0) -#else /* * Legacy non-SMTC code, which may be hazardous * but which might not support EHB */ #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) -#endif /* CONFIG_MIPS_MT_SMTC */ #define read_c0_cause() __read_32bit_c0_register($13, 0) #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index 5b3d45dc3c..bc78d2be8c 100644 --- a/arch/mips/lib/barebox.lds.S +++ b/arch/mips/lib/barebox.lds.S @@ -69,6 +69,8 @@ SECTIONS __usymtab : { BAREBOX_SYMS } __usymtab_end = .; + .dtb : { BAREBOX_DTB() } + _edata = .; . = ALIGN(4); __bss_start = .; diff --git a/arch/mips/mach-ar231x/Kconfig b/arch/mips/mach-ar231x/Kconfig new file mode 100644 index 0000000000..1c6a12f885 --- /dev/null +++ b/arch/mips/mach-ar231x/Kconfig @@ -0,0 +1,17 @@ +if MACH_MIPS_AR231X + +config ARCH_TEXT_BASE + hex + default 0xa0800000 + +choice + prompt "Board type" + +config BOARD_NETGEAR_WG102 + bool "Netgear WG102" + +endchoice + +source arch/mips/boards/netgear-wg102/Kconfig + +endif diff --git a/arch/mips/mach-ar231x/Makefile b/arch/mips/mach-ar231x/Makefile new file mode 100644 index 0000000000..eba8e818b5 --- /dev/null +++ b/arch/mips/mach-ar231x/Makefile @@ -0,0 +1,3 @@ +obj-y += ar231x.o +obj-y += board.o +obj-y += ar231x_reset.o diff --git a/arch/mips/mach-ar231x/ar231x.c b/arch/mips/mach-ar231x/ar231x.c new file mode 100644 index 0000000000..ca912bf0ef --- /dev/null +++ b/arch/mips/mach-ar231x/ar231x.c @@ -0,0 +1,195 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.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. + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <ns16550.h> +#include <mach/ar231x_platform.h> +#include <mach/ar2312_regs.h> + +struct ar231x_board_data ar231x_board; + +/* + * This table is indexed by bits 5..4 of the CLOCKCTL1 register + * to determine the predevisor value. + */ +static int CLOCKCTL1_PREDIVIDE_TABLE[4] = { 1, 2, 4, 5 }; + +static unsigned int +ar2312_cpu_frequency(void) +{ + unsigned int predivide_mask, predivide_shift; + unsigned int multiplier_mask, multiplier_shift; + unsigned int clock_ctl1, pre_divide_select, pre_divisor, multiplier; + unsigned int doubler_mask; + u32 devid; + + devid = __raw_readl((char *)KSEG1ADDR(AR2312_REV)); + devid &= AR2312_REV_MAJ; + devid >>= AR2312_REV_MAJ_S; + if (devid == AR2312_REV_MAJ_AR2313) { + predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK; + predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT; + multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK; + multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT; + doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK; + } else { /* AR5312 and AR2312 */ + predivide_mask = AR2312_CLOCKCTL1_PREDIVIDE_MASK; + predivide_shift = AR2312_CLOCKCTL1_PREDIVIDE_SHIFT; + multiplier_mask = AR2312_CLOCKCTL1_MULTIPLIER_MASK; + multiplier_shift = AR2312_CLOCKCTL1_MULTIPLIER_SHIFT; + doubler_mask = AR2312_CLOCKCTL1_DOUBLER_MASK; + } + + /* + * Clocking is derived from a fixed 40MHz input clock. + * + * cpuFreq = InputClock * MULT (where MULT is PLL multiplier) + * sysFreq = cpuFreq / 4 (used for APB clock, serial, + * flash, Timer, Watchdog Timer) + * + * cntFreq = cpuFreq / 2 (use for CPU count/compare) + * + * So, for example, with a PLL multiplier of 5, we have + * + * cpuFreq = 200MHz + * sysFreq = 50MHz + * cntFreq = 100MHz + * + * We compute the CPU frequency, based on PLL settings. + */ + + clock_ctl1 = __raw_readl((char *)KSEG1ADDR(AR2312_CLOCKCTL1)); + pre_divide_select = (clock_ctl1 & predivide_mask) >> predivide_shift; + pre_divisor = CLOCKCTL1_PREDIVIDE_TABLE[pre_divide_select]; + multiplier = (clock_ctl1 & multiplier_mask) >> multiplier_shift; + + if (clock_ctl1 & doubler_mask) + multiplier = multiplier << 1; + + return (40000000 / pre_divisor) * multiplier; +} + +static unsigned int +ar2312_sys_frequency(void) +{ + return ar2312_cpu_frequency() / 4; +} + +/* + * shutdown watchdog + */ +static int watchdog_init(void) +{ + pr_debug("Disable watchdog.\n"); + __raw_writeb(AR2312_WD_CTRL_IGNORE_EXPIRATION, + (char *)KSEG1ADDR(AR2312_WD_CTRL)); + return 0; +} + +static void flash_init(void) +{ + u32 ctl, old_ctl; + + /* Configure flash bank 0. + * Assume 8M maximum window size on this SoC. + * Flash will be aliased if it's smaller + */ + old_ctl = __raw_readl((char *)KSEG1ADDR(AR2312_FLASHCTL0)); + ctl = FLASHCTL_E | FLASHCTL_AC_8M | FLASHCTL_RBLE | + (0x01 << FLASHCTL_IDCY_S) | + (0x07 << FLASHCTL_WST1_S) | + (0x07 << FLASHCTL_WST2_S) | (old_ctl & FLASHCTL_MW); + + __raw_writel(ctl, (char *)KSEG1ADDR(AR2312_FLASHCTL0)); + /* Disable other flash banks */ + old_ctl = __raw_readl((char *)KSEG1ADDR(AR2312_FLASHCTL1)); + __raw_writel(old_ctl & ~(FLASHCTL_E | FLASHCTL_AC), + (char *)KSEG1ADDR(AR2312_FLASHCTL1)); + + old_ctl = __raw_readl((char *)KSEG1ADDR(AR2312_FLASHCTL2)); + __raw_writel(old_ctl & ~(FLASHCTL_E | FLASHCTL_AC), + (char *)KSEG1ADDR(AR2312_FLASHCTL2)); + + /* We need to find atheros config. MAC address is there. */ + ar231x_find_config((char *)KSEG1ADDR(AR2312_FLASH + + AR2312_MAX_FLASH_SIZE)); +} + +static int ether_init(void) +{ + static struct resource res[2]; + struct ar231x_eth_platform_data *eth = &ar231x_board.eth_pdata; + + /* Base ETH registers */ + res[0].start = KSEG1ADDR(AR2312_ENET1); + res[0].end = res[0].start + 0x100000 - 1; + res[0].flags = IORESOURCE_MEM; + /* Base PHY registers */ + res[1].start = KSEG1ADDR(AR2312_ENET0); + res[1].end = res[1].start + 0x100000 - 1; + res[1].flags = IORESOURCE_MEM; + + /* MAC address located in atheros config on flash. */ + eth->mac = ar231x_board.config->enet0_mac; + + eth->reset_mac = AR2312_RESET_ENET0 | AR2312_RESET_ENET1; + eth->reset_phy = AR2312_RESET_EPHY0 | AR2312_RESET_EPHY1; + + eth->reset_bit = ar231x_reset_bit; + + /* FIXME: base_reset should be replaced with reset driver */ + eth->base_reset = KSEG1ADDR(AR2312_RESET); + + add_generic_device_res("ar231x_eth", DEVICE_ID_DYNAMIC, res, 2, eth); + return 0; +} + +static int platform_init(void) +{ + add_generic_device("ar231x_reset", DEVICE_ID_SINGLE, NULL, + KSEG1ADDR(AR2312_RESET), 0x4, + IORESOURCE_MEM, NULL); + watchdog_init(); + flash_init(); + ether_init(); + return 0; +} +late_initcall(platform_init); + +static struct NS16550_plat serial_plat = { + .shift = AR2312_UART_SHIFT, +}; + +static int ar2312_console_init(void) +{ + u32 reset; + + /* reset UART0 */ + reset = __raw_readl((char *)KSEG1ADDR(AR2312_RESET)); + reset = ((reset & ~AR2312_RESET_APB) | AR2312_RESET_UART0); + __raw_writel(reset, (char *)KSEG1ADDR(AR2312_RESET)); + + reset &= ~AR2312_RESET_UART0; + __raw_writel(reset, (char *)KSEG1ADDR(AR2312_RESET)); + + /* Register the serial port */ + serial_plat.clock = ar2312_sys_frequency(); + add_ns16550_device(DEVICE_ID_DYNAMIC, KSEG1ADDR(AR2312_UART0), + 8 << AR2312_UART_SHIFT, IORESOURCE_MEM_8BIT, &serial_plat); + return 0; +} +console_initcall(ar2312_console_init); diff --git a/arch/mips/mach-ar231x/ar231x_reset.c b/arch/mips/mach-ar231x/ar231x_reset.c new file mode 100644 index 0000000000..5ececb5c01 --- /dev/null +++ b/arch/mips/mach-ar231x/ar231x_reset.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.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. + */ + +#include <common.h> +#include <init.h> +#include <io.h> + +#include <mach/ar2312_regs.h> +#include <mach/ar231x_platform.h> + +static void __iomem *reset_base; + +void __noreturn reset_cpu(ulong addr) +{ + printf("reseting cpu\n"); + __raw_writel(0x10000, + (char *)KSEG1ADDR(AR2312_WD_TIMER)); + __raw_writel(AR2312_WD_CTRL_RESET, + (char *)KSEG1ADDR(AR2312_WD_CTRL)); + unreachable(); +} +EXPORT_SYMBOL(reset_cpu); + +static u32 ar231x_reset_readl(void) +{ + return __raw_readl(reset_base); +} + +static void ar231x_reset_writel(u32 val) +{ + __raw_writel(val, reset_base); +} + +void ar231x_reset_bit(u32 val, enum reset_state state) +{ + u32 tmp; + + tmp = ar231x_reset_readl(); + + if (state == REMOVE) + ar231x_reset_writel(tmp & ~val); + else + ar231x_reset_writel(tmp | val); +} +EXPORT_SYMBOL(ar231x_reset_bit); + +static int ar231x_reset_probe(struct device_d *dev) +{ + reset_base = dev_request_mem_region(dev, 0); + if (!reset_base) { + dev_err(dev, "could not get memory region\n"); + return -ENODEV; + } + + return 0; +} + +static struct driver_d ar231x_reset_driver = { + .probe = ar231x_reset_probe, + .name = "ar231x_reset", +}; + +static int ar231x_reset_init(void) +{ + return platform_driver_register(&ar231x_reset_driver); +} +coredevice_initcall(ar231x_reset_init); diff --git a/arch/mips/mach-ar231x/board.c b/arch/mips/mach-ar231x/board.c new file mode 100644 index 0000000000..f1b876f762 --- /dev/null +++ b/arch/mips/mach-ar231x/board.c @@ -0,0 +1,188 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.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. + */ + + +#include <common.h> +#include <io.h> +#include <mach/ar2312_regs.h> +#include <mach/ar231x_platform.h> +#include <linux/stddef.h> +#include <net.h> + +#define HDR_SIZE 6 + +#define TAB_1 "\t" +#define TAB_2 "\t\t" + +extern struct ar231x_board_data ar231x_board; + +static void +ar231x_print_mac(unsigned char *mac) +{ + int i; + for (i = 0; i < 5; i++) + printf("%02x:", mac[i]); + printf("%02x\n", mac[5]); +} + +#ifdef DEBUG_BOARD +static void +ar231x_print_board_config(struct ar231x_board_config *config) +{ + printf("board config:\n"); + printf(TAB_1 "chsum:" TAB_2 "%04x\n", config->cksum); + printf(TAB_1 "rev:" TAB_2 "%04x\n", config->rev); + printf(TAB_1 "name:" TAB_2 "%s\n", config->board_name); + printf(TAB_1 "maj:" TAB_2 "%04x\n", config->major); + printf(TAB_1 "min:" TAB_2 "%04x\n", config->minor); + printf(TAB_1 "board flags:" TAB_1 "%08x\n", config->flags); + + if (config->flags & BD_ENET0) + printf(TAB_2 "ENET0 is stuffed\n"); + if (config->flags & BD_ENET1) + printf(TAB_2 "ENET1 is stuffed\n"); + if (config->flags & BD_UART1) + printf(TAB_2 "UART1 is stuffed\n"); + if (config->flags & BD_UART0) + printf(TAB_2 "UART0 is stuffed (dma)\n"); + if (config->flags & BD_RSTFACTORY) + printf(TAB_2 "Reset factory defaults stuffed\n"); + if (config->flags & BD_SYSLED) + printf(TAB_2 "System LED stuffed\n"); + if (config->flags & BD_EXTUARTCLK) + printf(TAB_2 "External UART clock\n"); + if (config->flags & BD_CPUFREQ) + printf(TAB_2 "cpu freq is valid in nvram\n"); + if (config->flags & BD_SYSFREQ) + printf(TAB_2 "sys freq is set in nvram\n"); + if (config->flags & BD_WLAN0) + printf(TAB_2 "Enable WLAN0\n"); + if (config->flags & BD_MEMCAP) + printf(TAB_2 "CAP SDRAM @ memCap for testing\n"); + if (config->flags & BD_DISWATCHDOG) + printf(TAB_2 "disable system watchdog\n"); + if (config->flags & BD_WLAN1) + printf(TAB_2 "Enable WLAN1 (ar5212)\n"); + if (config->flags & BD_ISCASPER) + printf(TAB_2 "FLAG for AR2312\n"); + if (config->flags & BD_WLAN0_2G_EN) + printf(TAB_2 "FLAG for radio0_2G\n"); + if (config->flags & BD_WLAN0_5G_EN) + printf(TAB_2 "FLAG for radio0_5G\n"); + if (config->flags & BD_WLAN1_2G_EN) + printf(TAB_2 "FLAG for radio1_2G\n"); + if (config->flags & BD_WLAN1_5G_EN) + printf(TAB_2 "FLAG for radio1_5G\n"); + + printf(TAB_1 "ResetConf GPIO pin:" TAB_1 "%04x\n", + config->reset_config_gpio); + printf(TAB_1 "Sys LED GPIO pin:" TAB_1 "%04x\n", config->sys_led_gpio); + printf(TAB_1 "CPU Freq:" TAB_2 "%u\n", config->cpu_freq); + printf(TAB_1 "Sys Freq:" TAB_2 "%u\n", config->sys_freq); + printf(TAB_1 "Calculated Freq:" TAB_1 "%u\n", config->cnt_freq); + + printf(TAB_1 "wlan0 mac:" TAB_2); + ar231x_print_mac(config->wlan0_mac); + printf(TAB_1 "wlan1 mac:" TAB_2); + ar231x_print_mac(config->wlan1_mac); + printf(TAB_1 "eth0 mac:" TAB_2); + ar231x_print_mac(config->enet0_mac); + printf(TAB_1 "eth1 mac:" TAB_2); + ar231x_print_mac(config->enet1_mac); + + printf(TAB_1 "Pseudo PCIID:" TAB_2 "%04x\n", config->pci_id); + printf(TAB_1 "Mem capacity:" TAB_2 "%u\n", config->mem_cap); +} +#endif + +static u16 +ar231x_cksum16(u8 *data, int size) +{ + int i; + u16 sum; + + for (i = 0; i < size; i++) + sum += data[i]; + + return sum; +} + +static void +ar231x_check_mac(u8 *addr) +{ + if (!is_valid_ether_addr(addr)) { + pr_warn("config: no valid mac was found. " + "Generating random mac: "); + random_ether_addr(addr); + ar231x_print_mac(addr); + } +} + +static u8 * +ar231x_find_board_config(u8 *flash_limit) +{ + u8 *addr; + int found = 0; + + for (addr = flash_limit - 0x1000; + addr >= flash_limit - 0x30000; + addr -= 0x1000) { + + if (*((u32 *)addr) == AR231X_BD_MAGIC) { + found = 1; + pr_debug("config at %x\n", addr); + break; + } + } + + if (!found) + addr = NULL; + + return addr; +} + +void +ar231x_find_config(u8 *flash_limit) +{ + struct ar231x_board_config *config; + u8 *bcfg, bsize; + u8 brocken; + + bcfg = ar231x_find_board_config(flash_limit); + + bsize = sizeof(struct ar231x_board_config); + config = xzalloc(bsize); + ar231x_board.config = config; + + if (bcfg) { + u16 cksum; + /* Copy the board and radio data to RAM. + * If flash will go to CFI mode, we won't + * be able to read to from mapped memory area */ + memcpy(config, bcfg, bsize); + cksum = 0xca + ar231x_cksum16((unsigned char *)config + HDR_SIZE, + sizeof(struct ar231x_board_config) - HDR_SIZE); + if (cksum != config->cksum) { + pr_err("config: checksum is invalid: %04x != %04x\n", + cksum, config->cksum); + brocken = 1; + } + /* ar231x_print_board_config(config); */ + } + + /* We do not care about wlans here */ + ar231x_check_mac(config->enet0_mac); + ar231x_check_mac(config->enet1_mac); +} diff --git a/arch/mips/mach-ar231x/include/mach/ar2312_regs.h b/arch/mips/mach-ar231x/include/mach/ar2312_regs.h new file mode 100644 index 0000000000..7ac1b09b9a --- /dev/null +++ b/arch/mips/mach-ar231x/include/mach/ar2312_regs.h @@ -0,0 +1,302 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.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 AR2312_H +#define AR2312_H + +#include <asm/addrspace.h> + +/* Address Map */ +#define AR2312_SDRAM0 0x00000000 +#define AR2312_SDRAM1 0x08000000 +#define AR2312_WLAN0 0x18000000 +#define AR2312_WLAN1 0x18500000 +#define AR2312_ENET0 0x18100000 +#define AR2312_ENET1 0x18200000 +#define AR2312_SDRAMCTL 0x18300000 +#define AR2312_FLASHCTL 0x18400000 +#define AR2312_APBBASE 0x1c000000 +#define AR2312_FLASH 0x1e000000 + +#define AR2312_CPU_CLOCK_RATE 180000000 +/* Used by romSizeMemory to set SDRAM Memory Refresh */ +#define AR2312_SDRAM_CLOCK_RATE (AR2312_CPU_CLOCK_RATE / 2) +/* + * SDRAM Memory Refresh (MEM_REF) value is computed as: + * 15.625us * SDRAM_CLOCK_RATE (in MHZ) + */ +#define DESIRED_MEMORY_REFRESH_NSECS 15625 +#define AR2312_SDRAM_MEMORY_REFRESH_VALUE \ + ((DESIRED_MEMORY_REFRESH_NSECS * AR2312_SDRAM_CLOCK_RATE/1000000) / 1000) + +/* + * APB Address Map + */ +#define AR2312_UART0 (AR2312_APBBASE + 0x0003) /* high speed uart */ +#define AR2312_UART_SHIFT 2 +#define AR2312_UART1 (AR2312_APBBASE + 0x1000) /* ar2312 only */ +#define AR2312_GPIO (AR2312_APBBASE + 0x2000) +#define AR2312_RESETTMR (AR2312_APBBASE + 0x3000) +#define AR2312_APB2AHB (AR2312_APBBASE + 0x4000) + +/* + * AR2312_NUM_ENET_MAC defines the number of ethernet MACs that + * should be considered available. The AR2312 supports 2 enet MACS, + * even though many reference boards only actually use 1 of them + * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch. + * The AR2312 supports 1 enet MAC. + */ +#define AR2312_NUM_ENET_MAC 2 + +/* + * Need these defines to determine true number of ethernet MACs + */ +#define AR5212_AR2312_REV2 0x52 /* AR2312 WMAC (AP31) */ +#define AR5212_AR2312_REV7 0x57 /* AR2312 WMAC (AP30-040) */ +#define AR5212_AR2313_REV8 0x58 /* AR2313 WMAC (AP43-030) */ + +/* Reset/Timer Block Address Map */ +#define AR2312_RESETTMR (AR2312_APBBASE + 0x3000) +#define AR2312_TIMER (AR2312_RESETTMR + 0x0000) /* countdown timer */ +#define AR2312_WD_CTRL (AR2312_RESETTMR + 0x0008) /* watchdog cntrl */ +#define AR2312_WD_TIMER (AR2312_RESETTMR + 0x000c) /* watchdog timer */ +#define AR2312_ISR (AR2312_RESETTMR + 0x0010) /* Intr Status Reg */ +#define AR2312_IMR (AR2312_RESETTMR + 0x0014) /* Intr Mask Reg */ +#define AR2312_RESET (AR2312_RESETTMR + 0x0020) +#define AR2312_CLOCKCTL0 (AR2312_RESETTMR + 0x0060) +#define AR2312_CLOCKCTL1 (AR2312_RESETTMR + 0x0064) +#define AR2312_CLOCKCTL2 (AR2312_RESETTMR + 0x0068) +#define AR2312_SCRATCH (AR2312_RESETTMR + 0x006c) +#define AR2312_PROCADDR (AR2312_RESETTMR + 0x0070) +#define AR2312_PROC1 (AR2312_RESETTMR + 0x0074) +#define AR2312_DMAADDR (AR2312_RESETTMR + 0x0078) +#define AR2312_DMA1 (AR2312_RESETTMR + 0x007c) +#define AR2312_ENABLE (AR2312_RESETTMR + 0x0080) /* interface enb */ +#define AR2312_REV (AR2312_RESETTMR + 0x0090) /* revision */ + +/* AR2312_WD_CTRL register bit field definitions */ +#define AR2312_WD_CTRL_IGNORE_EXPIRATION 0x0000 +#define AR2312_WD_CTRL_NMI 0x0001 +#define AR2312_WD_CTRL_RESET 0x0002 + +/* AR2312_ISR register bit field definitions */ +#define AR2312_ISR_NONE 0x0000 +#define AR2312_ISR_TIMER 0x0001 +#define AR2312_ISR_AHBPROC 0x0002 +#define AR2312_ISR_AHBDMA 0x0004 +#define AR2312_ISR_GPIO 0x0008 +#define AR2312_ISR_UART0 0x0010 +#define AR2312_ISR_UART0DMA 0x0020 +#define AR2312_ISR_WD 0x0040 +#define AR2312_ISR_LOCAL 0x0080 + +/* AR2312_RESET register bit field definitions */ +#define AR2312_RESET_SYSTEM 0x00000001 /* cold reset full system */ +#define AR2312_RESET_PROC 0x00000002 /* cold reset MIPS core */ +#define AR2312_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */ +#define AR2312_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ +#define AR2312_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */ +#define AR2312_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */ +#define AR2312_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */ +#define AR2312_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */ +#define AR2312_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */ +#define AR2312_RESET_APB 0x00000400 /* cold reset APB (ar2312) */ +#define AR2312_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */ +#define AR2312_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */ +#define AR2312_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */ +#define AR2312_RESET_NMI 0x00010000 /* send an NMI to the processor */ +#define AR2312_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */ +#define AR2312_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */ +#define AR2312_RESET_LOCAL_BUS 0x00080000 /* reset local bus */ +#define AR2312_RESET_WDOG 0x00100000 /* last reset was a watchdog */ + +/* Values for AR2312_CLOCKCTL1 + * + * The AR2312_CLOCKCTL1 register is loaded based on the speed of + * our incoming clock. Currently, all valid configurations + * for an AR2312 use an ar5112 radio clocked at 40MHz. Until + * there are other configurations available, we'll hardcode + * this 40MHz assumption. + */ +#define AR2312_INPUT_CLOCK 40000000 +#define AR2312_CLOCKCTL1_IN40_OUT160MHZ 0x0405 /* 40MHz in, 160Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT180MHZ 0x0915 /* 40MHz in, 180Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT200MHZ 0x1935 /* 40MHz in, 200Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT220MHZ 0x0b15 /* 40MHz in, 220Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT240MHZ 0x0605 /* 40MHz in, 240Mhz out */ + +#define AR2312_CLOCKCTL1_SELECTION AR2312_CLOCKCTL1_IN40_OUT180MHZ +#define AR2312_CPU_CLOCK_RATE 180000000 + +/* + * Special values for AR2313 'VIPER' PLL. + * + * These values do not match the latest datasheet for the AR2313, + * which appears to be an exact copy of the AR2312 in this area. + * The values were derived from the ECOS code provided in the Atheros + * LSDK-1.0 (and confirmed by checking values on an AR2313 reference + * design). + */ +#define AR2313_CLOCKCTL1_SELECTION 0x91245 + +/* Bit fields for AR2312_CLOCKCTL2 */ +#define AR2312_CLOCKCTL2_WANT_RESET 0x00000001 /* reset with new vals */ +#define AR2312_CLOCKCTL2_WANT_DIV2 0x00000010 /* request /2 clock */ +#define AR2312_CLOCKCTL2_WANT_DIV4 0x00000020 /* request /4 clock */ +#define AR2312_CLOCKCTL2_WANT_PLL_BYPASS 0x00000080 /* request PLL bypass */ +#define AR2312_CLOCKCTL2_STATUS_DIV2 0x10000000 /* have /2 clock */ +#define AR2312_CLOCKCTL2_STATUS_DIV4 0x20000000 /* have /4 clock */ +#define AR2312_CLOCKCTL2_STATUS_PLL_BYPASS 0x80000000 /* PLL is bypassed */ + +/* AR2312_CLOCKCTL1 register bit field definitions */ +#define AR2312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 +#define AR2312_CLOCKCTL1_PREDIVIDE_SHIFT 4 +#define AR2312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 +#define AR2312_CLOCKCTL1_MULTIPLIER_SHIFT 8 +#define AR2312_CLOCKCTL1_DOUBLER_MASK 0x00010000 + +/* Valid for AR2313 */ +#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000 +#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12 +#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000 +#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16 +#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000 + +/* Values for AR2312_CLOCKCTL */ +#define AR2312_CLOCKCTL_ETH0 0x0004 /* enable eth0 clock */ +#define AR2312_CLOCKCTL_ETH1 0x0008 /* enable eth1 clock */ +#define AR2312_CLOCKCTL_UART0 0x0010 /* enable UART0 external clock */ + + +/* AR2312_ENABLE register bit field definitions */ +#define AR2312_ENABLE_ENET0 0x0002 +#define AR2312_ENABLE_ENET1 0x0004 + +/* AR2312_REV register bit field definitions */ +#define AR2312_REV_WMAC_MAJ 0xf000 +#define AR2312_REV_WMAC_MAJ_S 12 +#define AR2312_REV_WMAC_MIN 0x0f00 +#define AR2312_REV_WMAC_MIN_S 8 +#define AR2312_REV_MAJ 0x00f0 +#define AR2312_REV_MAJ_S 4 +#define AR2312_REV_MIN 0x000f +#define AR2312_REV_MIN_S 0 +#define AR2312_REV_CHIP (AR2312_REV_MAJ|AR2312_REV_MIN) + +/* Major revision numbers, bits 7..4 of Revision ID register */ +#define AR2312_REV_MAJ_AR2312 0x4 +#define AR2312_REV_MAJ_AR2313 0x5 + +/* Minor revision numbers, bits 3..0 of Revision ID register */ +#define AR2312_REV_MIN_DUAL 0x0 /* Dual WLAN version */ +#define AR2312_REV_MIN_SINGLE 0x1 /* Single WLAN version */ + +/* AR2312_FLASHCTL register bit field definitions */ +#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */ +#define FLASHCTL_IDCY_S 0 +#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */ +#define FLASHCTL_WST1_S 5 +#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */ +#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */ +#define FLASHCTL_WST2_S 11 +#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */ +#define FLASHCTL_AC_S 16 +#define FLASHCTL_AC_128K 0x00000000 +#define FLASHCTL_AC_256K 0x00010000 +#define FLASHCTL_AC_512K 0x00020000 +#define FLASHCTL_AC_1M 0x00030000 +#define FLASHCTL_AC_2M 0x00040000 +#define FLASHCTL_AC_4M 0x00050000 +#define FLASHCTL_AC_8M 0x00060000 +#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */ +#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */ +#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */ +#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */ +#define FLASHCTL_WP 0x04000000 /* Write protect */ +#define FLASHCTL_BM 0x08000000 /* Burst mode */ +#define FLASHCTL_MW 0x30000000 /* Memory width */ +#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ +#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ +#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ +#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */ +#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */ +#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */ + +#define AR2312_MAX_FLASH_SIZE 0x800000 + +/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */ +#define AR2312_FLASHCTL0 (AR2312_FLASHCTL + 0x00) +#define AR2312_FLASHCTL1 (AR2312_FLASHCTL + 0x04) +#define AR2312_FLASHCTL2 (AR2312_FLASHCTL + 0x08) + +/* ARM SDRAM Controller -- just enough to determine memory size */ +#define AR2312_MEM_CFG0 (AR2312_SDRAMCTL + 0x00) +#define AR2312_MEM_CFG1 (AR2312_SDRAMCTL + 0x04) +#define AR2312_MEM_REF (AR2312_SDRAMCTL + 0x08) /* 16 bit value */ + +#define MEM_CFG0_F0 0x00000002 /* bank 0: 256Mb support */ +#define MEM_CFG0_T0 0x00000004 /* bank 0: chip width */ +#define MEM_CFG0_B0 0x00000008 /* bank 0: 2 vs 4 bank */ +#define MEM_CFG0_F1 0x00000020 /* bank 1: 256Mb support */ +#define MEM_CFG0_T1 0x00000040 /* bank 1: chip width */ +#define MEM_CFG0_B1 0x00000080 /* bank 1: 2 vs 4 bank */ + /* bank 2 and 3 are not supported */ +#define MEM_CFG0_E 0x00020000 /* SDRAM clock control */ +#define MEM_CFG0_C 0x00040000 /* SDRAM clock enable */ +#define MEM_CFG0_X 0x00080000 /* bus width (0 == 32b) */ +#define MEM_CFG0_CAS 0x00300000 /* CAS latency (1-3) */ +#define MEM_CFG0_C1 0x00100000 +#define MEM_CFG0_C2 0x00200000 +#define MEM_CFG0_C3 0x00300000 +#define MEM_CFG0_R 0x00c00000 /* RAS to CAS latency (1-3) */ +#define MEM_CFG0_R1 0x00400000 +#define MEM_CFG0_R2 0x00800000 +#define MEM_CFG0_R3 0x00c00000 +#define MEM_CFG0_A 0x01000000 /* AHB auto pre-charge */ + +#define MEM_CFG1_I 0x0001 /* memory init control */ +#define MEM_CFG1_M 0x0002 /* memory init control */ +#define MEM_CFG1_R 0x0004 /* read buffer enable (unused) */ +#define MEM_CFG1_W 0x0008 /* write buffer enable (unused) */ +#define MEM_CFG1_B 0x0010 /* SDRAM engine busy */ +#define MEM_CFG1_AC_2 0 /* AC of 2MB */ +#define MEM_CFG1_AC_4 1 /* AC of 4MB */ +#define MEM_CFG1_AC_8 2 /* AC of 8MB */ +#define MEM_CFG1_AC_16 3 /* AC of 16MB */ +#define MEM_CFG1_AC_32 4 /* AC of 32MB */ +#define MEM_CFG1_AC_64 5 /* AC of 64MB */ +#define MEM_CFG1_AC_128 6 /* AC of 128MB */ + +#define MEM_CFG1_AC0_S 8 +#define MEM_CFG1_AC0 0x0700 /* bank 0: SDRAM addr check (added) */ +#define MEM_CFG1_E0 0x0800 /* bank 0: enable */ +#define MEM_CFG1_AC1_S 12 +#define MEM_CFG1_AC1 0x7000 /* bank 1: SDRAM addr check (added) */ +#define MEM_CFG1_E1 0x8000 /* bank 1: enable */ + +/* GPIO Address Map */ +#define AR2312_GPIO (AR2312_APBBASE + 0x2000) +#define AR2312_GPIO_DO (AR2312_GPIO + 0x00) /* output register */ +#define AR2312_GPIO_DI (AR2312_GPIO + 0x04) /* intput register */ +#define AR2312_GPIO_CR (AR2312_GPIO + 0x08) /* control register */ + +/* GPIO Control Register bit field definitions */ +#define AR2312_GPIO_CR_M(x) (1 << (x)) /* mask for i/o */ +#define AR2312_GPIO_CR_O(x) (0 << (x)) /* mask for output */ +#define AR2312_GPIO_CR_I(x) (1 << (x)) /* mask for input */ +#define AR2312_GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */ +#define AR2312_GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */ +#define AR2312_NUM_GPIO 8 + +#endif diff --git a/arch/mips/mach-ar231x/include/mach/ar231x_platform.h b/arch/mips/mach-ar231x/include/mach/ar231x_platform.h new file mode 100644 index 0000000000..18f55b69c7 --- /dev/null +++ b/arch/mips/mach-ar231x/include/mach/ar231x_platform.h @@ -0,0 +1,104 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.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 __AR231X_PLATFORM_H +#define __AR231X_PLATFORM_H + +/* + * This is board-specific data that is stored in a "fixed" location in flash. + * It is shared across operating systems, so it should not be changed lightly. + * The main reason we need it is in order to extract the ethernet MAC + * address(es). + */ +struct ar231x_board_config { + u32 magic; /* board data is valid */ +#define AR231X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */ + u16 cksum; /* checksum (starting with BD_REV 2) */ + u16 rev; /* revision of this struct */ +#define BD_REV 4 + char boardName[64]; /* Name of board */ + u16 major; /* Board major number */ + u16 minor; /* Board minor number */ + u32 flags; /* Board configuration */ +#define BD_ENET0 0x00000001 /* ENET0 is stuffed */ +#define BD_ENET1 0x00000002 /* ENET1 is stuffed */ +#define BD_UART1 0x00000004 /* UART1 is stuffed */ +#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */ +#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */ +#define BD_SYSLED 0x00000020 /* System LED stuffed */ +#define BD_EXTUARTCLK 0x00000040 /* External UART clock */ +#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */ +#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */ +#define BD_WLAN0 0x00000200 /* Enable WLAN0 */ +#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */ +#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */ +#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */ +#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */ +#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */ +#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */ +#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */ +#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ + u16 resetConfigGpio; /* Reset factory GPIO pin */ + u16 sysLedGpio; /* System LED GPIO pin */ + + u32 cpuFreq; /* CPU core frequency in Hz */ + u32 sysFreq; /* System frequency in Hz */ + u32 cntFreq; /* Calculated C0_COUNT frequency */ + + u8 wlan0_mac[6]; + u8 enet0_mac[6]; + u8 enet1_mac[6]; + + u16 pciId; /* Pseudo PCIID for common code */ + u16 memCap; /* cap bank1 in MB */ + + /* version 3 */ + u8 wlan1_mac[6]; /* (ar5212) */ +}; + +#define BOARD_CONFIG_BUFSZ 0x1000 + +/* + * Platform device information for the Ethernet MAC + */ +enum reset_state { + SET, + REMOVE, +}; + +struct ar231x_eth_platform_data { + u32 base_reset; + u32 reset_mac; + u32 reset_phy; + + u8 *mac; + + void (*reset_bit)(u32 val, enum reset_state state); +}; + +struct ar231x_board_data { + u16 devid; + + /* board config data */ + struct ar231x_board_config *config; + + struct ar231x_eth_platform_data eth_pdata; +}; + +void ar231x_find_config(u8 *flash_limit); + +void ar231x_reset_bit(u32 val, enum reset_state state); + +#endif /* __AR231X_PLATFORM_H */ diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig index c72b7414d5..e6413d5637 100644 --- a/arch/mips/mach-xburst/Kconfig +++ b/arch/mips/mach-xburst/Kconfig @@ -17,6 +17,24 @@ config BOARD_RZX50 endchoice +if DEBUG_LL +if CPU_JZ4755 +choice + prompt "DEBUG_LL port" + +config JZ4750D_DEBUG_LL_UART0 + bool "UART0" + +config JZ4750D_DEBUG_LL_UART1 + bool "UART1" + +config JZ4750D_DEBUG_LL_UART2 + bool "UART2" + +endchoice +endif # CPU_JZ4755 +endif # DEBUG_LL + source arch/mips/boards/rzx50/Kconfig endif diff --git a/arch/mips/mach-xburst/Makefile b/arch/mips/mach-xburst/Makefile index e5634ba9cc..3e0cd7324e 100644 --- a/arch/mips/mach-xburst/Makefile +++ b/arch/mips/mach-xburst/Makefile @@ -1 +1,2 @@ +obj-y += serial.o obj-$(CONFIG_CPU_JZ4755) += csrc-jz4750.o reset-jz4750.o diff --git a/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h b/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h new file mode 100644 index 0000000000..7bf66b12ae --- /dev/null +++ b/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * 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. + * + */ + +#ifndef __INCLUDE_DEBUG_LL_JZ4750D_H__ +#define __INCLUDE_DEBUG_LL_JZ4750D_H__ + +#include <mach/jz4750d_regs.h> + +#ifdef CONFIG_JZ4750D_DEBUG_LL_UART0 +#define DEBUG_LL_UART_ADDR UART0_BASE +#endif + +#ifdef CONFIG_JZ4750D_DEBUG_LL_UART1 +#define DEBUG_LL_UART_ADDR UART1_BASE +#endif + +#ifdef CONFIG_JZ4750D_DEBUG_LL_UART2 +#define DEBUG_LL_UART_ADDR UART2_BASE +#endif + +#define DEBUG_LL_UART_SHIFT 2 + +#endif /* __INCLUDE_DEBUG_LL_JZ4750D_H__ */ diff --git a/arch/mips/mach-xburst/include/mach/devices.h b/arch/mips/mach-xburst/include/mach/devices.h new file mode 100644 index 0000000000..931749d424 --- /dev/null +++ b/arch/mips/mach-xburst/include/mach/devices.h @@ -0,0 +1,8 @@ +#ifndef __MACH_XBURST_DEVICES_H +#define __MACH_XBURST_DEVICES_H + +#include <driver.h> + +struct device_d *jz_add_uart(int id, unsigned long base, unsigned int clock); + +#endif /* __MACH_XBURST_DEVICES_H */ diff --git a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h index eafdd2fa79..7a3daadb18 100644 --- a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h +++ b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h @@ -16,7 +16,9 @@ #define TCU_BASE 0xb0002000 #define WDT_BASE 0xb0002000 #define RTC_BASE 0xb0003000 +#define UART0_BASE 0xb0030000 #define UART1_BASE 0xb0031000 +#define UART2_BASE 0xb0032000 /************************************************************************* * TCU (Timer Counter Unit) diff --git a/arch/mips/mach-xburst/serial.c b/arch/mips/mach-xburst/serial.c new file mode 100644 index 0000000000..acf5648467 --- /dev/null +++ b/arch/mips/mach-xburst/serial.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * Based on the linux kernel JZ4740 serial support: + * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * 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. + * + */ + +#include <common.h> +#include <ns16550.h> +#include <io.h> +#include <mach/devices.h> + +#define JZ_UART_SHIFT 2 + +#define ier (1 << JZ_UART_SHIFT) +#define fcr (2 << JZ_UART_SHIFT) + +static void jz_serial_reg_write(unsigned int val, unsigned long base, + unsigned char reg_offset) +{ + switch (reg_offset) { + case fcr: + val |= 0x10; /* Enable uart module */ + break; + case ier: + val |= (val & 0x4) << 2; + break; + default: + break; + } + + writeb(val & 0xff, (void *)(base + reg_offset)); +} + +struct device_d *jz_add_uart(int id, unsigned long base, unsigned int clock) +{ + struct NS16550_plat *serial_plat; + + serial_plat = xzalloc(sizeof(*serial_plat)); + + serial_plat->shift = JZ_UART_SHIFT; + serial_plat->reg_write = &jz_serial_reg_write; + serial_plat->clock = clock; + + return add_ns16550_device(id, base, 8 << JZ_UART_SHIFT, + IORESOURCE_MEM_8BIT, serial_plat); +} diff --git a/arch/ppc/boards/.gitignore b/arch/ppc/boards/.gitignore new file mode 100644 index 0000000000..d1165788c9 --- /dev/null +++ b/arch/ppc/boards/.gitignore @@ -0,0 +1 @@ +barebox.lds diff --git a/arch/ppc/include/asm/io.h b/arch/ppc/include/asm/io.h index 00529898dd..d3473e5c96 100644 --- a/arch/ppc/include/asm/io.h +++ b/arch/ppc/include/asm/io.h @@ -135,73 +135,76 @@ static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) /* * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. */ -extern inline int in_8(volatile u8 *addr) +extern inline u8 in_8(const volatile u8 __iomem *addr) { - int ret; + u8 ret; - __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); - return ret; + __asm__ __volatile__("sync; lbz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; } -extern inline void out_8(volatile u8 *addr, int val) +extern inline void out_8(volatile u8 __iomem *addr, u8 val) { - __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); + __asm__ __volatile__("sync;stb%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); } -extern inline int in_le16(volatile u16 *addr) +extern inline u16 in_le16(const volatile u16 __iomem *addr) { - int ret; + u16 ret; - __asm__ __volatile__("lhbrx %0,0,%1; eieio" : "=r" (ret) : - "r" (addr), "m" (*addr)); - return ret; + __asm__ __volatile__("sync; lhbrx %0,0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "r" (addr), "m" (*addr)); + return ret; } -extern inline int in_be16(volatile u16 *addr) +extern inline u16 in_be16(const volatile u16 __iomem *addr) { - int ret; + u16 ret; - __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); - return ret; + __asm__ __volatile__("sync; lhz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; } -extern inline void out_le16(volatile u16 *addr, int val) +extern inline void out_le16(volatile u16 __iomem *addr, u16 val) { - __asm__ __volatile__("sthbrx %1,0,%2; eieio" : "=m" (*addr) : - "r" (val), "r" (addr)); + __asm__ __volatile__("sync; sthbrx %1,0,%2" + : "=m" (*addr) : "r" (val), "r" (addr)); } -extern inline void out_be16(volatile u16 *addr, int val) +extern inline void out_be16(volatile u16 __iomem *addr, u16 val) { - __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); + __asm__ __volatile__("sync;sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); } -extern inline unsigned in_le32(volatile u32 *addr) +extern inline u32 in_le32(const volatile u32 __iomem *addr) { - unsigned ret; + u32 ret; - __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) : - "r" (addr), "m" (*addr)); - return ret; + __asm__ __volatile__("sync; lwbrx %0,0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "r" (addr), "m" (*addr)); + return ret; } -extern inline unsigned in_be32(volatile u32 *addr) +extern inline u32 in_be32(const volatile u32 __iomem *addr) { - unsigned ret; + u32 ret; - __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); - return ret; + __asm__ __volatile__("sync; lwz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; } -extern inline void out_le32(volatile unsigned *addr, int val) +extern inline void out_le32(volatile u32 __iomem *addr, u32 val) { - __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) : - "r" (val), "r" (addr)); + __asm__ __volatile__("sync; stwbrx %1,0,%2" + : "=m" (*addr) : "r" (val), "r" (addr)); } -extern inline void out_be32(volatile unsigned *addr, int val) +extern inline void out_be32(volatile u32 __iomem *addr, u32 val) { - __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); + __asm__ __volatile__("sync;stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); } /* diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c index 48c6ea35a8..ac29cfa47a 100644 --- a/arch/sandbox/board/hostfile.c +++ b/arch/sandbox/board/hostfile.c @@ -77,6 +77,9 @@ static int hf_probe(struct device_d *dev) priv->cdev.size = hf->size; priv->cdev.ops = &hf_fops; priv->cdev.priv = hf; + + dev->info = hf_info; + #ifdef CONFIG_FS_DEVFS devfs_create(&priv->cdev); #endif @@ -87,7 +90,6 @@ static int hf_probe(struct device_d *dev) static struct driver_d hf_drv = { .name = "hostfile", .probe = hf_probe, - .info = hf_info, }; device_platform_driver(hf_drv); @@ -111,4 +113,3 @@ int barebox_register_filedev(struct hf_platform_data *hf) return sandbox_add_device(dev); } - diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h index b0218d27c0..d473405ff9 100644 --- a/arch/x86/include/asm/types.h +++ b/arch/x86/include/asm/types.h @@ -29,12 +29,16 @@ typedef unsigned int __u32; typedef __signed__ long long __s64; typedef unsigned long long __u64; +typedef signed char s8; typedef unsigned char u8; +typedef signed short s16; typedef unsigned short u16; +typedef signed int s32; typedef unsigned int u32; +typedef signed long long s64; typedef unsigned long long u64; #endif /* __ASSEMBLY__ */ diff --git a/commands/Kconfig b/commands/Kconfig index 6a759ce204..a62ed9823b 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -728,6 +728,15 @@ config CMD_CLK Say yes here to get clk_set_rate, clk_set_parent and clk_dump commands to manipulate clocks on your system. +config CMD_DETECT + tristate + prompt "detect" + help + say yes here to get the 'detect' command. Some devices take longer + time to probe, like slow disks or SD/MMC cards. These can defer the + actual probe of the client devices until they are needed. Use the + 'detect' command on the physical device to trigger probing. + menuconfig CMD_WD bool depends on WATCHDOG diff --git a/commands/Makefile b/commands/Makefile index 953ecc284b..419d93bc0e 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -90,3 +90,4 @@ obj-$(CONFIG_CMD_TFTP) += tftp.o obj-$(CONFIG_CMD_FILETYPE) += filetype.o obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o obj-$(CONFIG_CMD_MIITOOL) += miitool.o +obj-$(CONFIG_CMD_DETECT) += detect.o diff --git a/commands/bootm.c b/commands/bootm.c index 5dd1703538..6ce2ca9897 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -395,13 +395,9 @@ static int do_bootm(int argc, char *argv[]) goto err_out; } else { data.of_root_node = of_get_root_node(); - if (bootm_verbose(&data) && data.of_root_node) + if (data.of_root_node) printf("using internal devicetree\n"); } - - - if (bootm_verbose(&data) > 1 && data.of_root_node) - of_print_nodes(data.of_root_node, 0); #endif if (data.os_address == UIMAGE_SOME_ADDRESS) data.os_address = UIMAGE_INVALID_ADDRESS; diff --git a/commands/detect.c b/commands/detect.c new file mode 100644 index 0000000000..0010a17779 --- /dev/null +++ b/commands/detect.c @@ -0,0 +1,77 @@ +/* + * detect.c - detect devices command + * + * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + */ +#include <common.h> +#include <command.h> +#include <complete.h> +#include <driver.h> +#include <getopt.h> + +static int do_detect(int argc, char *argv[]) +{ + struct device_d *dev; + int opt, i, ret; + int option_list = 0; + int option_error = 0; + + while ((opt = getopt(argc, argv, "el")) > 0) { + switch (opt) { + case 'l': + option_list = 1; + break; + case 'e': + option_error = 1; + break; + } + } + + if (option_list) { + for_each_device(dev) { + if (dev->detect) + printf("%s\n", dev_name(dev)); + } + return 0; + } + + if (argc == optind) + return COMMAND_ERROR_USAGE; + + for (i = optind; i < argc; i++) { + dev = get_device_by_name(argv[i]); + if (!dev) + return -ENODEV; + ret = device_detect(dev); + if (ret && option_error) + return ret; + } + + return 0; +} + +BAREBOX_CMD_HELP_START(detect) +BAREBOX_CMD_HELP_USAGE("detect [OPTIONS] [devices]\n") +BAREBOX_CMD_HELP_OPT ("-l", "list detectable devices\n") +BAREBOX_CMD_HELP_OPT ("-e", "bail out if one device fails to detect\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(detect) + .cmd = do_detect, + .usage = "detect devices", + BAREBOX_CMD_COMPLETE(device_complete) + BAREBOX_CMD_HELP(cmd_detect_help) +BAREBOX_CMD_END diff --git a/common/block.c b/common/block.c index 120d65928e..ad07f8b2e2 100644 --- a/common/block.c +++ b/common/block.c @@ -176,7 +176,7 @@ static void *block_get(struct block_device *blk, int block) return outdata; } -static ssize_t block_read(struct cdev *cdev, void *buf, size_t count, +static ssize_t block_op_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, unsigned long flags) { struct block_device *blk = cdev->priv; @@ -253,7 +253,7 @@ static int block_put(struct block_device *blk, const void *buf, int block) return 0; } -static ssize_t block_write(struct cdev *cdev, const void *buf, size_t count, +static ssize_t block_op_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) { struct block_device *blk = cdev->priv; @@ -310,14 +310,14 @@ static ssize_t block_write(struct cdev *cdev, const void *buf, size_t count, } #endif -static int block_close(struct cdev *cdev) +static int block_op_close(struct cdev *cdev) { struct block_device *blk = cdev->priv; return writebuffer_flush(blk); } -static int block_flush(struct cdev *cdev) +static int block_op_flush(struct cdev *cdev) { struct block_device *blk = cdev->priv; @@ -325,12 +325,12 @@ static int block_flush(struct cdev *cdev) } static struct file_operations block_ops = { - .read = block_read, + .read = block_op_read, #ifdef CONFIG_BLOCK_WRITE - .write = block_write, + .write = block_op_write, #endif - .close = block_close, - .flush = block_flush, + .close = block_op_close, + .flush = block_op_flush, .lseek = dev_lseek_default, }; @@ -387,3 +387,25 @@ int blockdevice_unregister(struct block_device *blk) return 0; } + +int block_read(struct block_device *blk, void *buf, int block, int num_blocks) +{ + int ret; + + ret = cdev_read(&blk->cdev, buf, + num_blocks << blk->blockbits, + (loff_t)block << blk->blockbits, 0); + + return ret < 0 ? ret : 0; +} + +int block_write(struct block_device *blk, void *buf, int block, int num_blocks) +{ + int ret; + + ret = cdev_write(&blk->cdev, buf, + num_blocks << blk->blockbits, + (loff_t)block << blk->blockbits, 0); + + return ret < 0 ? ret : 0; +} diff --git a/common/globalvar.c b/common/globalvar.c index a8aaa72553..abcd881adf 100644 --- a/common/globalvar.c +++ b/common/globalvar.c @@ -22,7 +22,7 @@ int globalvar_add(const char *name, * get a concatenated string of all globalvars beginning with 'match'. * This adds whitespaces between the different globalvars */ -char *globalvar_get_match(const char *match, const char *seperator) +char *globalvar_get_match(const char *match, const char *separator) { char *val = NULL; struct param_d *param; @@ -31,7 +31,7 @@ char *globalvar_get_match(const char *match, const char *seperator) if (!strncmp(match, param->name, strlen(match))) { const char *p = dev_get_param(&global_device, param->name); if (val) { - char *new = asprintf("%s%s%s", val, seperator, p); + char *new = asprintf("%s%s%s", val, separator, p); free(val); val = new; } else { diff --git a/common/hush.c b/common/hush.c index b5e111a019..a3235ba19f 100644 --- a/common/hush.c +++ b/common/hush.c @@ -1959,7 +1959,7 @@ BAREBOX_CMD_START(getopt) BAREBOX_CMD_END #endif -BAREBOX_MAGICVAR(PATH, "colon seperated list of pathes to search for executables"); +BAREBOX_MAGICVAR(PATH, "colon separated list of pathes to search for executables"); #ifdef CONFIG_HUSH_FANCY_PROMPT BAREBOX_MAGICVAR(PS1, "hush prompt"); #endif diff --git a/common/oftree.c b/common/oftree.c index 776d301186..475d418849 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -98,6 +98,21 @@ void of_print_property(const void *data, int len) } } +void of_print_cmdline(struct device_node *root) +{ + struct device_node *node = of_find_node_by_path(root, "/chosen"); + const char *cmdline; + + if (!node) { + printf("commandline: no /chosen node\n"); + return; + } + + cmdline = of_get_property(node, "bootargs", NULL); + + printf("commandline: %s\n", cmdline); +} + static int of_fixup_bootargs(struct device_node *root) { struct device_node *node; @@ -161,12 +176,6 @@ int of_fix_tree(struct device_node *node) } /* - * The size by which we increase the dtb to have space for additional - * fixups. Ideally this would be done by libfdt automatically - */ -#define OFTREE_SIZE_INCREASE 0x8000 - -/* * Get the fixed fdt. This function uses the fdt input pointer * if provided or the barebox internal devicetree if not. * It increases the size of the tree and applies the registered diff --git a/common/partitions.c b/common/partitions.c index 683b2586e4..35a604c35f 100644 --- a/common/partitions.c +++ b/common/partitions.c @@ -128,7 +128,7 @@ int parse_partition_table(struct block_device *blk) pdesc = xzalloc(sizeof(*pdesc)); buf = dma_alloc(SECTOR_SIZE * 2); - rc = blk->ops->read(blk, buf, 0, 2); + rc = block_read(blk, buf, 0, 2); if (rc != 0) { dev_err(blk->dev, "Cannot read MBR/partition table\n"); goto on_error; diff --git a/common/partitions/Kconfig b/common/partitions/Kconfig index 077091cde2..90238ad382 100644 --- a/common/partitions/Kconfig +++ b/common/partitions/Kconfig @@ -1,5 +1,6 @@ config PARTITION_DISK depends on PARTITION + depends on BLOCK bool "DISK partition support" help Add support for handling common partition tables on all kind of disk diff --git a/common/partitions/dos.c b/common/partitions/dos.c index 597f9ba581..b9f31c3784 100644 --- a/common/partitions/dos.c +++ b/common/partitions/dos.c @@ -16,6 +16,8 @@ #include <disks.h> #include <init.h> #include <asm/unaligned.h> +#include <dma.h> +#include <linux/err.h> #include "parser.h" @@ -40,6 +42,74 @@ static int disk_guess_size(struct device_d *dev, struct partition_entry *table) return (int)size; } +static void *read_mbr(struct block_device *blk) +{ + void *buf = dma_alloc(SECTOR_SIZE); + int ret; + + ret = block_read(blk, buf, 0, 1); + if (ret) { + free(buf); + return NULL; + } + + return buf; +} + +static int write_mbr(struct block_device *blk, void *buf) +{ + int ret; + + ret = block_write(blk, buf, 0, 1); + if (ret) + return ret; + + return block_flush(blk); +} + +struct disk_signature_priv { + uint32_t signature; + struct block_device *blk; +}; + +static int dos_set_disk_signature(struct param_d *p, void *_priv) +{ + struct disk_signature_priv *priv = _priv; + struct block_device *blk = priv->blk; + void *buf; + __le32 *disksigp; + int ret; + + buf = read_mbr(blk); + if (!buf) + return -EIO; + + disksigp = buf + 0x1b8; + + *disksigp = cpu_to_le32(priv->signature); + + ret = write_mbr(blk, buf); + + free(buf); + + return ret; +} + +static int dos_get_disk_signature(struct param_d *p, void *_priv) +{ + struct disk_signature_priv *priv = _priv; + struct block_device *blk = priv->blk; + void *buf; + + buf = read_mbr(blk); + if (!buf) + return -EIO; + + priv->signature = le32_to_cpup((__le32 *)(buf + 0x1b8)); + + return 0; +} + /** * Check if a DOS like partition describes this block device * @param blk Block device to register to @@ -55,6 +125,7 @@ static void dos_partition(void *buf, struct block_device *blk, struct partition pentry; uint8_t *buffer = buf; int i; + struct disk_signature_priv *dsp; table = (struct partition_entry *)&buffer[446]; @@ -74,6 +145,23 @@ static void dos_partition(void *buf, struct block_device *blk, dev_dbg(blk->dev, "Skipping empty partition %d\n", i); } } + + dsp = xzalloc(sizeof(*dsp)); + dsp->blk = blk; + + /* + * This parameter contains the NT disk signature. This allows to + * to specify the Linux rootfs using the following syntax: + * + * root=PARTUUID=ssssssss-pp + * + * where ssssssss is a zero-filled hex representation of the 32-bit + * signature and pp is a zero-filled hex representation of the 1-based + * partition number. + */ + dev_add_param_int(blk->dev, "nt_signature", + dos_set_disk_signature, dos_get_disk_signature, + &dsp->signature, "%08x", dsp); } static struct partition_parser dos = { diff --git a/common/partitions/efi.c b/common/partitions/efi.c index e450eebf77..ee1326e622 100644 --- a/common/partitions/efi.c +++ b/common/partitions/efi.c @@ -86,7 +86,7 @@ static gpt_entry *alloc_read_gpt_entries(struct block_device *blk, from = le64_to_cpu(pgpt_head->partition_entry_lba); size = count / GPT_BLOCK_SIZE; - ret = blk->ops->read(blk, pte, from, size); + ret = block_read(blk, pte, from, size); if (ret) { kfree(pte); pte=NULL; @@ -121,7 +121,7 @@ static gpt_header *alloc_read_gpt_header(struct block_device *blk, if (!gpt) return NULL; - ret = blk->ops->read(blk, gpt, lba, 1); + ret = block_read(blk, gpt, lba, 1); if (ret) { kfree(gpt); gpt=NULL; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 37419f239a..7def9a093b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -635,6 +635,7 @@ static int ahci_probe(struct device_d *dev) ahci->dev = dev; ahci->mmio_base = regs; dev->priv = ahci; + dev->info = ahci_info; ret = ahci_add_host(ahci); if (ret) @@ -654,7 +655,6 @@ static __maybe_unused struct of_device_id ahci_dt_ids[] = { static struct driver_d ahci_driver = { .name = "ahci", .probe = ahci_probe, - .info = ahci_info, .of_compatible = DRV_OF_COMPAT(ahci_dt_ids), }; device_platform_driver(ahci_driver); diff --git a/drivers/ata/sata-imx.c b/drivers/ata/sata-imx.c index bd48fae1f4..13bf116fdd 100644 --- a/drivers/ata/sata-imx.c +++ b/drivers/ata/sata-imx.c @@ -107,6 +107,7 @@ static int imx_sata_probe(struct device_d *dev) imx_ahci->ahci.dev = dev; dev->priv = &imx_ahci->ahci; + dev->info = ahci_info, ret = ahci_add_host(&imx_ahci->ahci); if (ret) @@ -143,7 +144,6 @@ static struct platform_device_id imx_sata_ids[] = { static struct driver_d imx_sata_driver = { .name = "imx-sata", .probe = imx_sata_probe, - .info = ahci_info, .id_table = imx_sata_ids, }; device_platform_driver(imx_sata_driver); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index edd49b367f..810d0011f6 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -93,6 +93,13 @@ int device_probe(struct device_d *dev) return 0; } +int device_detect(struct device_d *dev) +{ + if (!dev->detect) + return -ENOSYS; + return dev->detect(dev); +} + static int match(struct driver_d *drv, struct device_d *dev) { int ret; @@ -201,15 +208,6 @@ struct driver_d *get_driver_by_name(const char *name) return NULL; } -static void noinfo(struct device_d *dev) -{ - printf("no info available for %s\n", dev_name(dev)); -} - -static void noshortinfo(struct device_d *dev) -{ -} - int register_driver(struct driver_d *drv) { struct device_d *dev = NULL; @@ -221,11 +219,6 @@ int register_driver(struct driver_d *drv) list_add_tail(&drv->list, &driver_list); list_add_tail(&drv->bus_list, &drv->bus->driver_list); - if (!drv->info) - drv->info = noinfo; - if (!drv->shortinfo) - drv->shortinfo = noshortinfo; - bus_for_each_device(drv->bus, dev) match(drv, dev); @@ -489,14 +482,18 @@ static int do_devinfo(int argc, char *argv[]) printf("bus: %s\n\n", dev->bus ? dev->bus->name : "none"); - if (dev->driver) - dev->driver->info(dev); + if (dev->info) + dev->info(dev); printf("%s\n", list_empty(&dev->parameters) ? "no parameters available" : "Parameters:"); - list_for_each_entry(param, &dev->parameters, list) - printf("%16s = %s\n", param->name, dev_get_param(dev, param->name)); + list_for_each_entry(param, &dev->parameters, list) { + printf("%16s = %s", param->name, dev_get_param(dev, param->name)); + if (param->info) + param->info(param); + printf("\n"); + } #ifdef CONFIG_OFDEVICE if (dev->device_node) { printf("\ndevice node: %s\n", dev->device_node->full_name); diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 9f3558b6e4..4ef25ec45b 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -14,6 +14,14 @@ config CLOCKSOURCE_CLPS711X bool depends on ARCH_CLPS711X +config CLOCKSOURCE_MVEBU + bool + depends on ARCH_MVEBU + config CLOCKSOURCE_NOMADIK bool depends on ARM + +config CLOCKSOURCE_ORION + bool + depends on ARCH_MVEBU diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index d919881fb8..25b7f460da 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -2,4 +2,6 @@ obj-$(CONFIG_AMBA_SP804) += amba-sp804.o obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o +obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o +obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o diff --git a/drivers/clocksource/mvebu.c b/drivers/clocksource/mvebu.c new file mode 100644 index 0000000000..2b48a5c91b --- /dev/null +++ b/drivers/clocksource/mvebu.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.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. + * + */ + +#include <common.h> +#include <init.h> +#include <clock.h> +#include <linux/clk.h> +#include <io.h> + +#define TIMER_CTRL_OFF 0x0000 +#define TIMER0_EN 0x0001 +#define TIMER0_RELOAD_EN 0x0002 +#define TIMER0_25MHZ 0x0800 +#define TIMER0_DIV(div) ((div) << 19) +#define TIMER1_EN 0x0004 +#define TIMER1_RELOAD_EN 0x0008 +#define TIMER1_25MHZ 0x1000 +#define TIMER1_DIV(div) ((div) << 22) +#define TIMER_EVENTS_STATUS 0x0004 +#define TIMER0_CLR_MASK (~0x1) +#define TIMER1_CLR_MASK (~0x100) +#define TIMER0_RELOAD_OFF 0x0010 +#define TIMER0_VAL_OFF 0x0014 +#define TIMER1_RELOAD_OFF 0x0018 +#define TIMER1_VAL_OFF 0x001c + +#define TIMER_DIVIDER_SHIFT 5 + +static __iomem void *timer_base; + +uint64_t mvebu_clocksource_read(void) +{ + return __raw_readl(timer_base + TIMER0_VAL_OFF); +} + +static struct clocksource cs = { + .read = mvebu_clocksource_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 10, +}; + +static int mvebu_timer_probe(struct device_d *dev) +{ + struct clk *tclk; + u32 val; + + timer_base = dev_request_mem_region(dev, 0); + + tclk = clk_get(dev, "tclk"); + + val = __raw_readl(timer_base + TIMER_CTRL_OFF); + val &= ~TIMER0_25MHZ; + __raw_writel(val, timer_base + TIMER_CTRL_OFF); + + __raw_writel(0xffffffff, timer_base + TIMER0_VAL_OFF); + __raw_writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); + + val = __raw_readl(timer_base + TIMER_CTRL_OFF); + val |= TIMER0_EN | TIMER0_RELOAD_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); + __raw_writel(val, timer_base + TIMER_CTRL_OFF); + + cs.mult = clocksource_hz2mult(clk_get_rate(tclk), cs.shift); + + init_clock(&cs); + + return 0; +} + +static struct driver_d mvebu_timer_driver = { + .name = "mvebu-timer", + .probe = mvebu_timer_probe, +}; + +static int mvebu_timer_init(void) +{ + return platform_driver_register(&mvebu_timer_driver); +} +postcore_initcall(mvebu_timer_init); diff --git a/drivers/clocksource/orion.c b/drivers/clocksource/orion.c new file mode 100644 index 0000000000..604b414742 --- /dev/null +++ b/drivers/clocksource/orion.c @@ -0,0 +1,76 @@ +/* + * Copyright + * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@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. + * + */ + +#include <common.h> +#include <init.h> +#include <clock.h> +#include <linux/clk.h> +#include <io.h> + +#define TIMER_CTRL 0x00 +#define TIMER0_EN BIT(0) +#define TIMER0_RELOAD_EN BIT(1) +#define TIMER1_EN BIT(2) +#define TIMER1_RELOAD_EN BIT(3) +#define TIMER0_RELOAD 0x10 +#define TIMER0_VAL 0x14 +#define TIMER1_RELOAD 0x18 +#define TIMER1_VAL 0x1c + +static __iomem void *timer_base; + +static uint64_t orion_clocksource_read(void) +{ + return __raw_readl(timer_base + TIMER0_VAL); +} + +static struct clocksource clksrc = { + .read = orion_clocksource_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 10, +}; + +static int orion_timer_probe(struct device_d *dev) +{ + struct clk *tclk; + uint32_t val; + + timer_base = dev_request_mem_region(dev, 0); + tclk = clk_get(dev, "tclk"); + + /* setup TIMER0 as free-running clock source */ + __raw_writel(~0, timer_base + TIMER0_VAL); + __raw_writel(~0, timer_base + TIMER0_RELOAD); + val = __raw_readl(timer_base + TIMER_CTRL); + __raw_writel(val | TIMER0_EN | TIMER0_RELOAD_EN, + timer_base + TIMER_CTRL); + + clksrc.mult = clocksource_hz2mult(clk_get_rate(tclk), clksrc.shift); + init_clock(&clksrc); + + return 0; +} + +static struct driver_d orion_timer_driver = { + .name = "orion-timer", + .probe = orion_timer_probe, +}; + +static int orion_timer_init(void) +{ + return platform_driver_register(&orion_timer_driver); +} +postcore_initcall(orion_timer_init); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6398268eae..ca6e8adab4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) "gpiolib: " fmt + #include <init.h> #include <common.h> #include <command.h> @@ -32,20 +34,30 @@ static int gpio_ensure_requested(struct gpio_info *gi, int gpio) return gpio_request(gpio, "gpio"); } +static struct gpio_info *gpio_to_desc(unsigned gpio) +{ + if (gpio_is_valid(gpio)) + if (gpio_desc[gpio].chip) + return &gpio_desc[gpio]; + + pr_warning("invalid GPIO %d\n", gpio); + + return NULL; +} + int gpio_request(unsigned gpio, const char *label) { - struct gpio_info *gi = &gpio_desc[gpio]; - struct gpio_chip *chip = gi->chip; + struct gpio_info *gi = gpio_to_desc(gpio); int ret; - if (!gpio_is_valid(gpio)) - return -EINVAL; - if (!chip) - return -EINVAL; + if (!gi) + return -ENODEV; + if (gi->requested) return -EBUSY; - if (chip->ops->request) { - ret = chip->ops->request(chip, gpio - chip->base); + + if (gi->chip->ops->request) { + ret = gi->chip->ops->request(gi->chip, gpio - gi->chip->base); if (ret) return ret; } @@ -58,17 +70,16 @@ int gpio_request(unsigned gpio, const char *label) void gpio_free(unsigned gpio) { - struct gpio_info *gi = &gpio_desc[gpio]; - struct gpio_chip *chip = gi->chip; + struct gpio_info *gi = gpio_to_desc(gpio); - if (!gpio_is_valid(gpio)) - return; - if (!chip) + if (!gi) return; + if (!gi->requested) return; - if (chip->ops->free) - chip->ops->free(chip, gpio - chip->base); + + if (gi->chip->ops->free) + gi->chip->ops->free(gi->chip, gpio - gi->chip->base); gi->requested = false; free(gi->label); @@ -76,75 +87,71 @@ void gpio_free(unsigned gpio) void gpio_set_value(unsigned gpio, int value) { - struct gpio_info *gi = &gpio_desc[gpio]; - struct gpio_chip *chip = gi->chip; + struct gpio_info *gi = gpio_to_desc(gpio); - if (!gpio_is_valid(gpio)) - return; - if (!chip) + if (!gi) return; + if (gpio_ensure_requested(gi, gpio)) return; - if (!chip->ops->set) - return; - chip->ops->set(chip, gpio - chip->base, value); + + if (gi->chip->ops->set) + gi->chip->ops->set(gi->chip, gpio - gi->chip->base, value); } EXPORT_SYMBOL(gpio_set_value); int gpio_get_value(unsigned gpio) { - struct gpio_info *gi = &gpio_desc[gpio]; - struct gpio_chip *chip = gi->chip; + struct gpio_info *gi = gpio_to_desc(gpio); int ret; - if (!gpio_is_valid(gpio)) - return -EINVAL; - if (!chip) + if (!gi) return -ENODEV; + ret = gpio_ensure_requested(gi, gpio); if (ret) return ret; - if (!chip->ops->get) + + if (!gi->chip->ops->get) return -ENOSYS; - return chip->ops->get(chip, gpio - chip->base); + return gi->chip->ops->get(gi->chip, gpio - gi->chip->base); } EXPORT_SYMBOL(gpio_get_value); int gpio_direction_output(unsigned gpio, int value) { - struct gpio_info *gi = &gpio_desc[gpio]; - struct gpio_chip *chip = gi->chip; + struct gpio_info *gi = gpio_to_desc(gpio); int ret; - if (!gpio_is_valid(gpio)) - return -EINVAL; - if (!chip) + if (!gi) return -ENODEV; + ret = gpio_ensure_requested(gi, gpio); if (ret) return ret; - if (!chip->ops->direction_output) + + if (!gi->chip->ops->direction_output) return -ENOSYS; - return chip->ops->direction_output(chip, gpio - chip->base, value); + return gi->chip->ops->direction_output(gi->chip, gpio - gi->chip->base, + value); } EXPORT_SYMBOL(gpio_direction_output); int gpio_direction_input(unsigned gpio) { - struct gpio_info *gi = &gpio_desc[gpio]; - struct gpio_chip *chip = gi->chip; + struct gpio_info *gi = gpio_to_desc(gpio); int ret; - if (!gpio_is_valid(gpio)) - return -EINVAL; - if (!chip) + if (!gi) return -ENODEV; + ret = gpio_ensure_requested(gi, gpio); if (ret) return ret; - if (!chip->ops->direction_input) + + if (!gi->chip->ops->direction_input) return -ENOSYS; - return chip->ops->direction_input(chip, gpio - chip->base); + return gi->chip->ops->direction_input(gi->chip, gpio - gi->chip->base); } EXPORT_SYMBOL(gpio_direction_input); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 9fcfd5c6f7..c607bcba1a 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -545,6 +545,7 @@ static int __init i2c_fsl_probe(struct device_d *pdev) i2c_fsl->adapter.master_xfer = i2c_fsl_xfer; i2c_fsl->adapter.nr = pdev->id; i2c_fsl->adapter.dev.parent = pdev; + i2c_fsl->adapter.dev.device_node = pdev->device_node; i2c_fsl->base = dev_request_mem_region(pdev, 0); i2c_fsl->dfsrr = -1; @@ -572,8 +573,17 @@ fail: return ret; } +static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = { + { + .compatible = "fsl,imx21-i2c", + }, { + /* sentinel */ + } +}; + static struct driver_d i2c_fsl_driver = { .probe = i2c_fsl_probe, .name = DRIVER_NAME, + .of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids), }; device_platform_driver(i2c_fsl_driver); diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c index 4862df3c00..b63d94604d 100644 --- a/drivers/i2c/i2c.c +++ b/drivers/i2c/i2c.c @@ -254,33 +254,61 @@ struct i2c_client *i2c_new_device(struct i2c_adapter *adapter, client->dev.platform_data = chip->platform_data; client->dev.id = DEVICE_ID_DYNAMIC; client->dev.bus = &i2c_bus; + client->dev.device_node = chip->of_node; client->adapter = adapter; client->addr = chip->addr; client->dev.parent = &adapter->dev; status = register_device(&client->dev); - -#if 0 - /* drivers may modify this initial i/o setup */ - status = master->setup(client); - if (status < 0) { - printf("can't setup %s, status %d\n", - client->dev.name, status); - goto fail; + if (status) { + free(client); + return NULL; } -#endif return client; - -#if 0 - fail: - free(proxy); - return NULL; -#endif } EXPORT_SYMBOL(i2c_new_device); +void of_i2c_register_devices(struct i2c_adapter *adap) +{ + struct device_node *n; + + /* Only register child devices if the adapter has a node pointer set */ + if (!IS_ENABLED(CONFIG_OFDEVICE) || !adap->dev.device_node) + return; + + device_node_for_nach_child(adap->dev.device_node, n) { + struct i2c_board_info info = {}; + struct i2c_client *result; + const __be32 *addr; + int len; + + of_modalias_node(n, info.type, I2C_NAME_SIZE); + + info.of_node = n; + + addr = of_get_property(n, "reg", &len); + if (!addr || (len < sizeof(int))) { + dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", + n->full_name); + continue; + } + + info.addr = be32_to_cpup(addr); + if (info.addr > (1 << 10) - 1) { + dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", + info.addr, n->full_name); + continue; + } + + result = i2c_new_device(adap, &info); + if (!result) + dev_err(&adap->dev, "of_i2c: Failure registering %s\n", + n->full_name); + } +} + /** * i2c_new_dummy - return a new i2c device bound to a dummy driver * @adapter: the adapter managing the device @@ -396,8 +424,17 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter) { int ret; - if (i2c_get_adapter(adapter->nr)) - return -EBUSY; + if (adapter->nr < 0) { + int nr; + + for (nr = 0;; nr++) + if (!i2c_get_adapter(nr)) + break; + adapter->nr = nr; + } else { + if (i2c_get_adapter(adapter->nr)) + return -EBUSY; + } adapter->dev.id = adapter->nr; strcpy(adapter->dev.name, "i2c"); @@ -411,6 +448,8 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter) /* populate children from any i2c device tables */ scan_boardinfo(adapter); + of_i2c_register_devices(adapter); + return 0; } EXPORT_SYMBOL(i2c_add_numbered_adapter); diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 9558f287d3..7aff7df838 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -29,6 +29,9 @@ config MCI_WRITE default y select DISK_WRITE +config MCI_MMC_BOOT_PARTITIONS + bool "support MMC boot partitions" + comment "--- MCI host drivers ---" config MCI_MXS @@ -45,6 +48,10 @@ config MCI_S3C Enable this entry to add support to read and write SD cards on a Samsung S3C24xx based system. +config MCI_BCM2835 + bool "MCI support for BCM2835" + depends on ARCH_BCM2835 + config MCI_IMX bool "i.MX" depends on ARCH_IMX27 || ARCH_IMX31 diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index d46d5f50e8..df06a08f61 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -1,10 +1,10 @@ -obj-$(CONFIG_MCI) += mci-core.o -obj-$(CONFIG_MCI_MXS) += mxs.o -obj-$(CONFIG_MCI_S3C) += s3c.o -obj-$(CONFIG_MCI_IMX) += imx.o -obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o -obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o -obj-$(CONFIG_MFD_TWL6030) += twl6030.o -obj-$(CONFIG_MCI_PXA) += pxamci.o -obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o -obj-$(CONFIG_MCI_SPI) += mci_spi.o +obj-$(CONFIG_MCI) += mci-core.o +obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o +obj-$(CONFIG_MCI_BCM2835) += mci-bcm2835.o +obj-$(CONFIG_MCI_IMX) += imx.o +obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o +obj-$(CONFIG_MCI_MXS) += mxs.o +obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o +obj-$(CONFIG_MCI_PXA) += pxamci.o +obj-$(CONFIG_MCI_S3C) += s3c.o +obj-$(CONFIG_MCI_SPI) += mci_spi.o diff --git a/drivers/mci/atmel_mci.c b/drivers/mci/atmel_mci.c index c5fd306a9a..b5873f967b 100644 --- a/drivers/mci/atmel_mci.c +++ b/drivers/mci/atmel_mci.c @@ -470,7 +470,6 @@ static int atmci_request(struct mci_host *mci, struct mci_cmd *cmd, struct mci_d return atmci_cmd_done(host, stat); } -#ifdef CONFIG_MCI_INFO static void atmci_info(struct device_d *mci_dev) { struct atmel_mci *host = mci_dev->priv; @@ -493,7 +492,6 @@ static void atmci_info(struct device_d *mci_dev) gpio_is_valid(pd->detect_pin) ? "yes" : "no"); } -#endif /* CONFIG_MCI_INFO */ /* * HSMCI (High Speed MCI) module is not fully compatible with MCI module. * HSMCI provides DMA support and a new config register but no more supports @@ -603,6 +601,9 @@ static int atmci_probe(struct device_d *hw_dev) else host->sdc_reg = ATMCI_SDCSEL_SLOT_A; + if (IS_ENABLED(CONFIG_MCI_INFO)) + hw_dev->info = atmci_info; + mci_register(&host->mci); return 0; @@ -617,8 +618,5 @@ err_gpio_cd_request: static struct driver_d atmci_driver = { .name = "atmel_mci", .probe = atmci_probe, -#ifdef CONFIG_MCI_INFO - .info = atmci_info, -#endif }; device_platform_driver(atmci_driver); diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index f4fdac8e01..8053b79cb7 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -35,38 +35,15 @@ #include <mach/esdhc.h> #include <gpio.h> +#include "sdhci.h" #include "imx-esdhc.h" -struct fsl_esdhc { - u32 dsaddr; - u32 blkattr; - u32 cmdarg; - u32 xfertyp; - u32 cmdrsp0; - u32 cmdrsp1; - u32 cmdrsp2; - u32 cmdrsp3; - u32 datport; - u32 prsstat; - u32 proctl; - u32 sysctl; - u32 irqstat; - u32 irqstaten; - u32 irqsigen; - u32 autoc12err; - u32 hostcapblt; - u32 wml; - u32 mixctrl; - char reserved1[4]; - u32 fevt; - char reserved2[168]; - u32 hostver; -}; +#define IMX_SDHCI_WML 0x44 +#define IMX_SDHCI_MIXCTRL 0x48 struct fsl_esdhc_host { struct mci_host mci; - struct fsl_esdhc __iomem *regs; - unsigned long cur_clock; + void __iomem *regs; struct device_d *dev; struct clk *clk; }; @@ -81,34 +58,34 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) u32 xfertyp = 0; if (data) { - xfertyp |= XFERTYP_DPSEL; + xfertyp |= COMMAND_DPSEL; #ifndef CONFIG_MCI_IMX_ESDHC_PIO - xfertyp |= XFERTYP_DMAEN; + xfertyp |= TRANSFER_MODE_DMAEN; #endif if (data->blocks > 1) { - xfertyp |= XFERTYP_MSBSEL; - xfertyp |= XFERTYP_BCEN; + xfertyp |= TRANSFER_MODE_MSBSEL; + xfertyp |= TRANSFER_MODE_BCEN; } if (data->flags & MMC_DATA_READ) - xfertyp |= XFERTYP_DTDSEL; + xfertyp |= TRANSFER_MODE_DTDSEL; } if (cmd->resp_type & MMC_RSP_CRC) - xfertyp |= XFERTYP_CCCEN; + xfertyp |= COMMAND_CCCEN; if (cmd->resp_type & MMC_RSP_OPCODE) - xfertyp |= XFERTYP_CICEN; + xfertyp |= COMMAND_CICEN; if (cmd->resp_type & MMC_RSP_136) - xfertyp |= XFERTYP_RSPTYP_136; + xfertyp |= COMMAND_RSPTYP_136; else if (cmd->resp_type & MMC_RSP_BUSY) - xfertyp |= XFERTYP_RSPTYP_48_BUSY; + xfertyp |= COMMAND_RSPTYP_48_BUSY; else if (cmd->resp_type & MMC_RSP_PRESENT) - xfertyp |= XFERTYP_RSPTYP_48; + xfertyp |= COMMAND_RSPTYP_48; if ((cpu_is_mx51() || cpu_is_mx53()) && cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) xfertyp |= SDHCI_CMD_ABORTCMD; - return XFERTYP_CMD(cmd->cmdidx) | xfertyp; + return COMMAND_CMD(cmd->cmdidx) | xfertyp; } #ifdef CONFIG_MCI_IMX_ESDHC_PIO @@ -119,7 +96,7 @@ static void esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc *regs = host->regs; + void __iomem *regs = host->regs; u32 blocks; char *buffer; u32 databuf; @@ -133,8 +110,8 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) while (blocks) { timeout = PIO_TIMEOUT; size = data->blocksize; - irqstat = esdhc_read32(®s->irqstat); - while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN) + irqstat = esdhc_read32(regs + SDHCI_INT_STATUS); + while (!(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_BREN) && --timeout); if (timeout <= 0) { printf("\nData Read Failed in PIO Mode."); @@ -142,8 +119,8 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) } while (size && (!(irqstat & IRQSTAT_TC))) { udelay(100); /* Wait before last byte transfer complete */ - irqstat = esdhc_read32(®s->irqstat); - databuf = esdhc_read32(®s->datport); + irqstat = esdhc_read32(regs + SDHCI_INT_STATUS); + databuf = esdhc_read32(regs + SDHCI_BUFFER); *((u32 *)buffer) = databuf; buffer += 4; size -= 4; @@ -156,8 +133,8 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) while (blocks) { timeout = PIO_TIMEOUT; size = data->blocksize; - irqstat = esdhc_read32(®s->irqstat); - while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN) + irqstat = esdhc_read32(regs + SDHCI_INT_STATUS); + while (!(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_BWEN) && --timeout); if (timeout <= 0) { printf("\nData Write Failed in PIO Mode."); @@ -168,8 +145,8 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) databuf = *((u32 *)buffer); buffer += 4; size -= 4; - irqstat = esdhc_read32(®s->irqstat); - esdhc_write32(®s->datport, databuf); + irqstat = esdhc_read32(regs + SDHCI_INT_STATUS); + esdhc_write32(regs+ SDHCI_BUFFER, databuf); } blocks--; } @@ -180,7 +157,7 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc __iomem *regs = host->regs; + void __iomem *regs = host->regs; #ifndef CONFIG_MCI_IMX_ESDHC_PIO u32 wml_value; @@ -190,33 +167,33 @@ static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data) if (wml_value > 0x10) wml_value = 0x10; - esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); - esdhc_write32(®s->dsaddr, (u32)data->dest); + esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value); + esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest); } else { if (wml_value > 0x80) wml_value = 0x80; - if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) { + if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0) { printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); return -ETIMEDOUT; } - esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, + esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_WR_WML_MASK, wml_value << 16); - esdhc_write32(®s->dsaddr, (u32)data->src); + esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src); } #else /* CONFIG_MCI_IMX_ESDHC_PIO */ if (!(data->flags & MMC_DATA_READ)) { - if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) { + if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0) { printf("\nThe SD card is locked. " "Can not write to a locked card.\n\n"); return -ETIMEDOUT; } - esdhc_write32(®s->dsaddr, (u32)data->src); + esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src); } else - esdhc_write32(®s->dsaddr, (u32)data->dest); + esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest); #endif /* CONFIG_MCI_IMX_ESDHC_PIO */ - esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); + esdhc_write32(regs + SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize); return 0; } @@ -232,10 +209,10 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) u32 xfertyp, mixctrl; u32 irqstat; struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc __iomem *regs = host->regs; + void __iomem *regs = host->regs; int ret; - esdhc_write32(®s->irqstat, -1); + esdhc_write32(regs + SDHCI_INT_STATUS, -1); /* Wait at least 8 SD clock cycles before the next command */ udelay(1); @@ -260,28 +237,28 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) xfertyp = esdhc_xfertyp(cmd, data); /* Send the command */ - esdhc_write32(®s->cmdarg, cmd->cmdarg); + esdhc_write32(regs + SDHCI_ARGUMENT, cmd->cmdarg); if (cpu_is_mx6()) { /* write lower-half of xfertyp to mixctrl */ mixctrl = xfertyp & 0xFFFF; /* Keep the bits 22-25 of the register as is */ - mixctrl |= (esdhc_read32(®s->mixctrl) & (0xF << 22)); - esdhc_write32(®s->mixctrl, mixctrl); + mixctrl |= (esdhc_read32(regs + IMX_SDHCI_MIXCTRL) & (0xF << 22)); + esdhc_write32(regs + IMX_SDHCI_MIXCTRL, mixctrl); } - esdhc_write32(®s->xfertyp, xfertyp); + esdhc_write32(regs + SDHCI_TRANSFER_MODE__COMMAND, xfertyp); /* Wait for the command to complete */ ret = wait_on_timeout(100 * MSECOND, - esdhc_read32(®s->irqstat) & IRQSTAT_CC); + esdhc_read32(regs + SDHCI_INT_STATUS) & IRQSTAT_CC); if (ret) { dev_dbg(host->dev, "timeout 1\n"); return -ETIMEDOUT; } - irqstat = esdhc_read32(®s->irqstat); - esdhc_write32(®s->irqstat, irqstat); + irqstat = esdhc_read32(regs + SDHCI_INT_STATUS); + esdhc_write32(regs + SDHCI_INT_STATUS, irqstat); if (irqstat & CMD_ERR) return -EIO; @@ -293,16 +270,16 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) if (cmd->resp_type & MMC_RSP_136) { u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; - cmdrsp3 = esdhc_read32(®s->cmdrsp3); - cmdrsp2 = esdhc_read32(®s->cmdrsp2); - cmdrsp1 = esdhc_read32(®s->cmdrsp1); - cmdrsp0 = esdhc_read32(®s->cmdrsp0); + cmdrsp3 = esdhc_read32(regs + SDHCI_RESPONSE_3); + cmdrsp2 = esdhc_read32(regs + SDHCI_RESPONSE_2); + cmdrsp1 = esdhc_read32(regs + SDHCI_RESPONSE_1); + cmdrsp0 = esdhc_read32(regs + SDHCI_RESPONSE_0); cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); cmd->response[3] = (cmdrsp0 << 8); } else - cmd->response[0] = esdhc_read32(®s->cmdrsp0); + cmd->response[0] = esdhc_read32(regs + SDHCI_RESPONSE_0); /* Wait until all of the blocks are transferred */ if (data) { @@ -310,7 +287,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) esdhc_pio_read_write(mci, data); #else do { - irqstat = esdhc_read32(®s->irqstat); + irqstat = esdhc_read32(regs + SDHCI_INT_STATUS); if (irqstat & DATA_ERR) return -EIO; @@ -318,7 +295,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) if (irqstat & IRQSTAT_DTOE) return -ETIMEDOUT; } while (!(irqstat & IRQSTAT_TC) && - (esdhc_read32(®s->prsstat) & PRSSTAT_DLA)); + (esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_DLA)); if (data->flags & MMC_DATA_READ) { dma_inv_range((unsigned long)data->dest, @@ -327,11 +304,11 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) #endif } - esdhc_write32(®s->irqstat, -1); + esdhc_write32(regs + SDHCI_INT_STATUS, -1); /* Wait for the bus to be idle */ ret = wait_on_timeout(SECOND, - !(esdhc_read32(®s->prsstat) & + !(esdhc_read32(regs + SDHCI_PRESENT_STATE) & (PRSSTAT_CICHB | PRSSTAT_CIDHB))); if (ret) { dev_err(host->dev, "timeout 2\n"); @@ -339,7 +316,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) } ret = wait_on_timeout(100 * MSECOND, - !(esdhc_read32(®s->prsstat) & PRSSTAT_DLA)); + !(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_DLA)); if (ret) { dev_err(host->dev, "timeout 3\n"); return -ETIMEDOUT; @@ -352,63 +329,78 @@ static void set_sysctl(struct mci_host *mci, u32 clock) { int div, pre_div; struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc __iomem *regs = host->regs; + void __iomem *regs = host->regs; int sdhc_clk = clk_get_rate(host->clk); u32 clk; - - if (clock < mci->f_min) - clock = mci->f_min; - - pre_div = 0; - - for (pre_div = 1; pre_div < 256; pre_div <<= 1) { - if (sdhc_clk / pre_div < clock * 16) + unsigned long cur_clock; + + /* + * With eMMC and imx53 (sdhc_clk=200MHz) a pre_div of 1 results in + * pre_div=1,div=4 (=50MHz) + * which is valid and should work, but somehow doesn't. + * Starting with pre_div=2 gives + * pre_div=2, div=2 (=50MHz) + * and works fine. + */ + pre_div = 2; + + if (sdhc_clk == clock) + pre_div = 1; + else if (sdhc_clk / 16 > clock) + for (; pre_div < 256; pre_div *= 2) + if ((sdhc_clk / pre_div) <= (clock * 16)) + break; + + for (div = 1; div <= 16; div++) + if ((sdhc_clk / (div * pre_div)) <= clock) break; - }; - div = sdhc_clk / pre_div / clock; + cur_clock = sdhc_clk / pre_div / div; - if (sdhc_clk / pre_div / div > clock) - div++; - - host->cur_clock = sdhc_clk / pre_div / div; + dev_dbg(host->dev, "set clock: wanted: %d got: %ld\n", clock, cur_clock); + dev_dbg(host->dev, "pre_div: %d div: %d\n", pre_div, div); + /* the register values start with 0 */ div -= 1; pre_div >>= 1; - dev_dbg(host->dev, "set clock: wanted: %d got: %ld\n", clock, host->cur_clock); - dev_dbg(host->dev, "pre_div: %d div: %d\n", pre_div, div); - clk = (pre_div << 8) | (div << 4); - esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); + esdhc_clrbits32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_CKEN); - esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); + esdhc_clrsetbits32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_CLOCK_MASK, clk); - udelay(10000); + wait_on_timeout(10 * MSECOND, + !(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_SDSTB)); clk = SYSCTL_PEREN | SYSCTL_CKEN; - esdhc_setbits32(®s->sysctl, clk); + esdhc_setbits32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + clk); } static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc __iomem *regs = host->regs; + void __iomem *regs = host->regs; /* Set the clock speed */ set_sysctl(mci, ios->clock); /* Set the bus width */ - esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); + esdhc_clrbits32(regs + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + PROCTL_DTW_4 | PROCTL_DTW_8); switch (ios->bus_width) { case MMC_BUS_WIDTH_4: - esdhc_setbits32(®s->proctl, PROCTL_DTW_4); + esdhc_setbits32(regs + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + PROCTL_DTW_4); break; case MMC_BUS_WIDTH_8: - esdhc_setbits32(®s->proctl, PROCTL_DTW_8); + esdhc_setbits32(regs + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + PROCTL_DTW_8); break; case MMC_BUS_WIDTH_1: break; @@ -421,7 +413,7 @@ static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) static int esdhc_card_present(struct mci_host *mci) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc __iomem *regs = host->regs; + void __iomem *regs = host->regs; struct esdhc_platform_data *pdata = host->dev->platform_data; int ret; @@ -433,7 +425,7 @@ static int esdhc_card_present(struct mci_host *mci) case ESDHC_CD_PERMANENT: return 1; case ESDHC_CD_CONTROLLER: - return !(esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL); + return !(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL); case ESDHC_CD_GPIO: ret = gpio_direction_input(pdata->cd_gpio); if (ret) @@ -447,45 +439,52 @@ static int esdhc_card_present(struct mci_host *mci) static int esdhc_init(struct mci_host *mci, struct device_d *dev) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc __iomem *regs = host->regs; + void __iomem *regs = host->regs; int timeout = 1000; int ret = 0; /* Reset the entire host controller */ - esdhc_write32(®s->sysctl, SYSCTL_RSTA); + esdhc_write32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_RSTA); /* Wait until the controller is available */ - while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) + while ((esdhc_read32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET) + & SYSCTL_RSTA) && --timeout) udelay(1000); - esdhc_write32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); + esdhc_write32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_HCKEN | SYSCTL_IPGEN); /* Set the initial clock speed */ set_sysctl(mci, 400000); /* Disable the BRR and BWR bits in IRQSTAT */ - esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); + esdhc_clrbits32(regs + SDHCI_INT_ENABLE, IRQSTATEN_BRR | IRQSTATEN_BWR); /* Put the PROCTL reg back to the default */ - esdhc_write32(®s->proctl, PROCTL_INIT); + esdhc_write32(regs + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + PROCTL_INIT); /* Set timout to the maximum value */ - esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); + esdhc_clrsetbits32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_TIMEOUT_MASK, 14 << 16); return ret; } -static int esdhc_reset(struct fsl_esdhc __iomem *regs) +static int esdhc_reset(void __iomem *regs) { uint64_t start; /* reset the controller */ - esdhc_write32(®s->sysctl, SYSCTL_RSTA); + esdhc_write32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_RSTA); start = get_time_ns(); /* hardware clears the bit when it is done */ while (1) { - if (!(esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) + if (!(esdhc_read32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET) + & SYSCTL_RSTA)) break; if (is_timeout(start, 100 * MSECOND)) { printf("MMC/SD: Reset never completed.\n"); @@ -496,6 +495,13 @@ static int esdhc_reset(struct fsl_esdhc __iomem *regs) return 0; } +static int fsl_esdhc_detect(struct device_d *dev) +{ + struct fsl_esdhc_host *host = dev->priv; + + return mci_detect_card(&host->mci); +} + static int fsl_esdhc_probe(struct device_d *dev) { struct fsl_esdhc_host *host; @@ -522,7 +528,7 @@ static int fsl_esdhc_probe(struct device_d *dev) return ret; } - caps = esdhc_read32(&host->regs->hostcapblt); + caps = esdhc_read32(host->regs + SDHCI_CAPABILITIES); if (caps & ESDHC_HOSTCAPBLT_VS18) mci->voltages |= MMC_VDD_165_195; @@ -536,8 +542,13 @@ static int fsl_esdhc_probe(struct device_d *dev) else mci->host_caps = MMC_MODE_4BIT; - if (pdata && pdata->devname) + if (pdata && pdata->devname) { mci->devname = pdata->devname; + } else if (dev->device_node) { + const char *alias = of_alias_get(dev->device_node); + if (alias) + mci->devname = xstrdup(alias); + } if (caps & ESDHC_HOSTCAPBLT_HSS) mci->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; @@ -548,15 +559,19 @@ static int fsl_esdhc_probe(struct device_d *dev) host->mci.card_present = esdhc_card_present; host->mci.hw_dev = dev; + dev->detect = fsl_esdhc_detect, + rate = clk_get_rate(host->clk); host->mci.f_min = rate >> 12; if (host->mci.f_min < 200000) host->mci.f_min = 200000; host->mci.f_max = rate; - mci_register(&host->mci); + mci_of_parse(&host->mci); - return 0; + dev->priv = host; + + return mci_register(&host->mci); } static __maybe_unused struct of_device_id fsl_esdhc_compatible[] = { diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h index 2be63a5ba0..ea1cb318e5 100644 --- a/drivers/mci/imx-esdhc.h +++ b/drivers/mci/imx-esdhc.h @@ -25,8 +25,6 @@ #include <errno.h> #include <asm/byteorder.h> -/* FSL eSDHC-specific constants */ -#define SYSCTL 0x0002e02c #define SYSCTL_INITA 0x08000000 #define SYSCTL_TIMEOUT_MASK 0x000f0000 #define SYSCTL_CLOCK_MASK 0x0000fff0 @@ -36,104 +34,17 @@ #define SYSCTL_HCKEN 0x00000002 #define SYSCTL_IPGEN 0x00000001 -#define IRQSTAT 0x0002e030 -#define IRQSTAT_DMAE (0x10000000) -#define IRQSTAT_AC12E (0x01000000) -#define IRQSTAT_DEBE (0x00400000) -#define IRQSTAT_DCE (0x00200000) -#define IRQSTAT_DTOE (0x00100000) -#define IRQSTAT_CIE (0x00080000) -#define IRQSTAT_CEBE (0x00040000) -#define IRQSTAT_CCE (0x00020000) -#define IRQSTAT_CTOE (0x00010000) -#define IRQSTAT_CINT (0x00000100) -#define IRQSTAT_CRM (0x00000080) -#define IRQSTAT_CINS (0x00000040) -#define IRQSTAT_BRR (0x00000020) -#define IRQSTAT_BWR (0x00000010) -#define IRQSTAT_DINT (0x00000008) -#define IRQSTAT_BGE (0x00000004) -#define IRQSTAT_TC (0x00000002) -#define IRQSTAT_CC (0x00000001) - #define CMD_ERR (IRQSTAT_CIE | IRQSTAT_CEBE | IRQSTAT_CCE) #define DATA_ERR (IRQSTAT_DEBE | IRQSTAT_DCE | IRQSTAT_DTOE) -#define IRQSTATEN 0x0002e034 -#define IRQSTATEN_DMAE (0x10000000) -#define IRQSTATEN_AC12E (0x01000000) -#define IRQSTATEN_DEBE (0x00400000) -#define IRQSTATEN_DCE (0x00200000) -#define IRQSTATEN_DTOE (0x00100000) -#define IRQSTATEN_CIE (0x00080000) -#define IRQSTATEN_CEBE (0x00040000) -#define IRQSTATEN_CCE (0x00020000) -#define IRQSTATEN_CTOE (0x00010000) -#define IRQSTATEN_CINT (0x00000100) -#define IRQSTATEN_CRM (0x00000080) -#define IRQSTATEN_CINS (0x00000040) -#define IRQSTATEN_BRR (0x00000020) -#define IRQSTATEN_BWR (0x00000010) -#define IRQSTATEN_DINT (0x00000008) -#define IRQSTATEN_BGE (0x00000004) -#define IRQSTATEN_TC (0x00000002) -#define IRQSTATEN_CC (0x00000001) - -#define PRSSTAT 0x0002e024 -#define PRSSTAT_CLSL (0x00800000) -#define PRSSTAT_WPSPL (0x00080000) -#define PRSSTAT_CDPL (0x00040000) -#define PRSSTAT_CINS (0x00010000) -#define PRSSTAT_BREN (0x00000800) -#define PRSSTAT_BWEN (0x00000400) -#define PRSSTAT_DLA (0x00000004) -#define PRSSTAT_CICHB (0x00000002) -#define PRSSTAT_CIDHB (0x00000001) - -#define PROCTL 0x0002e028 #define PROCTL_INIT 0x00000020 #define PROCTL_DTW_4 0x00000002 #define PROCTL_DTW_8 0x00000004 -#define CMDARG 0x0002e008 - -#define XFERTYP 0x0002e00c -#define XFERTYP_CMD(x) ((x & 0x3f) << 24) -#define XFERTYP_CMDTYP_NORMAL 0x0 -#define XFERTYP_CMDTYP_SUSPEND 0x00400000 -#define XFERTYP_CMDTYP_RESUME 0x00800000 -#define XFERTYP_CMDTYP_ABORT 0x00c00000 -#define XFERTYP_DPSEL 0x00200000 -#define XFERTYP_CICEN 0x00100000 -#define XFERTYP_CCCEN 0x00080000 -#define XFERTYP_RSPTYP_NONE 0 -#define XFERTYP_RSPTYP_136 0x00010000 -#define XFERTYP_RSPTYP_48 0x00020000 -#define XFERTYP_RSPTYP_48_BUSY 0x00030000 -#define XFERTYP_MSBSEL 0x00000020 -#define XFERTYP_DTDSEL 0x00000010 -#define XFERTYP_AC12EN 0x00000004 -#define XFERTYP_BCEN 0x00000002 -#define XFERTYP_DMAEN 0x00000001 - -#define CINS_TIMEOUT 1000 -#define PIO_TIMEOUT 100000 - -#define DSADDR 0x2e004 - -#define CMDRSP0 0x2e010 -#define CMDRSP1 0x2e014 -#define CMDRSP2 0x2e018 -#define CMDRSP3 0x2e01c - -#define DATPORT 0x2e020 - -#define WML 0x2e044 #define WML_WRITE 0x00010000 #define WML_RD_WML_MASK 0xff #define WML_WR_WML_MASK 0xff0000 -#define BLKATTR 0x2e004 #define BLKATTR_CNT(x) ((x & 0xffff) << 16) #define BLKATTR_SIZE(x) (x & 0x1fff) #define MAX_BLK_CNT 0x7fff /* so malloc will have enough room with 32M */ diff --git a/drivers/mci/imx.c b/drivers/mci/imx.c index c98596434e..2bf48eb1d3 100644 --- a/drivers/mci/imx.c +++ b/drivers/mci/imx.c @@ -2,7 +2,7 @@ * This is a driver for the SDHC controller found in Freescale MX2/MX3 * SoCs. It is basically the same hardware as found on MX1 (imxmmc.c). * Unlike the hardware found on MX1, this hardware just works and does - * not need all the quirks found in imxmmc.c, hence the seperate driver. + * not need all the quirks found in imxmmc.c, hence the separate driver. * * Copyright (C) 2009 Ilya Yanok, <yanok@emcraft.com> * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c new file mode 100644 index 0000000000..b76f134af2 --- /dev/null +++ b/drivers/mci/mci-bcm2835.c @@ -0,0 +1,591 @@ +/* + * Raspberry PI MCI driver + * + * Support for SDHCI device on bcm2835 + * Based on sdhci-bcm2708.c (c) 2010 Broadcom + * Inspired by bcm2835_sdhci.c from git://github.com/gonzoua/u-boot-pi.git + * + * Portions (e.g. read/write macros, concepts for back-to-back register write + * timing workarounds) obviously extracted from the Linux kernel at: + * https://github.com/raspberrypi/linux.git rpi-3.6.y + * + * The Linux kernel code has the following (c) and license, which is hence + * propagated to here: + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Wilhelm Lundgren <wilhelm.lundgren@cybercom.com> + */ + +#include <common.h> +#include <init.h> +#include <mci.h> +#include <io.h> +#include <malloc.h> +#include <clock.h> +#include "mci-bcm2835.h" +#include "sdhci.h" + +#define to_bcm2835_host(h) container_of(h, struct bcm2835_mci_host, mci) +static int twoticks_delay; +struct bcm2835_mci_host { + struct mci_host mci; + void __iomem *regs; + struct device_d *hw_dev; + int bus_width; + u32 clock; + u32 max_clock; + u32 version; + uint64_t last_write; +}; + +void bcm2835_mci_write(struct bcm2835_mci_host *host, u32 reg, u32 val) +{ + /* + * The Arasan has a bugette whereby it may lose the content of + * successive writes to registers that are within two SD-card clock + * cycles of each other (a clock domain crossing problem). + * It seems, however, that the data register does not have this problem. + * (Which is just as well - otherwise we'd have to nobble the DMA engine + * too) + */ + + if (host->last_write != 0) + while ((get_time_ns() - host->last_write) < twoticks_delay) + ; + host->last_write = get_time_ns(); + writel(val, host->regs + reg); +} + +u32 bcm2835_mci_read(struct bcm2835_mci_host *host, u32 reg) +{ + return readl(host->regs + reg); +} + +/* Create special write data function since the data + * register is not affected by the twoticks_delay bug + * and we can thus get better speed here + */ +void bcm2835_mci_write_data(struct bcm2835_mci_host *host, u32 *p) +{ + writel(*p, host->regs + SDHCI_BUFFER); +} + +/* Make a read data functions as well just to keep structure */ +void bcm2835_mci_read_data(struct bcm2835_mci_host *host, u32 *p) +{ + *p = readl(host->regs + SDHCI_BUFFER); +} + +static int bcm2835_mci_transfer_data(struct bcm2835_mci_host *host, + struct mci_cmd *cmd, struct mci_data *data) { + u32 *p; + u32 data_size, status, intr_status = 0; + u32 data_ready_intr_mask; + u32 data_ready_status_mask; + int i = 0; + void (*read_write_func)(struct bcm2835_mci_host*, u32*); + + data_size = data->blocksize * data->blocks; + + if (data->flags & MMC_DATA_READ) { + p = (u32 *) data->dest; + data_ready_intr_mask = IRQSTAT_BRR; + data_ready_status_mask = PRSSTAT_BREN; + read_write_func = &bcm2835_mci_read_data; + } else { + p = (u32 *) data->src; + data_ready_intr_mask = IRQSTAT_BWR; + data_ready_status_mask = PRSSTAT_BWEN; + read_write_func = &bcm2835_mci_write_data; + } + do { + intr_status = bcm2835_mci_read(host, SDHCI_INT_STATUS); + if (intr_status & IRQSTAT_CIE) { + dev_err(host->hw_dev, + "Error occured while transferring data: 0x%X\n", + intr_status); + return -EPERM; + } + if (intr_status & data_ready_intr_mask) { + status = bcm2835_mci_read(host, SDHCI_PRESENT_STATE); + if ((status & data_ready_status_mask) == 0) + continue; + /*Clear latest int and transfer one block size of data*/ + bcm2835_mci_write(host, SDHCI_INT_STATUS, + data_ready_intr_mask); + for (i = 0; i < data->blocksize; i += 4) { + read_write_func(host, p); + p++; + data_size -= 4; + } + } + } while ((intr_status & IRQSTAT_TC) == 0); + + if (data_size != 0) { + if (data->flags & MMC_DATA_READ) + dev_err(host->hw_dev, "Error while reading:\n"); + else + dev_err(host->hw_dev, "Error while writing:\n"); + + dev_err(host->hw_dev, "Transferred %d bytes of data, wanted %d\n", + (data->blocksize * data->blocks) - data_size, + data->blocksize * data->blocks); + + dev_err(host->hw_dev, "Status: 0x%X, Interrupt: 0x%X\n", + bcm2835_mci_read(host, SDHCI_PRESENT_STATE), + bcm2835_mci_read(host, SDHCI_INT_STATUS)); + + return -EPERM; + } + return 0; +} + +static u32 bcm2835_mci_wait_command_done(struct bcm2835_mci_host *host) +{ + u32 interrupt = 0; + + while (true) { + interrupt = bcm2835_mci_read( + host, SDHCI_INT_STATUS); + if (interrupt & IRQSTAT_CIE) + return -EPERM; + if (interrupt & IRQSTAT_CC) + break; + } + return 0; +} + +static void bcm2835_mci_reset_emmc(struct bcm2835_mci_host *host, u32 reset, + u32 wait_for) +{ + u32 ret; + u32 current = bcm2835_mci_read(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); + + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + current | reset); + + while (true) { + ret = bcm2835_mci_read(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); + if (ret & wait_for) + continue; + break; + } +} + +/** + * Process one command to the MCI card + * @param host MCI host + * @param cmd The command to process + * @param data The data to handle in the command (can be NULL) + * @return 0 on success, negative value else + */ +static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, + struct mci_data *data) { + u32 command, block_data = 0, ret = 0; + u32 wait_inhibit_mask = PRSSTAT_CICHB | PRSSTAT_CIDHB; + struct bcm2835_mci_host *host = to_bcm2835_host(mci); + + command = COMMAND_CMD(cmd->cmdidx); + + if (cmd->resp_type != MMC_RSP_NONE) { + if (cmd->resp_type & MMC_RSP_136) + command |= COMMAND_RSPTYP_136; + else if (cmd->resp_type & MMC_RSP_BUSY) + command |= COMMAND_RSPTYP_48_BUSY; + else + command |= COMMAND_RSPTYP_48; + if (cmd->resp_type & MMC_RSP_CRC) + command |= COMMAND_CCCEN; + } + if (data != NULL) { + command |= COMMAND_DPSEL | TRANSFER_MODE_BCEN; + + if (data->blocks > 1) + command |= TRANSFER_MODE_MSBSEL; + + if (data->flags & MMC_DATA_READ) + command |= TRANSFER_MODE_DTDSEL; + + block_data = (data->blocks << BLOCK_SHIFT); + block_data |= data->blocksize; + } + + /* We shouldn't wait for data inihibit for stop commands, even + though they might use busy signaling */ + if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) + wait_inhibit_mask = PRSSTAT_CICHB; + + /*Wait for old command*/ + while (bcm2835_mci_read(host, SDHCI_PRESENT_STATE) + & wait_inhibit_mask) + ; + + bcm2835_mci_write(host, SDHCI_INT_ENABLE, 0xFFFFFFFF); + bcm2835_mci_write(host, SDHCI_INT_STATUS, 0xFFFFFFFF); + + bcm2835_mci_write(host, SDHCI_BLOCK_SIZE__BLOCK_COUNT, block_data); + bcm2835_mci_write(host, SDHCI_ARGUMENT, cmd->cmdarg); + bcm2835_mci_write(host, SDHCI_TRANSFER_MODE__COMMAND, command); + + ret = bcm2835_mci_wait_command_done(host); + if (ret) { + dev_err(host->hw_dev, "Error while executing command %d\n", + cmd->cmdidx); + dev_err(host->hw_dev, "Status: 0x%X, Interrupt: 0x%X\n", + bcm2835_mci_read(host, SDHCI_PRESENT_STATE), + bcm2835_mci_read(host, SDHCI_INT_STATUS)); + } + if (cmd->resp_type != 0 && ret != -1) { + int i = 0; + + /* CRC is stripped so we need to do some shifting. */ + if (cmd->resp_type & MMC_RSP_136) { + for (i = 0; i < 4; i++) { + cmd->response[i] = bcm2835_mci_read( + host, + SDHCI_RESPONSE_0 + (3 - i) * 4) << 8; + if (i != 3) + cmd->response[i] |= + readb((u32) (host->regs) + + SDHCI_RESPONSE_0 + + (3 - i) * 4 - 1); + } + } else { + cmd->response[0] = bcm2835_mci_read( + host, SDHCI_RESPONSE_0); + } + bcm2835_mci_write(host, SDHCI_INT_STATUS, + IRQSTAT_CC); + } + + if (!ret && data) + ret = bcm2835_mci_transfer_data(host, cmd, data); + + bcm2835_mci_write(host, SDHCI_INT_STATUS, 0xFFFFFFFF); + if (ret) { + bcm2835_mci_reset_emmc(host, CONTROL1_CMDRST, + CONTROL1_CMDRST); + bcm2835_mci_reset_emmc(host, CONTROL1_DATARST, + CONTROL1_DATARST); + } + + return ret; +} + +static u32 bcm2835_mci_get_clock_divider(struct bcm2835_mci_host *host, + u32 desired_hz) +{ + u32 div; + u32 clk_hz; + + if (host->version >= SDHCI_SPEC_300) { + /* Version 3.00 divisors must be a multiple of 2. */ + if (host->max_clock <= desired_hz) + div = 1; + else { + for (div = 2; div < MAX_CLK_DIVIDER_V3; div += 2) { + clk_hz = host->max_clock / div; + if (clk_hz <= desired_hz) + break; + } + } + } else { + /* Version 2.00 divisors must be a power of 2. */ + for (div = 1; div < MAX_CLK_DIVIDER_V2; div *= 2) { + clk_hz = host->max_clock / div; + if (clk_hz <= desired_hz) + break; + } + + } + + /*Since setting lowest bit means divide by two, shift down*/ + dev_dbg(host->hw_dev, + "Wanted %d hz, returning divider %d (%d) which yields %d hz\n", + desired_hz, div >> 1, div, host->max_clock / div); + twoticks_delay = ((2 * 1000000000) / (host->max_clock / div)) + 1; + + div = div >> 1; + host->clock = desired_hz; + return div; +} + +/** + * Setup the bus width and IO speed + * @param host MCI host + * @param bus_width New bus width value (1, 4 or 8) + * @param clock New clock in Hz (can be '0' to disable the clock) + */ +static void bcm2835_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) +{ + u32 divider; + u32 divider_msb, divider_lsb; + u32 enable; + u32 current_val; + + struct bcm2835_mci_host *host = to_bcm2835_host(mci); + + current_val = bcm2835_mci_read(host, + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL); + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_4: + bcm2835_mci_write(host, + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + current_val | CONTROL0_4DATA); + host->bus_width = 1; + dev_dbg(host->hw_dev, "Changing bus width to 4\n"); + break; + case MMC_BUS_WIDTH_1: + bcm2835_mci_write(host, + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + current_val & ~CONTROL0_4DATA); + host->bus_width = 0; + dev_dbg(host->hw_dev, "Changing bus width to 1\n"); + break; + default: + dev_warn(host->hw_dev, "Unsupported width received: %d\n", + ios->bus_width); + return; + } + if (ios->clock != host->clock && ios->clock != 0) { + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + 0x00); + + if (ios->clock > 26000000) { + enable = bcm2835_mci_read(host, + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL); + enable |= CONTROL0_HISPEED; + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + enable); + } + + divider = bcm2835_mci_get_clock_divider(host, ios->clock); + divider_msb = divider & 0x300; + divider_msb >>= CONTROL1_CLKLSB; + divider_lsb = divider & 0xFF; + enable = (divider_lsb << CONTROL1_CLKLSB); + enable |= (divider_msb << CONTROL1_CLKMSB); + enable |= CONTROL1_INTCLKENA | CONTROL1_TIMEOUT; + + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + enable); + while (true) { + u32 ret = bcm2835_mci_read(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); + if (ret & CONTROL1_CLK_STABLE) + break; + } + + enable |= CONTROL1_CLKENA; + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + enable); + + mdelay(100); + + bcm2835_mci_reset_emmc(host, CONTROL1_CMDRST, + CONTROL1_CMDRST); + bcm2835_mci_reset_emmc(host, CONTROL1_DATARST, + CONTROL1_DATARST); + + host->clock = ios->clock; + } + dev_dbg(host->hw_dev, "IO settings: bus width=%d, frequency=%u Hz\n", + host->bus_width, host->clock); +} + +int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev) +{ + struct bcm2835_mci_host *host; + u32 ret = 0; + u32 reset = CONTROL1_HOSTRST | CONTROL1_CMDRST | CONTROL1_DATARST; + u32 enable = 0; + u32 divider; + u32 divider_msb, divider_lsb; + + host = to_bcm2835_host(mci); + divider = bcm2835_mci_get_clock_divider(host, MIN_FREQ); + divider_msb = divider & 0x300; + divider_msb = divider_msb >> CONTROL1_CLKLSB; + divider_lsb = divider & 0xFF; + + enable = (divider_lsb << CONTROL1_CLKLSB); + enable |= (divider_msb << CONTROL1_CLKMSB); + enable |= CONTROL1_INTCLKENA | CONTROL1_TIMEOUT; + + bcm2835_mci_reset_emmc(host, enable | reset, CONTROL1_HOSTRST); + + bcm2835_mci_write(host, + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + 0x00); + bcm2835_mci_write(host, SDHCI_ACMD12_ERR__HOST_CONTROL2, + 0x00); + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + enable); + while (true) { + ret = bcm2835_mci_read(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); + if (ret & CONTROL1_CLK_STABLE) + break; + } + + enable |= CONTROL1_CLKENA; + bcm2835_mci_write(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + enable); + + /*Delay atelast 74 clk cycles for card init*/ + mdelay(100); + + bcm2835_mci_write(host, SDHCI_INT_ENABLE, + 0xFFFFFFFF); + bcm2835_mci_write(host, SDHCI_INT_STATUS, + 0xFFFFFFFF); + + /*Now write command 0 and see if we get response*/ + bcm2835_mci_write(host, SDHCI_ARGUMENT, 0x0); + bcm2835_mci_write(host, SDHCI_TRANSFER_MODE__COMMAND, 0x0); + return bcm2835_mci_wait_command_done(host); +} + +static u32 bcm2835_mci_get_emmc_clock(struct msg_get_clock_rate *clk_data) +{ + u32 val; + struct bcm2835_mbox_regs *regs = + (struct bcm2835_mbox_regs *) BCM2835_MBOX_PHYSADDR; + + /*Read out old msg*/ + while (true) { + val = readl(®s->status); + if (val & BCM2835_MBOX_STATUS_RD_EMPTY) + break; + val = readl(®s->read); + } + + /*Check for ok to write*/ + while (true) { + val = readl(®s->status); + if (!(val & BCM2835_MBOX_STATUS_WR_FULL)) + break; + } + val = BCM2835_MBOX_PROP_CHAN + ((u32) &clk_data->hdr); + writel(val, ®s->write); + + while (true) { + /* Wait for the response */ + while (true) { + val = readl(®s->status); + if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY)) + break; + } + + /* Read the response */ + val = readl(®s->read); + if ((val & 0x0F) == BCM2835_MBOX_PROP_CHAN) + break; + } + if ((val & ~0x0F) == ((u32) &clk_data->hdr)) + if (clk_data->get_clock_rate.tag_hdr.val_len + & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) + return 1; + return 0; +} + +static int bcm2835_mci_probe(struct device_d *hw_dev) +{ + struct bcm2835_mci_host *host; + struct msg_get_clock_rate *clk_data; + + host = xzalloc(sizeof(*host)); + host->mci.send_cmd = bcm2835_mci_request; + host->mci.set_ios = bcm2835_mci_set_ios; + host->mci.init = bcm2835_mci_reset; + host->mci.hw_dev = hw_dev; + host->hw_dev = hw_dev; + + /* Allocate a buffer thats 16 bytes aligned in memory + * Of the 32 bits address passed into the mbox 28 bits + * are the address of the buffer, lower 4 bits is channel + */ + clk_data = memalign(16, sizeof(struct msg_get_clock_rate)); + memset(clk_data, 0, sizeof(struct msg_get_clock_rate)); + clk_data->hdr.buf_size = sizeof(struct msg_get_clock_rate); + clk_data->get_clock_rate.tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE; + clk_data->get_clock_rate.tag_hdr.val_buf_size = + sizeof(clk_data->get_clock_rate.body); + clk_data->get_clock_rate.tag_hdr.val_len = + sizeof(clk_data->get_clock_rate.body.req); + clk_data->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC; + + if (!bcm2835_mci_get_emmc_clock(clk_data)) { + dev_warn(host->hw_dev, + "Failed getting emmc clock, lets go anyway with 50MHz\n"); + host->max_clock = 50000000; + } else { + host->max_clock = clk_data->get_clock_rate.body.resp.rate_hz; + dev_info(host->hw_dev, "Got emmc clock at %d Hz\n", + host->max_clock); + } + + host->regs = dev_request_mem_region(hw_dev, 0); + if (host->regs == NULL) { + dev_err(host->hw_dev, "Failed request mem region, aborting...\n"); + return -EBUSY; + } + + host->mci.host_caps |= MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; + + host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + + host->mci.f_min = MIN_FREQ; + host->mci.f_max = host->max_clock; + + /* + * The Arasan has a bugette whereby it may lose the content of + * successive writes to registers that are within two SD-card clock + * cycles of each other (a clock domain crossing problem). + * + * 1/MIN_FREQ is (max) time per tick of eMMC clock. + * 2/MIN_FREQ is time for two ticks. + * Multiply by 1000000000 to get nS per two ticks. + * +1 for hack rounding. + */ + + twoticks_delay = ((2 * 1000000000) / MIN_FREQ) + 1; + + host->version = bcm2835_mci_read( + host, BCM2835_MCI_SLOTISR_VER); + host->version = (host->version >> 16) & 0xFF; + return mci_register(&host->mci); +} + +static struct driver_d bcm2835_mci_driver = { + .name = "bcm2835_mci", + .probe = bcm2835_mci_probe, +}; + +static int bcm2835_mci_add(void) +{ + return platform_driver_register(&bcm2835_mci_driver); +} +coredevice_initcall(bcm2835_mci_add); diff --git a/drivers/mci/mci-bcm2835.h b/drivers/mci/mci-bcm2835.h new file mode 100644 index 0000000000..4158a18065 --- /dev/null +++ b/drivers/mci/mci-bcm2835.h @@ -0,0 +1,73 @@ +#define BCM2835_MCI_SLOTISR_VER 0xfc + +#define MIN_FREQ 400000 +#define BLOCK_SHIFT 16 + +#define SDHCI_SPEC_100 0 +#define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 + +#define CONTROL0_HISPEED (1 << 2) +#define CONTROL0_4DATA (1 << 1) + +#define CONTROL1_DATARST (1 << 26) +#define CONTROL1_CMDRST (1 << 25) +#define CONTROL1_HOSTRST (1 << 24) +#define CONTROL1_CLKSELPROG (1 << 5) +#define CONTROL1_CLKENA (1 << 2) +#define CONTROL1_CLK_STABLE (1 << 1) +#define CONTROL1_INTCLKENA (1 << 0) +#define CONTROL1_CLKMSB 6 +#define CONTROL1_CLKLSB 8 +#define CONTROL1_TIMEOUT (0x0E << 16) + +#define MAX_CLK_DIVIDER_V3 2046 +#define MAX_CLK_DIVIDER_V2 256 + +/*this is only for mbox comms*/ +#define BCM2835_MBOX_PHYSADDR 0x2000b880 +#define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002 +#define BCM2835_MBOX_CLOCK_ID_EMMC 1 +#define BCM2835_MBOX_STATUS_WR_FULL 0x80000000 +#define BCM2835_MBOX_STATUS_RD_EMPTY 0x40000000 +#define BCM2835_MBOX_PROP_CHAN 8 +#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000 + +struct bcm2835_mbox_regs { + u32 read; + u32 rsvd0[5]; + u32 status; + u32 config; + u32 write; +}; + + +struct bcm2835_mbox_hdr { + u32 buf_size; + u32 code; +}; + +struct bcm2835_mbox_tag_hdr { + u32 tag; + u32 val_buf_size; + u32 val_len; +}; + +struct bcm2835_mbox_tag_get_clock_rate { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 clock_id; + } req; + struct { + u32 clock_id; + u32 rate_hz; + } resp; + } body; +}; + +struct msg_get_clock_rate { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; + u32 end_tag; +}; diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 90ac2a3748..ce568df706 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -215,7 +215,7 @@ static int mci_go_idle(struct mci *mci) err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Activating IDLE state failed: %d\n", err); + dev_dbg(&mci->dev, "Activating IDLE state failed: %d\n", err); return err; } @@ -252,7 +252,7 @@ static int sd_send_op_cond(struct mci *mci) mci_setup_cmd(&cmd, MMC_CMD_APP_CMD, 0, MMC_RSP_R1); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Preparing SD for operating conditions failed: %d\n", err); + dev_dbg(&mci->dev, "Preparing SD for operating conditions failed: %d\n", err); return err; } @@ -264,7 +264,7 @@ static int sd_send_op_cond(struct mci *mci) mci_setup_cmd(&cmd, SD_CMD_APP_SEND_OP_COND, arg, MMC_RSP_R3); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "SD operation condition set failed: %d\n", err); + dev_dbg(&mci->dev, "SD operation condition set failed: %d\n", err); return err; } udelay(1000); @@ -277,7 +277,7 @@ static int sd_send_op_cond(struct mci *mci) } while (busy && timeout--); if (timeout <= 0) { - dev_dbg(mci->mci_dev, "SD operation condition set timed out\n"); + dev_dbg(&mci->dev, "SD operation condition set timed out\n"); return -ENODEV; } @@ -320,7 +320,7 @@ static int mmc_send_op_cond(struct mci *mci) err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Preparing MMC for operating conditions failed: %d\n", err); + dev_dbg(&mci->dev, "Preparing MMC for operating conditions failed: %d\n", err); return err; } @@ -328,7 +328,7 @@ static int mmc_send_op_cond(struct mci *mci) } while (!(cmd.response[0] & OCR_BUSY) && timeout--); if (timeout <= 0) { - dev_dbg(mci->mci_dev, "SD operation condition set timed out\n"); + dev_dbg(&mci->dev, "SD operation condition set timed out\n"); return -ENODEV; } @@ -388,6 +388,35 @@ static int mci_switch(struct mci *mci, unsigned set, unsigned index, return mci_send_cmd(mci, &cmd, NULL); } +static int mci_calc_blk_cnt(uint64_t cap, unsigned shift) +{ + unsigned ret = cap >> shift; + + if (ret > 0x7fffffff) { + pr_warn("Limiting card size due to 31 bit contraints\n"); + return 0x7fffffff; + } + + return (int)ret; +} + +static void mci_part_add(struct mci *mci, uint64_t size, + unsigned int part_cfg, char *name, int idx, bool ro, + int area_type) +{ + struct mci_part *part = &mci->part[mci->nr_parts]; + + part->mci = mci; + part->size = size; + part->blk.cdev.name = name; + part->blk.blockbits = SECTOR_SHIFT; + part->blk.num_blocks = mci_calc_blk_cnt(size, part->blk.blockbits); + part->area_type = area_type; + part->part_cfg = part_cfg; + + mci->nr_parts++; +} + /** * Change transfer frequency for an MMC card * @param mci MCI instance @@ -409,7 +438,7 @@ static int mmc_change_freq(struct mci *mci) err = mci_send_ext_csd(mci, mci->ext_csd); if (err) { - dev_dbg(mci->mci_dev, "Preparing for frequency setup failed: %d\n", err); + dev_dbg(&mci->dev, "Preparing for frequency setup failed: %d\n", err); return err; } @@ -418,7 +447,7 @@ static int mmc_change_freq(struct mci *mci) err = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); if (err) { - dev_dbg(mci->mci_dev, "MMC frequency changing failed: %d\n", err); + dev_dbg(&mci->dev, "MMC frequency changing failed: %d\n", err); return err; } @@ -426,13 +455,13 @@ static int mmc_change_freq(struct mci *mci) err = mci_send_ext_csd(mci, mci->ext_csd); if (err) { - dev_dbg(mci->mci_dev, "Verifying frequency change failed: %d\n", err); + dev_dbg(&mci->dev, "Verifying frequency change failed: %d\n", err); return err; } /* No high-speed support */ if (!mci->ext_csd[EXT_CSD_HS_TIMING]) { - dev_dbg(mci->mci_dev, "No high-speed support\n"); + dev_dbg(&mci->dev, "No high-speed support\n"); return 0; } @@ -442,6 +471,26 @@ static int mmc_change_freq(struct mci *mci) else mci->card_caps |= MMC_MODE_HS; + if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && + mci->ext_csd[EXT_CSD_REV] >= 3 && mci->ext_csd[EXT_CSD_BOOT_MULT]) { + int idx; + unsigned int part_size; + + for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) { + char *name; + part_size = mci->ext_csd[EXT_CSD_BOOT_MULT] << 17; + + name = asprintf("%s.boot%d", mci->cdevname, idx); + mci_part_add(mci, part_size, + EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx, + name, idx, true, + MMC_BLK_DATA_AREA_BOOT); + } + + mci->ext_csd_part_config = mci->ext_csd[EXT_CSD_PART_CONFIG]; + mci->bootpart = (mci->ext_csd_part_config >> 3) & 0x7; + } + return 0; } @@ -496,14 +545,14 @@ static int sd_change_freq(struct mci *mci) if (mmc_host_is_spi(host)) return 0; - dev_dbg(mci->mci_dev, "Changing transfer frequency\n"); + dev_dbg(&mci->dev, "Changing transfer frequency\n"); mci->card_caps = 0; /* Read the SCR to find out if this card supports higher speeds */ mci_setup_cmd(&cmd, MMC_CMD_APP_CMD, mci->rca << 16, MMC_RSP_R1); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Query SD card capabilities failed: %d\n", err); + dev_dbg(&mci->dev, "Query SD card capabilities failed: %d\n", err); return err; } @@ -512,7 +561,7 @@ static int sd_change_freq(struct mci *mci) timeout = 3; retry_scr: - dev_dbg(mci->mci_dev, "Trying to read the SCR (try %d of %d)\n", 4 - timeout, 3); + dev_dbg(&mci->dev, "Trying to read the SCR (try %d of %d)\n", 4 - timeout, 3); data.dest = (char *)scr; data.blocksize = 8; data.blocks = 1; @@ -520,12 +569,12 @@ retry_scr: err = mci_send_cmd(mci, &cmd, &data); if (err) { - dev_dbg(mci->mci_dev, " Catch error (%d)", err); + dev_dbg(&mci->dev, " Catch error (%d)", err); if (timeout--) { - dev_dbg(mci->mci_dev, "-- retrying\n"); + dev_dbg(&mci->dev, "-- retrying\n"); goto retry_scr; } - dev_dbg(mci->mci_dev, "-- giving up\n"); + dev_dbg(&mci->dev, "-- giving up\n"); return err; } @@ -556,7 +605,7 @@ retry_scr: err = sd_switch(mci, SD_SWITCH_CHECK, 0, 1, (uint8_t*)switch_status); if (err) { - dev_dbg(mci->mci_dev, "Checking SD transfer switch frequency feature failed: %d\n", err); + dev_dbg(&mci->dev, "Checking SD transfer switch frequency feature failed: %d\n", err); return err; } @@ -574,7 +623,7 @@ retry_scr: err = sd_switch(mci, SD_SWITCH_SWITCH, 0, 1, (uint8_t*)switch_status); if (err) { - dev_dbg(mci->mci_dev, "Switching SD transfer frequency failed: %d\n", err); + dev_dbg(&mci->dev, "Switching SD transfer frequency failed: %d\n", err); return err; } @@ -677,7 +726,7 @@ static void mci_detect_version_from_csd(struct mci *mci) break; } - dev_info(mci->mci_dev, "detected card version %s\n", vstr); + dev_info(&mci->dev, "detected card version %s\n", vstr); } } @@ -729,13 +778,13 @@ static void mci_extract_max_tran_speed_from_csd(struct mci *mci) unit = tran_speed_unit[(mci->csd[0] & 0x7)]; time = tran_speed_time[((mci->csd[0] >> 3) & 0xf)]; if ((unit == 0) || (time == 0)) { - dev_dbg(mci->mci_dev, "Unsupported 'TRAN_SPEED' unit/time value." + dev_dbg(&mci->dev, "Unsupported 'TRAN_SPEED' unit/time value." " Can't calculate card's max. transfer speed\n"); return; } mci->tran_speed = time * unit; - dev_dbg(mci->mci_dev, "Transfer speed: %u\n", mci->tran_speed); + dev_dbg(&mci->dev, "Transfer speed: %u\n", mci->tran_speed); } /** @@ -753,7 +802,7 @@ static void mci_extract_block_lengths_from_csd(struct mci *mci) else mci->write_bl_len = 1 << ((mci->csd[3] >> 22) & 0xf); - dev_dbg(mci->mci_dev, "Max. block length are: Write=%u, Read=%u Bytes\n", + dev_dbg(&mci->dev, "Max. block length are: Write=%u, Read=%u Bytes\n", mci->write_bl_len, mci->read_bl_len); } @@ -782,7 +831,7 @@ static void mci_extract_card_capacity_from_csd(struct mci *mci) } mci->capacity *= 1 << UNSTUFF_BITS(mci->csd, 80, 4);; - dev_dbg(mci->mci_dev, "Capacity: %u MiB\n", (unsigned)(mci->capacity >> 20)); + dev_dbg(&mci->dev, "Capacity: %u MiB\n", (unsigned)(mci->capacity >> 20)); } static int mmc_compare_ext_csds(struct mci *mci, unsigned bus_width) @@ -796,7 +845,7 @@ static int mmc_compare_ext_csds(struct mci *mci, unsigned bus_width) bw_ext_csd = xmalloc(512); err = mci_send_ext_csd(mci, bw_ext_csd); if (err) { - dev_info(mci->mci_dev, "mci_send_ext_csd failed with %d\n", err); + dev_info(&mci->dev, "mci_send_ext_csd failed with %d\n", err); if (bus_width != MMC_BUS_WIDTH_1) err = -EINVAL; goto out; @@ -852,19 +901,19 @@ static int mci_startup_sd(struct mci *mci) int err; if (mci->card_caps & MMC_MODE_4BIT) { - dev_dbg(mci->mci_dev, "Prepare for bus width change\n"); + dev_dbg(&mci->dev, "Prepare for bus width change\n"); mci_setup_cmd(&cmd, MMC_CMD_APP_CMD, mci->rca << 16, MMC_RSP_R1); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Preparing SD for bus width change failed: %d\n", err); + dev_dbg(&mci->dev, "Preparing SD for bus width change failed: %d\n", err); return err; } - dev_dbg(mci->mci_dev, "Set SD bus width to 4 bit\n"); + dev_dbg(&mci->dev, "Set SD bus width to 4 bit\n"); mci_setup_cmd(&cmd, SD_CMD_APP_SET_BUS_WIDTH, 2, MMC_RSP_R1); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Changing SD bus width failed: %d\n", err); + dev_dbg(&mci->dev, "Changing SD bus width failed: %d\n", err); /* TODO continue with 1 bit? */ return err; } @@ -955,25 +1004,25 @@ static int mci_startup(struct mci *mci) err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Can't enable CRC check : %d\n", err); + dev_dbg(&mci->dev, "Can't enable CRC check : %d\n", err); return err; } } #endif - dev_dbg(mci->mci_dev, "Put the Card in Identify Mode\n"); + dev_dbg(&mci->dev, "Put the Card in Identify Mode\n"); /* Put the Card in Identify Mode */ mci_setup_cmd(&cmd, mmc_host_is_spi(host) ? MMC_CMD_SEND_CID : MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Can't bring card into identify mode: %d\n", err); + dev_dbg(&mci->dev, "Can't bring card into identify mode: %d\n", err); return err; } memcpy(mci->cid, cmd.response, 16); - dev_dbg(mci->mci_dev, "Card's identification data is: %08X-%08X-%08X-%08X\n", + dev_dbg(&mci->dev, "Card's identification data is: %08X-%08X-%08X-%08X\n", mci->cid[0], mci->cid[1], mci->cid[2], mci->cid[3]); /* @@ -982,11 +1031,11 @@ static int mci_startup(struct mci *mci) * This also puts the cards into Standby State */ if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */ - dev_dbg(mci->mci_dev, "Get/Set relative address\n"); + dev_dbg(&mci->dev, "Get/Set relative address\n"); mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Get/Set relative address failed: %d\n", err); + dev_dbg(&mci->dev, "Get/Set relative address failed: %d\n", err); return err; } } @@ -994,19 +1043,19 @@ static int mci_startup(struct mci *mci) if (IS_SD(mci)) mci->rca = (cmd.response[0] >> 16) & 0xffff; - dev_dbg(mci->mci_dev, "Get card's specific data\n"); + dev_dbg(&mci->dev, "Get card's specific data\n"); /* Get the Card-Specific Data */ mci_setup_cmd(&cmd, MMC_CMD_SEND_CSD, mci->rca << 16, MMC_RSP_R2); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Getting card's specific data failed: %d\n", err); + dev_dbg(&mci->dev, "Getting card's specific data failed: %d\n", err); return err; } /* CSD is of 128 bit */ memcpy(mci->csd, cmd.response, 16); - dev_dbg(mci->mci_dev, "Card's specific data is: %08X-%08X-%08X-%08X\n", + dev_dbg(&mci->dev, "Card's specific data is: %08X-%08X-%08X-%08X\n", mci->csd[0], mci->csd[1], mci->csd[2], mci->csd[3]); mci_detect_version_from_csd(mci); @@ -1016,25 +1065,25 @@ static int mci_startup(struct mci *mci) /* sanitiy? */ if (mci->read_bl_len > SECTOR_SIZE) { mci->read_bl_len = SECTOR_SIZE; - dev_dbg(mci->mci_dev, "Limiting max. read block size down to %u\n", + dev_dbg(&mci->dev, "Limiting max. read block size down to %u\n", mci->read_bl_len); } if (mci->write_bl_len > SECTOR_SIZE) { mci->write_bl_len = SECTOR_SIZE; - dev_dbg(mci->mci_dev, "Limiting max. write block size down to %u\n", + dev_dbg(&mci->dev, "Limiting max. write block size down to %u\n", mci->read_bl_len); } - dev_dbg(mci->mci_dev, "Read block length: %u, Write block length: %u\n", + dev_dbg(&mci->dev, "Read block length: %u, Write block length: %u\n", mci->read_bl_len, mci->write_bl_len); if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */ - dev_dbg(mci->mci_dev, "Select the card, and put it into Transfer Mode\n"); + dev_dbg(&mci->dev, "Select the card, and put it into Transfer Mode\n"); /* Select the card, and put it into Transfer Mode */ mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Putting in transfer mode failed: %d\n", err); + dev_dbg(&mci->dev, "Putting in transfer mode failed: %d\n", err); return err; } } @@ -1063,6 +1112,10 @@ static int mci_startup(struct mci *mci) /* we setup the blocklength only one times for all accesses to this media */ err = mci_set_blocklen(mci, mci->read_bl_len); + mci_part_add(mci, mci->capacity, 0, + mci->cdevname, 0, true, + MMC_BLK_DATA_AREA_MAIN); + return err; } @@ -1089,21 +1142,51 @@ static int sd_send_if_cond(struct mci *mci) MMC_RSP_R7); err = mci_send_cmd(mci, &cmd, NULL); if (err) { - dev_dbg(mci->mci_dev, "Query interface conditions failed: %d\n", err); + dev_dbg(&mci->dev, "Query interface conditions failed: %d\n", err); return err; } if ((cmd.response[0] & 0xff) != 0xaa) { - dev_dbg(mci->mci_dev, "Card cannot work with hosts supply voltages\n"); + dev_dbg(&mci->dev, "Card cannot work with hosts supply voltages\n"); return -EINVAL; } else { - dev_dbg(mci->mci_dev, "SD Card Rev. 2.00 or later detected\n"); + dev_dbg(&mci->dev, "SD Card Rev. 2.00 or later detected\n"); mci->version = SD_VERSION_2; } return 0; } +static int mci_blk_part_switch(struct mci_part *part) +{ + struct mci *mci = part->mci; + int ret; + + if (!IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS)) + return 0; + + if (mci->part_curr == part) + return 0; + + if (!IS_SD(mci)) { + u8 part_config = mci->ext_csd_part_config; + + part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; + part_config |= part->part_cfg; + + ret = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_PART_CONFIG, part_config); + if (ret) + return ret; + + mci->ext_csd_part_config = part_config; + } + + mci->part_curr = part; + + return 0; +} + /* ------------------ attach to the blocklayer --------------------------- */ /** @@ -1119,33 +1202,36 @@ static int sd_send_if_cond(struct mci *mci) static int __maybe_unused mci_sd_write(struct block_device *blk, const void *buffer, int block, int num_blocks) { - struct mci *mci = container_of(blk, struct mci, blk); + struct mci_part *part = container_of(blk, struct mci_part, blk); + struct mci *mci = part->mci; struct mci_host *host = mci->host; int rc; + mci_blk_part_switch(part); + if (host->card_write_protected && host->card_write_protected(host)) { - dev_err(mci->mci_dev, "card write protected\n"); + dev_err(&mci->dev, "card write protected\n"); return -EPERM; } - dev_dbg(mci->mci_dev, "%s: Write %d block(s), starting at %d\n", + dev_dbg(&mci->dev, "%s: Write %d block(s), starting at %d\n", __func__, num_blocks, block); if (mci->write_bl_len != SECTOR_SIZE) { - dev_dbg(mci->mci_dev, "MMC/SD block size is not %d bytes (its %u bytes instead)\n", + dev_dbg(&mci->dev, "MMC/SD block size is not %d bytes (its %u bytes instead)\n", SECTOR_SIZE, mci->read_bl_len); return -EINVAL; } /* size of the block number field in the MMC/SD command is 32 bit only */ if (block > MAX_BUFFER_NUMBER) { - dev_dbg(mci->mci_dev, "Cannot handle block number %d. Too large!\n", block); + dev_dbg(&mci->dev, "Cannot handle block number %d. Too large!\n", block); return -EINVAL; } rc = mci_block_write(mci, buffer, block, num_blocks); if (rc != 0) { - dev_dbg(mci->mci_dev, "Writing block %d failed with %d\n", block, rc); + dev_dbg(&mci->dev, "Writing block %d failed with %d\n", block, rc); return rc; } @@ -1165,26 +1251,29 @@ static int __maybe_unused mci_sd_write(struct block_device *blk, static int mci_sd_read(struct block_device *blk, void *buffer, int block, int num_blocks) { - struct mci *mci = container_of(blk, struct mci, blk); + struct mci_part *part = container_of(blk, struct mci_part, blk); + struct mci *mci = part->mci; int rc; - dev_dbg(mci->mci_dev, "%s: Read %d block(s), starting at %d\n", + mci_blk_part_switch(part); + + dev_dbg(&mci->dev, "%s: Read %d block(s), starting at %d\n", __func__, num_blocks, block); if (mci->read_bl_len != 512) { - dev_dbg(mci->mci_dev, "MMC/SD block size is not 512 bytes (its %u bytes instead)\n", + dev_dbg(&mci->dev, "MMC/SD block size is not 512 bytes (its %u bytes instead)\n", mci->read_bl_len); return -EINVAL; } if (block > MAX_BUFFER_NUMBER) { - dev_err(mci->mci_dev, "Cannot handle block number %d. Too large!\n", block); + dev_err(&mci->dev, "Cannot handle block number %d. Too large!\n", block); return -EINVAL; } rc = mci_read_block(mci, buffer, block, num_blocks); if (rc != 0) { - dev_dbg(mci->mci_dev, "Reading block %d failed with %d\n", block, rc); + dev_dbg(&mci->dev, "Reading block %d failed with %d\n", block, rc); return rc; } @@ -1193,7 +1282,6 @@ static int mci_sd_read(struct block_device *blk, void *buffer, int block, /* ------------------ attach to the device API --------------------------- */ -#ifdef CONFIG_MCI_INFO /** * Extract the Manufacturer ID from the CID * @param mci Instance data @@ -1282,9 +1370,9 @@ static unsigned extract_mtd_year(struct mci *mci) * Output some valuable information when the user runs 'devinfo' on an MCI device * @param mci MCI device instance */ -static void mci_info(struct device_d *mci_dev) +static void mci_info(struct device_d *dev) { - struct mci *mci = mci_dev->priv; + struct mci *mci = container_of(dev, struct mci, dev); if (mci->ready_for_use == 0) { printf(" No information available:\n MCI card not probed yet\n"); @@ -1319,7 +1407,6 @@ static void mci_info(struct device_d *mci_dev) printf(" Manufacturing date: %u.%u\n", extract_mtd_month(mci), extract_mtd_year(mci)); } -#endif /** * Check if the MCI card is already probed @@ -1338,18 +1425,6 @@ static int mci_check_if_already_initialized(struct mci *mci) return 0; } -static int mci_calc_blk_cnt(uint64_t cap, unsigned shift) -{ - unsigned ret = cap >> shift; - - if (ret > 0x7fffffff) { - pr_warn("Limiting card size due to 31 bit contraints\n"); - return 0x7fffffff; - } - - return (int)ret; -} - static struct block_device_ops mci_ops = { .read = mci_sd_read, #ifdef CONFIG_BLOCK_WRITE @@ -1357,6 +1432,28 @@ static struct block_device_ops mci_ops = { #endif }; +static int mci_set_boot(struct param_d *param, void *priv) +{ + struct mci *mci = priv; + + mci->ext_csd_part_config &= ~(7 << 3); + mci->ext_csd_part_config |= mci->bootpart << 3; + + return mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_PART_CONFIG, mci->ext_csd_part_config); +} + +static const char *mci_boot_names[] = { + "disabled", + "boot0", + "boot1", + NULL, /* reserved */ + NULL, /* reserved */ + NULL, /* reserved */ + NULL, /* reserved */ + "user", +}; + /** * Probe an MCI card at the given host interface * @param mci MCI device instance @@ -1365,17 +1462,17 @@ static struct block_device_ops mci_ops = { static int mci_card_probe(struct mci *mci) { struct mci_host *host = mci->host; - int rc, disknum; + int i, rc, disknum; if (host->card_present && !host->card_present(host)) { - dev_err(mci->mci_dev, "no card inserted\n"); + dev_err(&mci->dev, "no card inserted\n"); return -ENODEV; } /* start with a host interface reset */ - rc = (host->init)(host, mci->mci_dev); + rc = (host->init)(host, &mci->dev); if (rc) { - dev_err(mci->mci_dev, "Cannot reset the SD/MMC interface\n"); + dev_err(&mci->dev, "Cannot reset the SD/MMC interface\n"); return rc; } @@ -1386,7 +1483,7 @@ static int mci_card_probe(struct mci *mci) /* reset the card */ rc = mci_go_idle(mci); if (rc) { - dev_warn(mci->mci_dev, "Cannot reset the SD/MMC card\n"); + dev_warn(&mci->dev, "Cannot reset the SD/MMC card\n"); goto on_error; } @@ -1395,55 +1492,65 @@ static int mci_card_probe(struct mci *mci) rc = sd_send_op_cond(mci); if (rc && rc == -ETIMEDOUT) { /* If the command timed out, we check for an MMC card */ - dev_dbg(mci->mci_dev, "Card seems to be a MultiMediaCard\n"); + dev_dbg(&mci->dev, "Card seems to be a MultiMediaCard\n"); rc = mmc_send_op_cond(mci); } if (rc) goto on_error; + if (host->devname) { + mci->cdevname = strdup(host->devname); + } else { + disknum = cdev_find_free_index("disk"); + mci->cdevname = asprintf("disk%d", disknum); + } + rc = mci_startup(mci); if (rc) { - dev_dbg(mci->mci_dev, "Card's startup fails with %d\n", rc); + dev_dbg(&mci->dev, "Card's startup fails with %d\n", rc); goto on_error; } - dev_dbg(mci->mci_dev, "Card is up and running now, registering as a disk\n"); + dev_dbg(&mci->dev, "Card is up and running now, registering as a disk\n"); mci->ready_for_use = 1; /* TODO now or later? */ - /* - * An MMC/SD card acts like an ordinary disk. - * So, re-use the disk driver to gain access to this media - */ - mci->blk.dev = mci->mci_dev; - mci->blk.ops = &mci_ops; - - if (host->devname) { - mci->blk.cdev.name = strdup(host->devname); - } else { - disknum = cdev_find_free_index("disk"); - mci->blk.cdev.name = asprintf("disk%d", disknum); - } - - mci->blk.blockbits = SECTOR_SHIFT; - mci->blk.num_blocks = mci_calc_blk_cnt(mci->capacity, mci->blk.blockbits); + for (i = 0; i < mci->nr_parts; i++) { + struct mci_part *part = &mci->part[i]; - rc = blockdevice_register(&mci->blk); - if (rc != 0) { - dev_err(mci->mci_dev, "Failed to register MCI/SD blockdevice\n"); - goto on_error; - } + /* + * An MMC/SD card acts like an ordinary disk. + * So, re-use the disk driver to gain access to this media + */ + part->blk.dev = &mci->dev; + part->blk.ops = &mci_ops; - dev_info(mci->mci_dev, "registered %s\n", mci->blk.cdev.name); + rc = blockdevice_register(&part->blk); + if (rc != 0) { + dev_err(&mci->dev, "Failed to register MCI/SD blockdevice\n"); + goto on_error; + } + dev_info(&mci->dev, "registered %s\n", part->blk.cdev.name); + + /* create partitions on demand */ + if (part->area_type == MMC_BLK_DATA_AREA_MAIN) { + rc = parse_partition_table(&part->blk); + if (rc != 0) { + dev_warn(&mci->dev, "No partition table found\n"); + rc = 0; /* it's not a failure */ + } + } - /* create partitions on demand */ - rc = parse_partition_table(&mci->blk); - if (rc != 0) { - dev_warn(mci->mci_dev, "No partition table found\n"); - rc = 0; /* it's not a failure */ + if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && + part->area_type == MMC_BLK_DATA_AREA_BOOT && + !mci->param_boot) { + mci->param_boot = dev_add_param_enum(&mci->dev, "boot", + mci_set_boot, NULL, &mci->bootpart, + mci_boot_names, ARRAY_SIZE(mci_boot_names), mci); + } } - dev_dbg(mci->mci_dev, "SD Card successfully added\n"); + dev_dbg(&mci->dev, "SD Card successfully added\n"); on_error: if (rc != 0) { @@ -1480,75 +1587,125 @@ static int mci_set_probe(struct param_d *param, void *priv) return 0; } +static int mci_init(void) +{ + sector_buf = xmemalign(32, 512); + + return 0; +} + +device_initcall(mci_init); + +int mci_detect_card(struct mci_host *host) +{ + int rc; + + rc = mci_check_if_already_initialized(host->mci); + if (rc != 0) + return 0; + + return mci_card_probe(host->mci); +} + +static int mci_detect(struct device_d *dev) +{ + struct mci *mci = container_of(dev, struct mci, dev); + + return mci_detect_card(mci->host); +} + /** - * Prepare for MCI card's usage - * @param mci_dev MCI device instance + * Create a new mci device (for convenience) + * @param host mci_host for this MCI device * @return 0 on success - * - * This routine will probe an attached MCI card immediately or provide - * a parameter to do it later on user's demand. */ -static int mci_probe(struct device_d *mci_dev) +int mci_register(struct mci_host *host) { struct mci *mci; - int rc; + int ret; - mci = xzalloc(sizeof(struct mci)); - mci_dev->priv = mci; - mci->mci_dev = mci_dev; - mci->host = mci_dev->platform_data; + mci = xzalloc(sizeof(*mci)); + mci->host = host; - dev_info(mci->host->hw_dev, "registered as %s\n", dev_name(mci_dev)); + if (host->devname) { + strcpy(mci->dev.name, host->devname); + mci->dev.id = DEVICE_ID_SINGLE; + } else { + strcpy(mci->dev.name, "mci"); + mci->dev.id = DEVICE_ID_DYNAMIC; + } + + mci->dev.platform_data = host; + mci->dev.parent = host->hw_dev; + mci->host = host; + host->mci = mci; + mci->dev.detect = mci_detect; + + ret = register_device(&mci->dev); + if (ret) + goto err_free; - mci->param_probe = dev_add_param_bool(mci_dev, "probe", + dev_info(mci->host->hw_dev, "registered as %s\n", dev_name(&mci->dev)); + + mci->param_probe = dev_add_param_bool(&mci->dev, "probe", mci_set_probe, NULL, &mci->probe, mci); if (IS_ERR(mci->param_probe)) { - dev_dbg(mci->mci_dev, "Failed to add 'probe' parameter to the MCI device\n"); - goto on_error; + dev_dbg(&mci->dev, "Failed to add 'probe' parameter to the MCI device\n"); + goto err_unregister; } -#ifdef CONFIG_MCI_STARTUP + if (IS_ENABLED(CONFIG_MCI_INFO)) + mci->dev.info = mci_info; + /* if enabled, probe the attached card immediately */ - mci_card_probe(mci); -#endif + if (IS_ENABLED(CONFIG_MCI_STARTUP)) + mci_card_probe(mci); return 0; -on_error: +err_unregister: + unregister_device(&mci->dev); +err_free: free(mci); - return rc; -} -static struct driver_d mci_driver = { - .name = "mci", - .probe = mci_probe, -#ifdef CONFIG_MCI_INFO - .info = mci_info, -#endif -}; + return ret; +} -static int mci_init(void) +void mci_of_parse(struct mci_host *host) { - sector_buf = xmemalign(32, 512); - return platform_driver_register(&mci_driver); -} + struct device_node *np; + u32 bus_width; -device_initcall(mci_init); + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return; -/** - * Create a new mci device (for convenience) - * @param host mci_host for this MCI device - * @return 0 on success - */ -int mci_register(struct mci_host *host) -{ - struct device_d *mci_dev = xzalloc(sizeof(struct device_d)); + if (!host->hw_dev || !host->hw_dev->device_node) + return; + + np = host->hw_dev->device_node; - mci_dev->id = DEVICE_ID_DYNAMIC; - strcpy(mci_dev->name, mci_driver.name); - mci_dev->platform_data = host; - mci_dev->parent = host->hw_dev; + /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */ + if (of_property_read_u32(np, "bus-width", &bus_width) < 0) { + dev_dbg(host->hw_dev, + "\"bus-width\" property is missing, assuming 1 bit.\n"); + bus_width = 1; + } + + switch (bus_width) { + case 8: + host->host_caps |= MMC_MODE_8BIT; + /* Hosts capable of 8-bit transfers can also do 4 bits */ + case 4: + host->host_caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + dev_err(host->hw_dev, + "Invalid \"bus-width\" value %ud!\n", bus_width); + } - return platform_device_register(mci_dev); + /* f_max is obtained from the optional "max-frequency" property */ + of_property_read_u32(np, "max-frequency", &host->f_max); } diff --git a/drivers/mci/mxs.c b/drivers/mci/mxs.c index 9dee863aaf..e6f40ebc35 100644 --- a/drivers/mci/mxs.c +++ b/drivers/mci/mxs.c @@ -536,7 +536,6 @@ static void mxs_mci_set_ios(struct mci_host *host, struct mci_ios *ios) /* ----------------------------------------------------------------------- */ -#ifdef CONFIG_MCI_INFO const unsigned char bus_width[3] = { 1, 4, 8 }; static void mxs_mci_info(struct device_d *hw_dev) @@ -550,7 +549,6 @@ static void mxs_mci_info(struct device_d *hw_dev) printf(" Bus width: %u bit\n", bus_width[mxs_mci->bus_width]); printf("\n"); } -#endif static int mxs_mci_probe(struct device_d *hw_dev) { @@ -617,10 +615,11 @@ static int mxs_mci_probe(struct device_d *hw_dev) host->f_max, mxs_mci_get_unit_clock(mxs_mci) / 2 / 1); } -#ifdef CONFIG_MCI_INFO - mxs_mci->f_min = host->f_min; - mxs_mci->f_max = host->f_max; -#endif + if (IS_ENABLED(CONFIG_MCI_INFO)) { + mxs_mci->f_min = host->f_min; + mxs_mci->f_max = host->f_max; + hw_dev->info = mxs_mci_info; + } return mci_register(host); } @@ -628,8 +627,5 @@ static int mxs_mci_probe(struct device_d *hw_dev) static struct driver_d mxs_mci_driver = { .name = "mxs_mci", .probe = mxs_mci_probe, -#ifdef CONFIG_MCI_INFO - .info = mxs_mci_info, -#endif }; device_platform_driver(mxs_mci_driver); diff --git a/drivers/mci/s3c.c b/drivers/mci/s3c.c index 4e7345c8d5..773c84ad09 100644 --- a/drivers/mci/s3c.c +++ b/drivers/mci/s3c.c @@ -700,7 +700,6 @@ static void mci_set_ios(struct mci_host *host, struct mci_ios *ios) /* ----------------------------------------------------------------------- */ -#ifdef CONFIG_MCI_INFO static void s3c_info(struct device_d *hw_dev) { struct s3c_mci_host *host = hw_dev->priv; @@ -720,7 +719,6 @@ static void s3c_info(struct device_d *hw_dev) printf("\n Card detection support: %s\n", pd->gpio_detect != 0 ? "yes" : "no"); } -#endif static int s3c_mci_probe(struct device_d *hw_dev) { @@ -751,6 +749,9 @@ static int s3c_mci_probe(struct device_d *hw_dev) s3c_host->host.f_min = pd->f_min == 0 ? s3c_get_pclk() / 256 : pd->f_min; s3c_host->host.f_max = pd->f_max == 0 ? s3c_get_pclk() / 2 : pd->f_max; + if (IS_ENABLED(iCONFIG_MCI_INFO)) + hw_dev->info = s3c_info; + /* * Start the clock to let the engine and the card finishes its startup */ @@ -763,8 +764,5 @@ static int s3c_mci_probe(struct device_d *hw_dev) static struct driver_d s3c_mci_driver = { .name = "s3c_mci", .probe = s3c_mci_probe, -#ifdef CONFIG_MCI_INFO - .info = s3c_info, -#endif }; device_platform_driver(s3c_mci_driver); diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h new file mode 100644 index 0000000000..b2d6779ef6 --- /dev/null +++ b/drivers/mci/sdhci.h @@ -0,0 +1,89 @@ +#ifndef __MCI_SDHCI_H +#define __MCI_SDHCI_H + +#define SDHCI_DMA_ADDRESS 0x00 +#define SDHCI_BLOCK_SIZE__BLOCK_COUNT 0x04 +#define SDHCI_ARGUMENT 0x08 +#define SDHCI_TRANSFER_MODE__COMMAND 0x0c +#define SDHCI_RESPONSE_0 0x10 +#define SDHCI_RESPONSE_1 0x14 +#define SDHCI_RESPONSE_2 0x18 +#define SDHCI_RESPONSE_3 0x1c +#define SDHCI_BUFFER 0x20 +#define SDHCI_PRESENT_STATE 0x24 +#define SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL 0x28 +#define SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET 0x2c +#define SDHCI_INT_STATUS 0x30 +#define SDHCI_INT_ENABLE 0x34 +#define SDHCI_SIGNAL_ENABLE 0x38 +#define SDHCI_ACMD12_ERR__HOST_CONTROL2 0x3C +#define SDHCI_CAPABILITIES 0x40 + +#define COMMAND_CMD(x) ((x & 0x3f) << 24) +#define COMMAND_CMDTYP_NORMAL 0x0 +#define COMMAND_CMDTYP_SUSPEND 0x00400000 +#define COMMAND_CMDTYP_RESUME 0x00800000 +#define COMMAND_CMDTYP_ABORT 0x00c00000 +#define COMMAND_DPSEL 0x00200000 +#define COMMAND_CICEN 0x00100000 +#define COMMAND_CCCEN 0x00080000 +#define COMMAND_RSPTYP_NONE 0 +#define COMMAND_RSPTYP_136 0x00010000 +#define COMMAND_RSPTYP_48 0x00020000 +#define COMMAND_RSPTYP_48_BUSY 0x00030000 +#define TRANSFER_MODE_MSBSEL 0x00000020 +#define TRANSFER_MODE_DTDSEL 0x00000010 +#define TRANSFER_MODE_AC12EN 0x00000004 +#define TRANSFER_MODE_BCEN 0x00000002 +#define TRANSFER_MODE_DMAEN 0x00000001 + +#define IRQSTAT_DMAE 0x10000000 +#define IRQSTAT_AC12E 0x01000000 +#define IRQSTAT_DEBE 0x00400000 +#define IRQSTAT_DCE 0x00200000 +#define IRQSTAT_DTOE 0x00100000 +#define IRQSTAT_CIE 0x00080000 +#define IRQSTAT_CEBE 0x00040000 +#define IRQSTAT_CCE 0x00020000 +#define IRQSTAT_CTOE 0x00010000 +#define IRQSTAT_CINT 0x00000100 +#define IRQSTAT_CRM 0x00000080 +#define IRQSTAT_CINS 0x00000040 +#define IRQSTAT_BRR 0x00000020 +#define IRQSTAT_BWR 0x00000010 +#define IRQSTAT_DINT 0x00000008 +#define IRQSTAT_BGE 0x00000004 +#define IRQSTAT_TC 0x00000002 +#define IRQSTAT_CC 0x00000001 + +#define IRQSTATEN_DMAE 0x10000000 +#define IRQSTATEN_AC12E 0x01000000 +#define IRQSTATEN_DEBE 0x00400000 +#define IRQSTATEN_DCE 0x00200000 +#define IRQSTATEN_DTOE 0x00100000 +#define IRQSTATEN_CIE 0x00080000 +#define IRQSTATEN_CEBE 0x00040000 +#define IRQSTATEN_CCE 0x00020000 +#define IRQSTATEN_CTOE 0x00010000 +#define IRQSTATEN_CINT 0x00000100 +#define IRQSTATEN_CRM 0x00000080 +#define IRQSTATEN_CINS 0x00000040 +#define IRQSTATEN_BRR 0x00000020 +#define IRQSTATEN_BWR 0x00000010 +#define IRQSTATEN_DINT 0x00000008 +#define IRQSTATEN_BGE 0x00000004 +#define IRQSTATEN_TC 0x00000002 +#define IRQSTATEN_CC 0x00000001 + +#define PRSSTAT_CLSL 0x00800000 +#define PRSSTAT_WPSPL 0x00080000 +#define PRSSTAT_CDPL 0x00040000 +#define PRSSTAT_CINS 0x00010000 +#define PRSSTAT_BREN 0x00000800 +#define PRSSTAT_BWEN 0x00000400 +#define PRSSTAT_SDSTB 0x00000008 +#define PRSSTAT_DLA 0x00000004 +#define PRSSTAT_CIDHB 0x00000002 +#define PRSSTAT_CICHB 0x00000001 + +#endif /* __MCI_SDHCI_H */ diff --git a/drivers/mci/twl6030.c b/drivers/mci/twl6030.c deleted file mode 100644 index 4a875bd62b..0000000000 --- a/drivers/mci/twl6030.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * MCI pmic power. - */ - -#include <mfd/twl6030.h> -#include <mci/twl6030.h> -#include <asm/io.h> - -static int twl6030_mci_write(u8 address, u8 data) -{ - int ret; - struct twl6030 *twl6030 = twl6030_get(); - - ret = twl6030_reg_write(twl6030, address, data); - if (ret != 0) - printf("TWL6030:MCI:Write[0x%x] Error %d\n", address, ret); - - return ret; -} - -void twl6030_mci_power_init(void) -{ - twl6030_mci_write(TWL6030_PMCS_VMMC_CFG_VOLTAGE, - TWL6030_VMMC_VSEL_0 | TWL6030_VMMC_VSEL_2 | - TWL6030_VMMC_VSEL_4); - twl6030_mci_write(TWL6030_PMCS_VMMC_CFG_STATE, - TWL6030_VMMC_STATE0 | TWL6030_VMMC_GRP_APP); -} - diff --git a/drivers/misc/jtag.c b/drivers/misc/jtag.c index d302237e37..310da81074 100644 --- a/drivers/misc/jtag.c +++ b/drivers/misc/jtag.c @@ -269,6 +269,25 @@ static struct file_operations jtag_operations = { .ioctl = jtag_ioctl, }; +static void jtag_info(struct device_d *pdev) +{ + int dn, ret; + struct jtag_rd_id jid; + struct jtag_info *info = pdev->priv; + + printf(" JTAG:\n"); + printf(" Devices found: %d\n", info->devices); + for (dn = 0; dn < info->devices; dn++) { + jid.device = dn; + ret = jtag_ioctl(&info->cdev, JTAG_GET_ID, &jid); + printf(" Device number: %d\n", dn); + if (ret == -1) + printf(" JTAG_GET_ID failed: %s\n", strerror(errno)); + else + printf(" ID: 0x%lX\n", jid.id); + } +} + static int jtag_probe(struct device_d *pdev) { int i, ret; @@ -323,6 +342,7 @@ static int jtag_probe(struct device_d *pdev) info->devices = i; info->pdata = pdata; pdev->priv = info; + pdev->info = jtag_info; info->cdev.name = JTAG_NAME; info->cdev.dev = pdev; @@ -341,25 +361,6 @@ fail_devfs_create: return ret; } -static void jtag_info(struct device_d *pdev) -{ - int dn, ret; - struct jtag_rd_id jid; - struct jtag_info *info = pdev->priv; - - printf(" JTAG:\n"); - printf(" Devices found: %d\n", info->devices); - for (dn = 0; dn < info->devices; dn++) { - jid.device = dn; - ret = jtag_ioctl(&info->cdev, JTAG_GET_ID, &jid); - printf(" Device number: %d\n", dn); - if (ret == -1) - printf(" JTAG_GET_ID failed: %s\n", strerror(errno)); - else - printf(" ID: 0x%lX\n", jid.id); - } -} - static void jtag_remove(struct device_d *pdev) { struct jtag_info *info = (struct jtag_info *) pdev->priv; @@ -374,7 +375,6 @@ static struct driver_d jtag_driver = { .name = JTAG_NAME, .probe = jtag_probe, .remove = jtag_remove, - .info = jtag_info, }; device_platform_driver(jtag_driver); diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index 61744b69dc..f3580981f0 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -107,6 +107,12 @@ static int mtd_op_erase(struct cdev *cdev, size_t count, loff_t offset) memset(&erase, 0, sizeof(erase)); erase.mtd = mtd; erase.addr = offset; + + if (!mtd->block_isbad) { + erase.len = count; + return mtd_erase(mtd, &erase); + } + erase.len = mtd->erasesize; while (count > 0) { diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 048d1783dc..57fe1f27ef 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -947,9 +947,18 @@ static int m25p_probe(struct device_d *dev) return add_mtd_device(&flash->mtd, flash->mtd.name); } +static __maybe_unused struct of_device_id m25p80_dt_ids[] = { + { + .compatible = "m25p80", + }, { + /* sentinel */ + } +}; + static struct driver_d m25p80_driver = { .name = "m25p80", .probe = m25p_probe, + .of_compatible = DRV_OF_COMPAT(m25p80_dt_ids), }; device_spi_driver(m25p80_driver); diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index ddab6bbb79..52bd84266c 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -871,9 +871,20 @@ static int dataflash_probe(struct device_d *dev) return status; } +static __maybe_unused struct of_device_id dataflash_dt_ids[] = { + { + .compatible = "atmel,at45", + }, { + .compatible = "atmel,dataflash", + }, { + /* sentinel */ + } +}; + static struct driver_d dataflash_driver = { .name = "mtd_dataflash", .probe = dataflash_probe, + .of_compatible = DRV_OF_COMPAT(dataflash_dt_ids), }; device_spi_driver(dataflash_driver); diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c index 0cfac2d036..51fc6bc89f 100644 --- a/drivers/mtd/nor/cfi_flash.c +++ b/drivers/mtd/nor/cfi_flash.c @@ -187,10 +187,10 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o addr = flash_make_addr (info, sect, offset); #ifdef DEBUG - debug ("long addr is at %p info->portwidth = %d\n", addr, + dev_dbg(info->dev, "long addr is at %p info->portwidth = %d\n", addr, info->portwidth); for (x = 0; x < 4 * info->portwidth; x++) { - debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x)); + dev_dbg(info->dev, "addr[%x] = 0x%x\n", x, flash_read8(addr + x)); } #endif #if defined __LITTLE_ENDIAN @@ -240,10 +240,10 @@ static void flash_read_cfi (struct flash_info *info, void *buf, p[i] = flash_read_uchar(info, start + i); } -static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry) +static int flash_detect_width (struct flash_info *info, struct cfi_qry *qry) { int cfi_offset; - debug ("flash detect cfi\n"); + for (info->portwidth = CFG_FLASH_CFI_WIDTH; info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { @@ -262,11 +262,11 @@ static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry) info->interface = le16_to_cpu(qry->interface_desc); info->cfi_offset=flash_offset_cfi[cfi_offset]; - debug ("device interface is %d\n", + dev_dbg(info->dev, "device interface is %d\n", info->interface); - debug ("found port %d chip %d ", - info->portwidth, info->chipwidth); - debug ("port %d bits chip %d bits\n", + dev_dbg(info->dev, "found port %d chip %d chip_lsb %d ", + info->portwidth, info->chipwidth, info->chip_lsb); + dev_dbg(info->dev, "port %d bits chip %d bits\n", info->portwidth << CFI_FLASH_SHIFT_WIDTH, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); return 1; @@ -274,10 +274,25 @@ static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry) } } } - debug ("not found\n"); + dev_dbg(info->dev, "not found\n"); return 0; } +static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry) +{ + int ret; + + dev_dbg(info->dev, "flash detect cfi\n"); + + info->chip_lsb = 0; + ret = flash_detect_width (info, qry); + if (!ret) { + info->chip_lsb = 1; + ret = flash_detect_width (info, qry); + } + return ret; +} + /* * The following code cannot be run from FLASH! */ @@ -339,7 +354,7 @@ static ulong flash_get_size (struct flash_info *info) break; #endif default: - printf("unsupported vendor\n"); + dev_err(info->dev, "unsupported vendor\n"); return 0; } info->cfi_cmd_set->flash_read_jedec_ids (info); @@ -347,22 +362,23 @@ static ulong flash_get_size (struct flash_info *info) info->cfi_cmd_set->flash_fixup (info, &qry); - debug ("manufacturer is %d\n", info->vendor); - debug ("manufacturer id is 0x%x\n", info->manufacturer_id); - debug ("device id is 0x%x\n", info->device_id); - debug ("device id2 is 0x%x\n", info->device_id2); - debug ("cfi version is 0x%04x\n", info->cfi_version); + dev_dbg(info->dev, "manufacturer is %d\n", info->vendor); + dev_dbg(info->dev, "manufacturer id is 0x%x\n", info->manufacturer_id); + dev_dbg(info->dev, "device id is 0x%x\n", info->device_id); + dev_dbg(info->dev, "device id2 is 0x%x\n", info->device_id2); + dev_dbg(info->dev, "cfi version is 0x%04x\n", info->cfi_version); size_ratio = info->portwidth / info->chipwidth; /* if the chip is x8/x16 reduce the ratio by half */ if ((info->interface == FLASH_CFI_X8X16) - && (info->chipwidth == FLASH_CFI_BY8)) { + && (info->chipwidth == FLASH_CFI_BY8) + && (size_ratio != 1)) { size_ratio >>= 1; } - debug ("size_ratio %d port %d bits chip %d bits\n", + dev_dbg(info->dev, "size_ratio %d port %d bits chip %d bits\n", size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); - debug ("found %d erase regions\n", num_erase_regions); + dev_dbg(info->dev, "found %d erase regions\n", num_erase_regions); info->eraseregions = xzalloc(sizeof(*(info->eraseregions)) * num_erase_regions); info->numeraseregions = num_erase_regions; sect_cnt = 0; @@ -372,19 +388,19 @@ static ulong flash_get_size (struct flash_info *info) struct mtd_erase_region_info *region = &info->eraseregions[i]; if (i > NUM_ERASE_REGIONS) { - printf ("%d erase regions found, only %d used\n", + dev_info(info->dev, "%d erase regions found, only %d used\n", num_erase_regions, NUM_ERASE_REGIONS); break; } tmp = le32_to_cpu(qry.erase_region_info[i]); - debug("erase region %u: 0x%08lx\n", i, tmp); + dev_dbg(info->dev, "erase region %u: 0x%08lx\n", i, tmp); erase_region_count = (tmp & 0xffff) + 1; tmp >>= 16; erase_region_size = (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128; - debug ("erase_region_count = %d erase_region_size = %d\n", + dev_dbg(info->dev, "erase_region_count = %d erase_region_size = %d\n", erase_region_count, erase_region_size); region->offset = cur_offset; @@ -459,7 +475,7 @@ static int cfi_erase(struct flash_info *finfo, size_t count, loff_t offset) unsigned long start, end; int i, ret = 0; - debug("%s: erase 0x%08llx (size %zu)\n", __func__, offset, count); + dev_dbg(finfo->dev, "%s: erase 0x%08llx (size %zu)\n", __func__, offset, count); start = find_sector(finfo, (unsigned long)finfo->base + offset); end = find_sector(finfo, (unsigned long)finfo->base + offset + @@ -786,7 +802,7 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector, start = get_time_ns(); while (info->cfi_cmd_set->flash_is_busy (info, sector)) { if (is_timeout(start, tout)) { - printf ("Flash %s timeout at address %lx data %lx\n", + dev_err(info->dev, "Flash %s timeout at address %lx data %lx\n", prompt, info->start[sector], flash_read_long (info, sector, 0)); flash_write_cmd (info, sector, 0, info->cmd_reset); @@ -823,7 +839,7 @@ void flash_write_cmd(struct flash_info *info, flash_sect_t sect, addr = flash_make_addr (info, sect, offset); flash_make_cmd (info, cmd, &cword); - debug("%s: %p %lX %X => %p " CFI_WORD_FMT "\n", __func__, + dev_dbg(info->dev, "%s: %p %lX %X => %p " CFI_WORD_FMT "\n", __func__, info, sect, offset, addr, cword); flash_write_word(info, cword, addr); @@ -839,15 +855,15 @@ int flash_isequal(struct flash_info *info, flash_sect_t sect, addr = flash_make_addr (info, sect, offset); flash_make_cmd (info, cmd, &cword); - debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr); + dev_dbg(info->dev, "is= cmd %x(%c) addr %p ", cmd, cmd, addr); if (bankwidth_is_1(info)) { - debug ("is= %x %x\n", flash_read8(addr), (u8)cword); + dev_dbg(info->dev, "is= %x %x\n", flash_read8(addr), (u8)cword); retval = (flash_read8(addr) == cword); } else if (bankwidth_is_2(info)) { - debug ("is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword); + dev_dbg(info->dev, "is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword); retval = (flash_read16(addr) == cword); } else if (bankwidth_is_4(info)) { - debug ("is= %8.8x %8.8x\n", flash_read32(addr), (u32)cword); + dev_dbg(info->dev, "is= %8.8x %8.8x\n", flash_read32(addr), (u32)cword); retval = (flash_read32(addr) == cword); } else if (bankwidth_is_8(info)) { #ifdef DEBUG @@ -857,7 +873,7 @@ int flash_isequal(struct flash_info *info, flash_sect_t sect, print_longlong (str1, flash_read32(addr)); print_longlong (str2, cword); - debug ("is= %s %s\n", str1, str2); + dev_dbg(info->dev, "is= %s %s\n", str1, str2); } #endif retval = (flash_read64(addr) == cword); @@ -947,6 +963,7 @@ static void cfi_init_mtd(struct flash_info *info) mtd->numeraseregions = info->numeraseregions; mtd->flags = MTD_CAP_NORFLASH; mtd->type = MTD_NORFLASH; + mtd->parent = info->dev; add_mtd_device(mtd, "nor"); } @@ -962,9 +979,10 @@ static int cfi_probe (struct device_d *dev) info->cmd_reset = FLASH_CMD_RESET; info->base = dev_request_mem_region(dev, 0); info->size = flash_get_size(info); + info->dev = dev; if (info->flash_id == FLASH_UNKNOWN) { - printf ("## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n", + dev_warn(dev, "## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n", dev->resource[0].start, info->size, info->size << 20); return -ENODEV; } @@ -972,6 +990,8 @@ static int cfi_probe (struct device_d *dev) dev_info(dev, "found cfi flash at %p, size %ld\n", info->base, info->size); + dev->info = cfi_info; + cfi_init_mtd(info); return 0; @@ -988,7 +1008,6 @@ static __maybe_unused struct of_device_id cfi_dt_ids[] = { static struct driver_d cfi_driver = { .name = "cfi_flash", .probe = cfi_probe, - .info = cfi_info, .of_compatible = DRV_OF_COMPAT(cfi_dt_ids), }; device_platform_driver(cfi_driver); diff --git a/drivers/mtd/nor/cfi_flash.h b/drivers/mtd/nor/cfi_flash.h index bcf5c40c73..9aad5c41f6 100644 --- a/drivers/mtd/nor/cfi_flash.h +++ b/drivers/mtd/nor/cfi_flash.h @@ -48,7 +48,7 @@ struct cfi_cmd_set; */ struct flash_info { - struct driver_d driver; + struct device_d *dev; ulong size; /* total bank size in bytes */ ushort sector_count; /* number of erase units */ ulong flash_id; /* combined device & manufacturer code */ @@ -57,6 +57,8 @@ struct flash_info { uchar portwidth; /* the width of the port */ uchar chipwidth; /* the width of the chip */ + uchar chip_lsb; /* extra Least Significant Bit in the */ + /* address of chip. */ ushort buffer_size; /* # of bytes in write buffer */ ulong erase_blk_tout; /* maximum block erase timeout */ ulong write_tout; /* maximum write timeout */ @@ -298,7 +300,7 @@ static inline u64 flash_read64(void *addr) */ static inline uchar *flash_make_addr (struct flash_info *info, flash_sect_t sect, uint offset) { - return ((uchar *) (info->start[sect] + (offset * info->portwidth))); + return ((uchar *) (info->start[sect] + ((offset * info->portwidth) << info->chip_lsb))); } uchar flash_read_uchar (struct flash_info *info, uint offset); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2736094b8b..5ad3e4d46e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -27,6 +27,13 @@ menu "Network drivers" source "drivers/net/phy/Kconfig" +config DRIVER_NET_AR231X + bool "AR231X Ethernet support" + depends on MACH_MIPS_AR231X + select PHYLIB + help + Support for the AR231x/531x ethernet controller + config DRIVER_NET_CALXEDA_XGMAC bool "Calxeda xgmac" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 42136f87c8..73403fecfd 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_DRIVER_NET_AR231X) += ar231x.o obj-$(CONFIG_DRIVER_NET_CALXEDA_XGMAC) += xgmac.o obj-$(CONFIG_DRIVER_NET_CS8900) += cs8900.o obj-$(CONFIG_DRIVER_NET_CPSW) += cpsw.o diff --git a/drivers/net/ar231x.c b/drivers/net/ar231x.c new file mode 100644 index 0000000000..5c091140ac --- /dev/null +++ b/drivers/net/ar231x.c @@ -0,0 +1,437 @@ +/* + * ar231x.c: driver for the Atheros AR231x Ethernet device. + * This device is build in to SoC on ar231x series. + * All known of them are big endian. + * + * Based on Linux driver: + * Copyright (C) 2004 by Sameer Dekate <sdekate@arubanetworks.com> + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.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. + */ +/* + * Known issues: + * - broadcast packets are not filtered by hardware. On noisy network with + * lots of bcast packages rx_buffer can be completely filled after. Currently + * we clear rx_buffer transmit some package. + */ + +#include <common.h> +#include <net.h> +#include <init.h> +#include <io.h> + +#include "ar231x.h" + +static inline void dma_writel(struct ar231x_eth_priv *priv, + u32 val, int reg) +{ + __raw_writel(val, priv->dma_regs + reg); +} + +static inline u32 dma_readl(struct ar231x_eth_priv *priv, int reg) +{ + return __raw_readl(priv->dma_regs + reg); +} + +static inline void eth_writel(struct ar231x_eth_priv *priv, + u32 val, int reg) +{ + __raw_writel(val, priv->eth_regs + reg); +} + +static inline u32 eth_readl(struct ar231x_eth_priv *priv, int reg) +{ + return __raw_readl(priv->eth_regs + reg); +} + +static inline void phy_writel(struct ar231x_eth_priv *priv, + u32 val, int reg) +{ + __raw_writel(val, priv->phy_regs + reg); +} + +static inline u32 phy_readl(struct ar231x_eth_priv *priv, int reg) +{ + return __raw_readl(priv->phy_regs + reg); +} + +static void ar231x_reset_bit_(struct ar231x_eth_priv *priv, + u32 val, enum reset_state state) +{ + if (priv->reset_bit) + (*priv->reset_bit)(val, state); +} + +static int ar231x_set_ethaddr(struct eth_device *edev, unsigned char *addr); +static void ar231x_reset_regs(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + struct ar231x_eth_platform_data *cfg = priv->cfg; + u32 flags; + + ar231x_reset_bit_(priv, cfg->reset_mac, SET); + mdelay(10); + + ar231x_reset_bit_(priv, cfg->reset_mac, REMOVE); + mdelay(10); + + ar231x_reset_bit_(priv, cfg->reset_phy, SET); + mdelay(10); + + ar231x_reset_bit_(priv, cfg->reset_phy, REMOVE); + mdelay(10); + + dma_writel(priv, DMA_BUS_MODE_SWR, AR231X_DMA_BUS_MODE); + mdelay(10); + + dma_writel(priv, ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE), + AR231X_DMA_BUS_MODE); + + /* FIXME: priv->{t,r}x_ring are virtual addresses, + * use virt-to-phys convertion */ + dma_writel(priv, (u32)priv->tx_ring, AR231X_DMA_TX_RING); + dma_writel(priv, (u32)priv->rx_ring, AR231X_DMA_RX_RING); + + dma_writel(priv, (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF), + AR231X_DMA_CONTROL); + + eth_writel(priv, FLOW_CONTROL_FCE, AR231X_ETH_FLOW_CONTROL); + /* TODO: not sure if we need it here. */ + eth_writel(priv, 0x8100, AR231X_ETH_VLAN_TAG); + + /* Enable Ethernet Interface */ + flags = (MAC_CONTROL_TE | /* transmit enable */ + /* FIXME: MAC_CONTROL_PM - pass mcast. + * Seems like it makes no difference on some WiSoCs, + * for example ar2313. + * It should be tested on ar231[5,6,7] */ + MAC_CONTROL_PM | + MAC_CONTROL_F | /* full duplex */ + MAC_CONTROL_HBD); /* heart beat disabled */ + eth_writel(priv, flags, AR231X_ETH_MAC_CONTROL); +} + +static void ar231x_flash_rxdsc(struct ar231x_descr *rxdsc) +{ + rxdsc->status = DMA_RX_OWN; + rxdsc->devcs = ((AR2313_RX_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | + DMA_RX1_CHAINED); +} + +static void ar231x_allocate_dma_descriptors(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u16 ar231x_descr_size = sizeof(struct ar231x_descr); + u16 i; + + priv->tx_ring = xmalloc(ar231x_descr_size); + dev_dbg(&edev->dev, "allocate tx_ring @ %p\n", priv->tx_ring); + + priv->rx_ring = xmalloc(ar231x_descr_size * AR2313_RXDSC_ENTRIES); + dev_dbg(&edev->dev, "allocate rx_ring @ %p\n", priv->rx_ring); + + priv->rx_buffer = xmalloc(AR2313_RX_BUFSIZE * AR2313_RXDSC_ENTRIES); + dev_dbg(&edev->dev, "allocate rx_buffer @ %p\n", priv->rx_buffer); + + /* Initialize the rx Descriptors */ + for (i = 0; i < AR2313_RXDSC_ENTRIES; i++) { + struct ar231x_descr *rxdsc = &priv->rx_ring[i]; + ar231x_flash_rxdsc(rxdsc); + rxdsc->buffer_ptr = + (u32)(priv->rx_buffer + AR2313_RX_BUFSIZE * i); + rxdsc->next_dsc_ptr = (u32)&priv->rx_ring[DSC_NEXT(i)]; + } + /* set initial position of ring descriptor */ + priv->next_rxdsc = &priv->rx_ring[0]; +} + +static void ar231x_adjust_link(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u32 mc; + + if (edev->phydev->duplex != priv->oldduplex) { + mc = eth_readl(priv, AR231X_ETH_MAC_CONTROL); + mc &= ~(MAC_CONTROL_F | MAC_CONTROL_DRO); + if (edev->phydev->duplex) + mc |= MAC_CONTROL_F; + else + mc |= MAC_CONTROL_DRO; + eth_writel(priv, mc, AR231X_ETH_MAC_CONTROL); + priv->oldduplex = edev->phydev->duplex; + } +} + +static int ar231x_eth_init(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + + ar231x_allocate_dma_descriptors(edev); + ar231x_reset_regs(edev); + ar231x_set_ethaddr(edev, priv->mac); + return 0; +} + +static int ar231x_eth_open(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u32 tmp; + + /* Enable RX. Now the rx_buffer will be filled. + * If it is full we may lose first transmission. In this case + * barebox should retry it. + * Or TODO: - force HW to filter some how broadcasts + * - disable RX if we do not need it. */ + tmp = eth_readl(priv, AR231X_ETH_MAC_CONTROL); + eth_writel(priv, (tmp | MAC_CONTROL_RE), AR231X_ETH_MAC_CONTROL); + + return phy_device_connect(edev, &priv->miibus, (int)priv->phy_regs, + ar231x_adjust_link, 0, PHY_INTERFACE_MODE_MII); +} + +static int ar231x_eth_recv(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + + while (1) { + struct ar231x_descr *rxdsc = priv->next_rxdsc; + u32 status = rxdsc->status; + + /* owned by DMA? */ + if (status & DMA_RX_OWN) + break; + + /* Pick only packets what we can handle: + * - only complete packet per buffer + * (First and Last at same time) + * - drop multicast */ + if (!priv->kill_rx_ring && + ((status & DMA_RX_MASK) == DMA_RX_FSLS)) { + u16 length = + ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) + - CRC_LEN; + net_receive((void *)rxdsc->buffer_ptr, length); + } + /* Clean descriptor. now it is owned by DMA. */ + priv->next_rxdsc = (struct ar231x_descr *)rxdsc->next_dsc_ptr; + ar231x_flash_rxdsc(rxdsc); + } + priv->kill_rx_ring = 0; + return 0; +} + +static int ar231x_eth_send(struct eth_device *edev, void *packet, + int length) +{ + struct ar231x_eth_priv *priv = edev->priv; + struct ar231x_descr *txdsc = priv->tx_ring; + u32 rx_missed; + + /* We do not do async work. + * If rx_ring is full, there is nothing we can use. */ + rx_missed = dma_readl(priv, AR231X_DMA_RX_MISSED); + if (rx_missed) { + priv->kill_rx_ring = 1; + ar231x_eth_recv(edev); + } + + /* Setup the transmit descriptor. */ + txdsc->devcs = ((length << DMA_TX1_BSIZE_SHIFT) | DMA_TX1_DEFAULT); + txdsc->buffer_ptr = (uint)packet; + txdsc->status = DMA_TX_OWN; + + /* Trigger transmission */ + dma_writel(priv, 0, AR231X_DMA_TX_POLL); + + /* Take enough time to transmit packet. 100 is not enough. */ + wait_on_timeout(2000 * MSECOND, + !(txdsc->status & DMA_TX_OWN)); + + /* We can't do match here. If it is still in progress, + * then engine is probably stalled or we wait not enough. */ + if (txdsc->status & DMA_TX_OWN) + dev_err(&edev->dev, "Frame is still in progress.\n"); + + if (txdsc->status & DMA_TX_ERROR) + dev_err(&edev->dev, "Frame was aborted by engine\n"); + + /* Ready or not. Stop it. */ + txdsc->status = 0; + return 0; +} + +static void ar231x_eth_halt(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u32 tmp; + + /* kill the MAC: disable RX and TX */ + tmp = eth_readl(priv, AR231X_ETH_MAC_CONTROL); + eth_writel(priv, tmp & ~(MAC_CONTROL_RE | MAC_CONTROL_TE), + AR231X_ETH_MAC_CONTROL); + + /* stop DMA */ + dma_writel(priv, 0, AR231X_DMA_CONTROL); + dma_writel(priv, DMA_BUS_MODE_SWR, AR231X_DMA_BUS_MODE); + + /* place PHY and MAC in reset */ + ar231x_reset_bit_(priv, (priv->cfg->reset_mac | priv->cfg->reset_phy), SET); +} + +static int ar231x_get_ethaddr(struct eth_device *edev, unsigned char *addr) +{ + struct ar231x_eth_priv *priv = edev->priv; + + /* MAC address is stored on flash, in some kind of atheros config + * area. Platform code should read it and pass to the driver. */ + memcpy(addr, priv->mac, 6); + return 0; +} + +/** + * These device do not have build in MAC address. + * It is located on atheros-config field on flash. + */ +static int ar231x_set_ethaddr(struct eth_device *edev, unsigned char *addr) +{ + struct ar231x_eth_priv *priv = edev->priv; + + eth_writel(priv, + (addr[5] << 8) | (addr[4]), + AR231X_ETH_MAC_ADDR1); + eth_writel(priv, + (addr[3] << 24) | (addr[2] << 16) | + (addr[1] << 8) | addr[0], + AR231X_ETH_MAC_ADDR2); + + mdelay(10); + return 0; +} + +#define MII_ADDR(phy, reg) \ + ((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT)) + +static int ar231x_miibus_read(struct mii_bus *bus, int phy_id, int regnum) +{ + struct ar231x_eth_priv *priv = bus->priv; + uint64_t time_start; + + phy_writel(priv, MII_ADDR(phy_id, regnum), AR231X_ETH_MII_ADDR); + time_start = get_time_ns(); + while (phy_readl(priv, AR231X_ETH_MII_ADDR) & MII_ADDR_BUSY) { + if (is_timeout(time_start, SECOND)) { + dev_err(&bus->dev, "miibus read timeout\n"); + return -ETIMEDOUT; + } + } + return phy_readl(priv, AR231X_ETH_MII_DATA) >> MII_DATA_SHIFT; +} + +static int ar231x_miibus_write(struct mii_bus *bus, int phy_id, + int regnum, u16 val) +{ + struct ar231x_eth_priv *priv = bus->priv; + uint64_t time_start = get_time_ns(); + + while (phy_readl(priv, AR231X_ETH_MII_ADDR) & MII_ADDR_BUSY) { + if (is_timeout(time_start, SECOND)) { + dev_err(&bus->dev, "miibus write timeout\n"); + return -ETIMEDOUT; + } + } + phy_writel(priv, val << MII_DATA_SHIFT, AR231X_ETH_MII_DATA); + phy_writel(priv, MII_ADDR(phy_id, regnum) | MII_ADDR_WRITE, + AR231X_ETH_MII_ADDR); + return 0; +} + +static int ar231x_mdiibus_reset(struct mii_bus *bus) +{ + struct ar231x_eth_priv *priv = bus->priv; + + ar231x_reset_regs(&priv->edev); + return 0; +} + +static int ar231x_eth_probe(struct device_d *dev) +{ + struct ar231x_eth_priv *priv; + struct eth_device *edev; + struct mii_bus *miibus; + struct ar231x_eth_platform_data *pdata; + + if (!dev->platform_data) { + dev_err(dev, "no platform data\n"); + return -ENODEV; + } + + pdata = dev->platform_data; + + priv = xzalloc(sizeof(struct ar231x_eth_priv)); + edev = &priv->edev; + miibus = &priv->miibus; + edev->priv = priv; + + /* link all platform depended regs */ + priv->mac = pdata->mac; + priv->reset_bit = pdata->reset_bit; + + priv->eth_regs = dev_request_mem_region(dev, 0); + if (priv->eth_regs == NULL) { + dev_err(dev, "No eth_regs!!\n"); + return -ENODEV; + } + /* we have 0x100000 for eth, part of it are dma regs. + * So they are already requested */ + priv->dma_regs = (void *)(priv->eth_regs + 0x1000); + + priv->phy_regs = dev_request_mem_region(dev, 1); + if (priv->phy_regs == NULL) { + dev_err(dev, "No phy_regs!!\n"); + return -ENODEV; + } + + priv->cfg = pdata; + edev->init = ar231x_eth_init; + edev->open = ar231x_eth_open; + edev->send = ar231x_eth_send; + edev->recv = ar231x_eth_recv; + edev->halt = ar231x_eth_halt; + edev->get_ethaddr = ar231x_get_ethaddr; + edev->set_ethaddr = ar231x_set_ethaddr; + + priv->miibus.read = ar231x_miibus_read; + priv->miibus.write = ar231x_miibus_write; + priv->miibus.reset = ar231x_mdiibus_reset; + priv->miibus.priv = priv; + priv->miibus.parent = dev; + + mdiobus_register(miibus); + eth_register(edev); + + return 0; +} + +static void ar231x_eth_remove(struct device_d *dev) +{ + +} + +static struct driver_d ar231x_eth_driver = { + .name = "ar231x_eth", + .probe = ar231x_eth_probe, + .remove = ar231x_eth_remove, +}; + +static int ar231x_eth_driver_init(void) +{ + return platform_driver_register(&ar231x_eth_driver); +} +device_initcall(ar231x_eth_driver_init); diff --git a/drivers/net/ar231x.h b/drivers/net/ar231x.h new file mode 100644 index 0000000000..24684127cc --- /dev/null +++ b/drivers/net/ar231x.h @@ -0,0 +1,219 @@ +/* + * ar231x.h: Linux driver for the Atheros AR231x Ethernet device. + * Based on Linux driver: + * Copyright (C) 2004 by Sameer Dekate <sdekate@arubanetworks.com> + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.de> + * + * Thanks to Atheros for providing hardware and documentation + * enabling me to write this driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 _AR2313_2_H_ +#define _AR2313_2_H_ + +#include <net.h> +#include <mach/ar231x_platform.h> + +/* Allocate 64 RX buffers. This will reduce packet loss, until we will start + * processing them. It is important in noisy network with lots of broadcasts. */ +#define AR2313_RXDSC_ENTRIES 64 +#define DSC_NEXT(idx) (((idx) + 1) & (AR2313_RXDSC_ENTRIES - 1)) + +/* Use system default buffers size. At the moment of writing it was 1518 */ +#define AR2313_RX_BUFSIZE PKTSIZE +#define CRC_LEN 4 + +/** + * DMA controller + */ +#define AR231X_DMA_BUS_MODE 0x00 /* (CSR0) */ +#define AR231X_DMA_TX_POLL 0x04 /* (CSR1) */ +#define AR231X_DMA_RX_POLL 0x08 /* (CSR2) */ +#define AR231X_DMA_RX_RING 0x0c /* (CSR3) */ +#define AR231X_DMA_TX_RING 0x10 /* (CSR4) */ +#define AR231X_DMA_STATUS 0x14 /* (CSR5) */ +#define AR231X_DMA_CONTROL 0x18 /* (CSR6) */ +#define AR231X_DMA_INTR_ENA 0x1c /* (CSR7) */ +#define AR231X_DMA_RX_MISSED 0x20 /* (CSR8) */ +/* reserverd 0x24-0x4c (CSR9-19) */ +#define AR231X_DMA_CUR_TX_BUF_ADDR 0x50 /* (CSR20) */ +#define AR231X_DMA_CUR_RX_BUF_ADDR 0x54 /* (CSR21) */ + +/** + * Ethernet controller + */ +#define AR231X_ETH_MAC_CONTROL 0x00 +#define AR231X_ETH_MAC_ADDR1 0x04 +#define AR231X_ETH_MAC_ADDR2 0x08 +#define AR231X_ETH_MCAST_TABLE1 0x0c +#define AR231X_ETH_MCAST_TABLE2 0x10 +#define AR231X_ETH_MII_ADDR 0x14 +#define AR231X_ETH_MII_DATA 0x18 +#define AR231X_ETH_FLOW_CONTROL 0x1c +#define AR231X_ETH_VLAN_TAG 0x20 +/* pad 0x24 - 0x3c */ +/* ucast_table 0x40-0x5c */ + +/** + * RX descriptor status bits. ar231x_descr.status + */ +#define DMA_RX_ERR_CRC BIT(1) +#define DMA_RX_ERR_DRIB BIT(2) +#define DMA_RX_ERR_MII BIT(3) +#define DMA_RX_EV2 BIT(5) +#define DMA_RX_ERR_COL BIT(6) +#define DMA_RX_LONG BIT(7) +#define DMA_RX_LS BIT(8) /* last descriptor */ +#define DMA_RX_FS BIT(9) /* first descriptor */ +#define DMA_RX_MF BIT(10) /* multicast frame */ +#define DMA_RX_ERR_RUNT BIT(11) /* runt frame */ +#define DMA_RX_ERR_LENGTH BIT(12) /* length error */ +#define DMA_RX_ERR_DESC BIT(14) /* descriptor error */ +#define DMA_RX_ERROR BIT(15) /* error summary */ +#define DMA_RX_LEN_MASK 0x3fff0000 +#define DMA_RX_LEN_SHIFT 16 +#define DMA_RX_FILT BIT(30) +#define DMA_RX_OWN BIT(31) /* desc owned by DMA controller */ +#define DMA_RX_FSLS (DMA_RX_LS | DMA_RX_FS) +#define DMA_RX_MASK (DMA_RX_FSLS | DMA_RX_MF | DMA_RX_ERROR) + +/** + * RX descriptor configuration bits. ar231x_descr.devcs + */ +#define DMA_RX1_BSIZE_MASK 0x000007ff +#define DMA_RX1_BSIZE_SHIFT 0 +#define DMA_RX1_CHAINED BIT(24) +#define DMA_RX1_RER BIT(25) + +/** + * TX descriptor status fields. ar231x_descr.status + */ +#define DMA_TX_ERR_UNDER BIT(1) /* underflow error */ +#define DMA_TX_ERR_DEFER BIT(2) /* excessive deferral */ +#define DMA_TX_COL_MASK 0x78 +#define DMA_TX_COL_SHIFT 3 +#define DMA_TX_ERR_HB BIT(7) /* hearbeat failure */ +#define DMA_TX_ERR_COL BIT(8) /* excessive collisions */ +#define DMA_TX_ERR_LATE BIT(9) /* late collision */ +#define DMA_TX_ERR_LINK BIT(10) /* no carrier */ +#define DMA_TX_ERR_LOSS BIT(11) /* loss of carrier */ +#define DMA_TX_ERR_JABBER BIT(14) /* transmit jabber timeout */ +#define DMA_TX_ERROR BIT(15) /* frame aborted */ +#define DMA_TX_OWN BIT(31) /* descr owned by DMA controller */ + +/** + * TX descriptor configuration bits. ar231x_descr.devcs + */ +#define DMA_TX1_BSIZE_MASK 0x000007ff +#define DMA_TX1_BSIZE_SHIFT 0 +#define DMA_TX1_CHAINED BIT(24) /* chained descriptors */ +#define DMA_TX1_TER BIT(25) /* transmit end of ring */ +#define DMA_TX1_FS BIT(29) /* first segment */ +#define DMA_TX1_LS BIT(30) /* last segment */ +#define DMA_TX1_IC BIT(31) /* interrupt on completion */ +#define DMA_TX1_DEFAULT (DMA_TX1_FS | DMA_TX1_LS | DMA_TX1_TER) + +#define MAC_CONTROL_RE BIT(2) /* receive enable */ +#define MAC_CONTROL_TE BIT(3) /* transmit enable */ +#define MAC_CONTROL_DC BIT(5) /* Deferral check */ +#define MAC_CONTROL_ASTP BIT(8) /* Auto pad strip */ +#define MAC_CONTROL_DRTY BIT(10) /* Disable retry */ +#define MAC_CONTROL_DBF BIT(11) /* Disable bcast frames */ +#define MAC_CONTROL_LCC BIT(12) /* late collision ctrl */ +#define MAC_CONTROL_HP BIT(13) /* Hash Perfect filtering */ +#define MAC_CONTROL_HASH BIT(14) /* Unicast hash filtering */ +#define MAC_CONTROL_HO BIT(15) /* Hash only filtering */ +#define MAC_CONTROL_PB BIT(16) /* Pass Bad frames */ +#define MAC_CONTROL_IF BIT(17) /* Inverse filtering */ +#define MAC_CONTROL_PR BIT(18) /* promiscuous mode + * (valid frames only) */ +#define MAC_CONTROL_PM BIT(19) /* pass multicast */ +#define MAC_CONTROL_F BIT(20) /* full-duplex */ +#define MAC_CONTROL_DRO BIT(23) /* Disable Receive Own */ +#define MAC_CONTROL_HBD BIT(28) /* heart-beat disabled (MUST BE SET) */ +#define MAC_CONTROL_BLE BIT(30) /* big endian mode */ +#define MAC_CONTROL_RA BIT(31) /* receive all + * (valid and invalid frames) */ + +#define MII_ADDR_BUSY BIT(0) +#define MII_ADDR_WRITE BIT(1) +#define MII_ADDR_REG_SHIFT 6 +#define MII_ADDR_PHY_SHIFT 11 +#define MII_DATA_SHIFT 0 + +#define FLOW_CONTROL_FCE BIT(1) + +#define DMA_BUS_MODE_SWR BIT(0) /* software reset */ +#define DMA_BUS_MODE_BLE BIT(7) /* big endian mode */ +#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */ +#define DMA_BUS_MODE_DBO BIT(20) /* big-endian descriptors */ + +#define DMA_STATUS_TI BIT(0) /* transmit interrupt */ +#define DMA_STATUS_TPS BIT(1) /* transmit process stopped */ +#define DMA_STATUS_TU BIT(2) /* transmit buffer unavailable */ +#define DMA_STATUS_TJT BIT(3) /* transmit buffer timeout */ +#define DMA_STATUS_UNF BIT(5) /* transmit underflow */ +#define DMA_STATUS_RI BIT(6) /* receive interrupt */ +#define DMA_STATUS_RU BIT(7) /* receive buffer unavailable */ +#define DMA_STATUS_RPS BIT(8) /* receive process stopped */ +#define DMA_STATUS_ETI BIT(10) /* early transmit interrupt */ +#define DMA_STATUS_FBE BIT(13) /* fatal bus interrupt */ +#define DMA_STATUS_ERI BIT(14) /* early receive interrupt */ +#define DMA_STATUS_AIS BIT(15) /* abnormal interrupt summary */ +#define DMA_STATUS_NIS BIT(16) /* normal interrupt summary */ +#define DMA_STATUS_RS_SHIFT 17 /* receive process state */ +#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */ +#define DMA_STATUS_EB_SHIFT 23 /* error bits */ + +#define DMA_CONTROL_SR BIT(1) /* start receive */ +#define DMA_CONTROL_ST BIT(13) /* start transmit */ +#define DMA_CONTROL_SF BIT(21) /* store and forward */ + + +struct ar231x_descr { + u32 status; /* OWN, Device control and status. */ + u32 devcs; /* Packet control bitmap + Length. */ + u32 buffer_ptr; /* Pointer to packet buffer. */ + u32 next_dsc_ptr; /* Pointer to next descriptor in chain. */ +}; + +/** + * Struct private for the Sibyte. + * + * Elements are grouped so variables used by the tx handling goes + * together, and will go into the same cache lines etc. in order to + * avoid cache line contention between the rx and tx handling on SMP. + * + * Frequently accessed variables are put at the beginning of the + * struct to help the compiler generate better/shorter code. + */ +struct ar231x_eth_priv { + struct ar231x_eth_platform_data *cfg; + u8 *mac; + void __iomem *phy_regs; + void __iomem *eth_regs; + void __iomem *dma_regs; + void __iomem *reset_regs; + + struct eth_device edev; + struct mii_bus miibus; + + struct ar231x_descr *tx_ring; + struct ar231x_descr *rx_ring; + struct ar231x_descr *next_rxdsc; + u8 kill_rx_ring; + void *rx_buffer; + + int oldduplex; + void (*reset_bit)(u32 val, enum reset_state state); +}; + +#endif /* _AR2313_H_ */ diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index b0d045a4e9..aa9d9a0798 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -459,6 +459,8 @@ static int cs8900_probe(struct device_d *dev) edev->set_ethaddr = cs8900_set_ethaddr; edev->parent = dev; + dev->info = cs8900_info; + eth_register(edev); return 0; } @@ -466,6 +468,5 @@ static int cs8900_probe(struct device_d *dev) static struct driver_d cs8900_driver = { .name = "cs8900", .probe = cs8900_probe, - .info = cs8900_info, }; device_platform_driver(cs8900_driver); diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 1a85d15b7b..1346c91348 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -707,6 +707,7 @@ static int fec_probe(struct device_d *dev) if (dev->device_node) { ret = fec_probe_dt(dev, fec); + fec->phy_addr = -1; } else if (pdata) { fec->interface = pdata->xcv_type; fec->phy_init = pdata->phy_init; @@ -746,6 +747,9 @@ static void fec_remove(struct device_d *dev) static __maybe_unused struct of_device_id imx_fec_dt_ids[] = { { + .compatible = "fsl,imx25-fec", + .data = FEC_TYPE_IMX27, + }, { .compatible = "fsl,imx27-fec", .data = FEC_TYPE_IMX27, }, { diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 56762e4f63..ffe063e0b7 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -1,6 +1,11 @@ config OFTREE bool +config OFTREE_MEM_GENERIC + depends on OFTREE + depends on PPC || ARM + def_bool y + config DTC bool diff --git a/drivers/of/Makefile b/drivers/of/Makefile index d16a94624d..c81bbec89b 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,4 +1,5 @@ obj-y += base.o fdt.o +obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o obj-$(CONFIG_GPIOLIB) += gpio.o obj-y += partition.o obj-y += of_net.o diff --git a/drivers/of/base.c b/drivers/of/base.c index 8383549821..4241e65b3f 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -145,6 +145,9 @@ static void of_alias_scan(void) INIT_LIST_HEAD(&aliases_lookup); + if (!root_node) + return; + of_aliases = of_find_node_by_path(root_node, "/aliases"); if (!of_aliases) return; @@ -212,6 +215,19 @@ int of_alias_get_id(struct device_node *np, const char *stem) } EXPORT_SYMBOL_GPL(of_alias_get_id); +const char *of_alias_get(struct device_node *np) +{ + struct property *pp; + + list_for_each_entry(pp, &of_aliases->properties, list) { + if (!strcmp(np->full_name, pp->value)) + return pp->name; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(of_alias_get); + u64 of_translate_address(struct device_node *node, const __be32 *in_addr) { struct property *p; @@ -295,21 +311,36 @@ int of_device_is_compatible(const struct device_node *device, } EXPORT_SYMBOL(of_device_is_compatible); +/** + * of_match_node - Tell if an device_node has a matching of_match structure + * @matches: array of of device match structures to search in + * @node: the of device structure to match against + * + * Low level utility function used by device matching. + */ +const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node) +{ + while (matches->compatible) { + if (of_device_is_compatible(node, matches->compatible) == 1) + return matches; + matches++; + } + + return NULL; +} + int of_match(struct device_d *dev, struct driver_d *drv) { - struct of_device_id *id; + const struct of_device_id *id; - id = drv->of_compatible; + id = of_match_node(drv->of_compatible, dev->device_node); + if (!id) + return 1; - while (id->compatible) { - if (of_device_is_compatible(dev->device_node, id->compatible) == 1) { - dev->of_id_entry = id; - return 0; - } - id++; - } + dev->of_id_entry = id; - return 1; + return 0; } EXPORT_SYMBOL(of_match); @@ -625,6 +656,33 @@ int of_property_read_string_index(struct device_node *np, const char *propname, } EXPORT_SYMBOL_GPL(of_property_read_string_index); +/** + * of_modalias_node - Lookup appropriate modalias for a device node + * @node: pointer to a device tree node + * @modalias: Pointer to buffer that modalias value will be copied into + * @len: Length of modalias value + * + * Based on the value of the compatible property, this routine will attempt + * to choose an appropriate modalias value for a particular device tree node. + * It does this by stripping the manufacturer prefix (as delimited by a ',') + * from the first entry in the compatible list property. + * + * This routine returns 0 on success, <0 on failure. + */ +int of_modalias_node(struct device_node *node, char *modalias, int len) +{ + const char *compatible, *p; + int cplen; + + compatible = of_get_property(node, "compatible", &cplen); + if (!compatible || strlen(compatible) > cplen) + return -ENODEV; + p = strchr(compatible, ','); + strlcpy(modalias, p ? p + 1 : compatible, len); + return 0; +} +EXPORT_SYMBOL_GPL(of_modalias_node); + struct device_node *of_get_root_node(void) { return root_node; @@ -663,9 +721,6 @@ void of_print_nodes(struct device_node *node, int indent) if (!node) return; - if (of_node_disabled(node)) - return; - for (i = 0; i < indent; i++) printf("\t"); @@ -810,13 +865,16 @@ static struct device_d *add_of_amba_device(struct device_node *node) return &dev->dev; } -static struct device_d *add_of_platform_device(struct device_node *node) +static struct device_d *add_of_platform_device(struct device_node *node, + struct device_d *parent) { struct device_d *dev; char *name, *at; dev = xzalloc(sizeof(*dev)); + dev->parent = parent; + name = xstrdup(node->name); at = strchr(name, '@'); if (at) { @@ -841,7 +899,8 @@ static struct device_d *add_of_platform_device(struct device_node *node) return dev; } -static struct device_d *add_of_device(struct device_node *node) +static struct device_d *add_of_device(struct device_node *node, + struct device_d *parent) { const struct property *cp; @@ -856,7 +915,7 @@ static struct device_d *add_of_device(struct device_node *node) of_device_is_compatible(node, "arm,primecell") == 1) return add_of_amba_device(node); else - return add_of_platform_device(node); + return add_of_platform_device(node, parent); } EXPORT_SYMBOL(add_of_device); @@ -873,7 +932,6 @@ int of_add_memory(struct device_node *node, bool dump) int na, nc; const __be32 *reg, *endp; int len, r = 0, ret; - static char str[6]; const char *device_type; ret = of_property_read_string(node, "device_type", &device_type); @@ -900,12 +958,7 @@ int of_add_memory(struct device_node *node, bool dump) if (size == 0) continue; - sprintf(str, "ram%d", r); - - barebox_add_memory_bank(str, base, size); - - if (dump) - pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); + of_add_memory_bank(node, dump, r, base, size); r++; } @@ -913,7 +966,8 @@ int of_add_memory(struct device_node *node, bool dump) return 0; } -static int add_of_device_resource(struct device_node *node) +static struct device_d *add_of_device_resource(struct device_node *node, + struct device_d *parent) { u64 address = 0, size; struct resource *res, *resp; @@ -923,13 +977,9 @@ static int add_of_device_resource(struct device_node *node) int na, nc, n_resources; int ret, len, index; - ret = of_add_memory(node, false); - if (ret != -ENXIO) - return ret; - reg = of_get_property(node, "reg", &len); if (!reg) - return -EINVAL; + return add_of_device(node, parent); of_bus_count_cells(node, &na, &nc); @@ -970,7 +1020,8 @@ static int add_of_device_resource(struct device_node *node) for_each_device(dev) { if (!dev->resource) continue; - if (dev->resource->start == address) { + if (dev->resource->start == res->start && + dev->resource->end == res->end) { debug("connecting %s to %s\n", node->name, dev_name(dev)); node->device = dev; dev->device_node = node; @@ -983,14 +1034,12 @@ static int add_of_device_resource(struct device_node *node) node->resource = res; node->num_resource = n_resources; - add_of_device(node); - - return 0; + return add_of_device(node, parent); err_free: free(res); - return ret; + return NULL; } void of_free(struct device_node *node) @@ -1030,17 +1079,23 @@ void of_free(struct device_node *node) of_set_root_node(NULL); } -static void __of_probe(struct device_node *node) +static void __of_probe(struct device_node *node, + const struct of_device_id *matches, + struct device_d *parent) { struct device_node *n; + struct device_d *dev; if (node->device) return; - add_of_device_resource(node); + dev = add_of_device_resource(node, parent); + + if (!of_match_node(matches, node)) + return; list_for_each_entry(n, &node->children, parent_list) - __of_probe(n); + __of_probe(n, matches, dev); } static void __of_parse_phandles(struct device_node *node) @@ -1067,8 +1122,18 @@ const char *of_get_model(void) return of_model; } +const struct of_device_id of_default_bus_match_table[] = { + { + .compatible = "simple-bus", + }, { + /* sentinel */ + } +}; + int of_probe(void) { + struct device_node *memory, *n; + if(!root_node) return -ENODEV; @@ -1076,7 +1141,13 @@ int of_probe(void) of_property_read_string(root_node, "model", &of_model); __of_parse_phandles(root_node); - __of_probe(root_node); + + memory = of_find_node_by_path(root_node, "/memory"); + if (memory) + of_add_memory(memory, false); + + list_for_each_entry(n, &root_node->children, parent_list) + __of_probe(n, of_default_bus_match_table, NULL); return 0; } diff --git a/drivers/of/mem_generic.c b/drivers/of/mem_generic.c new file mode 100644 index 0000000000..9094243c04 --- /dev/null +++ b/drivers/of/mem_generic.c @@ -0,0 +1,15 @@ +#include <common.h> +#include <of.h> +#include <memory.h> + +void of_add_memory_bank(struct device_node *node, bool dump, int r, + u64 base, u64 size) +{ + static char str[6]; + + sprintf(str, "ram%d", r); + barebox_add_memory_bank(str, base, size); + + if (dump) + pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); +} diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e6aee50a5f..0b859b8494 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -25,4 +25,10 @@ config PINCTRL_IMX_IOMUX_V3 help This iomux controller is found on i.MX25,35,51,53,6. +config PINCTRL_TEGRA20 + select PINCTRL + bool "Tegra 20 pinmux" + help + The pinmux controller found on the Tegra 20 line of SoCs. + endmenu diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e9272d0fb0..169ed184c7 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o obj-$(CONFIG_PINCTRL_IMX_IOMUX_V1) += imx-iomux-v1.o obj-$(CONFIG_PINCTRL_IMX_IOMUX_V2) += imx-iomux-v2.o obj-$(CONFIG_PINCTRL_IMX_IOMUX_V3) += imx-iomux-v3.o +obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c index 3ff3c1571d..c867a23703 100644 --- a/drivers/pinctrl/imx-iomux-v3.c +++ b/drivers/pinctrl/imx-iomux-v3.c @@ -177,7 +177,7 @@ static int imx_iomux_v3_probe(struct device_d *dev) iomuxv3_base = dev_request_mem_region(dev, 0); iomuxv3_dev = dev; - if (IS_ENABLED(CONFIG_PINCTRL)) + if (IS_ENABLED(CONFIG_PINCTRL) && dev->device_node) ret = imx_pinctrl_dt(dev, iomuxv3_base); return ret; diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c new file mode 100644 index 0000000000..053981f44c --- /dev/null +++ b/drivers/pinctrl/pinctrl-tegra20.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de> + * + * Partly based on code + * Copyright (C) 2011-2012 NVIDIA Corporation <www.nvidia.com> + * Copyright (C) 2010 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * @file + * @brief Device driver for the Tegra 20 pincontrol hardware module. + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <malloc.h> +#include <pinctrl.h> + +struct pinctrl_tegra20 { + struct { + u32 __iomem *tri; + u32 __iomem *mux; + u32 __iomem *pull; + } regs; + struct pinctrl_device pinctrl; +}; + +struct tegra20_pingroup { + const char *name; + const char *funcs[4]; + s16 trictrl_id; + s16 muxctrl_id; + s16 pullctrl_id; +}; + +#define PG(pg_name, f0, f1, f2, f3, tri, mux, pull) \ + { \ + .name = #pg_name, \ + .funcs = { #f0, #f1, #f2, #f3, }, \ + .trictrl_id = tri, \ + .muxctrl_id = mux, \ + .pullctrl_id = pull \ + } + +static const struct tegra20_pingroup tegra20_groups[] = { + /* name, f0, f1, f2, f3, tri, mux, pull */ + PG(ata, ide, nand, gmi, rsvd4, 0, 12, 0 ), + PG(atb, ide, nand, gmi, sdio4, 1, 8, 1 ), + PG(atc, ide, nand, gmi, sdio4, 2, 11, 2 ), + PG(atd, ide, nand, gmi, sdio4, 3, 10, 3 ), + PG(ate, ide, nand, gmi, rsvd4, 57, 6, 4 ), + PG(cdev1, osc, plla_out, pllm_out1, audio_sync, 4, 33, 32 ), + PG(cdev2, osc, ahb_clk, apb_clk, pllp_out4, 5, 34, 33 ), + PG(crtp, crt, rsvd2, rsvd3, rsvd4, 110, 105, 28 ), + PG(csus, pllc_out1, pllp_out2, pllp_out3, vi_sensor_clk, 6, 35, 60 ), + PG(dap1, dap1, rsvd2, gmi, sdio2, 7, 42, 5 ), + PG(dap2, dap2, twc, rsvd3, gmi, 8, 43, 6 ), + PG(dap3, dap3, rsvd2, rsvd3, rsvd4, 9, 44, 7 ), + PG(dap4, dap4, rsvd2, gmi, rsvd4, 10, 45, 8 ), + PG(ddc, i2c2, rsvd2, rsvd3, rsvd4, 63, 32, 78 ), + PG(dta, rsvd1, sdio2, vi, rsvd4, 11, 26, 9 ), + PG(dtb, rsvd1, rsvd2, vi, spi1, 12, 27, 10 ), + PG(dtc, rsvd1, rsvd2, vi, rsvd4, 13, 29, 11 ), + PG(dtd, rsvd1, sdio2, vi, rsvd4, 14, 30, 12 ), + PG(dte, rsvd1, rsvd2, vi, spi1, 15, 31, 13 ), + PG(dtf, i2c3, rsvd2, vi, rsvd4, 108, 110, 14 ), + PG(gma, uarte, spi3, gmi, sdio4, 28, 16, 74 ), + PG(gmb, ide, nand, gmi, gmi_int, 61, 46, 75 ), + PG(gmc, uartd, spi4, gmi, sflash, 29, 17, 76 ), + PG(gmd, rsvd1, nand, gmi, sflash, 62, 47, 77 ), + PG(gme, rsvd1, dap5, gmi, sdio4, 32, 48, 44 ), + PG(gpu, pwm, uarta, gmi, rsvd4, 16, 50, 26 ), + PG(gpu7, rtck, rsvd2, rsvd3, rsvd4, 107, 109, 19 ), + PG(gpv, pcie, rsvd2, rsvd3, rsvd4, 17, 49, 15 ), + PG(hdint, hdmi, rsvd2, rsvd3, rsvd4, 87, 18, -1 ), + PG(i2cp, i2cp, rsvd2, rsvd3, rsvd4, 18, 36, 17 ), + PG(irrx, uarta, uartb, gmi, spi4, 20, 41, 43 ), + PG(irtx, uarta, uartb, gmi, spi4, 19, 40, 42 ), + PG(kbca, kbc, nand, sdio2, emc_test0_dll, 22, 37, 20 ), + PG(kbcb, kbc, nand, sdio2, mio, 21, 38, 21 ), + PG(kbcc, kbc, nand, trace, emc_test1_dll, 58, 39, 22 ), + PG(kbcd, kbc, nand, sdio2, mio, 106, 108, 23 ), + PG(kbce, kbc, nand, owr, rsvd4, 26, 14, 65 ), + PG(kbcf, kbc, nand, trace, mio, 27, 13, 64 ), + PG(lcsn, displaya, displayb, spi3, rsvd4, 95, 70, -1 ), + PG(ld0, displaya, displayb, xio, rsvd4, 64, 80, -1 ), + PG(ld1, displaya, displayb, xio, rsvd4, 65, 81, -1 ), + PG(ld2, displaya, displayb, xio, rsvd4, 66, 82, -1 ), + PG(ld3, displaya, displayb, xio, rsvd4, 67, 83, -1 ), + PG(ld4, displaya, displayb, xio, rsvd4, 68, 84, -1 ), + PG(ld5, displaya, displayb, xio, rsvd4, 69, 85, -1 ), + PG(ld6, displaya, displayb, xio, rsvd4, 70, 86, -1 ), + PG(ld7, displaya, displayb, xio, rsvd4, 71, 87, -1 ), + PG(ld8, displaya, displayb, xio, rsvd4, 72, 88, -1 ), + PG(ld9, displaya, displayb, xio, rsvd4, 73, 89, -1 ), + PG(ld10, displaya, displayb, xio, rsvd4, 74, 90, -1 ), + PG(ld11, displaya, displayb, xio, rsvd4, 75, 91, -1 ), + PG(ld12, displaya, displayb, xio, rsvd4, 76, 92, -1 ), + PG(ld13, displaya, displayb, xio, rsvd4, 77, 93, -1 ), + PG(ld14, displaya, displayb, xio, rsvd4, 78, 94, -1 ), + PG(ld15, displaya, displayb, xio, rsvd4, 79, 95, -1 ), + PG(ld16, displaya, displayb, xio, rsvd4, 80, 96, -1 ), + PG(ld17, displaya, displayb, rsvd3, rsvd4, 81, 97, -1 ), + PG(ldc, displaya, displayb, rsvd3, rsvd4, 94, 71, -1 ), + PG(ldi, displaya, displayb, rsvd3, rsvd4, 102, 104, -1 ), + PG(lhp0, displaya, displayb, rsvd3, rsvd4, 82, 101, -1 ), + PG(lhp1, displaya, displayb, rsvd3, rsvd4, 83, 98, -1 ), + PG(lhp2, displaya, displayb, rsvd3, rsvd4, 84, 99, -1 ), + PG(lhs, displaya, displayb, xio, rsvd4, 103, 75, -1 ), + PG(lm0, displaya, displayb, spi3, rsvd4, 88, 77, -1 ), + PG(lm1, displaya, displayb, rsvd3, CRT, 89, 78, -1 ), + PG(lpp, displaya, displayb, rsvd3, rsvd4, 104, 103, -1 ), + PG(lpw0, displaya, displayb, spi3, hdmi, 99, 64, -1 ), + PG(lpw1, displaya, displayb, rsvd3, rsvd4, 100, 65, -1 ), + PG(lpw2, displaya, displayb, spi3, hdmi, 101, 66, -1 ), + PG(lsc0, displaya, displayb, xio, rsvd4, 91, 73, -1 ), + PG(lsc1, displaya, displayb, spi3, hdmi, 92, 74, -1 ), + PG(lsck, displaya, displayb, spi3, hdmi, 93, 72, -1 ), + PG(lsda, displaya, displayb, spi3, hdmi, 97, 68, -1 ), + PG(lsdi, displaya, displayb, spi3, rsvd4, 98, 67, -1 ), + PG(lspi, displaya, displayb, xio, hdmi, 96, 69, -1 ), + PG(lvp0, displaya, displayb, rsvd3, rsvd4, 85, 79, -1 ), + PG(lvp1, displaya, displayb, rsvd3, rsvd4, 86, 100, -1 ), + PG(lvs, displaya, displayb, xio, rsvd4, 90, 76, -1 ), + PG(owc, owr, rsvd2, rsvd3, rsvd4, 31, 20, 79 ), + PG(pmc, pwr_on, pwr_intr, rsvd3, rsvd4, 23, 105, -1 ), + PG(pta, i2c2, hdmi, gmi, rsvd4, 24, 107, 18 ), + PG(rm, i2c1, rsvd2, rsvd3, rsvd4, 25, 7, 16 ), + PG(sdb, uarta, pwm, sdio3, spi2, 111, 53, -1 ), + PG(sdc, pwm, twc, sdio3, spi3, 33, 54, 62 ), + PG(sdd, uarta, pwm, sdio3, spi3, 34, 55, 63 ), + PG(sdio1, sdio1, rsvd2, uarte, uarta, 30, 15, 73 ), + PG(slxa, pcie, spi4, sdio3, spi2, 36, 19, 27 ), + PG(slxc, spdif, spi4, sdio3, spi2, 37, 21, 29 ), + PG(slxd, spdif, spi4, sdio3, spi2, 38, 22, 30 ), + PG(slxk, pcie, spi4, sdio3, spi2, 39, 23, 31 ), + PG(spdi, spdif, rsvd2, i2c1, sdio2, 40, 52, 24 ), + PG(spdo, spdif, rsvd2, i2c1, sdio2, 41, 51, 25 ), + PG(spia, spi1, spi2, spi3, gmi, 42, 63, 34 ), + PG(spib, spi1, spi2, spi3, gmi, 43, 62, 35 ), + PG(spic, spi1, spi2, spi3, gmi, 44, 61, 36 ), + PG(spid, spi2, spi1, spi2_alt, gmi, 45, 60, 37 ), + PG(spie, spi2, spi1, spi2_alt, gmi, 46, 59, 38 ), + PG(spif, spi3, spi1, spi2, rsvd4, 47, 58, 39 ), + PG(spig, spi3, spi2, spi2_alt, i2c1, 48, 57, 40 ), + PG(spih, spi3, spi2, spi2_alt, i2c1, 49, 56, 41 ), + PG(uaa, spi3, mipi_hs, uarta, ulpi, 50, 0, 48 ), + PG(uab, spi2, mipi_hs, uarta, ulpi, 51, 1, 49 ), + PG(uac, owr, rsvd2, rsvd3, rsvd4, 52, 2, 50 ), + PG(uad, irda, spdif, uarta, spi4, 53, 3, 51 ), + PG(uca, uartc, rsvd2, gmi, rsvd4, 54, 24, 52 ), + PG(ucb, uartc, pwm, gmi, rsvd4, 55, 25, 53 ), + PG(uda, spi1, rsvd2, uartd, ulpi, 109, 4, 72 ), +}; + +static void pinctrl_tegra20_set_func(struct pinctrl_tegra20 *ctrl, + int muxctrl_id, int func) +{ + u32 __iomem *regaddr = ctrl->regs.mux; + u32 reg; + int maskbit; + + regaddr += muxctrl_id >> 4; + maskbit = (muxctrl_id << 1) & 0x1f; + + reg = readl(regaddr); + reg &= ~(0x3 << maskbit); + reg |= func << maskbit; + writel(reg, regaddr); +} + +static void pinctrl_tegra20_set_pull(struct pinctrl_tegra20 *ctrl, + int pullctrl_id, int pull) +{ + u32 __iomem *regaddr = ctrl->regs.pull; + u32 reg; + int maskbit; + + regaddr += pullctrl_id >> 4; + maskbit = (pullctrl_id << 1) & 0x1f; + + reg = readl(regaddr); + reg &= ~(0x3 << maskbit); + reg |= pull << maskbit; + writel(reg, regaddr); +} + +static void pinctrl_tegra20_set_tristate(struct pinctrl_tegra20 *ctrl, + int trictrl_id, int tristate) +{ + u32 __iomem *regaddr = ctrl->regs.tri; + u32 reg; + int maskbit; + + regaddr += trictrl_id >> 5; + maskbit = trictrl_id & 0x1f; + + reg = readl(regaddr); + reg &= ~(1 << maskbit); + reg |= tristate << maskbit; + writel(reg, regaddr); +} + +static int pinctrl_tegra20_set_state(struct pinctrl_device *pdev, + struct device_node *np) +{ + struct pinctrl_tegra20 *ctrl = + container_of(pdev, struct pinctrl_tegra20, pinctrl); + struct device_node *childnode; + int pull = -1, tri = -1, i, j, k; + const char *pins, *func = NULL; + const struct tegra20_pingroup *group; + + /* + * At first look if the node we are pointed at has children, + * which we may want to visit. + */ + list_for_each_entry(childnode, &np->children, parent_list) + pinctrl_tegra20_set_state(pdev, childnode); + + /* read relevant state from devicetree */ + of_property_read_string(np, "nvidia,function", &func); + of_property_read_u32_array(np, "nvidia,pull", &pull, 1); + of_property_read_u32_array(np, "nvidia,tristate", &tri, 1); + + /* iterate over all pingroups referenced in the dt node */ + for (i = 0; ; i++) { + if (of_property_read_string_index(np, "nvidia,pins", i, &pins)) + break; + + for (j = 0; j < ARRAY_SIZE(tegra20_groups); j++) { + if (!strcmp(pins, tegra20_groups[j].name)) { + group = &tegra20_groups[j]; + break; + } + } + /* if no matching pingroup is found bail out */ + if (j == ARRAY_SIZE(tegra20_groups)) { + dev_warn(ctrl->pinctrl.dev, + "invalid pingroup %s referenced in node %s\n", + pins, np->name); + continue; + } + + if (func) { + for (k = 0; k < 4; k++) { + if (!strcmp(func, group->funcs[k])) + break; + } + if (k < 4) + pinctrl_tegra20_set_func(ctrl, + group->muxctrl_id, k); + else + dev_warn(ctrl->pinctrl.dev, + "invalid function %s for pingroup %s in node %s\n", + func, group->name, np->name); + } + + if (pull >= 0) { + if (group->pullctrl_id >= 0) + pinctrl_tegra20_set_pull(ctrl, + group->pullctrl_id, + pull); + else + dev_warn(ctrl->pinctrl.dev, + "pingroup %s in node %s doesn't support pull configuration\n", + group->name, np->name); + } + + if (tri >= 0) + pinctrl_tegra20_set_tristate(ctrl, + group->trictrl_id, tri); + } + + return 0; +} + +static struct pinctrl_ops pinctrl_tegra20_ops = { + .set_state = pinctrl_tegra20_set_state, +}; + +static int pinctrl_tegra20_probe(struct device_d *dev) +{ + struct pinctrl_tegra20 *ctrl; + int i, ret; + u32 **regs; + + ctrl = xzalloc(sizeof(*ctrl)); + + /* + * Tegra pincontrol is split out into four independent memory ranges: + * tristate control, function mux, pullup/down control, pad control + * (from lowest to highest hardware address). + * We are only interested in the first three for now. + */ + regs = (u32 **)&ctrl->regs; + for (i = 0; i <= 2; i++) { + regs[i] = dev_request_mem_region(dev, i); + if (!regs[i]) { + dev_err(dev, "Could not get iomem region %d\n", i); + return -ENODEV; + } + } + + ctrl->pinctrl.dev = dev; + ctrl->pinctrl.ops = &pinctrl_tegra20_ops; + + ret = pinctrl_register(&ctrl->pinctrl); + if (ret) + free(ctrl); + + return ret; +} + +static __maybe_unused struct of_device_id pinctrl_tegra20_dt_ids[] = { + { + .compatible = "nvidia,tegra20-pinmux", + }, { + /* sentinel */ + } +}; + +static struct driver_d pinctrl_tegra20_driver = { + .name = "pinctrl-tegra20", + .probe = pinctrl_tegra20_probe, + .of_compatible = DRV_OF_COMPAT(pinctrl_tegra20_dt_ids), +}; + +static int pinctrl_tegra20_init(void) +{ + return platform_driver_register(&pinctrl_tegra20_driver); +} +postcore_initcall(pinctrl_tegra20_init); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d58b6646b5..f460a7a690 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -108,9 +108,20 @@ void spi_of_register_slaves(struct spi_master *master, struct device_node *node) struct property *reg; device_node_for_nach_child(node, n) { - chip.name = n->name; + memset(&chip, 0, sizeof(chip)); + chip.name = xstrdup(n->name); chip.bus_num = master->bus_num; - chip.max_speed_hz = 300000; /* FIXME */ + /* Mode (clock phase/polarity/etc.) */ + if (of_find_property(n, "spi-cpha")) + chip.mode |= SPI_CPHA; + if (of_find_property(n, "spi-cpol")) + chip.mode |= SPI_CPOL; + if (of_find_property(n, "spi-cs-high")) + chip.mode |= SPI_CS_HIGH; + if (of_find_property(n, "spi-3wire")) + chip.mode |= SPI_3WIRE; + of_property_read_u32(n, "spi-max-frequency", + &chip.max_speed_hz); reg = of_find_property(n, "reg"); if (!reg) continue; diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 0e00cb7675..a4a8b00966 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -144,7 +144,6 @@ static void fb_info(struct device_d *dev) static struct driver_d fb_driver = { .name = "fb", - .info = fb_info, }; static int fb_match(struct device_d *dev, struct driver_d *drv) @@ -165,6 +164,8 @@ static int fb_probe(struct device_d *dev) dev_set_param(dev, "mode_name", info->mode_list[0].name); } + dev->info = fb_info; + return devfs_create(&info->cdev); } diff --git a/drivers/video/s3c24xx.c b/drivers/video/s3c24xx.c index d641cfaa27..c3e05c6cd7 100644 --- a/drivers/video/s3c24xx.c +++ b/drivers/video/s3c24xx.c @@ -321,7 +321,6 @@ static int s3cfb_activate_var(struct fb_info *fb_info) * Print some information about the current hardware state * @param hw_dev S3C video device */ -#ifdef CONFIG_DRIVER_VIDEO_S3C_VERBOSE static void s3cfb_info(struct device_d *hw_dev) { uint32_t con1, addr1, addr2, addr3; @@ -340,7 +339,6 @@ static void s3cfb_info(struct device_d *hw_dev) printf(" Virtual screen offset size: %u half words\n", GET_OFFSIZE(addr3)); printf(" Virtual screen page width: %u half words\n", GET_PAGE_WIDTH(addr3)); } -#endif /* * There is only one video hardware instance available. @@ -390,6 +388,9 @@ static int s3cfb_probe(struct device_d *hw_dev) fbi.passive_display = pdata->passive_display; fbi.enable = pdata->enable; + if (IS_ENABLED(CONFIG_DRIVER_VIDEO_S3C_VERBOSE)) + hw_dev->info = s3cfb_info; + ret = register_framebuffer(&fbi.info); if (ret != 0) { dev_err(hw_dev, "Failed to register framebuffer\n"); @@ -402,9 +403,6 @@ static int s3cfb_probe(struct device_d *hw_dev) static struct driver_d s3cfb_driver = { .name = "s3c_fb", .probe = s3cfb_probe, -#ifdef CONFIG_DRIVER_VIDEO_S3C_VERBOSE - .info = s3cfb_info, -#endif }; device_platform_driver(s3cfb_driver); diff --git a/drivers/video/stm.c b/drivers/video/stm.c index cefdef2ab5..606e39a253 100644 --- a/drivers/video/stm.c +++ b/drivers/video/stm.c @@ -502,6 +502,8 @@ static int stmfb_probe(struct device_d *hw_dev) else fbi.info.bits_per_pixel = 16; + hw_dev->info = stmfb_info; + ret = register_framebuffer(&fbi.info); if (ret != 0) { dev_err(hw_dev, "Failed to register framebuffer\n"); @@ -514,7 +516,6 @@ static int stmfb_probe(struct device_d *hw_dev) static struct driver_d stmfb_driver = { .name = "stmfb", .probe = stmfb_probe, - .info = stmfb_info, }; device_platform_driver(stmfb_driver); diff --git a/include/block.h b/include/block.h index cfa4cb9ef1..eb31aca4db 100644 --- a/include/block.h +++ b/include/block.h @@ -8,8 +8,6 @@ struct block_device; struct block_device_ops { int (*read)(struct block_device *, void *buf, int block, int num_blocks); int (*write)(struct block_device *, const void *buf, int block, int num_blocks); - int (*read_start)(struct block_device *, void *buf, int block, int num_blocks); - int (*read_done)(struct block_device *); }; struct chunk; @@ -31,4 +29,12 @@ struct block_device { int blockdevice_register(struct block_device *blk); int blockdevice_unregister(struct block_device *blk); +int block_read(struct block_device *blk, void *buf, int block, int num_blocks); +int block_write(struct block_device *blk, void *buf, int block, int num_blocks); + +static inline int block_flush(struct block_device *blk) +{ + return cdev_flush(&blk->cdev); +} + #endif /* __BLOCK_H */ diff --git a/include/driver.h b/include/driver.h index 716f792afe..8b3af4de26 100644 --- a/include/driver.h +++ b/include/driver.h @@ -106,7 +106,14 @@ struct device_d { struct platform_device_id *id_entry; struct device_node *device_node; - struct of_device_id *of_id_entry; + const struct of_device_id *of_id_entry; + + void (*info) (struct device_d *); + /* + * For devices which take longer to probe this is called + * when the driver should actually detect client devices + */ + int (*detect) (struct device_d *); }; /** @brief Describes a driver present in the system */ @@ -124,9 +131,6 @@ struct driver_d { /*! Called if an instance of a device is gone. */ void (*remove)(struct device_d *); - void (*info) (struct device_d *); - void (*shortinfo) (struct device_d *); - struct bus_type *bus; struct platform_device_id *id_table; @@ -153,6 +157,9 @@ int register_device(struct device_d *); */ int device_probe(struct device_d *dev); +/* detect devices attached to this device (cards, disks,...) */ +int device_detect(struct device_d *dev); + /* Unregister a device. This function can fail, e.g. when the device * has children. */ diff --git a/include/environment.h b/include/environment.h index 7bdd213a52..ae1ecf5bd6 100644 --- a/include/environment.h +++ b/include/environment.h @@ -20,6 +20,8 @@ #ifndef _ENVIRONMENT_H_ #define _ENVIRONMENT_H_ +#include <linux/list.h> + /** * Managment of a environment variable */ diff --git a/include/fb.h b/include/fb.h index 23d6c6d025..df4ba8ebe7 100644 --- a/include/fb.h +++ b/include/fb.h @@ -3,6 +3,7 @@ #include <ioctl.h> #include <param.h> +#include <driver.h> #define FB_VISUAL_TRUECOLOR 2 /* True color */ #define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ diff --git a/include/filetype.h b/include/filetype.h index ee777acf99..c73c64aa60 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -1,6 +1,8 @@ #ifndef __FILE_TYPE_H #define __FILE_TYPE_H +#include <linux/string.h> + /* * List of file types we know */ diff --git a/include/globalvar.h b/include/globalvar.h index ddf885f18e..e3098bc403 100644 --- a/include/globalvar.h +++ b/include/globalvar.h @@ -8,7 +8,7 @@ int globalvar_add(const char *name, int (*set)(struct device_d *dev, struct param_d *p, const char *val), const char *(*get)(struct device_d *, struct param_d *p), unsigned long flags); -char *globalvar_get_match(const char *match, const char *seperator); +char *globalvar_get_match(const char *match, const char *separator); void globalvar_set_match(const char *match, const char *val); #else static inline int globalvar_add_simple(const char *name) @@ -24,7 +24,7 @@ static inline int globalvar_add(const char *name, return 0; } -static inline char *globalvar_get_match(const char *match, const char *seperator) +static inline char *globalvar_get_match(const char *match, const char *separator) { return NULL; } diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h index 7b59a5102d..46185ac921 100644 --- a/include/i2c/i2c.h +++ b/include/i2c/i2c.h @@ -16,6 +16,9 @@ #ifndef I2C_I2C_H #define I2C_I2C_H +#include <driver.h> +#include <linux/types.h> + #ifndef DOXYGEN_SHOULD_SKIP_THIS /* @@ -102,6 +105,7 @@ struct i2c_board_info { char type[I2C_NAME_SIZE]; /**< name of device */ unsigned short addr; /**< stored in i2c_client.addr */ void *platform_data; /**< platform data for device */ + struct device_node *of_node; }; /** diff --git a/include/image.h b/include/image.h index 219419b12b..0c8a4b138d 100644 --- a/include/image.h +++ b/include/image.h @@ -89,7 +89,7 @@ #define IH_ARCH IH_ARCH_PPC #elif defined(__ARM__) #define IH_ARCH IH_ARCH_ARM -#elif defined(__I386__) || defined(__x86_64__) +#elif defined(__I386__) || defined(__x86_64__) || defined(__i386__) #define IH_ARCH IH_ARCH_I386 #elif defined(__mips__) #define IH_ARCH IH_ARCH_MIPS diff --git a/include/linux/phy.h b/include/linux/phy.h index 99c96390c7..8e60758ca3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -15,6 +15,7 @@ #ifndef __PHY_H #define __PHY_H +#include <driver.h> #include <linux/list.h> #include <linux/ethtool.h> #include <linux/mii.h> diff --git a/include/mci.h b/include/mci.h index eca48a52f4..bca374a8bf 100644 --- a/include/mci.h +++ b/include/mci.h @@ -185,6 +185,8 @@ /* * EXT_CSD field definitions */ +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) #define EXT_CSD_CMD_SET_NORMAL (1<<0) #define EXT_CSD_CMD_SET_SECURE (1<<1) @@ -283,9 +285,12 @@ struct mci_ios { #define MMC_1_8V_SDR_MODE 4 }; +struct mci; + /** host information */ struct mci_host { struct device_d *hw_dev; /**< the host MCI hardware device */ + struct mci *mci; char *devname; /**< the devicename for the card, defaults to disk%d */ unsigned voltages; unsigned host_caps; /**< Host's interface capabilities, refer MMC_VDD_* */ @@ -306,11 +311,27 @@ struct mci_host { int (*card_write_protected)(struct mci_host *); }; +#define MMC_NUM_BOOT_PARTITION 2 +#define MMC_NUM_GP_PARTITION 4 +#define MMC_NUM_PHY_PARTITION 6 + +struct mci_part { + struct block_device blk; /**< the blockdevice for the card */ + struct mci *mci; + uint64_t size; /* partition size (in bytes) */ + unsigned int part_cfg; /* partition type */ + char *name; + unsigned int area_type; +#define MMC_BLK_DATA_AREA_MAIN (1<<0) +#define MMC_BLK_DATA_AREA_BOOT (1<<1) +#define MMC_BLK_DATA_AREA_GP (1<<2) +#define MMC_BLK_DATA_AREA_RPMB (1<<3) +}; + /** MMC/SD and interface instance information */ struct mci { struct mci_host *host; /**< the host for this card */ - struct block_device blk; /**< the blockdevice for the card */ - struct device_d *mci_dev; /**< the device for our disk (mcix) */ + struct device_d dev; /**< the device for our disk (mcix) */ unsigned version; /** != 0 when a high capacity card is connected (OCR -> OCR_HCS) */ int high_capacity; @@ -330,8 +351,19 @@ struct mci { char *ext_csd; int probe; struct param_d *param_probe; + struct param_d *param_boot; + int bootpart; + + struct mci_part part[MMC_NUM_PHY_PARTITION]; + int nr_parts; + char *cdevname; + + struct mci_part *part_curr; + u8 ext_csd_part_config; }; int mci_register(struct mci_host*); +void mci_of_parse(struct mci_host *host); +int mci_detect_card(struct mci_host *); #endif /* _MCI_H_ */ diff --git a/include/mci/twl6030.h b/include/mci/twl6030.h deleted file mode 100644 index 0ca828c117..0000000000 --- a/include/mci/twl6030.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * TWL6030 header file. - */ - -#ifndef __MCI_TWL6030_H__ -#define __MCI_TWL6030_H__ - -void twl6030_mci_power_init(void); - -#endif diff --git a/include/mfd/mc13xxx.h b/include/mfd/mc13xxx.h index 59042ebee6..cba85890c1 100644 --- a/include/mfd/mc13xxx.h +++ b/include/mfd/mc13xxx.h @@ -12,6 +12,8 @@ #ifndef __MFD_MC13XXX_H #define __MFD_MC13XXX_H +#include <linux/types.h> + #define MC13XXX_REG_IDENTIFICATION 0x07 #define MC13783_REG_INT_STATUS0 0x00 diff --git a/include/net.h b/include/net.h index bb6b8fa281..fa3c05a987 100644 --- a/include/net.h +++ b/include/net.h @@ -19,7 +19,9 @@ #include <stdlib.h> #include <clock.h> #include <led.h> +#include <xfuncs.h> #include <linux/phy.h> +#include <linux/string.h> /* memcpy */ #include <asm/byteorder.h> /* for nton* / ntoh* stuff */ /* How often do we retry to send packages */ @@ -76,8 +78,13 @@ int eth_rx(void); /* Check for received packets */ static inline void eth_register_ethaddr(int ethid, const char *ethaddr) { } +static inline void of_eth_register_ethaddr(struct device_node *node, + const char *ethaddr) +{ +} #else void eth_register_ethaddr(int ethid, const char *ethaddr); +void of_eth_register_ethaddr(struct device_node *node, const char *ethaddr); #endif /* * Ethernet header diff --git a/include/notifier.h b/include/notifier.h index cb2be5f548..c83e28b156 100644 --- a/include/notifier.h +++ b/include/notifier.h @@ -1,6 +1,8 @@ #ifndef __NOTIFIER_H #define __NOTIFIER_H +#include <linux/list.h> + /* * Notifer chains loosely based on the according Linux framework */ diff --git a/include/of.h b/include/of.h index 4dcf37e140..300b7069c0 100644 --- a/include/of.h +++ b/include/of.h @@ -72,6 +72,8 @@ struct fdt_header *fdt_get_tree(void); struct fdt_header *of_get_fixed_tree(struct device_node *node); +int of_modalias_node(struct device_node *node, char *modalias, int len); + #define device_node_for_nach_child(node, child) \ list_for_each_entry(child, &node->children, parent_list) @@ -138,6 +140,7 @@ int of_get_named_gpio(struct device_node *np, struct device_node *of_find_node_by_phandle(phandle phandle); void of_print_property(const void *data, int len); +void of_print_cmdline(struct device_node *root); int of_device_is_compatible(const struct device_node *device, const char *compat); @@ -167,19 +170,25 @@ int of_set_property(struct device_node *node, const char *p, const void *val, in int create); struct device_node *of_create_node(struct device_node *root, const char *path); -struct device_node *of_get_root_node(void); int of_set_root_node(struct device_node *); +const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node); + struct cdev; #ifdef CONFIG_OFTREE int of_parse_partitions(struct cdev *cdev, struct device_node *node); int of_alias_get_id(struct device_node *np, const char *stem); +const char *of_alias_get(struct device_node *np); int of_device_is_stdout_path(struct device_d *dev); const char *of_get_model(void); void *of_flatten_dtb(struct device_node *node); int of_add_memory(struct device_node *node, bool dump); +void of_add_memory_bank(struct device_node *node, bool dump, int r, + u64 base, u64 size); +struct device_node *of_get_root_node(void); #else static inline int of_parse_partitions(struct cdev *cdev, struct device_node *node) @@ -192,6 +201,11 @@ static inline int of_alias_get_id(struct device_node *np, const char *stem) return -ENOENT; } +static inline const char *of_alias_get(struct device_node *np) +{ + return NULL; +} + static inline int of_device_is_stdout_path(struct device_d *dev) { return 0; @@ -211,6 +225,11 @@ static inline int of_add_memory(struct device_node *node, bool dump) { return -EINVAL; } + +static inline struct device_node *of_get_root_node(void) +{ + return NULL; +} #endif #endif /* __OF_H */ diff --git a/include/param.h b/include/param.h index 4af2d09c4c..7830f6f159 100644 --- a/include/param.h +++ b/include/param.h @@ -12,6 +12,7 @@ typedef unsigned long IPaddr_t; struct param_d { const char* (*get)(struct device_d *, struct param_d *param); int (*set)(struct device_d *, struct param_d *param, const char *val); + void (*info)(struct param_d *param); unsigned int flags; char *name; char *value; @@ -40,6 +41,11 @@ struct param_d *dev_add_param_bool(struct device_d *dev, const char *name, int (*get)(struct param_d *p, void *priv), int *value, void *priv); +struct param_d *dev_add_param_enum(struct device_d *dev, const char *name, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, const char **names, int max, void *priv); + struct param_d *dev_add_param_int_ro(struct device_d *dev, const char *name, int value, const char *format); @@ -89,6 +95,15 @@ static inline struct param_d *dev_add_param_int(struct device_d *dev, const char return NULL; } +static inline struct param_d *dev_add_param_enum(struct device_d *dev, const char *name, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, const char **names, int max, void *priv) + +{ + return NULL; +} + static inline struct param_d *dev_add_param_bool(struct device_d *dev, const char *name, int (*set)(struct param_d *p, void *priv), int (*get)(struct param_d *p, void *priv), diff --git a/include/partition.h b/include/partition.h index 8ad7490d85..32570530eb 100644 --- a/include/partition.h +++ b/include/partition.h @@ -1,7 +1,7 @@ #ifndef __PARTITION_H #define __PARTITION_H -struct device_d; +#include <driver.h> struct partition { int num; @@ -18,4 +18,3 @@ struct partition { }; #endif /* __PARTITION_H */ - diff --git a/include/spi/spi.h b/include/spi/spi.h index 3da13e85ec..45fd22ce26 100644 --- a/include/spi/spi.h +++ b/include/spi/spi.h @@ -4,6 +4,7 @@ #ifndef DOXYGEN_SHOULD_SKIP_THIS #include <driver.h> +#include <linux/string.h> struct spi_board_info { char *name; diff --git a/lib/parameter.c b/lib/parameter.c index e47e8b9148..c5c6426bb2 100644 --- a/lib/parameter.c +++ b/lib/parameter.c @@ -299,6 +299,110 @@ struct param_d *dev_add_param_int(struct device_d *dev, const char *name, return &pi->param; } +struct param_enum { + struct param_d param; + int *value; + const char **names; + int num_names; + int (*set)(struct param_d *p, void *priv); + int (*get)(struct param_d *p, void *priv); +}; + +static inline struct param_enum *to_param_enum(struct param_d *p) +{ + return container_of(p, struct param_enum, param); +} + +static int param_enum_set(struct device_d *dev, struct param_d *p, const char *val) +{ + struct param_enum *pe = to_param_enum(p); + int value_save = *pe->value; + int i, ret; + + if (!val) + return -EINVAL; + + for (i = 0; i < pe->num_names; i++) + if (pe->names[i] && !strcmp(val, pe->names[i])) + break; + + if (i == pe->num_names) + return -EINVAL; + + *pe->value = i; + + if (!pe->set) + return 0; + + ret = pe->set(p, p->driver_priv); + if (ret) + *pe->value = value_save; + + return ret; +} + +static const char *param_enum_get(struct device_d *dev, struct param_d *p) +{ + struct param_enum *pe = to_param_enum(p); + int ret; + + if (pe->get) { + ret = pe->get(p, p->driver_priv); + if (ret) + return NULL; + } + + free(p->value); + p->value = strdup(pe->names[*pe->value]); + + return p->value; +} + +static void param_enum_info(struct param_d *p) +{ + struct param_enum *pe = to_param_enum(p); + int i; + + printf(" ("); + + for (i = 0; i < pe->num_names; i++) { + if (!pe->names[i] || !*pe->names[i]) + continue; + printf("\"%s\"%s", pe->names[i], + i == pe->num_names - 1 ? ")" : ", "); + } +} + +struct param_d *dev_add_param_enum(struct device_d *dev, const char *name, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, const char **names, int num_names, void *priv) +{ + struct param_enum *pe; + struct param_d *p; + int ret; + + pe = xzalloc(sizeof(*pe)); + + pe->value = value; + pe->set = set; + pe->get = get; + pe->names = names; + pe->num_names = num_names; + p = &pe->param; + p->driver_priv = priv; + + ret = __dev_add_param(p, dev, name, param_enum_set, param_enum_get, 0); + if (ret) { + free(pe); + return ERR_PTR(ret); + } + + p->info = param_enum_info; + + return &pe->param; +} + /** * dev_add_param_bool - add an boolean parameter to a device * @param dev The device @@ -36,16 +36,34 @@ struct eth_ethaddr { struct list_head list; u8 ethaddr[6]; int ethid; + struct device_node *node; }; static LIST_HEAD(ethaddr_list); -static int eth_get_registered_ethaddr(int ethid, void *buf) +static void register_preset_mac_address(struct eth_device *edev, const char *ethaddr) +{ + unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")]; + + ethaddr_to_string(ethaddr, ethaddr_str); + + if (is_valid_ether_addr(ethaddr)) { + dev_info(&edev->dev, "got preset MAC address: %s\n", ethaddr_str); + dev_set_param(&edev->dev, "ethaddr", ethaddr_str); + } +} + +static int eth_get_registered_ethaddr(struct eth_device *edev, void *buf) { struct eth_ethaddr *addr; + struct device_node *node = NULL; + + if (edev->parent) + node = edev->parent->device_node; list_for_each_entry(addr, ðaddr_list, list) { - if (addr->ethid == ethid) { + if ((node && node == addr->node) || + addr->ethid == edev->dev.id) { memcpy(buf, addr->ethaddr, 6); return 0; } @@ -78,6 +96,38 @@ void eth_register_ethaddr(int ethid, const char *ethaddr) list_add_tail(&addr->list, ðaddr_list); } +static struct eth_device *eth_get_by_node(struct device_node *node) +{ + struct eth_device *edev; + + list_for_each_entry(edev, &netdev_list, list) { + if (!edev->parent) + continue; + if (!edev->parent->device_node) + continue; + if (edev->parent->device_node == node) + return edev; + } + return NULL; +} + +void of_eth_register_ethaddr(struct device_node *node, const char *ethaddr) +{ + struct eth_ethaddr *addr; + struct eth_device *edev; + + edev = eth_get_by_node(node); + if (edev) { + register_preset_mac_address(edev, ethaddr); + return; + } + + addr = xzalloc(sizeof(*addr)); + addr->node = node; + memcpy(addr->ethaddr, ethaddr, 6); + list_add_tail(&addr->list, ðaddr_list); +} + void eth_set_current(struct eth_device *eth) { if (eth_current && eth_current->active) { @@ -225,8 +275,7 @@ static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const ch int eth_register(struct eth_device *edev) { - struct device_d *dev = &edev->dev; - unsigned char ethaddr_str[20]; + struct device_d *dev = &edev->dev; unsigned char ethaddr[6]; int ret, found = 0; @@ -254,7 +303,7 @@ int eth_register(struct eth_device *edev) list_add_tail(&edev->list, &netdev_list); - ret = eth_get_registered_ethaddr(dev->id, ethaddr); + ret = eth_get_registered_ethaddr(edev, ethaddr); if (!ret) found = 1; @@ -264,13 +313,8 @@ int eth_register(struct eth_device *edev) found = 1; } - if (found) { - ethaddr_to_string(ethaddr, ethaddr_str); - if (is_valid_ether_addr(ethaddr)) { - dev_info(dev, "got preset MAC address: %s\n", ethaddr_str); - dev_set_param(dev, "ethaddr", ethaddr_str); - } - } + if (found) + register_preset_mac_address(edev, ethaddr); if (!eth_current) eth_current = edev; diff --git a/scripts/.gitignore b/scripts/.gitignore index bff805ddf8..6518c0f076 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -2,6 +2,8 @@ bareboxenv bin2c gen_netx_image kallsyms +kwbimage +kwboot mk-am35xx-spi-image mkimage mkublheader diff --git a/scripts/Makefile b/scripts/Makefile index f062fc011b..307dc3d1a4 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -8,11 +8,13 @@ hostprogs-$(CONFIG_KALLSYMS) += kallsyms hostprogs-y += bin2c hostprogs-y += mkimage hostprogs-y += bareboxenv +hostprogs-$(CONFIG_ARCH_MVEBU) += kwbimage kwboot hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-am35xx-spi-image hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_mkimage +subdir-$(CONFIG_ARCH_IMX) += imx HOSTLOADLIBES_omap4_usbboot = -lpthread omap4_usbboot-objs := usb_linux.o omap4_usbboot.o diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index bbfd4cd2de..0b56dcc218 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -141,10 +141,10 @@ cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags) ld_flags = $(LDFLAGS) $(EXTRA_LDFLAGS) -dtc_cpp_flags = -Wp,-MD,$(depfile) -nostdinc \ - -I$(srctree)/arch/$(SRCARCH)/dts \ - -I$(srctree)/arch/$(SRCARCH)/include/dts \ - -undef -D__DTS__ +dtc_cpp_flags = -Wp,-MD,$(depfile).pre -nostdinc \ + -I$(srctree)/arch/$(SRCARCH)/dts \ + -I$(srctree)/arch/$(SRCARCH)/dts/include \ + -undef -D__DTS__ # Finds the multi-part object the current object will be linked into modname-multi = $(sort $(foreach m,$(multi-used),\ @@ -212,20 +212,17 @@ $(obj)/%.dtb.S: $(obj)/%.dtb $(call cmd,dt_S_dtb) quiet_cmd_dtc = DTC $@ -cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $< +cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ + $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \ + -i $(srctree)/arch/$(SRCARCH)/dts $(DTC_FLAGS) \ + -d $(depfile).dtc $(dtc-tmp) ; \ + cat $(depfile).pre $(depfile).dtc > $(depfile) $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep,dtc) dtc-tmp = $(subst $(comma),_,$(dot-target).dts) -quiet_cmd_dtc_cpp = DTC+CPP $@ -cmd_dtc_cpp = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ - $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $(dtc-tmp) - -$(obj)/%.dtb: $(src)/%.dtsp FORCE - $(call if_changed_dep,dtc_cpp) - # Bzip2 # --------------------------------------------------------------------------- @@ -308,3 +305,28 @@ quiet_cmd_check_file_size = CHKSIZE $@ echo "$@ size $$size > of the maximum size $$max_size" >&2; \ exit 1 ; \ fi; + +quiet_cmd_imximage__S_dcd= DCD_S $@ +cmd_imximage_S_dcd= \ +( \ + echo '\#include <asm-generic/barebox.lds.h>'; \ + echo '.balign STRUCT_ALIGNMENT'; \ + echo '.global $(subst -,_,$(*F))_start'; \ + echo '$(subst -,_,$(*F))_start:'; \ + echo '.incbin "$<" '; \ + echo '$(subst -,_,$(*F))_end:'; \ + echo '.global $(subst -,_,$(*F))_end'; \ + echo '.balign STRUCT_ALIGNMENT'; \ +) > $@ + +quiet_cmd_dcd = DCD $@ + cmd_dcd = $(objtree)/scripts/imx/imx-image -d -o $@ -c $< + +$(obj)/%.dcd: $(obj)/%.imxcfg FORCE + $(call if_changed,dcd) + +$(obj)/%.S: $(obj)/%.dcd + $(call cmd,imximage_S_dcd) + +quiet_cmd_imx_image = IMX-IMG $@ + cmd_imx_image = $(obj)/scripts/imx/imx-image -b -c $(CFG_$(@F)) -f $< -o $@ diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index ea26b23de0..078fe1d64e 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -138,38 +138,36 @@ static void print_cmdline(void) printf("cmd_%s := %s\n\n", target, cmdline); } -char * str_config = NULL; -int size_config = 0; -int len_config = 0; +struct item { + struct item *next; + unsigned int len; + unsigned int hash; + char name[0]; +}; -/* - * Grow the configuration string to a desired length. - * Usually the first growth is plenty. - */ -static void grow_config(int len) -{ - while (len_config + len > size_config) { - if (size_config == 0) - size_config = 2048; - str_config = realloc(str_config, size_config *= 2); - if (str_config == NULL) - { perror("fixdep:malloc"); exit(1); } - } -} +#define HASHSZ 256 +static struct item *hashtab[HASHSZ]; +static unsigned int strhash(const char *str, unsigned int sz) +{ + /* fnv32 hash */ + unsigned int i, hash = 2166136261U; + for (i = 0; i < sz; i++) + hash = (hash ^ str[i]) * 0x01000193; + return hash; +} /* * Lookup a value in the configuration string. */ -static int is_defined_config(const char * name, int len) +static int is_defined_config(const char *name, int len, unsigned int hash) { - const char * pconfig; - const char * plast = str_config + len_config - len; - for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { - if (pconfig[ -1] == '\n' - && pconfig[len] == '\n' - && !memcmp(pconfig, name, len)) + struct item *aux; + + for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) { + if (aux->hash == hash && aux->len == len && + memcmp(aux->name, name, len) == 0) return 1; } return 0; @@ -178,13 +176,19 @@ static int is_defined_config(const char * name, int len) /* * Add a new value to the configuration string. */ -static void define_config(const char * name, int len) +static void define_config(const char *name, int len, unsigned int hash) { - grow_config(len + 1); + struct item *aux = malloc(sizeof(*aux) + len); - memcpy(str_config+len_config, name, len); - len_config += len; - str_config[len_config++] = '\n'; + if (!aux) { + perror("fixdep:malloc"); + exit(1); + } + memcpy(aux->name, name, len); + aux->len = len; + aux->hash = hash; + aux->next = hashtab[hash % HASHSZ]; + hashtab[hash % HASHSZ] = aux; } /* @@ -192,40 +196,49 @@ static void define_config(const char * name, int len) */ static void clear_config(void) { - len_config = 0; - define_config("", 0); + struct item *aux, *next; + unsigned int i; + + for (i = 0; i < HASHSZ; i++) { + for (aux = hashtab[i]; aux; aux = next) { + next = aux->next; + free(aux); + } + hashtab[i] = NULL; + } } /* * Record the use of a CONFIG_* word. */ -static void use_config(char *m, int slen) +static void use_config(const char *m, int slen) { - char s[PATH_MAX]; - char *p; + unsigned int hash = strhash(m, slen); + int c, i; - if (is_defined_config(m, slen)) + if (is_defined_config(m, slen, hash)) return; - define_config(m, slen); - - memcpy(s, m, slen); s[slen] = 0; + define_config(m, slen, hash); - for (p = s; p < s + slen; p++) { - if (*p == '_') - *p = '/'; + printf(" $(wildcard include/config/"); + for (i = 0; i < slen; i++) { + c = m[i]; + if (c == '_') + c = '/'; else - *p = tolower((int)*p); + c = tolower(c); + putchar(c); } - printf(" $(wildcard include/config/%s.h) \\\n", s); + printf(".h) \\\n"); } -static void parse_config_file(char *map, size_t len) +static void parse_config_file(const char *map, size_t len) { - int *end = (int *) (map + len); + const int *end = (const int *) (map + len); /* start at +1, so that p can never be < map */ - int *m = (int *) map + 1; - char *p, *q; + const int *m = (const int *) map + 1; + const char *p, *q; for (; m < end; m++) { if (*m == INT_CONF) { p = (char *) m ; goto conf; } @@ -265,7 +278,7 @@ static int strrcmp(char *s, char *sub) return memcmp(s + slen - sublen, sub, sublen); } -static void do_config_file(char *filename) +static void do_config_file(const char *filename) { struct stat st; int fd; @@ -273,7 +286,7 @@ static void do_config_file(char *filename) fd = open(filename, O_RDONLY); if (fd < 0) { - fprintf(stderr, "fixdep: "); + fprintf(stderr, "fixdep: error opening config file: "); perror(filename); exit(2); } @@ -296,42 +309,89 @@ static void do_config_file(char *filename) close(fd); } +/* + * Important: The below generated source_foo.o and deps_foo.o variable + * assignments are parsed not only by make, but also by the rather simple + * parser in scripts/mod/sumversion.c. + */ static void parse_dep_file(void *map, size_t len) { char *m = map; char *end = m + len; char *p; char s[PATH_MAX]; - - p = strchr(m, ':'); - if (!p) { - fprintf(stderr, "fixdep: parse error\n"); - exit(1); - } - memcpy(s, m, p-m); s[p-m] = 0; - printf("deps_%s := \\\n", target); - m = p+1; + int is_target; + int saw_any_target = 0; + int is_first_dep = 0; clear_config(); while (m < end) { + /* Skip any "white space" */ while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) m++; + /* Find next "white space" */ p = m; - while (p < end && *p != ' ') p++; - if (p == end) { - do p--; while (!isalnum(*p)); + while (p < end && *p != ' ' && *p != '\\' && *p != '\n') p++; + /* Is the token we found a target name? */ + is_target = (*(p-1) == ':'); + /* Don't write any target names into the dependency file */ + if (is_target) { + /* The /next/ file is the first dependency */ + is_first_dep = 1; + } else { + /* Save this token/filename */ + memcpy(s, m, p-m); + s[p - m] = 0; + + /* Ignore certain dependencies */ + if (strrcmp(s, "include/generated/autoconf.h") && + strrcmp(s, "arch/um/include/uml-config.h") && + strrcmp(s, "include/linux/kconfig.h") && + strrcmp(s, ".ver")) { + /* + * Do not list the source file as dependency, + * so that kbuild is not confused if a .c file + * is rewritten into .S or vice versa. Storing + * it in source_* is needed for modpost to + * compute srcversions. + */ + if (is_first_dep) { + /* + * If processing the concatenation of + * multiple dependency files, only + * process the first target name, which + * will be the original source name, + * and ignore any other target names, + * which will be intermediate temporary + * files. + */ + if (!saw_any_target) { + saw_any_target = 1; + printf("source_%s := %s\n\n", + target, s); + printf("deps_%s := \\\n", + target); + } + is_first_dep = 0; + } else + printf(" %s \\\n", s); + do_config_file(s); + } } - memcpy(s, m, p-m); s[p-m] = 0; - if (strrcmp(s, "include/generated/autoconf.h") && - strrcmp(s, "arch/um/include/uml-config.h") && - strrcmp(s, ".ver")) { - printf(" %s \\\n", s); - do_config_file(s); - } + /* + * Start searching for next token immediately after the first + * "whitespace" character that follows this token. + */ m = p + 1; } + + if (!saw_any_target) { + fprintf(stderr, "fixdep: parse error; no targets found\n"); + exit(1); + } + printf("\n%s: $(deps_%s)\n\n", target, target); printf("$(deps_%s):\n", target); } @@ -344,11 +404,15 @@ static void print_deps(void) fd = open(depfile, O_RDONLY); if (fd < 0) { - fprintf(stderr, "fixdep: "); + fprintf(stderr, "fixdep: error opening depfile: "); perror(depfile); exit(2); } - fstat(fd, &st); + if (fstat(fd, &st) < 0) { + fprintf(stderr, "fixdep: error fstat'ing depfile: "); + perror(depfile); + exit(2); + } if (st.st_size == 0) { fprintf(stderr,"fixdep: %s is empty\n",depfile); close(fd); @@ -374,7 +438,7 @@ static void traps(void) int *p = (int *)test; if (*p != INT_CONF) { - fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n", + fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianness? %#x\n", *p); exit(2); } diff --git a/scripts/imx/.gitignore b/scripts/imx/.gitignore new file mode 100644 index 0000000000..84e6f2b406 --- /dev/null +++ b/scripts/imx/.gitignore @@ -0,0 +1,2 @@ +imx-usb-loader +imx-image diff --git a/scripts/imx/Makefile b/scripts/imx/Makefile new file mode 100644 index 0000000000..be0b490108 --- /dev/null +++ b/scripts/imx/Makefile @@ -0,0 +1,10 @@ +hostprogs-$(CONFIG_ARCH_IMX_IMXIMAGE) += imx-image +hostprogs-$(CONFIG_ARCH_IMX_USBLOADER) += imx-usb-loader + +always := $(hostprogs-y) + +HOSTCFLAGS_imx-usb-loader.o = `pkg-config --cflags libusb-1.0` +HOSTLOADLIBES_imx-usb-loader = `pkg-config --libs libusb-1.0` + +imx-usb-loader-objs := imx-usb-loader.o +imx-image-objs := imx-image.o diff --git a/scripts/imx/README b/scripts/imx/README new file mode 100644 index 0000000000..0d6d0d03a8 --- /dev/null +++ b/scripts/imx/README @@ -0,0 +1,89 @@ +imx-usb-loader Tools + +The Freescale i.MX SoCs support bootstrapping from USB. These are host +side utilities handling this bootstrap process. + +The imx-usb-loader tool is used to upload and start i.MX images. These +are images containing a DCD (Device Configuration Data) table. To generate +these images from raw binaries use the imx-image tool. + +imx-image +--------- + +The imx-image tool can be used to generate imximages from raw binaries. +It requires an configuration file describing how to setup the SDRAM on +a particular board. This mainly consists of a poke table. The recognized +options in this file are: + +soc <soctype> soctype can be one of imx35, imx51, imx53, imx6 +loadaddr <adr> The address the binary is uploaded to +dcdofs <ofs> The offset of the image header in the image. This should be: + 0x400 - MMC/SD, NAND, serial ROM, PATA, SATA + 0x1000 - NOR Flash + 0x100 - OneNAND +wm 8 <adr> <value> do a byte memory write +wm 16 <adr> <value> do a short memory write +wm 32 <adr> <value> do a word memory write +check <width> <cond> <addr> <mask> Poll until condition becomes true. + with <cond> being one of: + while_all_bits_clear, + while_all_bits_set, + while_any_bit_clear, + while_any_bit_set + +the i.MX SoCs support a wide range of fancy things doing with the flash header. +We limit ourselves to a very simple case, that is the flash header has a fixed +size of 0x1000 bytes. The application is expected right thereafter, so if you +specify a loadaddr of 0x80000000 in the config file, the first 0x1000 bytes +are occupied by the flash header. The raw image inside the imximage will then +end up at 0x80001000 from where it is then executed. + +Example config file, suitable for an Eukra cpuimx35: + +soc imx35 +dcdofs 0x400 +loadaddr 0x80000000 +wm 32 0x53F80004 0x00821000 +wm 32 0x53F80004 0x00821000 +wm 32 0xb8001010 0x00000004 +wm 32 0xB8001010 0x0000000C +wm 32 0xb8001004 0x0009572B +wm 32 0xb8001000 0x92220000 +wm 8 0x80000400 0xda +wm 32 0xb8001000 0xa2220000 +wm 32 0x80000000 0x12344321 +wm 32 0x80000000 0x12344321 +wm 32 0xb8001000 0xb2220000 +wm 8 0x80000033 0xda +wm 8 0x82000000 0xda +wm 32 0xb8001000 0x82224080 +wm 32 0xb8001010 0x00000004 + +example call: + +imx-image -c cpuimx35.cfg -f raw.bin -o imximage.bin + +imx-usb-loader +-------------- + +This utility is used to upload an imximage to a board. Some bootloaders directly +generate this file format, with others you can generate such an image with the +imx-image tool. The only required argument is the image file to upload. imx-usb-loader +will then look for a supported device, upload the file and execute it. + +example usage: + +imx-usb-loader imximage.bin + +Some technical notes: The i.MX SoCs USB ROM boot mode supports doing register writes +and file uploads. The files are usually uploaded to SDRAM. For this to work the SDRAM +has to be initialized first. The information necessary to do this is contained in the +imximage itself, more exactly in the DCD table. The imx-usb-loader parses this table +and translates the DCD into register writes, basically it resembles what the i.MX would +do in ROM code when the same image would be loaded from another bootsource like SD/MMC +cards. Still the i.MX needs the DCD table to be uploaded. The i.MX would execute the DCD +data again, which would result in corrupting the just configured SDRAM. The imx-usb-loader +prevents this by setting the DCD length to 0x0 before uploading the image. +The i.MX Boot ROM supports different types of images to upload. The imx-usb-loader currently +only handles the simple case of uploading a single image which is executed right after +downloading. diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c new file mode 100644 index 0000000000..2f52015ae1 --- /dev/null +++ b/scripts/imx/imx-image.c @@ -0,0 +1,744 @@ +/* + * (C) Copyright 2013 Sascha Hauer, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT 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 <stdio.h> +#include <unistd.h> +#include <getopt.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <endian.h> + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) + +#define MAX_DCD 1024 + +static uint32_t image_load_addr; +static uint32_t image_dcd_offset; +static uint32_t dcdtable[MAX_DCD]; +static int curdcd; +static int header_version; +static int add_barebox_header; + +/* + * ============================================================================ + * i.MX flash header v1 handling. Found on i.MX35 and i.MX51 + * ============================================================================ + */ +struct imx_flash_header { + uint32_t app_code_jump_vector; + uint32_t app_code_barker; + uint32_t app_code_csf; + uint32_t dcd_ptr_ptr; + uint32_t super_root_key; + uint32_t dcd; + uint32_t app_dest; + uint32_t dcd_barker; + uint32_t dcd_block_len; +} __attribute__((packed)); + +#define FLASH_HEADER_OFFSET 0x400 +#define DCD_BARKER 0xb17219e9 + +static uint32_t bb_header[] = { + 0xea0003fe, /* b 0x1000 */ + 0xeafffffe, /* 1: b 1b */ + 0xeafffffe, /* 1: b 1b */ + 0xeafffffe, /* 1: b 1b */ + 0xeafffffe, /* 1: b 1b */ + 0xeafffffe, /* 1: b 1b */ + 0xeafffffe, /* 1: b 1b */ + 0xeafffffe, /* 1: b 1b */ + 0x65726162, /* 'bare' */ + 0x00786f62, /* 'box\0' */ + 0x00000000, + 0x00000000, + 0x55555555, + 0x55555555, + 0x55555555, + 0x55555555, + 0x55555555, + 0x55555555, + 0x55555555, + 0x55555555, +}; + +static int add_header_v1(void *buf, int offset, uint32_t loadaddr, uint32_t imagesize) +{ + struct imx_flash_header *hdr; + int dcdsize = curdcd * sizeof(uint32_t); + + if (add_barebox_header) + memcpy(buf, bb_header, sizeof(bb_header)); + + buf += offset; + hdr = buf; + + hdr->app_code_jump_vector = loadaddr + 0x1000; + hdr->app_code_barker = 0x000000b1; + hdr->app_code_csf = 0x0; + hdr->dcd_ptr_ptr = loadaddr + offset + offsetof(struct imx_flash_header, dcd); + hdr->super_root_key = 0x0; + hdr->dcd = loadaddr + offset + offsetof(struct imx_flash_header, dcd_barker); + hdr->app_dest = loadaddr; + hdr->dcd_barker = DCD_BARKER; + hdr->dcd_block_len = dcdsize; + + buf += sizeof(struct imx_flash_header); + + memcpy(buf, dcdtable, dcdsize); + + buf += dcdsize; + + *(uint32_t *)buf = imagesize; + + return 0; +} + +static int write_mem_v1(uint32_t addr, uint32_t val, int width) +{ + if (curdcd > MAX_DCD - 3) { + fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD); + return -ENOMEM; + } + + dcdtable[curdcd++] = width; + dcdtable[curdcd++] = addr; + dcdtable[curdcd++] = val; + + return 0; +} + +/* + * ============================================================================ + * i.MX flash header v2 handling. Found on i.MX53 and i.MX6 + * ============================================================================ + */ + +struct imx_boot_data { + uint32_t start; + uint32_t size; + uint32_t plugin; +} __attribute__((packed)); + +#define TAG_IVT_HEADER 0xd1 +#define IVT_VERSION 0x40 +#define TAG_DCD_HEADER 0xd2 +#define DCD_VERSION 0x40 +#define TAG_WRITE 0xcc +#define TAG_CHECK 0xcf + +struct imx_ivt_header { + uint8_t tag; + uint16_t length; + uint8_t version; +} __attribute__((packed)); + +struct imx_flash_header_v2 { + struct imx_ivt_header header; + + uint32_t entry; + uint32_t reserved1; + uint32_t dcd_ptr; + uint32_t boot_data_ptr; + uint32_t self; + uint32_t csf; + uint32_t reserved2; + + struct imx_boot_data boot_data; + struct imx_ivt_header dcd_header; +} __attribute__((packed)); + +static int add_header_v2(void *buf, int offset, uint32_t loadaddr, uint32_t imagesize) +{ + struct imx_flash_header_v2 *hdr; + int dcdsize = curdcd * sizeof(uint32_t); + + if (add_barebox_header) + memcpy(buf, bb_header, sizeof(bb_header)); + + buf += offset; + hdr = buf; + + hdr->header.tag = TAG_IVT_HEADER; + hdr->header.length = htobe16(32); + hdr->header.version = IVT_VERSION; + + hdr->entry = loadaddr + 0x1000; + hdr->dcd_ptr = loadaddr + 0x400 + offsetof(struct imx_flash_header_v2, dcd_header); + hdr->boot_data_ptr = loadaddr + 0x400 + offsetof(struct imx_flash_header_v2, boot_data); + hdr->self = loadaddr + 0x400; + + hdr->boot_data.start = loadaddr; + hdr->boot_data.size = imagesize; + + hdr->dcd_header.tag = TAG_DCD_HEADER; + hdr->dcd_header.length = htobe16(sizeof(uint32_t) + dcdsize); + hdr->dcd_header.version = DCD_VERSION; + + buf += sizeof(*hdr); + + memcpy(buf, dcdtable, dcdsize); + + return 0; +} + +static void usage(const char *prgname) +{ + fprintf(stderr, "usage: %s [OPTIONS]\n\n" + "-c <config> specify configuration file\n" + "-f <input> input image file\n" + "-o <output> output file\n" + "-b add barebox header to image. If used, barebox recognizes\n" + " the image as regular barebox image which can be used as\n" + " second stage image\n" + "-h this help\n", prgname); + exit(1); +} + +#define MAXARGS 5 + +static int parse_line(char *line, char *argv[]) +{ + int nargs = 0; + + while (nargs < MAXARGS) { + + /* skip any white space */ + while ((*line == ' ') || (*line == '\t')) + ++line; + + if (*line == '\0') /* end of line, no more args */ + argv[nargs] = NULL; + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = NULL; + return nargs; + } + + argv[nargs++] = line; /* begin of argument string */ + + /* find end of string */ + while (*line && (*line != ' ') && (*line != '\t')) + ++line; + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = NULL; + return nargs; + } + + *line++ = '\0'; /* terminate current arg */ + } + + printf("** Too many args (max. %d) **\n", MAXARGS); + + return nargs; +} + +struct command { + const char *name; + int (*parse)(int argc, char *argv[]); +}; + +static uint32_t last_cmd; +static int last_cmd_len; +static uint32_t *last_dcd; + +static void check_last_dcd(uint32_t cmd) +{ + if (last_dcd) { + if (last_cmd == cmd) { + return; + } else { + uint32_t l = be32toh(*last_dcd); + + l |= last_cmd_len << 8; + + *last_dcd = htobe32(l); + + last_dcd = NULL; + } + } + + if (!cmd) + return; + + if (!last_dcd) { + last_dcd = &dcdtable[curdcd++]; + *last_dcd = htobe32(cmd); + last_cmd_len = sizeof(uint32_t); + last_cmd = cmd; + } +} + +static int write_mem_v2(uint32_t addr, uint32_t val, int width) +{ + uint32_t cmd; + + cmd = (TAG_WRITE << 24) | width; + + if (curdcd > MAX_DCD - 3) { + fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD); + return -ENOMEM; + } + + check_last_dcd(cmd); + + last_cmd_len += sizeof(uint32_t) * 2; + dcdtable[curdcd++] = htobe32(addr); + dcdtable[curdcd++] = htobe32(val); + + return 0; +} + +static const char *check_cmds[] = { + "while_all_bits_clear", /* while ((*address & mask) == 0); */ + "while_all_bits_set" , /* while ((*address & mask) == mask); */ + "while_any_bit_clear", /* while ((*address & mask) != mask); */ + "while_any_bit_set", /* while ((*address & mask) != 0); */ +}; + +static void do_cmd_check_usage(void) +{ + fprintf(stderr, + "usage: check <width> <cmd> <addr> <mask>\n" + "<width> access width in bytes [1|2|4]\n" + "with <cmd> one of:\n" + "while_all_bits_clear: while ((*addr & mask) == 0)\n" + "while_all_bits_set: while ((*addr & mask) == mask)\n" + "while_any_bit_clear: while ((*addr & mask) != mask)\n" + "while_any_bit_set: while ((*addr & mask) != 0)\n"); +} + +static int do_cmd_check(int argc, char *argv[]) +{ + uint32_t addr, mask, cmd; + int i, width; + const char *scmd; + + if (argc < 5) { + do_cmd_check_usage(); + return -EINVAL; + } + + width = strtoul(argv[1], NULL, 0) >> 3; + scmd = argv[2]; + addr = strtoul(argv[3], NULL, 0); + mask = strtoul(argv[4], NULL, 0); + + switch (width) { + case 1: + case 2: + case 4: + break; + default: + fprintf(stderr, "illegal width %d\n", width); + return -EINVAL; + }; + + if (curdcd > MAX_DCD - 3) { + fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD); + return -ENOMEM; + } + + for (i = 0; i < ARRAY_SIZE(check_cmds); i++) { + if (!strcmp(scmd, check_cmds[i])) + break; + } + + if (i == ARRAY_SIZE(check_cmds)) { + do_cmd_check_usage(); + return -EINVAL; + } + + cmd = (TAG_CHECK << 24) | (i << 3) | width; + + check_last_dcd(cmd); + + last_cmd_len += sizeof(uint32_t) * 2; + dcdtable[curdcd++] = htobe32(addr); + dcdtable[curdcd++] = htobe32(mask); + + return 0; +} + +static int do_cmd_write_mem(int argc, char *argv[]) +{ + uint32_t addr, val, width; + + if (argc != 4) { + fprintf(stderr, "usage: wm [8|16|32] <addr> <val>\n"); + return -EINVAL; + } + + width = strtoul(argv[1], NULL, 0); + addr = strtoul(argv[2], NULL, 0); + val = strtoul(argv[3], NULL, 0); + + width >>= 3; + + switch (width) { + case 1: + case 2: + case 4: + break; + default: + fprintf(stderr, "illegal width %d\n", width); + return -EINVAL; + }; + + switch (header_version) { + case 1: + return write_mem_v1(addr, val, width); + case 2: + return write_mem_v2(addr, val, width); + default: + return -EINVAL; + } +} + +static int do_loadaddr(int argc, char *argv[]) +{ + if (argc < 2) + return -EINVAL; + + image_load_addr = strtoul(argv[1], NULL, 0); + + return 0; +} + +static int do_dcd_offset(int argc, char *argv[]) +{ + if (argc < 2) + return -EINVAL; + + image_dcd_offset = strtoul(argv[1], NULL, 0); + + return 0; +} + +struct soc_type { + char *name; + int header_version; +}; + +static struct soc_type socs[] = { + { .name = "imx35", .header_version = 1, }, + { .name = "imx51", .header_version = 1, }, + { .name = "imx53", .header_version = 2, }, + { .name = "imx6", .header_version = 2, }, +}; + +static int do_soc(int argc, char *argv[]) +{ + char *soc; + int i; + + if (argc < 2) + return -EINVAL; + + soc = argv[1]; + + for (i = 0; i < ARRAY_SIZE(socs); i++) { + if (!strcmp(socs[i].name, soc)) { + header_version = socs[i].header_version; + return 0; + } + } + + fprintf(stderr, "unkown SoC type \"%s\". Known SoCs are:\n", soc); + for (i = 0; i < ARRAY_SIZE(socs); i++) + fprintf(stderr, "%s ", socs[i].name); + fprintf(stderr, "\n"); + + return -EINVAL; +} + +struct command cmds[] = { + { + .name = "wm", + .parse = do_cmd_write_mem, + }, { + .name = "check", + .parse = do_cmd_check, + }, { + .name = "loadaddr", + .parse = do_loadaddr, + }, { + .name = "dcdofs", + .parse = do_dcd_offset, + }, { + .name = "soc", + .parse = do_soc, + }, +}; + +static int parse_config(const char *filename) +{ + FILE *f; + int lineno = 0; + char *line = NULL, *tmp; + size_t len; + char *argv[MAXARGS]; + int nargs, i, ret; + + f = fopen(filename, "r"); + if (!f) { + fprintf(stderr, "Error: %s - Can't open DCD file\n", filename); + exit(1); + } + + while ((getline(&line, &len, f)) > 0) { + lineno++; + + tmp = strchr(line, '#'); + if (tmp) + *tmp = 0; + tmp = strrchr(line, '\n'); + if (tmp) + *tmp = 0; + + nargs = parse_line(line, argv); + if (!nargs) + continue; + + ret = -ENOENT; + + for (i = 0; i < ARRAY_SIZE(cmds); i++) { + if (!strcmp(cmds[i].name, argv[0])) { + ret = cmds[i].parse(nargs, argv); + if (ret) { + fprintf(stderr, "error in line %d: %s\n", + lineno, strerror(-ret)); + return ret; + } + break; + } + } + + if (ret == -ENOENT) { + fprintf(stderr, "no such command: %s\n", argv[0]); + return ret; + } + } + + return 0; +} + +static int xread(int fd, void *buf, int len) +{ + int ret; + + while (len) { + ret = read(fd, buf, len); + if (ret < 0) + return ret; + if (!ret) + return EOF; + buf += ret; + len -= ret; + } + + return 0; +} + +static int xwrite(int fd, void *buf, int len) +{ + int ret; + + while (len) { + ret = write(fd, buf, len); + if (ret < 0) + return ret; + buf += ret; + len -= ret; + } + + return 0; +} + +static int write_dcd(const char *outfile) +{ + int outfd, ret; + int dcdsize = curdcd * sizeof(uint32_t); + + outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (outfd < 0) { + perror("open"); + exit(1); + } + + ret = xwrite(outfd, dcdtable, dcdsize); + if (ret < 0) { + perror("write"); + exit(1); + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int opt, ret; + char *configfile = NULL; + char *imagename = NULL; + char *outfile = NULL; + void *buf; + size_t image_size = 0; + struct stat s; + int infd, outfd; + int dcd_only = 0; + + while ((opt = getopt(argc, argv, "c:hf:o:bd")) != -1) { + switch (opt) { + case 'c': + configfile = optarg; + break; + case 'f': + imagename = optarg; + break; + case 'o': + outfile = optarg; + break; + case 'b': + add_barebox_header = 1; + break; + case 'd': + dcd_only = 1; + break; + case 'h': + usage(argv[0]); + default: + exit(1); + } + } + + if (!imagename && !dcd_only) { + fprintf(stderr, "image name not given\n"); + exit(1); + } + + if (!configfile) { + fprintf(stderr, "config file not given\n"); + exit(1); + } + + if (!outfile) { + fprintf(stderr, "output file not given\n"); + exit(1); + } + + if (!dcd_only) { + ret = stat(imagename, &s); + if (ret) { + perror("stat"); + exit(1); + } + + image_size = s.st_size; + } + + ret = parse_config(configfile); + if (ret) + exit(1); + + buf = calloc(4096, 1); + if (!buf) + exit(1); + + if (!image_dcd_offset) { + fprintf(stderr, "no dcd offset given ('dcdofs'). Defaulting to 0x400\n"); + image_dcd_offset = 0x400; + } + + if (!header_version) { + fprintf(stderr, "no SoC given. (missing 'soc' in config)\n"); + exit(1); + } + + if (header_version == 2) + check_last_dcd(0); + + if (dcd_only) { + ret = write_dcd(outfile); + if (ret) + exit(1); + exit (0); + } + + switch (header_version) { + case 1: + add_header_v1(buf, image_dcd_offset, image_load_addr, image_size + 0x1000); + break; + case 2: + add_header_v2(buf, image_dcd_offset, image_load_addr, image_size + 0x1000); + break; + default: + fprintf(stderr, "Congratulations! You're welcome to implement header version %d\n", + header_version); + exit(1); + } + + outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (outfd < 0) { + perror("open"); + exit(1); + } + + ret = xwrite(outfd, buf, 4096); + if (ret < 0) { + perror("write"); + exit(1); + } + + infd = open(imagename, O_RDONLY); + if (infd < 0) { + perror("open"); + exit(1); + } + + while (image_size) { + int now = image_size < 4096 ? image_size : 4096; + + ret = xread(infd, buf, now); + if (ret) { + perror("read"); + exit(1); + } + + ret = xwrite(outfd, buf, now); + if (ret) { + perror("write"); + exit(1); + } + + image_size -= now; + } + + ret = close(outfd); + if (ret) { + perror("close"); + exit(1); + } + + exit(0); +} diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c new file mode 100644 index 0000000000..d58b1da3bd --- /dev/null +++ b/scripts/imx/imx-usb-loader.c @@ -0,0 +1,1427 @@ +/* + * imx_usb: + * + * Program to download and execute an image over the USB boot protocol + * on i.MX series processors. + * + * Code originally written by Eric Nelson. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <stdio.h> +#include <sys/types.h> +#include <time.h> + +#include <unistd.h> +#include <ctype.h> +#include <sys/io.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <libusb.h> +#include <getopt.h> + +#define get_min(a, b) (((a) < (b)) ? (a) : (b)) + +int verbose; + +struct mach_id { + struct mach_id * next; + unsigned short vid; + unsigned short pid; + char file_name[256]; + char *name; +#define MODE_HID 0 +#define MODE_BULK 1 + unsigned char mode; +#define HDR_NONE 0 +#define HDR_MX51 1 +#define HDR_MX53 2 + unsigned char header_type; + unsigned short max_transfer; +}; + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#ifndef offsetof +#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) +#endif + +struct usb_work { + char filename[256]; + unsigned char dcd; + unsigned char clear_dcd; + unsigned char plug; +#define J_ADDR 1 +#define J_HEADER 2 +#define J_HEADER2 3 + unsigned char jump_mode; + unsigned jump_addr; +}; + +struct usb_id { + struct mach_id *mach_id; + struct usb_work *work; +}; + +struct mach_id imx_ids[] = { + { + .vid = 0x066f, + .pid = 0x3780, + .name = "i.MX23", + .mode = MODE_BULK, + }, { + .vid = 0x15a2, + .pid = 0x004f, + .name = "i.MX28", + }, { + .vid = 0x15a2, + .pid = 0x0052, + .name = "i.MX50", + }, { + .vid = 0x15a2, + .pid = 0x0054, + .name = "i.MX6", + .header_type = HDR_MX53, + .mode = MODE_HID, + .max_transfer = 1024, + }, { + .vid = 0x15a2, + .pid = 0x0041, + .name = "i.MX51", + .header_type = HDR_MX51, + .mode = MODE_BULK, + .max_transfer = 64, + }, { + .vid = 0x15a2, + .pid = 0x004e, + .name = "i.MX53", + .header_type = HDR_MX53, + .mode = MODE_BULK, + .max_transfer = 512, + }, { + .vid = 0x15a2, + .pid = 0x0030, + .name = "i.MX35", + .header_type = HDR_MX51, + .mode = MODE_BULK, + .max_transfer = 64, + }, +}; + +static struct mach_id *imx_device(unsigned short vid, unsigned short pid) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx_ids); i++) { + struct mach_id *id = &imx_ids[i]; + if (id->vid == vid && id->pid == pid) { + fprintf(stderr, "found %s USB device [%04x:%04x]\n", + id->name, vid, pid); + return id; + } + } + + return NULL; +} + +static libusb_device *find_imx_dev(libusb_device **devs, struct mach_id **pp_id) +{ + int i = 0; + struct mach_id *p; + + for (;;) { + struct libusb_device_descriptor desc; + int r; + + libusb_device *dev = devs[i++]; + if (!dev) + break; + + r = libusb_get_device_descriptor(dev, &desc); + if (r < 0) { + fprintf(stderr, "failed to get device descriptor"); + return NULL; + } + + p = imx_device(desc.idVendor, desc.idProduct); + if (p) { + *pp_id = p; + return dev; + } + } + *pp_id = NULL; + + return NULL; +} + +static void dump_long(unsigned char *src, unsigned cnt, unsigned addr) +{ + unsigned *p = (unsigned *)src; + while (cnt >= 32) { + printf("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + addr, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + p += 8; + cnt -= 32; + addr += 32; + } + if (cnt) { + printf("%08x:", addr); + while (cnt >= 4) { + printf(" %08x", p[0]); + p++; + cnt -= 4; + } + printf("\n"); + } +} + +static void dump_bytes(unsigned char *src, unsigned cnt, unsigned addr) +{ + unsigned char *p = src; + int i; + + while (cnt >= 16) { + printf("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + addr, + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], + p[11], p[12], p[13], p[14], p[15]); + p += 16; + cnt -= 16; + addr += 16; + } + + if (cnt) { + printf("%08x:", addr); + i = 0; + while (cnt) { + printf(" %02x", p[0]); + p++; + cnt--; + i++; + if (cnt) if (i == 4) { + i = 0; + printf(" "); + } + } + printf("\n"); + } +} + +static long get_file_size(FILE *xfile) +{ + long size; + fseek(xfile, 0, SEEK_END); + size = ftell(xfile); + rewind(xfile); + + return size; +} + +/* + * HID Class-Specific Requests values. See section 7.2 of the HID specifications + */ +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#define HID_REPORT_TYPE_INPUT 0x01 +#define HID_REPORT_TYPE_OUTPUT 0x02 +#define HID_REPORT_TYPE_FEATURE 0x03 +#define CTRL_IN LIBUSB_ENDPOINT_IN |LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE +#define CTRL_OUT LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE + +#define EP_IN 0x80 + +/* + * For HID class drivers, 4 reports are used to implement + * Serial Download protocol(SDP) + * Report 1 (control out endpoint) 16 byte SDP comand + * (total of 17 bytes with 1st byte report id of 0x01 + * Report 2 (control out endpoint) data associated with report 1 commands + * (max size of 1025 with 1st byte of 0x02) + * Report 3 (interrupt in endpoint) HAB security state + * (max size of 5 bytes with 1st byte of 0x03) + * (0x12343412 production) + * (0x56787856 engineering) + * Report 4 (interrupt in endpoint) date associated with report 1 commands + * (max size of 65 bytes with 1st byte of 0x04) + * + */ +/* + * For Bulk class drivers, the device is configured as + * EP0IN, EP0OUT control transfer + * EP1OUT - bulk out + * (max packet size of 512 bytes) + * EP2IN - bulk in + * (max packet size of 512 bytes) + */ +static int transfer(struct libusb_device_handle *h, int report, unsigned char *p, unsigned cnt, + int* last_trans, struct usb_id *p_id) +{ + int err; + if (cnt > p_id->mach_id->max_transfer) + cnt = p_id->mach_id->max_transfer; + + if (verbose > 4) { + printf("report=%i\n", report); + if (report < 3) + dump_bytes(p, cnt, 0); + } + + if (p_id->mach_id->mode == MODE_BULK) { + *last_trans = 0; + err = libusb_bulk_transfer(h, (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000); + } else { + unsigned char tmp[1028]; + + tmp[0] = (unsigned char)report; + + if (report < 3) { + memcpy(&tmp[1], p, cnt); + err = libusb_control_transfer(h, + CTRL_OUT, + HID_SET_REPORT, + (HID_REPORT_TYPE_OUTPUT << 8) | report, + 0, + tmp, cnt + 1, 1000); + *last_trans = (err > 0) ? err - 1 : 0; + if (err > 0) + err = 0; + } else { + *last_trans = 0; + memset(&tmp[1], 0, cnt); + err = libusb_interrupt_transfer(h, 1 + EP_IN, tmp, cnt + 1, last_trans, 1000); + if (err >= 0) { + if (tmp[0] == (unsigned char)report) { + if (*last_trans > 1) { + *last_trans -= 1; + memcpy(p, &tmp[1], *last_trans); + } + } else { + printf("Unexpected report %i err=%i, cnt=%i, last_trans=%i, %02x %02x %02x %02x\n", + tmp[0], err, cnt, *last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + err = 0; + } + } + } + } + + if (verbose > 4 && report >= 3) + dump_bytes(p, cnt, 0); + + return err; +} + +int do_status(libusb_device_handle *h, struct usb_id *p_id) +{ + int last_trans; + unsigned char tmp[64]; + int retry = 0; + int err; + const unsigned char status_command[] = { + 5, 5, 0, 0, 0, 0, + 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0 + }; + + for (;;) { + err = transfer(h, 1, (unsigned char*)status_command, 16, &last_trans, p_id); + + if (verbose > 2) + printf("report 1, wrote %i bytes, err=%i\n", last_trans, err); + + memset(tmp, 0, sizeof(tmp)); + + err = transfer(h, 3, tmp, 64, &last_trans, p_id); + + if (verbose > 2) { + printf("report 3, read %i bytes, err=%i\n", last_trans, err); + printf("read=%02x %02x %02x %02x\n", tmp[0], tmp[1], tmp[2], tmp[3]); + } + + if (!err) + break; + + retry++; + + if (retry > 5) + break; + } + + if (p_id->mach_id->mode == MODE_HID) { + err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id); + if (err) + printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + } + + return err; +} + +struct boot_data { + uint32_t dest; + uint32_t image_len; + uint32_t plugin; +}; + +struct imx_flash_header_v2 { +#define IVT_BARKER 0x402000d1 + uint32_t barker; + uint32_t start_addr; + uint32_t reserv1; + uint32_t dcd_ptr; + uint32_t boot_data_ptr; /* struct boot_data * */ + uint32_t self_ptr; /* struct imx_flash_header_v2 *, this - boot_data.start = offset linked at */ + uint32_t app_code_csf; + uint32_t reserv2; +}; + +/* + * MX51 header type + */ +struct imx_flash_header_v1 { + uint32_t app_start_addr; +#define APP_BARKER 0xb1 +#define DCD_BARKER 0xb17219e9 + uint32_t app_barker; + uint32_t csf_ptr; + uint32_t dcd_ptr_ptr; + uint32_t srk_ptr; + uint32_t dcd_ptr; + uint32_t app_dest_ptr; +}; + +#define V(a) (((a) >> 24) & 0xff), (((a) >> 16) & 0xff), (((a) >> 8) & 0xff), ((a) & 0xff) + +static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id, + unsigned addr, unsigned char *dest, unsigned cnt) +{ + static unsigned char read_reg_command[] = { + 1, + 1, + V(0), /* address */ + 0x20, /* format */ + V(0x00000004), /* data count */ + V(0), /* data */ + 0x00, /* type */ + }; + + int retry = 0; + int last_trans; + int err; + int rem; + unsigned char tmp[64]; + read_reg_command[2] = (unsigned char)(addr >> 24); + read_reg_command[3] = (unsigned char)(addr >> 16); + read_reg_command[4] = (unsigned char)(addr >> 8); + read_reg_command[5] = (unsigned char)(addr); + + read_reg_command[7] = (unsigned char)(cnt >> 24); + read_reg_command[8] = (unsigned char)(cnt >> 16); + read_reg_command[9] = (unsigned char)(cnt >> 8); + read_reg_command[10] = (unsigned char)(cnt); + + for (;;) { + err = transfer(h, 1, read_reg_command, 16, &last_trans, p_id); + if (!err) + break; + printf("read_reg_command err=%i, last_trans=%i\n", err, last_trans); + if (retry > 5) { + return -4; + } + retry++; + } + + err = transfer(h, 3, tmp, 4, &last_trans, p_id); + if (err) { + printf("r3 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + return err; + } + + rem = cnt; + + while (rem) { + tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; + err = transfer(h, 4, tmp, 64, &last_trans, p_id); + if (err) { + printf("r4 in err=%i, last_trans=%i %02x %02x %02x %02x cnt=%d rem=%d\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem); + break; + } + if ((last_trans > rem) || (last_trans > 64)) { + if ((last_trans == 64) && (cnt == rem)) { + /* Last transfer is expected to be too large for HID */ + } else { + printf("err: %02x %02x %02x %02x cnt=%d rem=%d last_trans=%i\n", + tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem, last_trans); + } + last_trans = rem; + if (last_trans > 64) + last_trans = 64; + } + memcpy(dest, tmp, last_trans); + dest += last_trans; + rem -= last_trans; + } + return err; +} + +static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id, + unsigned addr, unsigned val, int width) +{ + int retry = 0; + int last_trans; + int err = 0; + unsigned char tmp[64]; + unsigned char ds; + unsigned char write_reg_command[] = { + 2, + 2, + V(0), /* address */ + 0x0, /* format */ + V(0x00000004), /* data count */ + V(0), /* data */ + 0x00, /* type */ + }; + write_reg_command[2] = (unsigned char)(addr >> 24); + write_reg_command[3] = (unsigned char)(addr >> 16); + write_reg_command[4] = (unsigned char)(addr >> 8); + write_reg_command[5] = (unsigned char)(addr); + + switch (width) { + case 1: + ds = 0x8; + break; + case 2: + ds = 0x10; + break; + case 4: + ds = 0x20; + break; + default: + return -1; + } + + write_reg_command[6] = ds; + + write_reg_command[11] = (unsigned char)(val >> 24); + write_reg_command[12] = (unsigned char)(val >> 16); + write_reg_command[13] = (unsigned char)(val >> 8); + write_reg_command[14] = (unsigned char)(val); + + for (;;) { + err = transfer(h, 1, write_reg_command, 16, &last_trans, p_id); + if (!err) + break; + printf("write_reg_command err=%i, last_trans=%i\n", err, last_trans); + if (retry > 5) { + return -4; + } + retry++; + } + + memset(tmp, 0, sizeof(tmp)); + + err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id); + if (err) { + printf("w3 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + printf("addr=0x%08x, val=0x%08x\n", addr, val); + } + + memset(tmp, 0, sizeof(tmp)); + + err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id); + if (err) + printf("w4 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + return err; +} + +static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_id, + struct imx_flash_header_v2 *hdr, unsigned char *file_start, unsigned cnt) +{ + unsigned char *dcd_end; + unsigned m_length; +#define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self_ptr) + unsigned char* dcd; + unsigned char* file_end = file_start + cnt; + int err = 0; + + if (!hdr->dcd_ptr) { + printf("No dcd table, barker=%x\n", hdr->barker); + return 0; /* nothing to do */ + } + + dcd = hdr->dcd_ptr + cvt_dest_to_src; + + if ((dcd < file_start) || ((dcd + 4) > file_end)) { + printf("bad dcd_ptr %08x\n", hdr->dcd_ptr); + return -1; + } + + m_length = (dcd[1] << 8) + dcd[2]; + + printf("main dcd length %x\n", m_length); + + if ((dcd[0] != 0xd2) || (dcd[3] != 0x40)) { + printf("Unknown tag\n"); + return -1; + } + + dcd_end = dcd + m_length; + + if (dcd_end > file_end) { + printf("bad dcd length %08x\n", m_length); + return -1; + } + dcd += 4; + + while (dcd < dcd_end) { + unsigned s_length = (dcd[1] << 8) + dcd[2]; + unsigned char *s_end = dcd + s_length; + + printf("sub dcd length %x\n", s_length); + + if ((dcd[0] != 0xcc) || (dcd[3] != 0x04)) { + printf("Unknown sub tag\n"); + return -1; + } + dcd += 4; + + if (s_end > dcd_end) { + printf("error s_end(%p) > dcd_end(%p)\n", s_end, dcd_end); + return -1; + } + + while (dcd < s_end) { + unsigned addr = (dcd[0] << 24) | (dcd[1] << 16) | (dcd[2] << 8) | dcd[3]; + unsigned val = (dcd[4] << 24) | (dcd[5] << 16) | (dcd[6] << 8) | dcd[7]; + + dcd += 8; + err = write_memory(h, p_id, addr, val, 4); + if (err < 0) + return err; + } + } + return err; +} + +static int get_dcd_range_old(struct imx_flash_header_v1 *hdr, + unsigned char *file_start, unsigned cnt, + unsigned char **pstart, unsigned char **pend) +{ + unsigned char *dcd_end; + unsigned m_length; +#define cvt_dest_to_src_old (((unsigned char *)&hdr->dcd_ptr) - hdr->dcd_ptr_ptr) + unsigned char* dcd; + unsigned val; + unsigned char* file_end = file_start + cnt; + + if (!hdr->dcd_ptr) { + printf("No dcd table, barker=%x\n", hdr->app_barker); + *pstart = *pend = ((unsigned char *)hdr) + sizeof(struct imx_flash_header_v1); + return 0; /* nothing to do */ + } + + dcd = hdr->dcd_ptr + cvt_dest_to_src_old; + + if ((dcd < file_start) || ((dcd + 8) > file_end)) { + printf("bad dcd_ptr %08x\n", hdr->dcd_ptr); + return -1; + } + + val = (dcd[0] << 0) | (dcd[1] << 8) | (dcd[2] << 16) | (dcd[3] << 24); + + if (val != DCD_BARKER) { + printf("Unknown tag\n"); + return -1; + } + + dcd += 4; + m_length = (dcd[0] << 0) | (dcd[1] << 8) | (dcd[2] << 16) | (dcd[3] << 24); + dcd += 4; + dcd_end = dcd + m_length; + + if (dcd_end > file_end) { + printf("bad dcd length %08x\n", m_length); + return -1; + } + + *pstart = dcd; + *pend = dcd_end; + + return 0; +} + +static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_id, + struct imx_flash_header_v1 *hdr, unsigned char *file_start, unsigned cnt) +{ + unsigned val; + unsigned char *dcd_end; + unsigned char* dcd; + int err = get_dcd_range_old(hdr, file_start, cnt, &dcd, &dcd_end); + if (err < 0) + return err; + + printf("writing DCD table...\n"); + + while (dcd < dcd_end) { + unsigned type = (dcd[0] << 0) | (dcd[1] << 8) | (dcd[2] << 16) | (dcd[3] << 24); + unsigned addr = (dcd[4] << 0) | (dcd[5] << 8) | (dcd[6] << 16) | (dcd[7] << 24); + val = (dcd[8] << 0) | (dcd[9] << 8) | (dcd[10] << 16) | (dcd[11] << 24); + dcd += 12; + + switch (type) { + case 1: + if (verbose > 1) + printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val); + err = write_memory(h, p_id, addr, val, 1); + if (err < 0) + return err; + break; + case 4: + if (verbose > 1) + printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val); + err = write_memory(h, p_id, addr, val, 4); + if (err < 0) + return err; + break; + default: + printf("!!!unknown type=%08x *0x%08x = 0x%08x\n", type, addr, val); + } + } + + if (err) + fprintf(stderr, "writing DCD table failed with %d\n", err); + else + printf("DCD table successfully written\n"); + + return err; +} + +static int verify_memory(struct libusb_device_handle *h, struct usb_id *p_id, + FILE *xfile, unsigned offset, unsigned addr, unsigned size, + unsigned char *verify_buffer, unsigned verify_cnt) +{ + int mismatch = 0; + unsigned char file_buf[1024]; + fseek(xfile, offset + verify_cnt, SEEK_SET); + + while (size) { + unsigned char mem_buf[64]; + unsigned char *p = file_buf; + int cnt = addr & 0x3f; + int request = get_min(size, sizeof(file_buf)); + + if (cnt) { + cnt = 64 - cnt; + if (request > cnt) + request = cnt; + } + + if (verify_cnt) { + p = verify_buffer; + cnt = get_min(request, verify_cnt); + verify_buffer += cnt; + verify_cnt -= cnt; + } else { + cnt = fread(p, 1, request, xfile); + if (cnt <= 0) { + printf("Unexpected end of file, request=0x%0x, size=0x%x, cnt=%i\n", + request, size, cnt); + return -1; + } + } + + size -= cnt; + + while (cnt) { + int ret; + + request = get_min(cnt, sizeof(mem_buf)); + + ret = read_memory(h, p_id, addr, mem_buf, request); + if (ret < 0) + return ret; + + if (memcmp(p, mem_buf, request)) { + unsigned char * m = mem_buf; + if (!mismatch) + printf("!!!!mismatch\n"); + mismatch++; + + while (request) { + unsigned req = get_min(request, 32); + if (memcmp(p, m, req)) { + dump_long(p, req, offset); + dump_long(m, req, addr); + printf("\n"); + } + p += req; + m+= req; + offset += req; + addr += req; + cnt -= req; + request -= req; + } + if (mismatch >= 5) + return -1; + } + p += request; + offset += request; + addr += request; + cnt -= request; + } + } + + return mismatch ? -1 : 0; +} + +static int is_header(struct usb_id *p_id, unsigned char *p) +{ + struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p; + struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p; + + switch (p_id->mach_id->header_type) { + case HDR_MX51: + if (ohdr->app_barker == 0xb1) + return 1; + break; + case HDR_MX53: + if (hdr->barker == IVT_BARKER) + return 1; + } + + return 0; +} + +static int perform_dcd(struct libusb_device_handle *h, struct usb_id *p_id, unsigned char *p, + unsigned char *file_start, unsigned cnt) +{ + struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p; + struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p; + int ret = 0; + + switch (p_id->mach_id->header_type) { + case HDR_MX51: + ret = write_dcd_table_old(h, p_id, ohdr, file_start, cnt); + ohdr->dcd_ptr = 0; + + break; + case HDR_MX53: + ret = write_dcd_table_ivt(h, p_id, hdr, file_start, cnt); + hdr->dcd_ptr = 0; + + break; + } + + return ret; +} + +static int clear_dcd_ptr(struct libusb_device_handle *h, struct usb_id *p_id, + unsigned char *p, unsigned char *file_start, unsigned cnt) +{ + struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p; + struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p; + + switch (p_id->mach_id->header_type) { + case HDR_MX51: + printf("clear dcd_ptr=0x%08x\n", ohdr->dcd_ptr); + ohdr->dcd_ptr = 0; + break; + case HDR_MX53: + printf("clear dcd_ptr=0x%08x\n", hdr->dcd_ptr); + hdr->dcd_ptr = 0; + break; + } + return 0; +} + +static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *file_start, + unsigned cnt, unsigned *dladdr, unsigned *max_length, unsigned *plugin, + unsigned *header_addr) +{ + unsigned char* file_end = file_start + cnt; + switch (p_id->mach_id->header_type) { + case HDR_MX51: + { + struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p; + unsigned char *dcd_end; + unsigned char* dcd; + int err = get_dcd_range_old(ohdr, file_start, cnt, &dcd, &dcd_end); + + *dladdr = ohdr->app_dest_ptr; + *header_addr = ohdr->dcd_ptr_ptr - offsetof(struct imx_flash_header_v1, dcd_ptr); + *plugin = 0; + if (err >= 0) + *max_length = dcd_end[0] | (dcd_end[1] << 8) | (dcd_end[2] << 16) | (dcd_end[3] << 24); + + break; + } + case HDR_MX53: + { + unsigned char *bd; + struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p; + + *dladdr = hdr->self_ptr; + *header_addr = hdr->self_ptr; + bd = hdr->boot_data_ptr + cvt_dest_to_src; + if ((bd < file_start) || ((bd + 4) > file_end)) { + printf("bad boot_data_ptr %08x\n", hdr->boot_data_ptr); + return -1; + } + + *dladdr = ((struct boot_data *)bd)->dest; + *max_length = ((struct boot_data *)bd)->image_len; + *plugin = ((struct boot_data *)bd)->plugin; + ((struct boot_data *)bd)->plugin = 0; + + hdr->boot_data_ptr = 0; + + break; + } + } + return 0; +} + +static int process_header(struct libusb_device_handle *h, struct usb_id *p_id, + struct usb_work *curr, unsigned char *buf, int cnt, + unsigned *p_dladdr, unsigned *p_max_length, unsigned *p_plugin, + unsigned *p_header_addr) +{ + int ret; + unsigned header_max = 0x800; + unsigned header_inc = 0x400; + unsigned header_offset = 0; + int header_cnt = 0; + unsigned char *p = buf; + + for (header_offset = 0; header_offset < header_max; header_offset += header_inc, p += header_inc) { + + if (!is_header(p_id, p)) + continue; + + ret = get_dl_start(p_id, p, buf, cnt, p_dladdr, p_max_length, p_plugin, p_header_addr); + if (ret < 0) { + printf("!!get_dl_start returned %i\n", ret); + return ret; + } + + if (curr->dcd) { + ret = perform_dcd(h, p_id, p, buf, cnt); + if (ret < 0) { + printf("!!perform_dcd returned %i\n", ret); + return ret; + } + curr->dcd = 0; + if ((!curr->jump_mode) && (!curr->plug)) { + printf("!!dcd done, nothing else requested\n"); + return 0; + } + } + + if (curr->clear_dcd) { + ret = clear_dcd_ptr(h, p_id, p, buf, cnt); + if (ret < 0) { + printf("!!clear_dcd returned %i\n", ret); + return ret; + } + } + + if (*p_plugin && (!curr->plug) && (!header_cnt)) { + header_cnt++; + header_max = header_offset + *p_max_length + 0x400; + if (header_max > cnt - 32) + header_max = cnt - 32; + printf("header_max=%x\n", header_max); + header_inc = 4; + } else { + if (!*p_plugin) + curr->plug = 0; + return header_offset; + } + } + + fprintf(stderr, "no DCD header found in image, run imx-image first\n"); + + return -ENODEV; +} + +static int load_file(struct libusb_device_handle *h, struct usb_id *p_id, + unsigned char *p, int cnt, unsigned char *buf, unsigned buf_cnt, + unsigned dladdr, unsigned fsize, unsigned char type, FILE* xfile) +{ + static unsigned char dl_command[] = { + 0x04, + 0x04, + V(0), /* address */ + 0x00, /* format */ + V(0x00000020), /* data count */ + V(0), /* data */ + 0xaa, /* type */ + }; + int last_trans, err; + int retry = 0; + unsigned transfer_size = 0; + int max = p_id->mach_id->max_transfer; + unsigned char tmp[64]; + + dl_command[2] = (unsigned char)(dladdr >> 24); + dl_command[3] = (unsigned char)(dladdr >> 16); + dl_command[4] = (unsigned char)(dladdr >> 8); + dl_command[5] = (unsigned char)(dladdr); + + dl_command[7] = (unsigned char)(fsize >> 24); + dl_command[8] = (unsigned char)(fsize >> 16); + dl_command[9] = (unsigned char)(fsize >> 8); + dl_command[10] = (unsigned char)(fsize); + dl_command[15] = type; + + for (;;) { + err = transfer(h, 1, dl_command, 16, &last_trans, p_id); + if (!err) + break; + + printf("dl_command err=%i, last_trans=%i\n", err, last_trans); + + if (retry > 5) + return -4; + retry++; + } + + retry = 0; + + if (p_id->mach_id->mode == MODE_BULK) { + err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id); + if (err) + printf("in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + } + + while (1) { + int retry; + + if (cnt > (int)(fsize - transfer_size)) + cnt = (fsize - transfer_size); + + if (cnt <= 0) + break; + + retry = 0; + + while (cnt) { + err = transfer(h, 2, p, get_min(cnt, max), &last_trans, p_id); + if (err) { + printf("out err=%i, last_trans=%i cnt=0x%x max=0x%x transfer_size=0x%X retry=%i\n", + err, last_trans, cnt, max, transfer_size, retry); + if (retry >= 10) { + printf("Giving up\n"); + return err; + } + if (max >= 16) + max >>= 1; + else + max <<= 1; + usleep(10000); + retry++; + continue; + } + max = p_id->mach_id->max_transfer; + retry = 0; + if (cnt < last_trans) { + printf("error: last_trans=0x%x, attempted only=0%x\n", last_trans, cnt); + cnt = last_trans; + } + if (!last_trans) { + printf("Nothing last_trans, err=%i\n", err); + break; + } + p += last_trans; + cnt -= last_trans; + transfer_size += last_trans; + } + + if (!last_trans) + break; + + if (feof(xfile)) + break; + + cnt = fsize - transfer_size; + if (cnt <= 0) + break; + + cnt = fread(buf, 1 , get_min(cnt, buf_cnt), xfile); + p = buf; + } + + if (p_id->mach_id->mode == MODE_HID) { + err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id); + if (err) + printf("3 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id); + if (err) + printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + } else { + do_status(h, p_id); + } + + return transfer_size; +} + +#define FT_APP 0xaa +#define FT_CSF 0xcc +#define FT_DCD 0xee +#define FT_LOAD_ONLY 0x00 + +static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id, + struct usb_work *curr, int verify) +{ + static unsigned char jump_command[] = {0x0b,0x0b, V(0), 0x00, V(0x00000000), V(0), 0x00}; + + int ret; + FILE* xfile; + unsigned char type; + unsigned fsize; + unsigned header_offset; + int cnt; + unsigned file_base; + int last_trans, err; +#define BUF_SIZE (1024*16) + unsigned char *buf = NULL; + unsigned char *verify_buffer = NULL; + unsigned verify_cnt; + unsigned char *p; + unsigned char tmp[64]; + unsigned dladdr = 0; + unsigned max_length; + unsigned plugin = 0; + unsigned header_addr = 0; + + unsigned skip = 0; + unsigned transfer_size=0; + int retry = 0; + + xfile = fopen(curr->filename, "rb" ); + if (!xfile) { + printf("error, can not open input file: %s\n", curr->filename); + return -5; + } + + buf = malloc(BUF_SIZE); + if (!buf) { + printf("error, out of memory\n"); + ret = -2; + goto cleanup; + } + + fsize = get_file_size(xfile); + + cnt = fread(buf, 1 , BUF_SIZE, xfile); + + if (cnt < 0x20) { + printf("error, file: %s is too small\n", curr->filename); + ret = -2; + goto cleanup; + } + + max_length = fsize; + + ret = process_header(h, p_id, curr, buf, cnt, + &dladdr, &max_length, &plugin, &header_addr); + if (ret < 0) + goto cleanup; + + header_offset = ret; + + if ((!curr->jump_mode) && (!curr->plug)) { + /* nothing else requested */ + ret = 0; + goto cleanup; + } + + if (plugin && (!curr->plug)) { + printf("Only plugin header found\n"); + ret = -1; + goto cleanup; + } + + if (!dladdr) { + printf("unknown load address\n"); + ret = -3; + goto cleanup; + } + + file_base = header_addr - header_offset; + + type = (curr->plug || curr->jump_mode) ? FT_APP : FT_LOAD_ONLY; + + if (p_id->mach_id->mode == MODE_BULK && type == FT_APP) { + /* No jump command, dladdr should point to header */ + dladdr = header_addr; + } + + if (file_base > dladdr) { + max_length -= (file_base - dladdr); + dladdr = file_base; + } + + skip = dladdr - file_base; + + if (skip > cnt) { + if (skip > fsize) { + printf("skip(0x%08x) > fsize(0x%08x) file_base=0x%08x, header_offset=0x%x\n", + skip, fsize, file_base, header_offset); + ret = -4; + goto cleanup; + } + + fseek(xfile, skip, SEEK_SET); + cnt -= skip; + fsize -= skip; + skip = 0; + cnt = fread(buf, 1 , BUF_SIZE, xfile); + } + + p = &buf[skip]; + cnt -= skip; + fsize -= skip; + + if (fsize > max_length) + fsize = max_length; + + if (verify) { + /* + * we need to save header for verification + * because some of the file is changed + * before download + */ + verify_buffer = malloc(cnt); + verify_cnt = cnt; + + if (!verify_buffer) { + printf("error, out of memory\n"); + ret = -2; + goto cleanup; + } + + memcpy(verify_buffer, p, cnt); + + if ((type == FT_APP) && (p_id->mach_id->mode != MODE_HID)) { + type = FT_LOAD_ONLY; + verify = 2; + } + } + + printf("loading binary file(%s) to %08x, skip=0x%x, fsize=%d type=%d...\n", + curr->filename, dladdr, skip, fsize, type); + + ret = load_file(h, p_id, p, cnt, buf, BUF_SIZE, + dladdr, fsize, type, xfile); + if (ret < 0) + goto cleanup; + + printf("binary file successfully loaded\n"); + + transfer_size = ret; + + if (verify) { + printf("verifying file...\n"); + + ret = verify_memory(h, p_id, xfile, skip, dladdr, fsize, verify_buffer, verify_cnt); + if (ret < 0) { + printf("verifying failed\n"); + goto cleanup; + } + + printf("file successfully verified\n"); + + if (verify == 2) { + if (verify_cnt > 64) + verify_cnt = 64; + ret = load_file(h, p_id, verify_buffer, verify_cnt, + buf, BUF_SIZE, dladdr, verify_cnt, + FT_APP, xfile); + if (ret < 0) + goto cleanup; + + } + } + + if (p_id->mach_id->mode == MODE_HID && type == FT_APP) { + printf("jumping to 0x%08x\n", header_addr); + + jump_command[2] = (unsigned char)(header_addr >> 24); + jump_command[3] = (unsigned char)(header_addr >> 16); + jump_command[4] = (unsigned char)(header_addr >> 8); + jump_command[5] = (unsigned char)(header_addr); + + /* Any command will initiate jump for mx51, jump address is ignored by mx51 */ + retry = 0; + + for (;;) { + err = transfer(h, 1, jump_command, 16, &last_trans, p_id); + if (!err) + break; + + printf("jump_command err=%i, last_trans=%i\n", err, last_trans); + + if (retry > 5) + return -4; + + retry++; + } + + memset(tmp, 0, sizeof(tmp)); + err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id); + + if (err) + printf("j3 in err=%i, last_trans=%i %02x %02x %02x %02x\n", + err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); + } + + ret = (fsize == transfer_size) ? 0 : -16; +cleanup: + fclose(xfile); + free(verify_buffer); + free(buf); + + return ret; +} + +static void usage(const char *prgname) +{ + fprintf(stderr, "usage: %s [OPTIONS] [FILENAME]\n\n" + "-c check correctness of flashed image\n" + "-v verbose (give multiple times to increase)\n" + "-h this help\n", prgname); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct usb_id *p_id; + struct mach_id *mach; + libusb_device **devs; + libusb_device *dev; + int r; + int err; + int ret = 1; + ssize_t cnt; + libusb_device_handle *h = NULL; + int config = 0; + int verify = 0; + struct usb_work w = {}; + int opt; + + while ((opt = getopt(argc, argv, "cvh")) != -1) { + switch (opt) { + case 'c': + verify = 1; + break; + case 'v': + verbose++; + break; + case 'h': + usage(argv[0]); + default: + exit(1); + } + } + + if (optind == argc) { + fprintf(stderr, "no filename given\n"); + usage(argv[0]); + exit(1); + } + + w.plug = 1; + w.dcd = 1; + w.jump_mode = J_HEADER; + strncpy(w.filename, argv[optind], sizeof(w.filename) - 1); + + r = libusb_init(NULL); + if (r < 0) + goto out; + + cnt = libusb_get_device_list(NULL, &devs); + if (cnt < 0) { + fprintf(stderr, "no supported device found\n"); + goto out; + } + + dev = find_imx_dev(devs, &mach); + if (!dev) { + fprintf(stderr, "no supported device found\n"); + goto out; + } + + err = libusb_open(dev, &h); + if (err) { + fprintf(stderr, "Could not open device vid=0x%x pid=0x%x err=%d\n", + mach->vid, mach->pid, err); + goto out; + } + + libusb_free_device_list(devs, 1); + + libusb_get_configuration(h, &config); + + if (libusb_kernel_driver_active(h, 0)) + libusb_detach_kernel_driver(h, 0); + + err = libusb_claim_interface(h, 0); + if (err) { + printf("Claim failed\n"); + goto out; + } + + p_id = malloc(sizeof(*p_id)); + if (!p_id) { + perror("malloc"); + exit(1); + } + + p_id->mach_id = mach; + + err = do_status(h, p_id); + if (err) { + printf("status failed\n"); + goto out; + } + + err = do_irom_download(h, p_id, &w, verify); + if (err) { + err = do_status(h, p_id); + goto out; + } + + ret = 0; +out: + if (h) + libusb_close(h); + + libusb_exit(NULL); + + return ret; +} diff --git a/scripts/kwbimage.c b/scripts/kwbimage.c new file mode 100644 index 0000000000..4ebb07fe22 --- /dev/null +++ b/scripts/kwbimage.c @@ -0,0 +1,1496 @@ +/* + * Image manipulator for Marvell SoCs + * supports Kirkwood, Dove, Armada 370, and Armada XP + * + * (C) Copyright 2013 Thomas Petazzoni + * <thomas.petazzoni@free-electrons.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. + * + * This tool allows to extract and create bootable images for Marvell + * Kirkwood, Dove, Armada 370, and Armada XP SoCs. It supports two + * versions of the bootable image format: version 0 (used on Marvell + * Kirkwood and Dove) and version 1 (used on Marvell Armada 370/XP). + * + * To extract an image, run: + * ./scripts/kwbimage -x -i <image-file> -o <some-directory> + * + * In <some-directory>, kwbimage will output 'kwbimage.cfg', the + * configuration file that describes the image, 'payload', which is + * the bootloader code itself, and it may output a 'binary.0' file + * that corresponds to a binary blob (only possible in version 1 + * images). + * + * To create an image, run: + * ./scripts/kwbimage -c -i <image-cfg-file> -o <image-file> + * + * The given configuration file is in the format of the 'kwbimage.cfg' + * file, and should reference the payload file (generally the + * bootloader code) and optionally a binary blob. + * + * Not implemented: support for the register headers and secure + * headers in v1 images + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#define ALIGN_SUP(x, a) (((x) + (a - 1)) & ~(a - 1)) + +/* Structure of the main header, version 0 (Kirkwood, Dove) */ +struct main_hdr_v0 { + uint8_t blockid; /*0 */ + uint8_t nandeccmode; /*1 */ + uint16_t nandpagesize; /*2-3 */ + uint32_t blocksize; /*4-7 */ + uint32_t rsvd1; /*8-11 */ + uint32_t srcaddr; /*12-15 */ + uint32_t destaddr; /*16-19 */ + uint32_t execaddr; /*20-23 */ + uint8_t satapiomode; /*24 */ + uint8_t rsvd3; /*25 */ + uint16_t ddrinitdelay; /*26-27 */ + uint16_t rsvd2; /*28-29 */ + uint8_t ext; /*30 */ + uint8_t checksum; /*31 */ +}; + +struct ext_hdr_v0_reg { + uint32_t raddr; + uint32_t rdata; +}; + +#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20)/sizeof(struct ext_hdr_v0_reg)) + +struct ext_hdr_v0 { + uint32_t offset; + uint8_t reserved[0x20 - sizeof(uint32_t)]; + struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT]; + uint8_t reserved2[7]; + uint8_t checksum; +}; + +/* Structure of the main header, version 1 (Armada 370, Armada XP) */ +struct main_hdr_v1 { + uint8_t blockid; /* 0 */ + uint8_t reserved1; /* 1 */ + uint16_t reserved2; /* 2-3 */ + uint32_t blocksize; /* 4-7 */ + uint8_t version; /* 8 */ + uint8_t headersz_msb; /* 9 */ + uint16_t headersz_lsb; /* A-B */ + uint32_t srcaddr; /* C-F */ + uint32_t destaddr; /* 10-13 */ + uint32_t execaddr; /* 14-17 */ + uint8_t reserved3; /* 18 */ + uint8_t nandblocksize; /* 19 */ + uint8_t nandbadblklocation; /* 1A */ + uint8_t reserved4; /* 1B */ + uint16_t reserved5; /* 1C-1D */ + uint8_t ext; /* 1E */ + uint8_t checksum; /* 1F */ +}; + +/* + * Header for the optional headers, version 1 (Armada 370, Armada XP) + */ +struct opt_hdr_v1 { + uint8_t headertype; + uint8_t headersz_msb; + uint16_t headersz_lsb; + char data[0]; +}; + +/* + * Various values for the opt_hdr_v1->headertype field, describing the + * different types of optional headers. The "secure" header contains + * informations related to secure boot (encryption keys, etc.). The + * "binary" header contains ARM binary code to be executed prior to + * executing the main payload (usually the bootloader). This is + * typically used to execute DDR3 training code. The "register" header + * allows to describe a set of (address, value) tuples that are + * generally used to configure the DRAM controller. + */ +#define OPT_HDR_V1_SECURE_TYPE 0x1 +#define OPT_HDR_V1_BINARY_TYPE 0x2 +#define OPT_HDR_V1_REGISTER_TYPE 0x3 + +#define KWBHEADER_V1_SIZE(hdr) \ + (((hdr)->headersz_msb << 16) | (hdr)->headersz_lsb) + +struct boot_mode { + unsigned int id; + const char *name; +}; + +struct boot_mode boot_modes[] = { + { 0x4D, "i2c" }, + { 0x5A, "spi" }, + { 0x8B, "nand" }, + { 0x78, "sata" }, + { 0x9C, "pex" }, + { 0x69, "uart" }, + {}, +}; + +struct nand_ecc_mode { + unsigned int id; + const char *name; +}; + +struct nand_ecc_mode nand_ecc_modes[] = { + { 0x00, "default" }, + { 0x01, "hamming" }, + { 0x02, "rs" }, + { 0x03, "disabled" }, + {}, +}; + +/* Used to identify an undefined execution or destination address */ +#define ADDR_INVALID ((uint32_t)-1) + +#define BINARY_MAX_ARGS 8 + +/* In-memory representation of a line of the configuration file */ +struct image_cfg_element { + enum { + IMAGE_CFG_VERSION = 0x1, + IMAGE_CFG_BOOT_FROM, + IMAGE_CFG_DEST_ADDR, + IMAGE_CFG_EXEC_ADDR, + IMAGE_CFG_NAND_BLKSZ, + IMAGE_CFG_NAND_BADBLK_LOCATION, + IMAGE_CFG_NAND_ECC_MODE, + IMAGE_CFG_NAND_PAGESZ, + IMAGE_CFG_BINARY, + IMAGE_CFG_PAYLOAD, + IMAGE_CFG_DATA, + } type; + union { + unsigned int version; + unsigned int bootfrom; + struct { + const char *file; + unsigned int args[BINARY_MAX_ARGS]; + unsigned int nargs; + } binary; + const char *payload; + unsigned int dstaddr; + unsigned int execaddr; + unsigned int nandblksz; + unsigned int nandbadblklocation; + unsigned int nandeccmode; + unsigned int nandpagesz; + struct ext_hdr_v0_reg regdata; + }; +}; + +#define IMAGE_CFG_ELEMENT_MAX 256 + +/* + * Byte 8 of the image header contains the version number. In the v0 + * header, byte 8 was reserved, and always set to 0. In the v1 header, + * byte 8 has been changed to a proper field, set to 1. + */ +static unsigned int image_version(void *header) +{ + unsigned char *ptr = header; + return ptr[8]; +} + +/* + * Utility functions to manipulate boot mode and ecc modes (convert + * them back and forth between description strings and the + * corresponding numerical identifiers). + */ + +static const char *image_boot_mode_name(unsigned int id) +{ + int i; + for (i = 0; boot_modes[i].name; i++) + if (boot_modes[i].id == id) + return boot_modes[i].name; + return NULL; +} + +int image_boot_mode_id(const char *boot_mode_name) +{ + int i; + for (i = 0; boot_modes[i].name; i++) + if (!strcmp(boot_modes[i].name, boot_mode_name)) + return boot_modes[i].id; + + return -1; +} + +static const char *image_nand_ecc_mode_name(unsigned int id) +{ + int i; + for (i = 0; nand_ecc_modes[i].name; i++) + if (nand_ecc_modes[i].id == id) + return nand_ecc_modes[i].name; + return NULL; +} + +int image_nand_ecc_mode_id(const char *nand_ecc_mode_name) +{ + int i; + for (i = 0; nand_ecc_modes[i].name; i++) + if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name)) + return nand_ecc_modes[i].id; + return -1; +} + +static struct image_cfg_element * +image_find_option(struct image_cfg_element *image_cfg, + int cfgn, unsigned int optiontype) +{ + int i; + + for (i = 0; i < cfgn; i++) { + if (image_cfg[i].type == optiontype) + return &image_cfg[i]; + } + + return NULL; +} + +static unsigned int +image_count_options(struct image_cfg_element *image_cfg, + int cfgn, unsigned int optiontype) +{ + int i; + unsigned int count = 0; + + for (i = 0; i < cfgn; i++) + if (image_cfg[i].type == optiontype) + count++; + + return count; +} + +/* + * Compute a 8-bit checksum of a memory area. This algorithm follows + * the requirements of the Marvell SoC BootROM specifications. + */ +static uint8_t image_checksum8(void *start, uint32_t len) +{ + uint8_t csum = 0; + uint8_t *p = start; + + /* check len and return zero checksum if invalid */ + if (!len) + return 0; + + do { + csum += *p; + p++; + } while (--len); + + return csum; +} + +static uint32_t image_checksum32 (void *start, uint32_t len) +{ + uint32_t csum = 0; + uint32_t *p = start; + + /* check len and return zero checksum if invalid */ + if (!len) + return 0; + + if (len % sizeof(uint32_t)) { + fprintf (stderr, "Length %d is not in multiple of %zu\n", + len, sizeof(uint32_t)); + return 0; + } + + do { + csum += *p; + p++; + len -= sizeof(uint32_t); + } while (len > 0); + + return csum; +} + +static void usage(const char *prog) +{ + printf("Usage: %s [-c | -x] -i <input> -o <output>\n", prog); + printf(" -c: create a new image\n"); + printf(" -x: extract an existing image\n"); + printf(" -i: input file\n"); + printf(" when used with -c, should point to a kwbimage.cfg file\n"); + printf(" when used with -x, should point to the image to be extracted\n"); + printf(" -o: output file/directory\n"); + printf(" when used with -c, should point to the image file to create\n"); + printf(" when used with -x, should point to a directory when the image will be extracted\n"); + printf(" -v: verbose\n"); + printf(" -h: this help text\n"); + printf(" Options specific to image creation:\n"); + printf(" -p: path to payload image. Overrides the PAYLOAD line from kwbimage.cfg\n"); + printf(" -m: boot media. Overrides the BOOT_FROM line from kwbimage.cfg\n"); + printf(" -d: load address. Overrides the DEST_ADDR line from kwbimage.cfg\n"); + printf(" -e: exec address. Overrides the EXEC_ADDR line from kwbimage.cfg\n"); +} + +static int image_extract_payload(void *payload, size_t sz, const char *output) +{ + char *imageoutname; + FILE *imageout; + int ret; + + ret = asprintf(&imageoutname, "%s/payload", output); + if (ret < 0) { + fprintf(stderr, "Cannot allocate memory\n"); + return -1; + } + + imageout = fopen(imageoutname, "w+"); + if (!imageout) { + fprintf(stderr, "Could not open output file %s\n", + imageoutname); + free(imageoutname); + return -1; + } + + ret = fwrite(payload, sz, 1, imageout); + if (ret != 1) { + fprintf(stderr, "Could not write to open file %s\n", + imageoutname); + fclose(imageout); + free(imageoutname); + return -1; + } + + fclose(imageout); + free(imageoutname); + return 0; +} + +static int image_extract_v0(void *fdimap, const char *output, FILE *focfg) +{ + struct main_hdr_v0 *main_hdr = fdimap; + struct ext_hdr_v0 *ext_hdr; + const char *boot_mode_name; + uint32_t *img_checksum; + size_t payloadsz; + int cksum, i; + + /* + * Verify checksum. When calculating the header, discard the + * last byte of the header, which itself contains the + * checksum. + */ + cksum = image_checksum8(main_hdr, sizeof(struct main_hdr_v0)-1); + if (cksum != main_hdr->checksum) { + fprintf(stderr, + "Invalid main header checksum: 0x%08x vs. 0x%08x\n", + cksum, main_hdr->checksum); + return -1; + } + + boot_mode_name = image_boot_mode_name(main_hdr->blockid); + if (!boot_mode_name) { + fprintf(stderr, "Invalid boot ID: 0x%x\n", + main_hdr->blockid); + return -1; + } + + fprintf(focfg, "VERSION 0\n"); + fprintf(focfg, "BOOT_FROM %s\n", boot_mode_name); + fprintf(focfg, "DESTADDR %08x\n", main_hdr->destaddr); + fprintf(focfg, "EXECADDR %08x\n", main_hdr->execaddr); + + if (!strcmp(boot_mode_name, "nand")) { + const char *nand_ecc_mode = + image_nand_ecc_mode_name(main_hdr->nandeccmode); + fprintf(focfg, "NAND_ECCMODE %s\n", + nand_ecc_mode); + fprintf(focfg, "NAND_PAGESZ %08x\n", + main_hdr->nandpagesize); + } + + /* No extension header, we're done */ + if (!main_hdr->ext) + return 0; + + ext_hdr = fdimap + sizeof(struct main_hdr_v0); + + for (i = 0; i < EXT_HDR_V0_REG_COUNT; i++) { + if (ext_hdr->rcfg[i].raddr == 0 && + ext_hdr->rcfg[i].rdata == 0) + break; + + fprintf(focfg, "DATA %08x %08x\n", + ext_hdr->rcfg[i].raddr, + ext_hdr->rcfg[i].rdata); + } + + /* The image is concatenated with a 32 bits checksum */ + payloadsz = main_hdr->blocksize - sizeof(uint32_t); + img_checksum = (uint32_t *) (fdimap + main_hdr->srcaddr + payloadsz); + + if (*img_checksum != image_checksum32(fdimap + main_hdr->srcaddr, + payloadsz)) { + fprintf(stderr, "The image checksum does not match\n"); + return -1; + } + + /* Finally, handle the image itself */ + fprintf(focfg, "PAYLOAD %s/payload\n", output); + return image_extract_payload(fdimap + main_hdr->srcaddr, + payloadsz, output); +} + +static int image_extract_binary_hdr_v1(const void *binary, const char *output, + FILE *focfg, int hdrnum, size_t binsz) +{ + char *binaryoutname; + FILE *binaryout; + const unsigned int *args; + unsigned int nargs; + int ret, i; + + args = binary; + nargs = args[0]; + args++; + + ret = asprintf(&binaryoutname, "%s/binary.%d", output, + hdrnum); + if (ret < 0) { + fprintf(stderr, "Couldn't not allocate memory\n"); + return ret; + } + + binaryout = fopen(binaryoutname, "w+"); + if (!binaryout) { + fprintf(stderr, "Couldn't open output file %s\n", + binaryoutname); + free(binaryoutname); + return -1; + } + + ret = fwrite(binary + (nargs + 1) * sizeof(unsigned int), + binsz - (nargs + 1) * sizeof(unsigned int), 1, + binaryout); + if (ret != 1) { + fprintf(stderr, "Could not write to output file %s\n", + binaryoutname); + fclose(binaryout); + free(binaryoutname); + return -1; + } + + fclose(binaryout); + + fprintf(focfg, "BINARY %s", binaryoutname); + for (i = 0; i < nargs; i++) + fprintf(focfg, " %08x", args[i]); + fprintf(focfg, "\n"); + + free(binaryoutname); + + return 0; +} + +static int image_extract_v1(void *fdimap, const char *output, FILE *focfg) +{ + struct main_hdr_v1 *main_hdr = fdimap; + struct opt_hdr_v1 *opt_hdr; + const char *boot_mode_name; + int headersz = KWBHEADER_V1_SIZE(main_hdr); + int hasheaders; + uint8_t cksum; + int opthdrid; + + /* + * Verify the checkum. We have to substract the checksum + * itself, because when the checksum is calculated, the + * checksum field is 0. + */ + cksum = image_checksum8(main_hdr, headersz); + cksum -= main_hdr->checksum; + + if (cksum != main_hdr->checksum) { + fprintf(stderr, + "Invalid main header checksum: 0x%08x vs. 0x%08x\n", + cksum, main_hdr->checksum); + return -1; + } + + /* First, take care of the main header */ + boot_mode_name = image_boot_mode_name(main_hdr->blockid); + if (!boot_mode_name) { + fprintf(stderr, "Invalid boot ID: 0x%x\n", + main_hdr->blockid); + return -1; + } + + fprintf(focfg, "VERSION 1\n"); + fprintf(focfg, "BOOT_FROM %s\n", boot_mode_name); + fprintf(focfg, "DESTADDR %08x\n", main_hdr->destaddr); + fprintf(focfg, "EXECADDR %08x\n", main_hdr->execaddr); + fprintf(focfg, "NAND_BLKSZ %08x\n", + main_hdr->nandblocksize * 64 * 1024); + fprintf(focfg, "NAND_BADBLK_LOCATION %02x\n", + main_hdr->nandbadblklocation); + + hasheaders = main_hdr->ext; + opt_hdr = fdimap + sizeof(struct main_hdr_v1); + opthdrid = 0; + + /* Then, go through all the extension headers */ + while (hasheaders) { + int opthdrsz = KWBHEADER_V1_SIZE(opt_hdr); + + switch (opt_hdr->headertype) { + case OPT_HDR_V1_BINARY_TYPE: + image_extract_binary_hdr_v1(opt_hdr->data, output, + focfg, opthdrid, + opthdrsz - + sizeof(struct opt_hdr_v1)); + break; + case OPT_HDR_V1_SECURE_TYPE: + case OPT_HDR_V1_REGISTER_TYPE: + fprintf(stderr, + "Support for header type 0x%x not implemented\n", + opt_hdr->headertype); + exit(1); + break; + default: + fprintf(stderr, "Invalid header type 0x%x\n", + opt_hdr->headertype); + exit(1); + } + + /* + * The first byte of the last double word of the + * current header indicates whether there is a next + * header or not. + */ + hasheaders = ((char *)opt_hdr)[opthdrsz - 4]; + + /* Move to the next header */ + opt_hdr = ((void *)opt_hdr) + opthdrsz; + opthdrid++; + } + + /* Finally, handle the image itself */ + fprintf(focfg, "PAYLOAD %s/payload\n", output); + return image_extract_payload(fdimap + main_hdr->srcaddr, + main_hdr->blocksize - 4, + output); +} + +static int image_extract(const char *input, const char *output) +{ + int fdi, ret; + struct stat fdistat, fdostat; + void *fdimap; + char *focfgname; + FILE *focfg; + + fdi = open(input, O_RDONLY); + if (fdi < 0) { + fprintf(stderr, "Cannot open input file %s: %m\n", + input); + return -1; + } + + ret = fstat(fdi, &fdistat); + if (ret < 0) { + fprintf(stderr, "Cannot stat input file %s: %m\n", + input); + close(fdi); + return -1; + } + + fdimap = mmap(NULL, fdistat.st_size, PROT_READ, MAP_PRIVATE, fdi, 0); + if (fdimap == MAP_FAILED) { + fprintf(stderr, "Cannot map input file %s: %m\n", + input); + close(fdi); + return -1; + } + + close(fdi); + + ret = stat(output, &fdostat); + if (ret < 0) { + fprintf(stderr, "Cannot stat output directory %s: %m\n", + output); + munmap(fdimap, fdistat.st_size); + return -1; + } + + if (!S_ISDIR(fdostat.st_mode)) { + fprintf(stderr, "Output %s should be a directory\n", + output); + munmap(fdimap, fdistat.st_size); + return -1; + } + + ret = asprintf(&focfgname, "%s/kwbimage.cfg", output); + if (ret < 0) { + fprintf(stderr, "Failed to allocate memory\n"); + munmap(fdimap, fdistat.st_size); + return -1; + } + + focfg = fopen(focfgname, "w+"); + if (!focfg) { + fprintf(stderr, "Output file %s could not be created\n", + focfgname); + free(focfgname); + munmap(fdimap, fdistat.st_size); + return -1; + } + + free(focfgname); + + if (image_version(fdimap) == 0) + ret = image_extract_v0(fdimap, output, focfg); + else if (image_version(fdimap) == 1) + ret = image_extract_v1(fdimap, output, focfg); + else { + fprintf(stderr, "Invalid image version %d\n", + image_version(fdimap)); + ret = -1; + } + + fclose(focfg); + munmap(fdimap, fdistat.st_size); + return ret; +} + +static int image_create_payload(void *payload_start, size_t payloadsz, + const char *payload_filename) +{ + FILE *payload; + uint32_t *payload_checksum = + (uint32_t *) (payload_start + payloadsz); + int ret; + + payload = fopen(payload_filename, "r"); + if (!payload) { + fprintf(stderr, "Cannot open payload file %s\n", + payload_filename); + return -1; + } + + ret = fread(payload_start, payloadsz, 1, payload); + if (ret != 1) { + fprintf(stderr, "Cannot read payload file %s\n", + payload_filename); + return -1; + } + + fclose(payload); + + *payload_checksum = image_checksum32(payload_start, payloadsz); + return 0; +} + +static void *image_create_v0(struct image_cfg_element *image_cfg, + int cfgn, const char *output, size_t *imagesz) +{ + struct image_cfg_element *e, *payloade; + size_t headersz, payloadsz, totalsz; + struct main_hdr_v0 *main_hdr; + struct ext_hdr_v0 *ext_hdr; + void *image; + int has_ext = 0; + int ret; + + /* Calculate the size of the header and the size of the + * payload */ + headersz = sizeof(struct main_hdr_v0); + payloadsz = 0; + + if (image_count_options(image_cfg, cfgn, IMAGE_CFG_DATA) > 0) { + has_ext = 1; + headersz += sizeof(struct ext_hdr_v0); + } + + if (image_count_options(image_cfg, cfgn, IMAGE_CFG_PAYLOAD) > 1) { + fprintf(stderr, "More than one payload, not possible\n"); + return NULL; + } + + payloade = image_find_option(image_cfg, cfgn, IMAGE_CFG_PAYLOAD); + if (payloade) { + struct stat s; + int ret; + + ret = stat(payloade->payload, &s); + if (ret < 0) { + fprintf(stderr, "Cannot stat payload file %s\n", + payloade->payload); + return NULL; + } + + payloadsz = s.st_size; + } + + /* Headers, payload and 32-bits checksum */ + totalsz = headersz + payloadsz + sizeof(uint32_t); + + image = malloc(totalsz); + if (!image) { + fprintf(stderr, "Cannot allocate memory for image\n"); + return NULL; + } + + memset(image, 0, totalsz); + + main_hdr = image; + + /* Fill in the main header */ + main_hdr->blocksize = payloadsz + sizeof(uint32_t); + main_hdr->srcaddr = headersz; + main_hdr->ext = has_ext; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_BOOT_FROM); + if (e) + main_hdr->blockid = e->bootfrom; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_DEST_ADDR); + if (e) + main_hdr->destaddr = e->dstaddr; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_EXEC_ADDR); + if (e) + main_hdr->execaddr = e->execaddr; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_ECC_MODE); + if (e) + main_hdr->nandeccmode = e->nandeccmode; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_PAGESZ); + if (e) + main_hdr->nandpagesize = e->nandpagesz; + main_hdr->checksum = image_checksum8(image, + sizeof(struct main_hdr_v0)); + + /* Generate the ext header */ + if (has_ext) { + int cfgi, datai; + + ext_hdr = image + sizeof(struct main_hdr_v0); + ext_hdr->offset = 0x40; + + for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) { + e = &image_cfg[cfgi]; + + if (e->type != IMAGE_CFG_DATA) + continue; + + ext_hdr->rcfg[datai].raddr = e->regdata.raddr; + ext_hdr->rcfg[datai].rdata = e->regdata.rdata; + datai++; + } + + ext_hdr->checksum = image_checksum8(ext_hdr, + sizeof(struct ext_hdr_v0)); + } + + if (payloade) { + ret = image_create_payload(image + headersz, payloadsz, + payloade->payload); + if (ret < 0) + return NULL; + } + + *imagesz = totalsz; + return image; +} + +static void *image_create_v1(struct image_cfg_element *image_cfg, + int cfgn, const char *output, size_t *imagesz) +{ + struct image_cfg_element *e, *payloade, *binarye; + struct main_hdr_v1 *main_hdr; + size_t headersz, payloadsz, totalsz; + void *image, *cur; + int hasext = 0; + int ret; + + /* Calculate the size of the header and the size of the + * payload */ + headersz = sizeof(struct main_hdr_v1); + payloadsz = 0; + + if (image_count_options(image_cfg, cfgn, IMAGE_CFG_BINARY) > 1) { + fprintf(stderr, "More than one binary blob, not supported\n"); + return NULL; + } + + if (image_count_options(image_cfg, cfgn, IMAGE_CFG_PAYLOAD) > 1) { + fprintf(stderr, "More than one payload, not possible\n"); + return NULL; + } + + binarye = image_find_option(image_cfg, cfgn, IMAGE_CFG_BINARY); + if (binarye) { + struct stat s; + + ret = stat(binarye->binary.file, &s); + if (ret < 0) { + char *cwd = get_current_dir_name(); + fprintf(stderr, + "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" + "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" + "image for your board. See 'kwbimage -x' to extract it from an existing image.\n", + binarye->binary.file, cwd); + free(cwd); + return NULL; + } + + headersz += s.st_size + + binarye->binary.nargs * sizeof(unsigned int); + hasext = 1; + } + + payloade = image_find_option(image_cfg, cfgn, IMAGE_CFG_PAYLOAD); + if (payloade) { + struct stat s; + + ret = stat(payloade->payload, &s); + if (ret < 0) { + fprintf(stderr, "Cannot stat payload file %s\n", + payloade->payload); + return NULL; + } + + payloadsz = s.st_size; + } + + /* The payload should be aligned on some reasonable + * boundary */ + headersz = ALIGN_SUP(headersz, 4096); + + /* The total size includes the headers, the payload, and the + * 32 bits checksum at the end of the payload */ + totalsz = headersz + payloadsz + sizeof(uint32_t); + + image = malloc(totalsz); + if (!image) { + fprintf(stderr, "Cannot allocate memory for image\n"); + return NULL; + } + + memset(image, 0, totalsz); + + cur = main_hdr = image; + cur += sizeof(struct main_hdr_v1); + + /* Fill the main header */ + main_hdr->blocksize = payloadsz + sizeof(uint32_t); + main_hdr->headersz_lsb = headersz & 0xFFFF; + main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; + main_hdr->srcaddr = headersz; + main_hdr->ext = hasext; + main_hdr->version = 1; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_BOOT_FROM); + if (e) + main_hdr->blockid = e->bootfrom; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_DEST_ADDR); + if (e) + main_hdr->destaddr = e->dstaddr; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_EXEC_ADDR); + if (e) + main_hdr->execaddr = e->execaddr; + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_BLKSZ); + if (e) + main_hdr->nandblocksize = e->nandblksz / (64 * 1024); + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_BADBLK_LOCATION); + if (e) + main_hdr->nandbadblklocation = e->nandbadblklocation; + + if (binarye) { + struct opt_hdr_v1 *hdr = cur; + unsigned int *args; + size_t binhdrsz; + struct stat s; + int argi; + FILE *bin; + + hdr->headertype = OPT_HDR_V1_BINARY_TYPE; + + bin = fopen(binarye->binary.file, "r"); + if (!bin) { + fprintf(stderr, "Cannot open binary file %s\n", + binarye->binary.file); + return NULL; + } + + fstat(fileno(bin), &s); + + binhdrsz = sizeof(struct opt_hdr_v1) + + (binarye->binary.nargs + 1) * sizeof(unsigned int) + + s.st_size; + hdr->headersz_lsb = binhdrsz & 0xFFFF; + hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; + + cur += sizeof(struct opt_hdr_v1); + + args = cur; + *args = binarye->binary.nargs; + args++; + for (argi = 0; argi < binarye->binary.nargs; argi++) + args[argi] = binarye->binary.args[argi]; + + cur += (binarye->binary.nargs + 1) * sizeof(unsigned int); + + ret = fread(cur, s.st_size, 1, bin); + if (ret != 1) { + fprintf(stderr, + "Could not read binary image %s\n", + binarye->binary.file); + return NULL; + } + + fclose(bin); + + cur += s.st_size; + + /* + * For now, we don't support more than one binary + * header, and no other header types are + * supported. So, the binary header is necessarily the + * last one + */ + *((unsigned char *) cur) = 0; + + cur += sizeof(uint32_t); + } + + /* Calculate and set the header checksum */ + main_hdr->checksum = image_checksum8(main_hdr, headersz); + + if (payloade) { + ret = image_create_payload(image + headersz, payloadsz, + payloade->payload); + if (ret < 0) + return NULL; + } + + *imagesz = totalsz; + return image; +} + +static int image_create_config_parse_oneline(char *line, + struct image_cfg_element *el) +{ + char *keyword, *saveptr; + + keyword = strtok_r(line, " ", &saveptr); + if (!strcmp(keyword, "VERSION")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_VERSION; + el->version = atoi(value); + } else if (!strcmp(keyword, "BOOT_FROM")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_BOOT_FROM; + el->bootfrom = image_boot_mode_id(value); + if (el->bootfrom < 0) { + fprintf(stderr, + "Invalid boot media '%s'\n", value); + return -1; + } + } else if (!strcmp(keyword, "DESTADDR")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_DEST_ADDR; + el->dstaddr = strtol(value, NULL, 16); + } else if (!strcmp(keyword, "EXECADDR")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_EXEC_ADDR; + el->execaddr = strtol(value, NULL, 16); + } else if (!strcmp(keyword, "NAND_BLKSZ")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_NAND_BLKSZ; + el->nandblksz = strtol(value, NULL, 16); + } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_NAND_BADBLK_LOCATION; + el->nandbadblklocation = + strtol(value, NULL, 16); + } else if (!strcmp(keyword, "NAND_ECCMODE")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_NAND_ECC_MODE; + el->nandeccmode = image_nand_ecc_mode_id(value); + if (el->nandeccmode < 0) { + fprintf(stderr, + "Invalid NAND ECC mode '%s'\n", value); + return -1; + } + } else if (!strcmp(keyword, "NAND_PAGESZ")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_NAND_PAGESZ; + el->nandpagesz = strtol(value, NULL, 16); + } else if (!strcmp(keyword, "BINARY")) { + char *value = strtok_r(NULL, " ", &saveptr); + int argi = 0; + + el->type = IMAGE_CFG_BINARY; + el->binary.file = strdup(value); + while (1) { + value = strtok_r(NULL, " ", &saveptr); + if (!value) + break; + el->binary.args[argi] = strtol(value, NULL, 16); + argi++; + if (argi >= BINARY_MAX_ARGS) { + fprintf(stderr, + "Too many argument for binary\n"); + return -1; + } + } + el->binary.nargs = argi; + } else if (!strcmp(keyword, "DATA")) { + char *value1 = strtok_r(NULL, " ", &saveptr); + char *value2 = strtok_r(NULL, " ", &saveptr); + + if (!value1 || !value2) { + fprintf(stderr, "Invalid number of arguments for DATA\n"); + return -1; + } + + el->type = IMAGE_CFG_DATA; + el->regdata.raddr = strtol(value1, NULL, 16); + el->regdata.rdata = strtol(value2, NULL, 16); + } else if (!strcmp(keyword, "PAYLOAD")) { + char *value = strtok_r(NULL, " ", &saveptr); + el->type = IMAGE_CFG_PAYLOAD; + el->payload = strdup(value); + } else { + fprintf(stderr, "Ignoring unknown line '%s'\n", line); + } + + return 0; +} + +/* + * Parse the configuration file 'fcfg' into the array of configuration + * elements 'image_cfg', and return the number of configuration + * elements in 'cfgn'. + */ +static int image_create_config_parse(FILE *fcfg, + struct image_cfg_element *image_cfg, + int *cfgn) +{ + int ret; + int cfgi = 0; + + /* Parse the configuration file */ + while (!feof(fcfg)) { + char *line; + char buf[256]; + + /* Read the current line */ + memset(buf, 0, sizeof(buf)); + line = fgets(buf, sizeof(buf), fcfg); + if (!line) + break; + + /* Ignore useless lines */ + if (line[0] == '\n' || line[0] == '#') + continue; + + /* Strip final newline */ + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = 0; + + /* Parse the current line */ + ret = image_create_config_parse_oneline(line, + &image_cfg[cfgi]); + if (ret) + return ret; + + cfgi++; + + if (cfgi >= IMAGE_CFG_ELEMENT_MAX) { + fprintf(stderr, "Too many configuration elements in .cfg file\n"); + return -1; + } + } + + *cfgn = cfgi; + return 0; +} + +static int image_override_payload(struct image_cfg_element *image_cfg, + int *cfgn, const char *payload) +{ + struct image_cfg_element *e; + int cfgi = *cfgn; + + if (!payload) + return 0; + + e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_PAYLOAD); + if (e) { + e->payload = payload; + return 0; + } + + image_cfg[cfgi].type = IMAGE_CFG_PAYLOAD; + image_cfg[cfgi].payload = payload; + cfgi++; + + *cfgn = cfgi; + return 0; +} + +static int image_override_bootmedia(struct image_cfg_element *image_cfg, + int *cfgn, const char *bootmedia) +{ + struct image_cfg_element *e; + int bootfrom; + int cfgi = *cfgn; + + if (!bootmedia) + return 0; + + bootfrom = image_boot_mode_id(bootmedia); + if (!bootfrom) { + fprintf(stderr, + "Invalid boot media '%s'\n", bootmedia); + return -1; + } + + e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_BOOT_FROM); + if (e) { + e->bootfrom = bootfrom; + return 0; + } + + image_cfg[cfgi].type = IMAGE_CFG_BOOT_FROM; + image_cfg[cfgi].bootfrom = bootfrom; + cfgi++; + + *cfgn = cfgi; + return 0; +} + +static int image_override_dstaddr(struct image_cfg_element *image_cfg, + int *cfgn, uint32_t dstaddr) +{ + struct image_cfg_element *e; + int cfgi = *cfgn; + + if (dstaddr == ADDR_INVALID) + return 0; + + e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_DEST_ADDR); + if (e) { + e->dstaddr = dstaddr; + return 0; + } + + image_cfg[cfgi].type = IMAGE_CFG_DEST_ADDR; + image_cfg[cfgi].dstaddr = dstaddr; + cfgi++; + + *cfgn = cfgi; + return 0; +} + +static int image_override_execaddr(struct image_cfg_element *image_cfg, + int *cfgn, uint32_t execaddr) +{ + struct image_cfg_element *e; + int cfgi = *cfgn; + + if (execaddr == ADDR_INVALID) + return 0; + + e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_EXEC_ADDR); + if (e) { + e->execaddr = execaddr; + return 0; + } + + image_cfg[cfgi].type = IMAGE_CFG_EXEC_ADDR; + image_cfg[cfgi].execaddr = execaddr; + cfgi++; + + *cfgn = cfgi; + return 0; +} + +static int image_get_version(struct image_cfg_element *image_cfg, + int cfgn) +{ + struct image_cfg_element *e; + + e = image_find_option(image_cfg, cfgn, IMAGE_CFG_VERSION); + if (!e) + return -1; + + return e->version; +} + +static void image_dump_config(struct image_cfg_element *image_cfg, + int cfgn) +{ + int cfgi; + + printf("== configuration dump\n"); + + for (cfgi = 0; cfgi < cfgn; cfgi++) { + struct image_cfg_element *e = &image_cfg[cfgi]; + switch (e->type) { + case IMAGE_CFG_VERSION: + printf("VERSION %d\n", e->version); + break; + case IMAGE_CFG_BOOT_FROM: + printf("BOOTFROM %s\n", + image_boot_mode_name(e->bootfrom)); + break; + case IMAGE_CFG_DEST_ADDR: + printf("DESTADDR 0x%x\n", e->dstaddr); + break; + case IMAGE_CFG_EXEC_ADDR: + printf("EXECADDR 0x%x\n", e->execaddr); + break; + case IMAGE_CFG_NAND_BLKSZ: + printf("NANDBLKSZ 0x%x\n", e->nandblksz); + break; + case IMAGE_CFG_NAND_BADBLK_LOCATION: + printf("NANDBADBLK 0x%x\n", e->nandbadblklocation); + break; + case IMAGE_CFG_NAND_ECC_MODE: + printf("NAND_ECCMODE 0x%x\n", e->nandeccmode); + break; + case IMAGE_CFG_NAND_PAGESZ: + printf("NAND_PAGESZ 0x%x\n", e->nandpagesz); + break; + case IMAGE_CFG_BINARY: + printf("BINARY %s (%d args)\n", e->binary.file, + e->binary.nargs); + break; + case IMAGE_CFG_PAYLOAD: + printf("PAYLOAD %s\n", e->payload); + break; + case IMAGE_CFG_DATA: + printf("DATA 0x%x 0x%x\n", + e->regdata.raddr, + e->regdata.rdata); + break; + default: + printf("Error, unknown type\n"); + break; + } + } + + printf("== end configuration dump\n"); +} + +static int image_create(const char *input, const char *output, + const char *payload, const char *bootmedia, + uint32_t dstaddr, uint32_t execaddr, + int verbose) +{ + struct image_cfg_element *image_cfg; + FILE *fcfg, *outputimg; + void *image = NULL; + int version; + size_t imagesz; + int cfgn; + int ret; + + fcfg = fopen(input, "r"); + if (!fcfg) { + fprintf(stderr, "Could not open input file %s\n", + input); + return -1; + } + + image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX * + sizeof(struct image_cfg_element)); + if (!image_cfg) { + fprintf(stderr, "Cannot allocate memory\n"); + fclose(fcfg); + return -1; + } + + memset(image_cfg, 0, + IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); + rewind(fcfg); + + ret = image_create_config_parse(fcfg, image_cfg, &cfgn); + if (ret) { + free(image_cfg); + return -1; + } + + image_override_payload(image_cfg, &cfgn, payload); + image_override_bootmedia(image_cfg, &cfgn, bootmedia); + image_override_dstaddr(image_cfg, &cfgn, dstaddr); + image_override_execaddr(image_cfg, &cfgn, execaddr); + + if (!image_find_option(image_cfg, cfgn, IMAGE_CFG_BOOT_FROM) || + !image_find_option(image_cfg, cfgn, IMAGE_CFG_DEST_ADDR) || + !image_find_option(image_cfg, cfgn, IMAGE_CFG_EXEC_ADDR)) { + fprintf(stderr, + "Missing information (either boot media, exec addr or dest addr)\n"); + free(image_cfg); + return -1; + } + + if (verbose) + image_dump_config(image_cfg, cfgn); + + version = image_get_version(image_cfg, cfgn); + + if (version == 0) + image = image_create_v0(image_cfg, cfgn, output, &imagesz); + else if (version == 1) + image = image_create_v1(image_cfg, cfgn, output, &imagesz); + else if (version == -1) { + fprintf(stderr, "File %s does not have the VERSION field\n", + input); + free(image_cfg); + return -1; + } + + if (!image) { + fprintf(stderr, "Could not create image\n"); + free(image_cfg); + return -1; + } + + free(image_cfg); + + outputimg = fopen(output, "w"); + if (!outputimg) { + fprintf(stderr, "Cannot open output image %s for writing\n", + output); + free(image); + return -1; + } + + ret = fwrite(image, imagesz, 1, outputimg); + if (ret != 1) { + fprintf(stderr, "Cannot write to output image %s\n", + output); + fclose(outputimg); + free(image); + return -1; + } + + fclose(outputimg); + free(image); + + return 0; +} + +enum { + ACTION_CREATE, + ACTION_EXTRACT, + ACTION_DUMP, + ACTION_HELP, +}; + +int main(int argc, char *argv[]) +{ + int action = -1, opt, verbose = 0; + const char *input = NULL, *output = NULL, + *payload = NULL, *bootmedia = NULL; + uint32_t execaddr = ADDR_INVALID, dstaddr = ADDR_INVALID; + + while ((opt = getopt(argc, argv, "hxci:o:p:m:e:d:v")) != -1) { + switch (opt) { + case 'x': + action = ACTION_EXTRACT; + break; + case 'c': + action = ACTION_CREATE; + break; + case 'i': + input = optarg; + break; + case 'o': + output = optarg; + break; + case 'p': + payload = optarg; + break; + case 'm': + bootmedia = optarg; + break; + case 'e': + execaddr = strtol(optarg, NULL, 0); + break; + case 'd': + dstaddr = strtol(optarg, NULL, 0); + break; + case 'v': + verbose = 1; + break; + case 'h': + action = ACTION_HELP; + break; + } + } + + /* We should have consumed all arguments */ + if (optind != argc) { + usage(argv[0]); + exit(1); + } + + if (action != ACTION_HELP && !input) { + fprintf(stderr, "Missing input file\n"); + usage(argv[0]); + exit(1); + } + + if ((action == ACTION_EXTRACT || action == ACTION_CREATE) && + !output) { + fprintf(stderr, "Missing output file\n"); + usage(argv[0]); + exit(1); + } + + if (action == ACTION_EXTRACT && + (bootmedia || payload || + (execaddr != ADDR_INVALID) || (dstaddr != ADDR_INVALID))) { + fprintf(stderr, + "-m, -p, -e or -d do not make sense when extracting an image"); + usage(argv[0]); + exit(1); + } + + switch (action) { + case ACTION_EXTRACT: + return image_extract(input, output); + case ACTION_CREATE: + return image_create(input, output, payload, + bootmedia, dstaddr, execaddr, + verbose); + case ACTION_HELP: + usage(argv[0]); + return 0; + default: + fprintf(stderr, "No action specified\n"); + usage(argv[0]); + exit(1); + } + + return 0; +} diff --git a/scripts/kwboot.c b/scripts/kwboot.c new file mode 100644 index 0000000000..33c94b3a8b --- /dev/null +++ b/scripts/kwboot.c @@ -0,0 +1,730 @@ +/* + * Boot a Marvell SoC, with Xmodem over UART0. + * supports Kirkwood, Dove, Armada 370, Armada XP + * + * (c) 2012 Daniel Stodden <daniel.stodden@gmail.com> + * + * References: marvell.com, "88F6180, 88F6190, 88F6192, and 88F6281 + * Integrated Controller: Functional Specifications" December 2, + * 2008. Chapter 24.2 "BootROM Firmware". + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <libgen.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdint.h> +#include <termios.h> +#include <sys/mman.h> +#include <sys/stat.h> + +/* + * Marvell BootROM UART Sensing + */ + +static unsigned char kwboot_msg_boot[] = { + 0xBB, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 +}; + +static unsigned char kwboot_msg_debug[] = { + 0xDD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 +}; + +#define KWBOOT_MSG_REQ_DELAY 1000 /* ms */ +#define KWBOOT_MSG_RSP_TIMEO 1000 /* ms */ + +/* + * Xmodem Transfers + */ + +#define SOH 1 /* sender start of block header */ +#define EOT 4 /* sender end of block transfer */ +#define ACK 6 /* target block ack */ +#define NAK 21 /* target block negative ack */ +#define CAN 24 /* target/sender transfer cancellation */ + +struct kwboot_block { + uint8_t soh; + uint8_t pnum; + uint8_t _pnum; + uint8_t data[128]; + uint8_t csum; +} __attribute((packed)); + +#define KWBOOT_BLK_RSP_TIMEO 1000 /* ms */ + +static int kwboot_verbose; + +static void +kwboot_printv(const char *fmt, ...) +{ + va_list ap; + + if (kwboot_verbose) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + fflush(stdout); + } +} + +static void +__spinner(void) +{ + const char seq[] = { '-', '\\', '|', '/' }; + const int div = 8; + static int state, bs; + + if (state % div == 0) { + fputc(bs, stdout); + fputc(seq[state / div % sizeof(seq)], stdout); + fflush(stdout); + } + + bs = '\b'; + state++; +} + +static void +kwboot_spinner(void) +{ + if (kwboot_verbose) + __spinner(); +} + +static void +__progress(int pct, char c) +{ + const int width = 70; + static const char *nl = ""; + static int pos; + + if (pos % width == 0) + printf("%s%3d %% [", nl, pct); + + fputc(c, stdout); + + nl = "]\n"; + pos++; + + if (pct == 100) { + while (pos++ < width) + fputc(' ', stdout); + fputs(nl, stdout); + } + + fflush(stdout); + +} + +static void +kwboot_progress(int _pct, char c) +{ + static int pct; + + if (_pct != -1) + pct = _pct; + + if (kwboot_verbose) + __progress(pct, c); +} + +static int +kwboot_tty_recv(int fd, void *buf, size_t len, int timeo) +{ + int rc, nfds; + fd_set rfds; + struct timeval tv; + ssize_t n; + + rc = -1; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = 0; + tv.tv_usec = timeo * 1000; + if (tv.tv_usec > 1000000) { + tv.tv_sec += tv.tv_usec / 1000000; + tv.tv_usec %= 1000000; + } + + do { + nfds = select(fd + 1, &rfds, NULL, NULL, &tv); + if (nfds < 0) + goto out; + if (!nfds) { + errno = ETIMEDOUT; + goto out; + } + + n = read(fd, buf, len); + if (n < 0) + goto out; + + buf = (char *)buf + n; + len -= n; + } while (len > 0); + + rc = 0; +out: + return rc; +} + +static int +kwboot_tty_send(int fd, const void *buf, size_t len) +{ + int rc; + ssize_t n; + + if (!buf) + return 0; + + rc = -1; + + do { + n = write(fd, buf, len); + if (n < 0) + goto out; + + buf = (char *)buf + n; + len -= n; + } while (len > 0); + + rc = tcdrain(fd); +out: + return rc; +} + +static int +kwboot_tty_send_char(int fd, unsigned char c) +{ + return kwboot_tty_send(fd, &c, 1); +} + +static speed_t +kwboot_tty_speed(int baudrate) +{ + switch (baudrate) { + case 115200: + return B115200; + case 57600: + return B57600; + case 38400: + return B38400; + case 19200: + return B19200; + case 9600: + return B9600; + } + + return -1; +} + +static int +kwboot_open_tty(const char *path, speed_t speed) +{ + int rc, fd; + struct termios tio; + + rc = -1; + + fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY); + if (fd < 0) + goto out; + + memset(&tio, 0, sizeof(tio)); + + tio.c_iflag = 0; + tio.c_cflag = CREAD|CLOCAL|CS8; + + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 10; + + cfsetospeed(&tio, speed); + cfsetispeed(&tio, speed); + + rc = tcsetattr(fd, TCSANOW, &tio); + if (rc) + goto out; + + rc = fd; +out: + if (rc < 0) { + if (fd >= 0) + close(fd); + } + + return rc; +} + +static int +kwboot_bootmsg(int tty, void *msg) +{ + int rc; + char c; + + if (msg == NULL) + kwboot_printv("Please reboot the target into UART boot mode..."); + else + kwboot_printv("Sending boot message. Please reboot the target..."); + + do { + rc = tcflush(tty, TCIOFLUSH); + if (rc) + break; + + rc = kwboot_tty_send(tty, msg, 8); + if (rc) { + usleep(KWBOOT_MSG_REQ_DELAY * 1000); + continue; + } + + rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO); + + kwboot_spinner(); + + } while (rc || c != NAK); + + kwboot_printv("\n"); + + return rc; +} + +static int +kwboot_debugmsg(int tty, void *msg) +{ + int rc; + + kwboot_printv("Sending debug message. Please reboot the target..."); + + do { + char buf[16]; + + rc = tcflush(tty, TCIOFLUSH); + if (rc) + break; + + rc = kwboot_tty_send(tty, msg, 8); + if (rc) { + usleep(KWBOOT_MSG_REQ_DELAY * 1000); + continue; + } + + rc = kwboot_tty_recv(tty, buf, 16, KWBOOT_MSG_RSP_TIMEO); + + kwboot_spinner(); + + } while (rc); + + kwboot_printv("\n"); + + return rc; +} + +static int +kwboot_xm_makeblock(struct kwboot_block *block, const void *data, + size_t size, int pnum) +{ + const size_t blksz = sizeof(block->data); + size_t n; + int i; + + block->pnum = pnum; + block->_pnum = ~block->pnum; + + n = size < blksz ? size : blksz; + memcpy(&block->data[0], data, n); + memset(&block->data[n], 0, blksz - n); + + block->csum = 0; + for (i = 0; i < n; i++) + block->csum += block->data[i]; + + return n; +} + +static int +kwboot_xm_sendblock(int fd, struct kwboot_block *block) +{ + int rc, retries; + char c; + + retries = 16; + do { + rc = kwboot_tty_send(fd, block, sizeof(*block)); + if (rc) + break; + + do { + rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO); + if (rc) + break; + + if (c != ACK && c!= NAK && c != CAN) + printf("%c", c); + + } while (c != ACK && c != NAK && c != CAN); + + if (c != ACK) + kwboot_progress(-1, '+'); + + } while (c == NAK && retries-- > 0); + + rc = -1; + + switch (c) { + case ACK: + rc = 0; + break; + case NAK: + errno = EBADMSG; + break; + case CAN: + errno = ECANCELED; + break; + default: + errno = EPROTO; + break; + } + + return rc; +} + +static int +kwboot_xmodem(int tty, const void *_data, size_t size) +{ + const uint8_t *data = _data; + int rc, pnum, N, err; + + pnum = 1; + N = 0; + + kwboot_printv("Sending boot image...\n"); + + do { + struct kwboot_block block; + int n; + + n = kwboot_xm_makeblock(&block, + data + N, size - N, + pnum++); + if (n < 0) + goto can; + + if (!n) + break; + + rc = kwboot_xm_sendblock(tty, &block); + if (rc) + goto out; + + N += n; + kwboot_progress(N * 100 / size, '.'); + } while (1); + + rc = kwboot_tty_send_char(tty, EOT); + +out: + return rc; + +can: + err = errno; + kwboot_tty_send_char(tty, CAN); + errno = err; + goto out; +} + +static int +kwboot_term_pipe(int in, int out, char *quit, int *s) +{ + ssize_t nin, nout; + char _buf[128], *buf = _buf; + + nin = read(in, buf, sizeof(buf)); + if (nin < 0) + return -1; + + if (quit) { + int i; + + for (i = 0; i < nin; i++) { + if (*buf == quit[*s]) { + (*s)++; + if (!quit[*s]) + return 0; + buf++; + nin--; + } else + while (*s > 0) { + nout = write(out, quit, *s); + if (nout <= 0) + return -1; + (*s) -= nout; + } + } + } + + while (nin > 0) { + nout = write(out, buf, nin); + if (nout <= 0) + return -1; + nin -= nout; + } + + return 0; +} + +static int +kwboot_terminal(int tty) +{ + int rc, in, s; + char *quit = "\34c"; + struct termios otio, tio; + + rc = -1; + + in = STDIN_FILENO; + if (isatty(in)) { + rc = tcgetattr(in, &otio); + if (!rc) { + tio = otio; + cfmakeraw(&tio); + rc = tcsetattr(in, TCSANOW, &tio); + } + if (rc) { + perror("tcsetattr"); + goto out; + } + + kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n", + quit[0]|0100, quit[1]); + } else + in = -1; + + rc = 0; + s = 0; + + do { + fd_set rfds; + int nfds = 0; + + FD_SET(tty, &rfds); + nfds = nfds < tty ? tty : nfds; + + if (in >= 0) { + FD_SET(in, &rfds); + nfds = nfds < in ? in : nfds; + } + + nfds = select(nfds + 1, &rfds, NULL, NULL, NULL); + if (nfds < 0) + break; + + if (FD_ISSET(tty, &rfds)) { + rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL); + if (rc) + break; + } + + if (FD_ISSET(in, &rfds)) { + rc = kwboot_term_pipe(in, tty, quit, &s); + if (rc) + break; + } + } while (quit[s] != 0); + + tcsetattr(in, TCSANOW, &otio); +out: + return rc; +} + +static void * +kwboot_mmap_image(const char *path, size_t *size, int prot) +{ + int rc, fd, flags; + struct stat st; + void *img; + + rc = -1; + fd = -1; + img = NULL; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto out; + + rc = fstat(fd, &st); + if (rc) + goto out; + + flags = (prot & PROT_WRITE) ? MAP_PRIVATE : MAP_SHARED; + + img = mmap(NULL, st.st_size, prot, flags, fd, 0); + if (img == MAP_FAILED) { + img = NULL; + goto out; + } + + rc = 0; + *size = st.st_size; +out: + if (rc && img) { + munmap(img, st.st_size); + img = NULL; + } + if (fd >= 0) + close(fd); + + return img; +} + +static void +kwboot_usage(FILE *stream, char *progname) +{ + fprintf(stream, + "Usage: %s [-d | -b <image> | -D <image> ] [ -t ] [-B <baud> ] <TTY>\n", + progname); + fprintf(stream, "\n"); + fprintf(stream, + " -b <image>: boot <image> with preamble (Kirkwood, Armada 370/XP)\n"); + fprintf(stream, + " -D <image>: boot <image> without preamble (Dove)\n"); + fprintf(stream, " -d: enter debug mode\n"); + fprintf(stream, "\n"); + fprintf(stream, " -t: mini terminal\n"); + fprintf(stream, "\n"); + fprintf(stream, " -B <baud>: set baud rate\n"); + fprintf(stream, "\n"); +} + +int +main(int argc, char **argv) +{ + const char *ttypath, *imgpath; + int rv, rc, tty, term; + void *bootmsg; + void *debugmsg; + void *img; + size_t size; + speed_t speed; + + rv = 1; + tty = -1; + bootmsg = NULL; + debugmsg = NULL; + imgpath = NULL; + img = NULL; + term = 0; + size = 0; + speed = B115200; + + kwboot_verbose = isatty(STDOUT_FILENO); + + do { + int c = getopt(argc, argv, "hb:dtB:D:"); + if (c < 0) + break; + + switch (c) { + case 'b': + bootmsg = kwboot_msg_boot; + imgpath = optarg; + break; + + case 'D': + bootmsg = NULL; + imgpath = optarg; + break; + + case 'd': + debugmsg = kwboot_msg_debug; + break; + + case 't': + term = 1; + break; + + case 'B': + speed = kwboot_tty_speed(atoi(optarg)); + if (speed == -1) + goto usage; + break; + + case 'h': + rv = 0; + default: + goto usage; + } + } while (1); + + if (!bootmsg && !term && !debugmsg) + goto usage; + + if (argc - optind < 1) + goto usage; + + ttypath = argv[optind++]; + + tty = kwboot_open_tty(ttypath, speed); + if (tty < 0) { + perror(ttypath); + goto out; + } + + if (imgpath) { + img = kwboot_mmap_image(imgpath, &size, PROT_READ); + if (!img) { + perror(imgpath); + goto out; + } + } + + if (debugmsg) { + rc = kwboot_debugmsg(tty, debugmsg); + if (rc) { + perror("debugmsg"); + goto out; + } + } else { + rc = kwboot_bootmsg(tty, bootmsg); + if (rc) { + perror("bootmsg"); + goto out; + } + } + + if (img) { + rc = kwboot_xmodem(tty, img, size); + if (rc) { + perror("xmodem"); + goto out; + } + } + + if (term) { + rc = kwboot_terminal(tty); + if (rc && !(errno == EINTR)) { + perror("terminal"); + goto out; + } + } + + rv = 0; +out: + if (tty >= 0) + close(tty); + + if (img) + munmap(img, size); + + return rv; + +usage: + kwboot_usage(rv ? stderr : stdout, basename(argv[0])); + goto out; +} |