#
# Normal rules
#
-
-*.rej
-*.orig
-*.a
+.*
*.o
+*.o.*
+*.a
+*.s
*.su
-*~
+*.mod.c
+*.i
+*.lst
+*.order
+*.elf
*.swp
-*.patch
*.bin
+*.patch
*.cfgtmp
-*.dts.tmp
+
+# host programs on Cygwin
+*.exe
# Build tree
/build-*
#
# Top-level generic files
#
-
-/MLO
+/MLO*
/SPL
/System.map
-/u-boot
-/u-boot.hex
-/u-boot.imx
-/u-boot-with-spl.imx
-/u-boot-with-nand-spl.imx
-/u-boot.map
-/u-boot.srec
-/u-boot.ldr
-/u-boot.ldr.hex
-/u-boot.ldr.srec
-/u-boot.img
-/u-boot.kwb
-/u-boot.sha1
-/u-boot.dis
-/u-boot.lds
-/u-boot.ubl
-/u-boot.ais
-/u-boot.dtb
-/u-boot.sb
-/u-boot.bd
-/u-boot.geany
+/u-boot*
+/boards.cfg
#
-# Generated files
+# git files that we don't want to ignore even it they are dot-files
#
+!.gitignore
+!.mailmap
-*.depend*
+#
+# Generated files
+#
/LOG
-/errlog
-/reloc_off
+/spl/
+/tpl/
+#
+# Generated include files
+#
+/include/config/
/include/generated/
-asm-offsets.s
# stgit generated dirs
patches-*
# quilt's files
patches
series
+ .pc
# gdb files
.gdb_history
GSYMS
GTAGS
-# spl ais files
-/spl/*.ais
+*.orig
+*~
+\#*#
--- /dev/null
- depends on $KCONFIG_OBJDIR="spl" || $KCONFIG_OBJDIR="tpl"
- default y
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+mainmenu "U-Boot $UBOOTVERSION Configuration"
+
+config UBOOTVERSION
+ string
+ option env="UBOOTVERSION"
+
+config KCONFIG_OBJDIR
+ string
+ option env="KCONFIG_OBJDIR"
+
+menu "General setup"
+
+config LOCALVERSION
+ string "Local version - append to U-Boot release"
+ depends on !SPL_BUILD
+ help
+ Append an extra string to the end of your U-Boot version.
+ This will show up on your boot log, for example.
+ The string you set here will be appended after the contents of
+ any files with a filename matching localversion* in your
+ object and source tree, in that order. Your total string can
+ be a maximum of 64 characters.
+
+config LOCALVERSION_AUTO
+ bool "Automatically append version information to the version string"
+ depends on !SPL_BUILD
+ default y
+ help
+ This will try to automatically determine if the current tree is a
+ release tree by looking for git tags that belong to the current
+ top of tree revision.
+
+ A string of the format -gxxxxxxxx will be added to the localversion
+ if a git-based tree is found. The string generated by this will be
+ appended after any matching localversion* files, and after the value
+ set in CONFIG_LOCALVERSION.
+
+ (The actual string used here is the first eight characters produced
+ by running the command:
+
+ $ git rev-parse --verify HEAD
+
+ which is done within the script "scripts/setlocalversion".)
+
+config CC_OPTIMIZE_FOR_SIZE
+ bool "Optimize for size"
+ depends on !SPL_BUILD
+ default y
+ help
+ Enabling this option will pass "-Os" instead of "-O2" to gcc
+ resulting in a smaller U-Boot image.
+
+ This option is enabled by default for U-Boot.
+
+menuconfig EXPERT
+ bool "Configure standard U-Boot features (expert users)"
+ help
+ This option allows certain base U-Boot options and settings
+ to be disabled or tweaked. This is for specialized
+ environments which can tolerate a "non-standard" U-Boot.
+ Only use this if you really know what you are doing.
+
+endmenu # General setup
+
+menu "Boot images"
+
+config SPL_BUILD
+ bool
++ default y if $KCONFIG_OBJDIR="spl" || $KCONFIG_OBJDIR="tpl"
+
+config TPL_BUILD
+ bool
+ depends on $KCONFIG_OBJDIR="tpl"
+ default y
+
+config SUPPORT_SPL
+ bool
+
+config SUPPORT_TPL
+ bool
+
+config SPL
+ bool
+ depends on SUPPORT_SPL
+ prompt "Enable SPL" if !SPL_BUILD
+ default y if SPL_BUILD
+ help
+ If you want to build SPL as well as the normal image, say Y.
+
+config TPL
+ bool
+ depends on SPL && SUPPORT_TPL
+ prompt "Enable TPL" if !SPL_BUILD
+ default y if TPL_BUILD
+ default n
+ help
+ If you want to build TPL as well as the normal image and SPL, say Y.
+
+config FIT
+ bool "Support Flattened Image Tree"
+ depends on !SPL_BUILD
+ help
+ This option allows to boot the new uImage structrure,
+ Flattened Image Tree. FIT is formally a FDT, which can include
+ images of various types (kernel, FDT blob, ramdisk, etc.)
+ in a single blob. To boot this new uImage structure,
+ pass the the address of the blob to the "bootm" command.
+
+config FIT_VERBOSE
+ bool "Display verbose messages on FIT boot"
+ depends on FIT
+
+config FIT_SIGNATURE
+ bool "Enabel signature verification of FIT uImages"
+ depends on FIT
+ help
+ This option enables signature verification of FIT uImages,
+ using a hash signed and verified using RSA.
+ See doc/uImage.FIT/signature.txt for more details.
+
+config SYS_EXTRA_OPTIONS
+ string "Extra Options (DEPRECATED)"
+ depends on !SPL_BUILD
+ help
+ The old configuration infrastructure (= mkconfig + boards.cfg)
+ provided the extra options field. If you have something like
+ "HAS_BAR,BAZ=64", the optional options
+ #define CONFIG_HAS
+ #define CONFIG_BAZ 64
+ will be defined in include/config.h.
+ This option was prepared for the smooth migration from the old
+ configuration to Kconfig. Since this option will be removed sometime,
+ new boards should not use this option.
+
+config SYS_TEXT_BASE
+ depends on SPARC
+ hex "Text Base"
+ help
+ TODO: Move CONFIG_SYS_TEXT_BASE for all the architecture
+
+endmenu # Boot images
+
+source "arch/Kconfig"
+
+source "common/Kconfig"
+
+source "dts/Kconfig"
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "lib/Kconfig"
"working". In fact, many of them are used in production systems.
In case of problems see the CHANGELOG and CREDITS files to find out
-who contributed the specific port. The MAINTAINERS file lists board
+who contributed the specific port. The boards.cfg file lists board
maintainers.
Note: There is no CHANGELOG file in the actual U-Boot source tree;
====================
/arch Architecture specific files
+ /arc Files generic to ARC architecture
+ /cpu CPU specific files
+ /arc700 Files specific to ARC 700 CPUs
+ /lib Architecture specific library files
/arm Files generic to ARM architecture
/cpu CPU specific files
/arm720t Files specific to ARM 720 CPUs
/at91 Files specific to Atmel AT91RM9200 CPU
/imx Files specific to Freescale MC9328 i.MX CPUs
/s3c24x0 Files specific to Samsung S3C24X0 CPUs
- /arm925t Files specific to ARM 925 CPUs
/arm926ejs Files specific to ARM 926 CPUs
/arm1136 Files specific to ARM 1136 CPUs
- /ixp Files specific to Intel XScale IXP CPUs
/pxa Files specific to Intel XScale PXA CPUs
- /s3c44b0 Files specific to Samsung S3C44B0 CPUs
/sa1100 Files specific to Intel StrongARM SA1100 CPUs
/lib Architecture specific library files
/avr32 Files generic to AVR32 architecture
/blackfin Files generic to Analog Devices Blackfin architecture
/cpu CPU specific files
/lib Architecture specific library files
- /x86 Files generic to x86 architecture
- /cpu CPU specific files
- /lib Architecture specific library files
/m68k Files generic to m68k architecture
/cpu CPU specific files
/mcf52x2 Files specific to Freescale ColdFire MCF52x2 CPUs
/mips Files generic to MIPS architecture
/cpu CPU specific files
/mips32 Files specific to MIPS32 CPUs
- /xburst Files specific to Ingenic XBurst CPUs
+ /mips64 Files specific to MIPS64 CPUs
/lib Architecture specific library files
/nds32 Files generic to NDS32 architecture
/cpu CPU specific files
/nios2 Files generic to Altera NIOS2 architecture
/cpu CPU specific files
/lib Architecture specific library files
+ /openrisc Files generic to OpenRISC architecture
+ /cpu CPU specific files
+ /lib Architecture specific library files
/powerpc Files generic to PowerPC architecture
/cpu CPU specific files
/74xx_7xx Files specific to Freescale MPC74xx and 7xx CPUs
/mpc5xx Files specific to Freescale MPC5xx CPUs
/mpc5xxx Files specific to Freescale MPC5xxx CPUs
/mpc8xx Files specific to Freescale MPC8xx CPUs
- /mpc824x Files specific to Freescale MPC824x CPUs
/mpc8260 Files specific to Freescale MPC8260 CPUs
/mpc85xx Files specific to Freescale MPC85xx CPUs
/ppc4xx Files specific to AMCC PowerPC 4xx CPUs
/leon2 Files specific to Gaisler LEON2 SPARC CPU
/leon3 Files specific to Gaisler LEON3 SPARC CPU
/lib Architecture specific library files
+ /x86 Files generic to x86 architecture
+ /cpu CPU specific files
+ /lib Architecture specific library files
/api Machine/arch independent API for external apps
/board Board dependent files
/common Misc architecture independent functions
/disk Code for disk drive partition handling
/doc Documentation (don't expect too much)
/drivers Commonly used device drivers
+/dts Contains Makefile for building internal U-Boot fdt.
/examples Example code for standalone applications, etc.
/fs Filesystem code (cramfs, ext2, jffs2, etc.)
/include Header Files
/lzo Library files to support LZO decompression
/net Networking code
/post Power On Self Test
-/rtc Real Time Clock drivers
+/spl Secondary Program Loader framework
/tools Tools to build S-Record or U-Boot images, etc.
Software Configuration:
---------------------------------------------------
For all supported boards there are ready-to-use default
-configurations available; just type "make <board_name>_config".
+configurations available; just type "make <board_name>_defconfig".
Example: For a TQM823L module type:
cd u-boot
- make TQM823L_config
+ make TQM823L_defconfig
For the Cogent platform, you need to specify the CPU type as well;
-e.g. "make cogent_mpc8xx_config". And also configure the cogent
+e.g. "make cogent_mpc8xx_defconfig". And also configure the cogent
directory according to the instructions in cogent/README.
+Sandbox Environment:
+--------------------
+
+U-Boot can be built natively to run on a Linux host using the 'sandbox'
+board. This allows feature development which is not board- or architecture-
+specific to be undertaken on a native platform. The sandbox is also used to
+run some of U-Boot's tests.
+
+See board/sandbox/README.sandbox for more details.
+
+
Configuration Options:
----------------------
the LCD display every second with
a "rotator" |\-/|\-/
-- Board flavour: (if CONFIG_MPC8260ADS is defined)
- CONFIG_ADSTYPE
- Possible values are:
- CONFIG_SYS_8260ADS - original MPC8260ADS
- CONFIG_SYS_8266ADS - MPC8266ADS
- CONFIG_SYS_PQ2FADS - PQ2FADS-ZU or PQ2FADS-VR
- CONFIG_SYS_8272ADS - MPC8272ADS
-
- Marvell Family Member
CONFIG_SYS_MVFS - define it if you want to enable
multiple fs option at one time
for marvell soc family
-- MPC824X Family Member (if CONFIG_MPC824X is defined)
- Define exactly one of
- CONFIG_MPC8240, CONFIG_MPC8245
-
- 8xx CPU Options: (if using an MPC8xx CPU)
CONFIG_8xx_GCLK_FREQ - deprecated: CPU clock if
get_gclk_freq() cannot work
CONFIG_A003399_NOR_WORKAROUND
Enables a workaround for IFC erratum A003399. It is only
- requred during NOR boot.
+ required during NOR boot.
+
+ CONFIG_A008044_WORKAROUND
+ Enables a workaround for T1040/T1042 erratum A008044. It is only
+ required during NAND boot and valid for Rev 1.0 SoC revision
CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
This is the value to write into CCSR offset 0x18600
according to the A004510 workaround.
+ CONFIG_SYS_FSL_DSP_DDR_ADDR
+ This value denotes start offset of DDR memory which is
+ connected exclusively to the DSP cores.
+
CONFIG_SYS_FSL_DSP_M2_RAM_ADDR
This value denotes start offset of M2 memory
which is directly connected to the DSP core.
+ CONFIG_SYS_FSL_DSP_M3_RAM_ADDR
+ This value denotes start offset of M3 memory which is directly
+ connected to the DSP core.
+
CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
This value denotes start offset of DSP CCSR space.
+ CONFIG_SYS_FSL_SINGLE_SOURCE_CLK
+ Single Source Clock is clocking mode present in some of FSL SoC's.
+ In this mode, a single differential clock is used to supply
+ clocks to the sysclock, ddrclock and usbclock.
+
+ CONFIG_SYS_CPC_REINIT_F
+ This CONFIG is defined when the CPC is configured as SRAM at the
+ time of U-boot entry and is required to be re-initialized.
+
+ CONFIG_DEEP_SLEEP
+ Indicates this SoC supports deep sleep feature. If deep sleep is
+ supported, core will start to execute uboot when wakes up.
+
- Generic CPU options:
+ CONFIG_SYS_GENERIC_GLOBAL_DATA
+ Defines global data is initialized in generic board board_init_f().
+ If this macro is defined, global data is created and cleared in
+ generic board board_init_f(). Without this macro, architecture/board
+ should initialize global data before calling board_init_f().
+
CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN
Defines the endianess of the CPU. Implementation of those
values is arch specific.
+ CONFIG_SYS_FSL_DDR
+ Freescale DDR driver in use. This type of DDR controller is
+ found in mpc83xx, mpc85xx, mpc86xx as well as some ARM core
+ SoCs.
+
+ CONFIG_SYS_FSL_DDR_ADDR
+ Freescale DDR memory-mapped register base.
+
+ CONFIG_SYS_FSL_DDR_EMU
+ Specify emulator support for DDR. Some DDR features such as
+ deskew training are not available.
+
+ CONFIG_SYS_FSL_DDRC_GEN1
+ Freescale DDR1 controller.
+
+ CONFIG_SYS_FSL_DDRC_GEN2
+ Freescale DDR2 controller.
+
+ CONFIG_SYS_FSL_DDRC_GEN3
+ Freescale DDR3 controller.
+
+ CONFIG_SYS_FSL_DDRC_GEN4
+ Freescale DDR4 controller.
+
+ CONFIG_SYS_FSL_DDRC_ARM_GEN3
+ Freescale DDR3 controller for ARM-based SoCs.
+
+ CONFIG_SYS_FSL_DDR1
+ Board config to use DDR1. It can be enabled for SoCs with
+ Freescale DDR1 or DDR2 controllers, depending on the board
+ implemetation.
+
+ CONFIG_SYS_FSL_DDR2
+ Board config to use DDR2. It can be eanbeld for SoCs with
+ Freescale DDR2 or DDR3 controllers, depending on the board
+ implementation.
+
+ CONFIG_SYS_FSL_DDR3
+ Board config to use DDR3. It can be enabled for SoCs with
+ Freescale DDR3 or DDR3L controllers.
+
+ CONFIG_SYS_FSL_DDR3L
+ Board config to use DDR3L. It can be enabled for SoCs with
+ DDR3L controllers.
+
+ CONFIG_SYS_FSL_DDR4
+ Board config to use DDR4. It can be enabled for SoCs with
+ DDR4 controllers.
+
+ CONFIG_SYS_FSL_IFC_BE
+ Defines the IFC controller register space as Big Endian
+
+ CONFIG_SYS_FSL_IFC_LE
+ Defines the IFC controller register space as Little Endian
+
+ CONFIG_SYS_FSL_PBL_PBI
+ It enables addition of RCW (Power on reset configuration) in built image.
+ Please refer doc/README.pblimage for more details
+
+ CONFIG_SYS_FSL_PBL_RCW
+ It adds PBI(pre-boot instructions) commands in u-boot build image.
+ PBI commands can be used to configure SoC before it starts the execution.
+ Please refer doc/README.pblimage for more details
+
+ CONFIG_SPL_FSL_PBL
+ It adds a target to create boot binary having SPL binary in PBI format
+ concatenated with u-boot binary.
+
+ CONFIG_SYS_FSL_DDR_BE
+ Defines the DDR controller register space as Big Endian
+
+ CONFIG_SYS_FSL_DDR_LE
+ Defines the DDR controller register space as Little Endian
+
+ CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY
+ Physical address from the view of DDR controllers. It is the
+ same as CONFIG_SYS_DDR_SDRAM_BASE for all Power SoCs. But
+ it could be different for ARM SoCs.
+
+ CONFIG_SYS_FSL_DDR_INTLV_256B
+ DDR controller interleaving on 256-byte. This is a special
+ interleaving mode, handled by Dickens for Freescale layerscape
+ SoCs with ARM core.
+
+ CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS
+ Number of controllers used as main memory.
+
+ CONFIG_SYS_FSL_OTHER_DDR_NUM_CTRLS
+ Number of controllers used for other than main memory.
+
+ CONFIG_SYS_FSL_SEC_BE
+ Defines the SEC controller register space as Big Endian
+
+ CONFIG_SYS_FSL_SEC_LE
+ Defines the SEC controller register space as Little Endian
+
- Intel Monahans options:
CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO
CONFIG_ARM_ERRATA_742230
CONFIG_ARM_ERRATA_743622
CONFIG_ARM_ERRATA_751472
+ CONFIG_ARM_ERRATA_794072
+ CONFIG_ARM_ERRATA_761320
If set, the workarounds for these ARM errata are applied early
during U-Boot startup. Note that these options force the
exists, unlike the similar options in the Linux kernel. Do not
set these options unless they apply!
-- CPU timer options:
- CONFIG_SYS_HZ
+- Driver Model
+ Driver model is a new framework for devices in U-Boot
+ introduced in early 2014. U-Boot is being progressively
+ moved over to this. It offers a consistent device structure,
+ supports grouping devices into classes and has built-in
+ handling of platform data and device tree.
+
+ To enable transition to driver model in a relatively
+ painful fashion, each subsystem can be independently
+ switched between the legacy/ad-hoc approach and the new
+ driver model using the options below. Also, many uclass
+ interfaces include compatibility features which may be
+ removed once the conversion of that subsystem is complete.
+ As a result, the API provided by the subsystem may in fact
+ not change with driver model.
+
+ See doc/driver-model/README.txt for more information.
+
+ CONFIG_DM
+
+ Enable driver model. This brings in the core support,
+ including scanning of platform data on start-up. If
+ CONFIG_OF_CONTROL is enabled, the device tree will be
+ scanned also when available.
+
+ CONFIG_CMD_DM
+
+ Enable driver model test commands. These allow you to print
+ out the driver model tree and the uclasses.
+
+ CONFIG_DM_DEMO
+
+ Enable some demo devices and the 'demo' command. These are
+ really only useful for playing around while trying to
+ understand driver model in sandbox.
+
+ CONFIG_SPL_DM
+
+ Enable driver model in SPL. You will need to provide a
+ suitable malloc() implementation. If you are not using the
+ full malloc() enabled by CONFIG_SYS_SPL_MALLOC_START,
+ consider using CONFIG_SYS_MALLOC_SIMPLE. In that case you
+ must provide CONFIG_SYS_MALLOC_F_LEN to set the size.
+ In most cases driver model will only allocate a few uclasses
+ and devices in SPL, so 1KB should be enable. See
+ CONFIG_SYS_MALLOC_F_LEN for more details on how to enable
+ it.
+
+ CONFIG_DM_SERIAL
+
+ Enable driver model for serial. This replaces
+ drivers/serial/serial.c with the serial uclass, which
+ implements serial_putc() etc. The uclass interface is
+ defined in include/serial.h.
+
+ CONFIG_DM_GPIO
+
+ Enable driver model for GPIO access. The standard GPIO
+ interface (gpio_get_value(), etc.) is then implemented by
+ the GPIO uclass. Drivers provide methods to query the
+ particular GPIOs that they provide. The uclass interface
+ is defined in include/asm-generic/gpio.h.
+
+ CONFIG_DM_SPI
+
+ Enable driver model for SPI. The SPI slave interface
+ (spi_setup_slave(), spi_xfer(), etc.) is then implemented by
+ the SPI uclass. Drivers provide methods to access the SPI
+ buses that they control. The uclass interface is defined in
+ include/spi.h. The existing spi_slave structure is attached
+ as 'parent data' to every slave on each bus. Slaves
+ typically use driver-private data instead of extending the
+ spi_slave structure.
+
+ CONFIG_DM_SPI_FLASH
+
+ Enable driver model for SPI flash. This SPI flash interface
+ (spi_flash_probe(), spi_flash_write(), etc.) is then
+ implemented by the SPI flash uclass. There is one standard
+ SPI flash driver which knows how to probe most chips
+ supported by U-Boot. The uclass interface is defined in
+ include/spi_flash.h, but is currently fully compatible
+ with the old interface to avoid confusion and duplication
+ during the transition parent. SPI and SPI flash must be
+ enabled together (it is not possible to use driver model
+ for one and not the other).
+
+ CONFIG_DM_CROS_EC
+
+ Enable driver model for the Chrome OS EC interface. This
+ allows the cros_ec SPI driver to operate with CONFIG_DM_SPI
+ but otherwise makes few changes. Since cros_ec also supports
+ I2C and LPC (which don't support driver model yet), a full
+ conversion is not yet possible.
+
+
+ ** Code size options: The following options are enabled by
+ default except in SPL. Enable them explicitly to get these
+ features in SPL.
+
+ CONFIG_DM_WARN
+
+ Enable the dm_warn() function. This can use up quite a bit
+ of space for its strings.
+
+ CONFIG_DM_STDIO
+
+ Enable registering a serial device with the stdio library.
+
+ CONFIG_DM_DEVICE_REMOVE
+
+ Enable removing of devices.
- The frequency of the timer returned by get_timer().
- get_timer() must operate in milliseconds and this CONFIG
- option must be set to 1000.
- Linux Kernel Interface:
CONFIG_CLOCKS_IN_MHZ
CONFIG_MEMSIZE_IN_BYTES [relevant for MIPS only]
- When transferring memsize parameter to linux, some versions
+ When transferring memsize parameter to Linux, some versions
expect it to be in bytes, others in MB.
Define CONFIG_MEMSIZE_IN_BYTES to make it in bytes.
Board code has addition modification that it wants to make
to the flat device tree before handing it off to the kernel
+ CONFIG_OF_SYSTEM_SETUP
+
+ Other code has addition modification that it wants to make
+ to the flat device tree before handing it off to the kernel.
+ This causes ft_system_setup() to be called before booting
+ the kernel.
+
CONFIG_OF_BOOT_CPU
This define fills in the correct boot CPU in the boot
boot loader that has already initialized the UART. Define this
variable to flush the UART at init time.
+ CONFIG_SERIAL_HW_FLOW_CONTROL
+
+ Define this variable to enable hw flow control in serial driver.
+ Current user of this option is drivers/serial/nsl16550.c driver
- Console Interface:
Depending on board, define exactly one serial port
the "silent" environment variable. See
doc/README.silent for more information.
+ CONFIG_SYS_CONSOLE_BG_COL: define the backgroundcolor, default
+ is 0x00.
+ CONFIG_SYS_CONSOLE_FG_COL: define the foregroundcolor, default
+ is 0xa0.
+
- Console Baudrate:
CONFIG_BAUDRATE - in bps
Select one of the baudrates listed in
as a convenience, when switching between booting from
RAM and NFS.
+- Bootcount:
+ CONFIG_BOOTCOUNT_LIMIT
+ Implements a mechanism for detecting a repeating reboot
+ cycle, see:
+ http://www.denx.de/wiki/view/DULG/UBootBootCountLimit
+
+ CONFIG_BOOTCOUNT_ENV
+ If no softreset save registers are found on the hardware
+ "bootcount" is stored in the environment. To prevent a
+ saveenv on all reboots, the environment variable
+ "upgrade_available" is used. If "upgrade_available" is
+ 0, "bootcount" is always 0, if "upgrade_available" is
+ 1 "bootcount" is incremented in the environment.
+ So the Userspace Applikation must set the "upgrade_available"
+ and "bootcount" variable to 0, if a boot was successfully.
+
- Pre-Boot Commands:
CONFIG_PREBOOT
The default command configuration includes all commands
except those marked below with a "*".
+ CONFIG_CMD_AES AES 128 CBC encrypt/decrypt
CONFIG_CMD_ASKENV * ask for env variable
CONFIG_CMD_BDI bdinfo
CONFIG_CMD_BEDBUG * Include BedBug Debugger
CONFIG_CMD_BMP * BMP support
CONFIG_CMD_BSP * Board specific commands
CONFIG_CMD_BOOTD bootd
+ CONFIG_CMD_BOOTI * ARM64 Linux kernel Image support
CONFIG_CMD_CACHE * icache, dcache
+ CONFIG_CMD_CLK * clock command support
CONFIG_CMD_CONSOLE coninfo
CONFIG_CMD_CRC32 * crc32
CONFIG_CMD_DATE * support for RTC, date/time...
CONFIG_CMD_ELF * bootelf, bootvx
CONFIG_CMD_ENV_CALLBACK * display details about env callbacks
CONFIG_CMD_ENV_FLAGS * display details about env flags
+ CONFIG_CMD_ENV_EXISTS * check existence of env variable
CONFIG_CMD_EXPORTENV * export the environment
CONFIG_CMD_EXT2 * ext2 command support
CONFIG_CMD_EXT4 * ext4 command support
+ CONFIG_CMD_FS_GENERIC * filesystem commands (e.g. load, ls)
+ that work for multiple fs types
+ CONFIG_CMD_FS_UUID * Look up a filesystem UUID
CONFIG_CMD_SAVEENV saveenv
CONFIG_CMD_FDC * Floppy Disk Support
CONFIG_CMD_FAT * FAT command support
- CONFIG_CMD_FDOS * Dos diskette Support
CONFIG_CMD_FLASH flinfo, erase, protect
CONFIG_CMD_FPGA FPGA device initialization support
CONFIG_CMD_FUSE * Device fuse support
CONFIG_CMD_IMLS List all images found in NOR flash
CONFIG_CMD_IMLS_NAND * List all images found in NAND flash
CONFIG_CMD_IMMAP * IMMR dump support
+ CONFIG_CMD_IOTRACE * I/O tracing for debugging
CONFIG_CMD_IMPORTENV * import an environment
CONFIG_CMD_INI * import data from an ini file into the env
CONFIG_CMD_IRQ * irqinfo
CONFIG_CMD_CDP * Cisco Discover Protocol support
CONFIG_CMD_MFSL * Microblaze FSL support
CONFIG_CMD_XIMG Load part of Multi Image
-
+ CONFIG_CMD_UUID * Generate random UUID or GUID string
EXAMPLE: If you want all functions except of network
support you can write:
- Regular expression support:
CONFIG_REGEX
- If this variable is defined, U-Boot is linked against
- the SLRE (Super Light Regular Expression) library,
- which adds regex support to some commands, as for
- example "env grep" and "setexpr".
+ If this variable is defined, U-Boot is linked against
+ the SLRE (Super Light Regular Expression) library,
+ which adds regex support to some commands, as for
+ example "env grep" and "setexpr".
- Device tree:
CONFIG_OF_CONTROL
CONFIG_RTC_DS1307 - use Maxim, Inc. DS1307 RTC
CONFIG_RTC_DS1337 - use Maxim, Inc. DS1337 RTC
CONFIG_RTC_DS1338 - use Maxim, Inc. DS1338 RTC
+ CONFIG_RTC_DS1339 - use Maxim, Inc. DS1339 RTC
CONFIG_RTC_DS164x - use Dallas DS164x RTC
CONFIG_RTC_ISL1208 - use Intersil ISL1208 RTC
CONFIG_RTC_MAX6900 - use Maxim, Inc. MAX6900 RTC
- GPIO Support:
CONFIG_PCA953X - use NXP's PCA953X series I2C GPIO
- CONFIG_PCA953X_INFO - enable pca953x info command
The CONFIG_SYS_I2C_PCA953X_WIDTH option specifies a list of
chip-ngpio pairs that tell the PCA953X driver the number of
Note that if the GPIO device uses I2C, then the I2C interface
must also be configured. See I2C Support, below.
+- I/O tracing:
+ When CONFIG_IO_TRACE is selected, U-Boot intercepts all I/O
+ accesses and can checksum them or write a list of them out
+ to memory. See the 'iotrace' command for details. This is
+ useful for testing device drivers since it can confirm that
+ the driver behaves the same way before and after a code
+ change. Currently this is supported on sandbox and arm. To
+ add support for your architecture, add '#include <iotrace.h>'
+ to the bottom of arch/<arch>/include/asm/io.h and test.
+
+ Example output from the 'iotrace stats' command is below.
+ Note that if the trace buffer is exhausted, the checksum will
+ still continue to operate.
+
+ iotrace is enabled
+ Start: 10000000 (buffer start address)
+ Size: 00010000 (buffer size)
+ Offset: 00000120 (current buffer offset)
+ Output: 10000120 (start + offset)
+ Count: 00000018 (number of trace records)
+ CRC32: 9526fb66 (CRC32 of all trace records)
+
- Timestamp Support:
When CONFIG_TIMESTAMP is selected, the timestamp
devices.
CONFIG_SYS_SCSI_SYM53C8XX_CCF to fix clock timing (80Mhz)
- The environment variable 'scsidevs' is set to the number of
- SCSI devices found during the last scan.
+ The environment variable 'scsidevs' is set to the number of
+ SCSI devices found during the last scan.
- NETWORK Support (PCI):
CONFIG_E1000
CONFIG_SH_ETHER_CACHE_WRITEBACK
If this option is set, the driver enables cache flush.
+- PWM Support:
+ CONFIG_PWM_IMX
+ Support for PWM modul on the imx6.
+
- TPM Support:
CONFIG_TPM
Support TPM devices.
CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the
txfilltuning field in the EHCI controller on reset.
- CONFIG_USB_HUB_MIN_POWER_ON_DELAY defines the minimum
- interval for usb hub power-on delay.(minimum 100msec)
+ CONFIG_USB_DWC2_REG_ADDR the physical CPU address of the DWC2
+ HW module registers.
- USB Device:
Define the below if you wish to use the USB console.
CONFIG_SH_MMCIF_CLK
Define the clock frequency for MMCIF
+ CONFIG_GENERIC_MMC
+ Enable the generic MMC driver
+
+ CONFIG_SUPPORT_EMMC_BOOT
+ Enable some additional features of the eMMC boot partitions.
+
+ CONFIG_SUPPORT_EMMC_RPMB
+ Enable the commands for reading, writing and programming the
+ key for the Replay Protection Memory Block partition in eMMC.
+
- USB Device Firmware Update (DFU) class support:
CONFIG_DFU_FUNCTION
This enables the USB portion of the DFU USB class
CONFIG_DFU_NAND
This enables support for exposing NAND devices via DFU.
+ CONFIG_DFU_RAM
+ This enables support for exposing RAM via DFU.
+ Note: DFU spec refer to non-volatile memory usage, but
+ allow usages beyond the scope of spec - here RAM usage,
+ one that would help mostly the developer.
+
CONFIG_SYS_DFU_DATA_BUF_SIZE
Dfu transfer uses a buffer before writing data to the
raw storage device. Make the size (in bytes) of this buffer
this to the maximum filesize (in bytes) for the buffer.
Default is 4 MiB if undefined.
+ DFU_DEFAULT_POLL_TIMEOUT
+ Poll timeout [ms], is the timeout a device can send to the
+ host. The host must wait for this timeout before sending
+ a subsequent DFU_GET_STATUS request to the device.
+
+ DFU_MANIFEST_POLL_TIMEOUT
+ Poll timeout [ms], which the device sends to the host when
+ entering dfuMANIFEST state. Host waits this timeout, before
+ sending again an USB request to the device.
+
+- USB Device Android Fastboot support:
+ CONFIG_CMD_FASTBOOT
+ This enables the command "fastboot" which enables the Android
+ fastboot mode for the platform's USB device. Fastboot is a USB
+ protocol for downloading images, flashing and device control
+ used on Android devices.
+ See doc/README.android-fastboot for more information.
+
+ CONFIG_ANDROID_BOOT_IMAGE
+ This enables support for booting images which use the Android
+ image format header.
+
+ CONFIG_USB_FASTBOOT_BUF_ADDR
+ The fastboot protocol requires a large memory buffer for
+ downloads. Define this to the starting RAM address to use for
+ downloaded images.
+
+ CONFIG_USB_FASTBOOT_BUF_SIZE
+ The fastboot protocol requires a large memory buffer for
+ downloads. This buffer should be as large as possible for a
+ platform. Define this to the size available RAM for fastboot.
+
+ CONFIG_FASTBOOT_FLASH
+ The fastboot protocol includes a "flash" command for writing
+ the downloaded image to a non-volatile storage device. Define
+ this to enable the "fastboot flash" command.
+
+ CONFIG_FASTBOOT_FLASH_MMC_DEV
+ The fastboot "flash" command requires additional information
+ regarding the non-volatile storage device. Define this to
+ the eMMC device that fastboot should use to store the image.
+
+ CONFIG_FASTBOOT_GPT_NAME
+ The fastboot "flash" command supports writing the downloaded
+ image to the Protective MBR and the Primary GUID Partition
+ Table. (Additionally, this downloaded image is post-processed
+ to generate and write the Backup GUID Partition Table.)
+ This occurs when the specified "partition name" on the
+ "fastboot flash" command line matches this value.
+ Default is GPT_ENTRY_NAME (currently "gpt") if undefined.
+
- Journaling Flash filesystem support:
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
CONFIG_JFFS2_NAND_DEV
filesystem. Available commands are cbfsinit, cbfsinfo, cbfsls
and cbfsload.
+- FAT(File Allocation Table) filesystem cluster size:
+ CONFIG_FS_FAT_MAX_CLUSTSIZE
+
+ Define the max cluster size for fat operations else
+ a default value of 65536 will be defined.
+
- Keyboard Support:
CONFIG_ISA_KEYBOARD
CONFIG_LCD_ALIGNMENT
- Normally the LCD is page-aligned (tyically 4KB). If this is
+ Normally the LCD is page-aligned (typically 4KB). If this is
defined then the LCD will be aligned to this value instead.
For ARM it is sometimes useful to use MMU_SECTION_SIZE
here, since it is cheaper to change data cache settings on
If this option is set, then U-Boot will prevent the environment
variable "splashimage" from being set to a problematic address
- (see README.displaying-bmps and README.arm-unaligned-accesses).
+ (see README.displaying-bmps).
This option is useful for targets where, due to alignment
restrictions, an improperly aligned BMP image will cause a data
abort. If you think you will not have problems with unaligned
can be displayed via the splashscreen support or the
bmp command.
-- Do compresssing for memory range:
+- Do compressing for memory range:
CONFIG_CMD_ZIP
If this option is set, it would use zlib deflate method
to compress the specified memory at its best effort.
- Compression support:
+ CONFIG_GZIP
+
+ Enabled by default to support gzip compressed images.
+
CONFIG_BZIP2
If this option is set, support for bzip2 compressed
then calculate the amount of needed dynamic memory (ensuring
the appropriate CONFIG_SYS_MALLOC_LEN value).
+ CONFIG_LZO
+
+ If this option is set, support for LZO compressed images
+ is included.
+
- MII/PHY support:
CONFIG_PHY_ADDR
4th and following
BOOTP requests: delay 0 ... 8 sec
+ CONFIG_BOOTP_ID_CACHE_SIZE
+
+ BOOTP packets are uniquely identified using a 32-bit ID. The
+ server will copy the ID from client requests to responses and
+ U-Boot will use this to determine if it is the destination of
+ an incoming response. Some servers will check that addresses
+ aren't in use before handing them out (usually using an ARP
+ ping) and therefore take up to a few hundred milliseconds to
+ respond. Network congestion may also influence the time it
+ takes for a response to make it back to the client. If that
+ time is too long, U-Boot will retransmit requests. In order
+ to allow earlier responses to still be accepted after these
+ retransmissions, U-Boot's BOOTP client keeps a small cache of
+ IDs. The CONFIG_BOOTP_ID_CACHE_SIZE controls the size of this
+ cache. The default is to keep IDs for up to four outstanding
+ requests. Increasing this will allow U-Boot to accept offers
+ from a BOOTP client in networks with unusually high latency.
+
+ - BOOTP Random transaction ID:
+ CONFIG_BOOTP_RANDOM_ID
+
+ The standard algorithm to generate a DHCP/BOOTP transaction ID
+ by using the MAC address and the current time stamp may not
+ quite unlikely produce duplicate transaction IDs from different
+ clients in the same network. This option creates a transaction
+ ID using the rand() function. Provided that the RNG has been
+ seeded well, this should guarantee unique transaction IDs
+ always.
+
- DHCP Advanced Options:
You can fine tune the DHCP functionality by defining
CONFIG_BOOTP_* symbols:
kernel). Defining CONFIG_STATUS_LED enables this
feature in U-Boot.
+ Additional options:
+
+ CONFIG_GPIO_LED
+ The status LED can be connected to a GPIO pin.
+ In such cases, the gpio_led driver can be used as a
+ status LED backend implementation. Define CONFIG_GPIO_LED
+ to include the gpio_led driver in the U-Boot binary.
+
+ CONFIG_GPIO_LED_INVERTED_TABLE
+ Some GPIO connected LEDs may have inverted polarity in which
+ case the GPIO high value corresponds to LED off state and
+ GPIO low value corresponds to LED on state.
+ In such cases CONFIG_GPIO_LED_INVERTED_TABLE may be defined
+ with a list of GPIO LEDs that have inverted polarity.
+
- CAN Support: CONFIG_CAN_DRIVER
Defining CONFIG_CAN_DRIVER enables CAN driver support
offset CONFIG_SYS_FSL_I2C_SPEED for the i2c speed and
CONFIG_SYS_FSL_I2C_SLAVE for the slave addr of the first
bus.
- - If your board supports a second fsl i2c bus, define
+ - If your board supports a second fsl i2c bus, define
CONFIG_SYS_FSL_I2C2_OFFSET for the register offset
CONFIG_SYS_FSL_I2C2_SPEED for the speed and
CONFIG_SYS_FSL_I2C2_SLAVE for the slave address of the
second bus.
- drivers/i2c/tegra_i2c.c:
- - activate this driver with CONFIG_SYS_I2C_TEGRA
- - This driver adds 4 i2c buses with a fix speed from
- 100000 and the slave addr 0!
+ - activate this driver with CONFIG_SYS_I2C_TEGRA
+ - This driver adds 4 i2c buses with a fix speed from
+ 100000 and the slave addr 0!
- drivers/i2c/ppc4xx_i2c.c
- activate this driver with CONFIG_SYS_I2C_PPC4XX
- CONFIG_SYS_I2C_PPC4XX_CH0 activate hardware channel 0
- CONFIG_SYS_I2C_PPC4XX_CH1 activate hardware channel 1
+ - drivers/i2c/i2c_mxc.c
+ - activate this driver with CONFIG_SYS_I2C_MXC
+ - define speed for bus 1 with CONFIG_SYS_MXC_I2C1_SPEED
+ - define slave for bus 1 with CONFIG_SYS_MXC_I2C1_SLAVE
+ - define speed for bus 2 with CONFIG_SYS_MXC_I2C2_SPEED
+ - define slave for bus 2 with CONFIG_SYS_MXC_I2C2_SLAVE
+ - define speed for bus 3 with CONFIG_SYS_MXC_I2C3_SPEED
+ - define slave for bus 3 with CONFIG_SYS_MXC_I2C3_SLAVE
+ If those defines are not set, default value is 100000
+ for speed, and 0 for slave.
+
+ - drivers/i2c/rcar_i2c.c:
+ - activate this driver with CONFIG_SYS_I2C_RCAR
+ - This driver adds 4 i2c buses
+
+ - CONFIG_SYS_RCAR_I2C0_BASE for setting the register channel 0
+ - CONFIG_SYS_RCAR_I2C0_SPEED for for the speed channel 0
+ - CONFIG_SYS_RCAR_I2C1_BASE for setting the register channel 1
+ - CONFIG_SYS_RCAR_I2C1_SPEED for for the speed channel 1
+ - CONFIG_SYS_RCAR_I2C2_BASE for setting the register channel 2
+ - CONFIG_SYS_RCAR_I2C2_SPEED for for the speed channel 2
+ - CONFIG_SYS_RCAR_I2C3_BASE for setting the register channel 3
+ - CONFIG_SYS_RCAR_I2C3_SPEED for for the speed channel 3
+ - CONFIF_SYS_RCAR_I2C_NUM_CONTROLLERS for number of i2c buses
+
+ - drivers/i2c/sh_i2c.c:
+ - activate this driver with CONFIG_SYS_I2C_SH
+ - This driver adds from 2 to 5 i2c buses
+
+ - CONFIG_SYS_I2C_SH_BASE0 for setting the register channel 0
+ - CONFIG_SYS_I2C_SH_SPEED0 for for the speed channel 0
+ - CONFIG_SYS_I2C_SH_BASE1 for setting the register channel 1
+ - CONFIG_SYS_I2C_SH_SPEED1 for for the speed channel 1
+ - CONFIG_SYS_I2C_SH_BASE2 for setting the register channel 2
+ - CONFIG_SYS_I2C_SH_SPEED2 for for the speed channel 2
+ - CONFIG_SYS_I2C_SH_BASE3 for setting the register channel 3
+ - CONFIG_SYS_I2C_SH_SPEED3 for for the speed channel 3
+ - CONFIG_SYS_I2C_SH_BASE4 for setting the register channel 4
+ - CONFIG_SYS_I2C_SH_SPEED4 for for the speed channel 4
+ - CONFIG_SYS_I2C_SH_BASE5 for setting the register channel 5
+ - CONFIG_SYS_I2C_SH_SPEED5 for for the speed channel 5
+ - CONFIG_SYS_I2C_SH_NUM_CONTROLLERS for number of i2c buses
+
+ - drivers/i2c/omap24xx_i2c.c
+ - activate this driver with CONFIG_SYS_I2C_OMAP24XX
+ - CONFIG_SYS_OMAP24_I2C_SPEED speed channel 0
+ - CONFIG_SYS_OMAP24_I2C_SLAVE slave addr channel 0
+ - CONFIG_SYS_OMAP24_I2C_SPEED1 speed channel 1
+ - CONFIG_SYS_OMAP24_I2C_SLAVE1 slave addr channel 1
+ - CONFIG_SYS_OMAP24_I2C_SPEED2 speed channel 2
+ - CONFIG_SYS_OMAP24_I2C_SLAVE2 slave addr channel 2
+ - CONFIG_SYS_OMAP24_I2C_SPEED3 speed channel 3
+ - CONFIG_SYS_OMAP24_I2C_SLAVE3 slave addr channel 3
+ - CONFIG_SYS_OMAP24_I2C_SPEED4 speed channel 4
+ - CONFIG_SYS_OMAP24_I2C_SLAVE4 slave addr channel 4
+
+ - drivers/i2c/zynq_i2c.c
+ - activate this driver with CONFIG_SYS_I2C_ZYNQ
+ - set CONFIG_SYS_I2C_ZYNQ_SPEED for speed setting
+ - set CONFIG_SYS_I2C_ZYNQ_SLAVE for slave addr
+
+ - drivers/i2c/s3c24x0_i2c.c:
+ - activate this driver with CONFIG_SYS_I2C_S3C24X0
+ - This driver adds i2c buses (11 for Exynos5250, Exynos5420
+ 9 i2c buses for Exynos4 and 1 for S3C24X0 SoCs from Samsung)
+ with a fix speed from 100000 and the slave addr 0!
+
+ - drivers/i2c/ihs_i2c.c
+ - activate this driver with CONFIG_SYS_I2C_IHS
+ - CONFIG_SYS_I2C_IHS_CH0 activate hardware channel 0
+ - CONFIG_SYS_I2C_IHS_SPEED_0 speed channel 0
+ - CONFIG_SYS_I2C_IHS_SLAVE_0 slave addr channel 0
+ - CONFIG_SYS_I2C_IHS_CH1 activate hardware channel 1
+ - CONFIG_SYS_I2C_IHS_SPEED_1 speed channel 1
+ - CONFIG_SYS_I2C_IHS_SLAVE_1 slave addr channel 1
+ - CONFIG_SYS_I2C_IHS_CH2 activate hardware channel 2
+ - CONFIG_SYS_I2C_IHS_SPEED_2 speed channel 2
+ - CONFIG_SYS_I2C_IHS_SLAVE_2 slave addr channel 2
+ - CONFIG_SYS_I2C_IHS_CH3 activate hardware channel 3
+ - CONFIG_SYS_I2C_IHS_SPEED_3 speed channel 3
+ - CONFIG_SYS_I2C_IHS_SLAVE_3 slave addr channel 3
+
additional defines:
CONFIG_SYS_NUM_I2C_BUSES
- Hold the number of i2c busses you want to use. If you
+ Hold the number of i2c buses you want to use. If you
don't use/have i2c muxes on your i2c bus, this
is equal to CONFIG_SYS_NUM_I2C_ADAPTERS, and you can
omit this define.
define.
CONFIG_SYS_I2C_BUSES
- hold a list of busses you want to use, only used if
+ hold a list of buses you want to use, only used if
CONFIG_SYS_I2C_DIRECT_BUS is not defined, for example
a board with CONFIG_SYS_I2C_MAX_HOPS = 1 and
CONFIG_SYS_NUM_I2C_BUSES = 9:
Enables the driver for the SPI controllers on i.MX and MXC
SoCs. Currently i.MX31/35/51 are supported.
+ CONFIG_SYS_SPI_MXC_WAIT
+ Timeout for waiting until spi transfer completed.
+ default: (CONFIG_SYS_HZ/100) /* 10 ms */
+
- FPGA Support: CONFIG_FPGA
Enables FPGA subsystem.
Specify the number of FPGA devices to support.
+ CONFIG_CMD_FPGA_LOADMK
+
+ Enable support for fpga loadmk command
+
+ CONFIG_CMD_FPGA_LOADP
+
+ Enable support for fpga loadp command - load partial bitstream
+
+ CONFIG_CMD_FPGA_LOADBP
+
+ Enable support for fpga loadbp command - load partial bitstream
+ (Xilinx only)
+
CONFIG_SYS_FPGA_PROG_FEEDBACK
Enable printing of hash marks during FPGA configuration.
CONFIG_SYS_FPGA_WAIT_INIT
- Maximum time to wait for the INIT_B line to deassert
- after PROB_B has been deasserted during a Virtex II
+ Maximum time to wait for the INIT_B line to de-assert
+ after PROB_B has been de-asserted during a Virtex II
FPGA configuration sequence. The default time is 500
ms.
CONFIG_SYS_FPGA_WAIT_BUSY
- Maximum time to wait for BUSY to deassert during
+ Maximum time to wait for BUSY to de-assert during
Virtex II FPGA configuration. The default is 5 ms.
CONFIG_SYS_FPGA_WAIT_CONFIG
200 ms.
- Configuration Management:
+ CONFIG_BUILD_TARGET
+
+ Some SoCs need special image types (e.g. U-Boot binary
+ with a special header) as build targets. By defining
+ CONFIG_BUILD_TARGET in the SoC / board header, this
+ special image will be automatically built upon calling
+ make / MAKEALL.
+
CONFIG_IDENT_STRING
If defined, this string will be added to the U-Boot
Enable auto completion of commands using TAB.
- Note that this feature has NOT been implemented yet
- for the "hush" shell.
-
-
- CONFIG_SYS_HUSH_PARSER
-
- Define this variable to enable the "hush" shell (from
- Busybox) as command line interpreter, thus enabling
- powerful command line syntax like
- if...then...else...fi conditionals or `&&' and '||'
- constructs ("shell scripts").
-
- If undefined, you get the old, much simpler behaviour
- with a somewhat smaller memory footprint.
-
-
CONFIG_SYS_PROMPT_HUSH_PS2
This defines the secondary prompt string, which is
of the backslashes before semicolons and special
symbols.
-- Commandline Editing and History:
+- Command Line Editing and History:
CONFIG_CMDLINE_EDITING
Enable editing and History functions for interactive
- commandline input operations
+ command line input operations
- Default Environment:
CONFIG_EXTRA_ENV_SETTINGS
CONFIG_DELAY_ENVIRONMENT
Normally the environment is loaded when the board is
- intialised so that it is available to U-Boot. This inhibits
+ initialised so that it is available to U-Boot. This inhibits
that so that the environment is not available until
explicitly loaded later by U-Boot code. With CONFIG_OF_CONTROL
this is instead controlled by the value of
Define this option to use the Bank addr/Extended addr
support on SPI flashes which has size > 16Mbytes.
+ CONFIG_SF_DUAL_FLASH Dual flash memories
+
+ Define this option to use dual flash support where two flash
+ memories can be connected with a given cs line.
+ Currently Xilinx Zynq qspi supports these type of connections.
+
+ CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
+ enable the W#/Vpp signal to disable writing to the status
+ register on ST MICRON flashes like the N25Q128.
+ The status register write enable/disable bit, combined with
+ the W#/VPP signal provides hardware data protection for the
+ device as follows: When the enable/disable bit is set to 1,
+ and the W#/VPP signal is driven LOW, the status register
+ nonvolatile bits become read-only and the WRITE STATUS REGISTER
+ operation will not execute. The only way to exit this
+ hardware-protected mode is to drive W#/VPP HIGH.
+
- SystemACE Support:
CONFIG_SYSTEMACE
Note: There is also a sha1sum command, which should perhaps
be deprecated in favour of 'hash sha1'.
+- Freescale i.MX specific commands:
+ CONFIG_CMD_HDMIDETECT
+ This enables 'hdmidet' command which returns true if an
+ HDMI monitor is detected. This command is i.MX 6 specific.
+
+ CONFIG_CMD_BMODE
+ This enables the 'bmode' (bootmode) command for forcing
+ a boot from specific media.
+
+ This is useful for forcing the ROM's usb downloader to
+ activate upon a watchdog reset which is nice when iterating
+ on U-Boot. Using the reset button or running bmode normal
+ will set it back to normal. This command currently
+ supports i.MX53 and i.MX6.
+
- Signing support:
CONFIG_RSA
This enables the RSA algorithm used for FIT image verification
- in U-Boot. See doc/uImage/signature for more information.
+ in U-Boot. See doc/uImage.FIT/signature.txt for more information.
The signing part is build into mkimage regardless of this
option.
+- bootcount support:
+ CONFIG_BOOTCOUNT_LIMIT
+
+ This enables the bootcounter support, see:
+ http://www.denx.de/wiki/DULG/UBootBootCountLimit
+
+ CONFIG_AT91SAM9XE
+ enable special bootcounter support on at91sam9xe based boards.
+ CONFIG_BLACKFIN
+ enable special bootcounter support on blackfin based boards.
+ CONFIG_SOC_DA8XX
+ enable special bootcounter support on da850 based boards.
+ CONFIG_BOOTCOUNT_RAM
+ enable support for the bootcounter in RAM
+ CONFIG_BOOTCOUNT_I2C
+ enable support for the bootcounter on an i2c (like RTC) device.
+ CONFIG_SYS_I2C_RTC_ADDR = i2c chip address
+ CONFIG_SYS_BOOTCOUNT_ADDR = i2c addr which is used for
+ the bootcounter.
+ CONFIG_BOOTCOUNT_ALEN = address len
- Show boot progress:
CONFIG_SHOW_BOOT_PROGRESS
-150 common/cmd_nand.c Incorrect FIT image format
151 common/cmd_nand.c FIT image format OK
+- legacy image format:
+ CONFIG_IMAGE_FORMAT_LEGACY
+ enables the legacy image format support in U-Boot.
+
+ Default:
+ enabled if CONFIG_FIT_SIGNATURE is not defined.
+
+ CONFIG_DISABLE_IMAGE_LEGACY
+ disable the legacy image format
+
+ This define is introduced, as the legacy image format is
+ enabled per default for backward compatibility.
+
- FIT image support:
CONFIG_FIT
Enable support for the FIT uImage format.
using a hash signed and verified using RSA. See
doc/uImage.FIT/signature.txt for more details.
+ WARNING: When relying on signed FIT images with required
+ signature check the legacy image format is default
+ disabled. If a board need legacy image format support
+ enable this through CONFIG_IMAGE_FORMAT_LEGACY
+
+ CONFIG_FIT_DISABLE_SHA256
+ Supporting SHA256 hashes has quite an impact on binary size.
+ For constrained systems sha256 hash support can be disabled
+ with this option.
+
- Standalone program support:
CONFIG_STANDALONE_LOAD_ADDR
Adds the MTD partitioning infrastructure from the Linux
kernel. Needed for UBI support.
+ CONFIG_MTD_NAND_VERIFY_WRITE
+ verify if the written data is correct reread.
+
- UBI support
CONFIG_CMD_UBI
Make the verbose messages from UBI stop printing. This leaves
warnings and errors enabled.
+
+ CONFIG_MTD_UBI_WL_THRESHOLD
+ This parameter defines the maximum difference between the highest
+ erase counter value and the lowest erase counter value of eraseblocks
+ of UBI devices. When this threshold is exceeded, UBI starts performing
+ wear leveling by means of moving data from eraseblock with low erase
+ counter to eraseblocks with high erase counter.
+
+ The default value should be OK for SLC NAND flashes, NOR flashes and
+ other flashes which have eraseblock life-cycle 100000 or more.
+ However, in case of MLC NAND flashes which typically have eraseblock
+ life-cycle less than 10000, the threshold should be lessened (e.g.,
+ to 128 or 256, although it does not have to be power of 2).
+
+ default: 4096
+
+ CONFIG_MTD_UBI_BEB_LIMIT
+ This option specifies the maximum bad physical eraseblocks UBI
+ expects on the MTD device (per 1024 eraseblocks). If the
+ underlying flash does not admit of bad eraseblocks (e.g. NOR
+ flash), this value is ignored.
+
+ NAND datasheets often specify the minimum and maximum NVM
+ (Number of Valid Blocks) for the flashes' endurance lifetime.
+ The maximum expected bad eraseblocks per 1024 eraseblocks
+ then can be calculated as "1024 * (1 - MinNVB / MaxNVB)",
+ which gives 20 for most NANDs (MaxNVB is basically the total
+ count of eraseblocks on the chip).
+
+ To put it differently, if this value is 20, UBI will try to
+ reserve about 1.9% of physical eraseblocks for bad blocks
+ handling. And that will be 1.9% of eraseblocks on the entire
+ NAND chip, not just the MTD partition UBI attaches. This means
+ that if you have, say, a NAND flash chip admits maximum 40 bad
+ eraseblocks, and it is split on two MTD partitions of the same
+ size, UBI will reserve 40 eraseblocks when attaching a
+ partition.
+
+ default: 20
+
+ CONFIG_MTD_UBI_FASTMAP
+ Fastmap is a mechanism which allows attaching an UBI device
+ in nearly constant time. Instead of scanning the whole MTD device it
+ only has to locate a checkpoint (called fastmap) on the device.
+ The on-flash fastmap contains all information needed to attach
+ the device. Using fastmap makes only sense on large devices where
+ attaching by scanning takes long. UBI will not automatically install
+ a fastmap on old images, but you can set the UBI parameter
+ CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT to 1 if you want so. Please note
+ that fastmap-enabled images are still usable with UBI implementations
+ without fastmap support. On typical flash devices the whole fastmap
+ fits into one PEB. UBI will reserve PEBs to hold two fastmaps.
+
+ CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT
+ Set this parameter to enable fastmap automatically on images
+ without a fastmap.
+ default: 0
+
- UBIFS support
CONFIG_CMD_UBIFS
supports MMC, NAND and YMODEM loading of U-Boot and NAND
NAND loading of the Linux Kernel.
+ CONFIG_SPL_OS_BOOT
+ Enable booting directly to an OS from SPL.
+ See also: doc/README.falcon
+
CONFIG_SPL_DISPLAY_PRINT
For ARM, enable an optional function to print more information
about the running system.
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS,
- CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION
- Address, size and partition on the MMC to load U-Boot from
+ Address and partition on the MMC to load U-Boot from
when the MMC is being used in raw mode.
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
+ Partition on the MMC to load U-Boot from when the MMC is being
+ used in raw mode
+
CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR
Sector to load kernel uImage from when MMC is being
used in raw mode (for Falcon mode)
parameters from when MMC is being used in raw mode
(for falcon mode)
+ CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
+ Partition on the MMC to load U-Boot from when the MMC is being
+ used in fs mode
+
CONFIG_SPL_FAT_SUPPORT
Support for fs/fat/libfat.o in SPL binary
- CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME
- Filename to read to load U-Boot when reading from FAT
+ CONFIG_SPL_EXT_SUPPORT
+ Support for EXT filesystem in SPL binary
- CONFIG_SPL_FAT_LOAD_KERNEL_NAME
+ CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
+ Filename to read to load U-Boot when reading from filesystem
+
+ CONFIG_SPL_FS_LOAD_KERNEL_NAME
Filename to read to load kernel uImage when reading
- from FAT (for Falcon mode)
+ from filesystem (for Falcon mode)
- CONFIG_SPL_FAT_LOAD_ARGS_NAME
+ CONFIG_SPL_FS_LOAD_ARGS_NAME
Filename to read to load kernel argument parameters
- when reading from FAT (for Falcon mode)
+ when reading from filesystem (for Falcon mode)
CONFIG_SPL_MPC83XX_WAIT_FOR_NAND
Set this for NAND SPL on PPC mpc83xx targets, so that
continuing (the hardware starts execution after just
loading the first page rather than the full 4K).
+ CONFIG_SPL_SKIP_RELOCATE
+ Avoid SPL relocation
+
CONFIG_SPL_NAND_BASE
Include nand_base.c in the SPL. Requires
CONFIG_SPL_NAND_DRIVERS.
Support for NAND boot using simple NAND drivers that
expose the cmd_ctrl() interface.
+ CONFIG_SPL_MTD_SUPPORT
+ Support for the MTD subsystem within SPL. Useful for
+ environment on NAND support within SPL.
+
+ CONFIG_SPL_NAND_RAW_ONLY
+ Support to boot only raw u-boot.bin images. Use this only
+ if you need to save space.
+
+ CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
+ Set for the SPL on PPC mpc8xxx targets, support for
+ drivers/ddr/fsl/libddr.o in SPL binary.
+
+ CONFIG_SPL_COMMON_INIT_DDR
+ Set for common ddr init with serial presence detect in
+ SPL binary.
+
CONFIG_SYS_NAND_5_ADDR_CYCLE, CONFIG_SYS_NAND_PAGE_COUNT,
CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE,
CONFIG_SYS_NAND_BLOCK_SIZE, CONFIG_SYS_NAND_BAD_BLOCK_POS,
Defines the size and behavior of the NAND that SPL uses
to read U-Boot
+ CONFIG_SPL_NAND_BOOT
+ Add support NAND boot
+
CONFIG_SYS_NAND_U_BOOT_OFFS
Location in NAND to read U-Boot from
CONFIG_SYS_NAND_HW_ECC_OOBFIRST
Define this if you need to first read the OOB and then the
- data. This is used for example on davinci plattforms.
+ data. This is used, for example, on davinci platforms.
CONFIG_SPL_OMAP3_ID_NAND
Support for an OMAP3-specific set of functions to return the
option to re-enable it. This will affect the output of the
bootm command when booting a FIT image.
+- TPL framework
+ CONFIG_TPL
+ Enable building of TPL globally.
+
+ CONFIG_TPL_PAD_TO
+ Image offset to which the TPL should be padded before appending
+ the TPL payload. By default, this is defined as
+ CONFIG_SPL_MAX_SIZE, or 0 if CONFIG_SPL_MAX_SIZE is undefined.
+ CONFIG_SPL_PAD_TO must be either 0, meaning to append the SPL
+ payload without any padding, or >= CONFIG_SPL_MAX_SIZE.
+
Modem Support:
--------------
Configuration Settings:
-----------------------
+- CONFIG_SYS_SUPPORT_64BIT_DATA: Defined automatically if compiled as 64-bit.
+ Optionally it can be defined to support 64-bit memory commands.
+
- CONFIG_SYS_LONGHELP: Defined when you want long help messages included;
undefine this when you're short of memory.
- CONFIG_SYS_MALLOC_LEN:
Size of DRAM reserved for malloc() use.
+- CONFIG_SYS_MALLOC_F_LEN
+ Size of the malloc() pool for use before relocation. If
+ this is defined, then a very simple malloc() implementation
+ will become available before relocation. The address is just
+ below the global data, and the stack is moved down to make
+ space.
+
+ This feature allocates regions with increasing addresses
+ within the region. calloc() is supported, but realloc()
+ is not available. free() is supported but does nothing.
+ The memory will be freed (or in fact just forgotten) when
+ U-Boot relocates itself.
+
+ Pre-relocation malloc() is only supported on ARM and sandbox
+ at present but is fairly easy to enable for other archs.
+
+- CONFIG_SYS_MALLOC_SIMPLE
+ Provides a simple and small malloc() and calloc() for those
+ boards which do not use the full malloc in SPL (which is
+ enabled with CONFIG_SYS_SPL_MALLOC_START).
+
+- CONFIG_SYS_NONCACHED_MEMORY:
+ Size of non-cached memory area. This area of memory will be
+ typically located right below the malloc() area and mapped
+ uncached in the MMU. This is useful for drivers that would
+ otherwise require a lot of explicit cache maintenance. For
+ some drivers it's also impossible to properly maintain the
+ cache. For example if the regions that need to be flushed
+ are not a multiple of the cache-line size, *and* padding
+ cannot be allocated between the regions to align them (i.e.
+ if the HW requires a contiguous array of regions, and the
+ size of each region is not cache-aligned), then a flush of
+ one region may result in overwriting data that hardware has
+ written to another region in the same cache-line. This can
+ happen for example in network drivers where descriptors for
+ buffers are typically smaller than the CPU cache-line (e.g.
+ 16 bytes vs. 32 or 64 bytes).
+
+ Non-cached memory is only supported on 32-bit ARM at present.
+
- CONFIG_SYS_BOOTM_LEN:
Normally compressed uImages are limited to an
uncompressed size of 8 MBytes. If this is not enough,
the Linux kernel; all data that must be processed by
the Linux kernel (bd_info, boot arguments, FDT blob if
used) must be put below this limit, unless "bootm_low"
- enviroment variable is defined and non-zero. In such case
+ environment variable is defined and non-zero. In such case
all data for the Linux kernel must be between "bootm_low"
and "bootm_low" + CONFIG_SYS_BOOTMAPSZ. The environment
variable "bootm_mapsize" will override the value of
- CONFIG_ENV_FLAGS_LIST_DEFAULT
- CONFIG_ENV_FLAGS_LIST_STATIC
- Enable validation of the values given to enviroment variables when
+ Enable validation of the values given to environment variables when
calling env set. Variables can be restricted to only decimal,
hexadecimal, or boolean. If CONFIG_CMD_NET is also defined,
the variables can also be restricted to IP address or MAC address.
The format of the list is:
type_attribute = [s|d|x|b|i|m]
- access_atribute = [a|r|o|c]
- attributes = type_attribute[access_atribute]
+ access_attribute = [a|r|o|c]
+ attributes = type_attribute[access_attribute]
entry = variable_name[:attributes]
list = entry[,list]
- CONFIG_ENV_FLAGS_LIST_DEFAULT
Define this to a list (string) to define the ".flags"
- envirnoment variable in the default or embedded environment.
+ environment variable in the default or embedded environment.
- CONFIG_ENV_FLAGS_LIST_STATIC
Define this to a list (string) to define validation that
its config.mk file). If you find problems enabling this option on
your board please report the problem and send patches!
-- CONFIG_SYS_SYM_OFFSETS
- This is set by architectures that use offsets for link symbols
- instead of absolute values. So bss_start is obtained using an
- offset _bss_start_ofs from CONFIG_SYS_TEXT_BASE, rather than
- directly. You should not need to touch this setting.
-
- CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC (OMAP only)
This is set by OMAP boards for the max time that reset should
be asserted. See doc/README.omap-reset-time for details on how
- the value can be calulated on a given board.
+ the value can be calculated on a given board.
+
+- CONFIG_USE_STDINT
+ If stdint.h is available with your toolchain you can define this
+ option to enable it. You can provide option 'USE_STDINT=1' when
+ building U-Boot to enable this.
The following definitions that deal with the placement and management
of environment data (variable area); in general, we support the
provision.
BE CAREFUL! The first access to the environment happens quite early
-in U-Boot initalization (when we try to get the setting of for the
+in U-Boot initialization (when we try to get the setting of for the
console baudrate). You *MUST* have mapped your NVRAM area then, or
U-Boot will hang.
environment area within the total memory of your DataFlash placed
at the specified address.
+- CONFIG_ENV_IS_IN_SPI_FLASH:
+
+ Define this if you have a SPI Flash memory device which you
+ want to use for the environment.
+
+ - CONFIG_ENV_OFFSET:
+ - CONFIG_ENV_SIZE:
+
+ These two #defines specify the offset and size of the
+ environment area within the SPI Flash. CONFIG_ENV_OFFSET must be
+ aligned to an erase sector boundary.
+
+ - CONFIG_ENV_SECT_SIZE:
+
+ Define the SPI flash's sector size.
+
+ - CONFIG_ENV_OFFSET_REDUND (optional):
+
+ This setting describes a second storage area of CONFIG_ENV_SIZE
+ size used to hold a redundant copy of the environment data, so
+ that there is a valid backup copy in case there is a power failure
+ during a "saveenv" operation. CONFIG_ENV_OFFSET_RENDUND must be
+ aligned to an erase sector boundary.
+
+ - CONFIG_ENV_SPI_BUS (optional):
+ - CONFIG_ENV_SPI_CS (optional):
+
+ Define the SPI bus and chip select. If not defined they will be 0.
+
+ - CONFIG_ENV_SPI_MAX_HZ (optional):
+
+ Define the SPI max work clock. If not defined then use 1MHz.
+
+ - CONFIG_ENV_SPI_MODE (optional):
+
+ Define the SPI work mode. If not defined then use SPI_MODE_3.
+
- CONFIG_ENV_IS_IN_REMOTE:
Define this if you have a remote memory space which you
You will probably want to define these to avoid a really noisy system
when storing the env in UBI.
+- CONFIG_ENV_IS_IN_FAT:
+ Define this if you want to use the FAT file system for the environment.
+
+ - FAT_ENV_INTERFACE:
+
+ Define this to a string that is the name of the block device.
+
+ - FAT_ENV_DEV_AND_PART:
+
+ Define this to a string to specify the partition of the device. It can
+ be as following:
+
+ "D:P", "D:0", "D", "D:" or "D:auto" (D, P are integers. And P >= 1)
+ - "D:P": device D partition P. Error occurs if device D has no
+ partition table.
+ - "D:0": device D.
+ - "D" or "D:": device D partition 1 if device D has partition
+ table, or the whole device D if has no partition
+ table.
+ - "D:auto": first partition in device D with bootable flag set.
+ If none, first valid partition in device D. If no
+ partition table then means device D.
+
+ - FAT_ENV_FILE:
+
+ It's a string of the FAT file name. This file use to store the
+ environment.
+
+ - CONFIG_FAT_WRITE:
+ This should be defined. Otherwise it cannot save the environment file.
+
- CONFIG_ENV_IS_IN_MMC:
Define this if you have an MMC device which you want to use for the
later, once stdio is running and output goes to the LCD, if
present.
+- CONFIG_BOARD_SIZE_LIMIT:
+ Maximum size of the U-Boot image. When defined, the
+ build system checks that the actual size does not
+ exceed it.
+
Low Level (hardware related) configuration options:
---------------------------------------------------
if CONFIG_SYS_FDC_HW_INIT is defined, then the function
fdc_hw_init() is called at the beginning of the FDC
setup. fdc_hw_init() must be provided by the board
- source code. It is used to make hardware dependant
+ source code. It is used to make hardware-dependent
initializations.
- CONFIG_IDE_AHB:
When software is doing ATA command and data transfer to
IDE devices through IDE-AHB controller, some additional
registers accessing to these kind of IDE-AHB controller
- is requierd.
+ is required.
- CONFIG_SYS_IMMR: Physical address of the Internal Memory.
DO NOT CHANGE unless you know exactly what you're
required.
- CONFIG_PCI_ENUM_ONLY
- Only scan through and get the devices on the busses.
+ Only scan through and get the devices on the buses.
Don't do any setup work, presumably because someone or
something has already done it, and we don't need to do it
a second time. Useful for platforms that are pre-booted
that is executed before the actual U-Boot. E.g. when
compiling a NAND SPL.
+- CONFIG_TPL_BUILD
+ Modifies the behaviour of start.S when compiling a loader
+ that is executed after the SPL and before the actual U-Boot.
+ It is loaded by the SPL.
+
- CONFIG_SYS_MPC85XX_NO_RESETVEC
Only for 85xx systems. If this variable is specified, the section
.resetvec is not kept and the section .bootpg is placed in the
NOTE : currently only supported on AM335x platforms.
+- CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC:
+ Enables the RTC32K OSC on AM33xx based plattforms
+
+- CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
+ Option to disable subpage write in NAND driver
+ driver that uses this:
+ drivers/mtd/nand/davinci_nand.c
+
Freescale QE/FMAN Firmware Support:
-----------------------------------
are used to identify the storage device (NOR flash, SPI, etc) and the address
within that device.
-- CONFIG_SYS_QE_FMAN_FW_ADDR
- The address in the storage device where the firmware is located. The
+- CONFIG_SYS_FMAN_FW_ADDR
+ The address in the storage device where the FMAN microcode is located. The
+ meaning of this address depends on which CONFIG_SYS_QE_FW_IN_xxx macro
+ is also specified.
+
+- CONFIG_SYS_QE_FW_ADDR
+ The address in the storage device where the QE microcode is located. The
meaning of this address depends on which CONFIG_SYS_QE_FW_IN_xxx macro
is also specified.
window->master inbound window->master LAW->the ucode address in
master's memory space.
+Freescale Layerscape Management Complex Firmware Support:
+---------------------------------------------------------
+The Freescale Layerscape Management Complex (MC) supports the loading of
+"firmware".
+This firmware often needs to be loaded during U-Boot booting, so macros
+are used to identify the storage device (NOR flash, SPI, etc) and the address
+within that device.
+
+- CONFIG_FSL_MC_ENET
+ Enable the MC driver for Layerscape SoCs.
+
+- CONFIG_SYS_LS_MC_FW_ADDR
+ The address in the storage device where the firmware is located. The
+ meaning of this address depends on which CONFIG_SYS_LS_MC_FW_IN_xxx macro
+ is also specified.
+
+- CONFIG_SYS_LS_MC_FW_LENGTH
+ The maximum possible size of the firmware. The firmware binary format
+ has a field that specifies the actual size of the firmware, but it
+ might not be possible to read any part of the firmware unless some
+ local storage is allocated to hold the entire firmware first.
+
+- CONFIG_SYS_LS_MC_FW_IN_NOR
+ Specifies that MC firmware is located in NOR flash, mapped as
+ normal addressable memory via the LBC. CONFIG_SYS_LS_MC_FW_ADDR is the
+ virtual address in NOR flash.
+
Building the Software:
======================
sources you must configure U-Boot for one specific board type. This
is done by typing:
- make NAME_config
+ make NAME_defconfig
-where "NAME_config" is the name of one of the existing configu-
+where "NAME_defconfig" is the name of one of the existing configu-
rations; see boards.cfg for supported names.
Note: for some board special configuration names may exist; check if
or with LCD support. You can select such additional "features"
when choosing the configuration, i. e.
- make TQM823L_config
+ make TQM823L_defconfig
- will configure for a plain TQM823L, i. e. no LCD support
- make TQM823L_LCD_config
+ make TQM823L_LCD_defconfig
- will configure for a TQM823L with U-Boot console on LCD
etc.
1. Add O= to the make command line invocations:
make O=/tmp/build distclean
- make O=/tmp/build NAME_config
+ make O=/tmp/build NAME_defconfig
make O=/tmp/build all
-2. Set environment variable BUILD_DIR to point to the desired location:
+2. Set environment variable KBUILD_OUTPUT to point to the desired location:
- export BUILD_DIR=/tmp/build
+ export KBUILD_OUTPUT=/tmp/build
make distclean
- make NAME_config
+ make NAME_defconfig
make all
-Note that the command line "O=" setting overrides the BUILD_DIR environment
+Note that the command line "O=" setting overrides the KBUILD_OUTPUT environment
variable.
your board
3. If you're porting U-Boot to a new CPU, then also create a new
directory to hold your CPU specific code. Add any files you need.
-4. Run "make <board>_config" with your new name.
+4. Run "make <board>_defconfig" with your new name.
5. Type "make", and you should get a working "u-boot.srec" file
to be installed on your target system.
6. Debug and solve any problems that might arise.
npe_ucode - set load address for the NPE microcode
+ silent_linux - If set then Linux will be told to boot silently, by
+ changing the console to be empty. If "yes" it will be
+ made silent. If "no" it will not be made silent. If
+ unset, then it will be made silent if the U-Boot console
+ is silent.
+
tftpsrcport - If this is set, the value is used for TFTP's
UDP source port.
---------------------------------------------
For some environment variables, the behavior of u-boot needs to change
-when their values are changed. This functionailty allows functions to
+when their values are changed. This functionality allows functions to
be associated with arbitrary variables. On creation, overwrite, or
deletion, the callback will provide the opportunity for some side
effect to happen or for the change to be rejected.
with the same list format above. Any association in ".callbacks" will
override any association in the static list. You can define
CONFIG_ENV_CALLBACK_LIST_DEFAULT to a list (string) to define the
-".callbacks" envirnoment variable in the default or embedded environment.
+".callbacks" environment variable in the default or embedded environment.
Command Line Parsing:
and make sure that your definition of IMAP_ADDR uses the same value
as your U-Boot configuration in CONFIG_SYS_IMMR.
+Note that U-Boot now has a driver model, a unified model for drivers.
+If you are adding a new driver, plumb it into driver model. If there
+is no uclass available, you are encouraged to create one. See
+doc/driver-model.
+
Configuring the Linux kernel:
-----------------------------
Example:
- make TQM850L_config
+ make TQM850L_defconfig
make oldconfig
make dep
make uImage
Load Address: 0x00000000
Entry Point: 0x00000000
+The "dumpimage" is a tool to disassemble images built by mkimage. Its "-i"
+option performs the converse operation of the mkimage's second form (the "-d"
+option). Given an image built by mkimage, the dumpimage extracts a "data file"
+from the image:
+
+ tools/dumpimage -i image -p position data_file
+ -i ==> extract from the 'image' a specific 'data_file', \
+ indexed by 'position'
+
Installing a Linux Image:
-------------------------
* Initialized global data (data segment) is read-only. Do not attempt
to write it.
-* Do not use any uninitialized global data (or implicitely initialized
+* Do not use any uninitialized global data (or implicitly initialized
as zero data - BSS segment) at all - this is undefined, initiali-
zation is performed later (when relocating to RAM).
that.
Having only the stack as writable memory limits means we cannot use
-normal global data to share information beween the code. But it
+normal global data to share information between the code. But it
turned out that the implementation of U-Boot can be greatly
simplified by making a global data structure (gd_t) available to all
functions. We could pass a pointer to this data as argument to _all_
R0: function argument word/integer result
R1-R3: function argument word
- R9: GOT pointer
- R10: stack limit (used only if stack checking if enabled)
+ R9: platform specific
+ R10: stack limit (used only if stack checking is enabled)
R11: argument (frame) pointer
R12: temporary workspace
R13: stack pointer
R14: link register
R15: program counter
- ==> U-Boot will use R8 to hold a pointer to the global data
+ ==> U-Boot will use R9 to hold a pointer to the global data
+
+ Note: on ARM, only R_ARM_RELATIVE relocations are supported.
On Nios II, the ABI is documented here:
http://www.altera.com/literature/hb/nios2/n2cpu_nii51016.pdf
In the reset configuration, U-Boot starts at the reset entry point
(on most PowerPC systems at address 0x00000100). Because of the reset
-configuration for CS0# this is a mirror of the onboard Flash memory.
+configuration for CS0# this is a mirror of the on board Flash memory.
To be able to re-map memory U-Boot then jumps to its link address.
To be able to implement the initialization code in C, a (small!)
initial stack is set up in the internal Dual Ported RAM (in case CPUs
Source files originating from a different project (for example the
MTD subsystem) are generally exempt from these guidelines and are not
-reformated to ease subsequent migration to newer versions of those
+reformatted to ease subsequent migration to newer versions of those
sources.
Please note that U-Boot is implemented in C (and to some small parts in
* For major contributions, your entry to the CREDITS file
-* When you add support for a new board, don't forget to add this
- board to the MAINTAINERS file, too.
+* When you add support for a new board, don't forget to add a
+ maintainer e-mail address to the boards.cfg file, too.
* If your patch adds new configuration options, don't forget to
document these in the README file.
--- /dev/null
+menu "ARM architecture"
+ depends on ARM
+
+config SYS_ARCH
+ default "arm"
+
+config ARM64
+ bool
+
+config HAS_VBAR
+ bool
+
+config CPU_ARM720T
+ bool
+
+config CPU_ARM920T
+ bool
+
+config CPU_ARM926EJS
+ bool
+
+config CPU_ARM946ES
+ bool
+
+config CPU_ARM1136
+ bool
+
+config CPU_ARM1176
+ bool
+ select HAS_VBAR
+
+config CPU_V7
+ bool
+ select HAS_VBAR
+
+config CPU_PXA
+ bool
+
+config CPU_SA1100
+ bool
+
+config SYS_CPU
+ default "arm720t" if CPU_ARM720T
+ default "arm920t" if CPU_ARM920T
+ default "arm926ejs" if CPU_ARM926EJS
+ default "arm946es" if CPU_ARM946ES
+ default "arm1136" if CPU_ARM1136
+ default "arm1176" if CPU_ARM1176
+ default "armv7" if CPU_V7
+ default "pxa" if CPU_PXA
+ default "sa1100" if CPU_SA1100
+ default "armv8" if ARM64
+
+choice
+ prompt "Target select"
+
+config TARGET_INTEGRATORAP_CM720T
+ bool "Support integratorap_cm720t"
+ select CPU_ARM720T
+
+config TARGET_INTEGRATORAP_CM920T
+ bool "Support integratorap_cm920t"
+ select CPU_ARM920T
+
+config TARGET_INTEGRATORCP_CM920T
+ bool "Support integratorcp_cm920t"
+ select CPU_ARM920T
+
+config TARGET_A320EVB
+ bool "Support a320evb"
+ select CPU_ARM920T
+
+config TARGET_AT91RM9200EK
+ bool "Support at91rm9200ek"
+ select CPU_ARM920T
+
+config TARGET_EB_CPUX9K2
+ bool "Support eb_cpux9k2"
+ select CPU_ARM920T
+
+config TARGET_CPUAT91
+ bool "Support cpuat91"
+ select CPU_ARM920T
+
+config TARGET_EDB93XX
+ bool "Support edb93xx"
+ select CPU_ARM920T
+
+config TARGET_SCB9328
+ bool "Support scb9328"
+ select CPU_ARM920T
+
+config TARGET_CM4008
+ bool "Support cm4008"
+ select CPU_ARM920T
+
+config TARGET_CM41XX
+ bool "Support cm41xx"
+ select CPU_ARM920T
+
+config TARGET_VCMA9
+ bool "Support VCMA9"
+ select CPU_ARM920T
+
+config TARGET_SMDK2410
+ bool "Support smdk2410"
+ select CPU_ARM920T
+
+config TARGET_INTEGRATORAP_CM926EJS
+ bool "Support integratorap_cm926ejs"
+ select CPU_ARM926EJS
+
+config TARGET_INTEGRATORCP_CM926EJS
+ bool "Support integratorcp_cm926ejs"
+ select CPU_ARM926EJS
+
+config TARGET_ASPENITE
+ bool "Support aspenite"
+ select CPU_ARM926EJS
+
+config TARGET_GPLUGD
+ bool "Support gplugd"
+ select CPU_ARM926EJS
+
+config TARGET_AFEB9260
+ bool "Support afeb9260"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9260EK
+ bool "Support at91sam9260ek"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9261EK
+ bool "Support at91sam9261ek"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9263EK
+ bool "Support at91sam9263ek"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9M10G45EK
+ bool "Support at91sam9m10g45ek"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9N12EK
+ bool "Support at91sam9n12ek"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9RLEK
+ bool "Support at91sam9rlek"
+ select CPU_ARM926EJS
+
+config TARGET_AT91SAM9X5EK
+ bool "Support at91sam9x5ek"
+ select CPU_ARM926EJS
+
+config TARGET_SNAPPER9260
+ bool "Support snapper9260"
+ select CPU_ARM926EJS
+
+config TARGET_VL_MA2SC
+ bool "Support vl_ma2sc"
+ select CPU_ARM926EJS
+
+config TARGET_SBC35_A9G20
+ bool "Support sbc35_a9g20"
+ select CPU_ARM926EJS
+
+config TARGET_TNY_A9260
+ bool "Support tny_a9260"
+ select CPU_ARM926EJS
+
+config TARGET_USB_A9263
+ bool "Support usb_a9263"
+ select CPU_ARM926EJS
+
+config TARGET_ETHERNUT5
+ bool "Support ethernut5"
+ select CPU_ARM926EJS
+
+config TARGET_MEESC
+ bool "Support meesc"
+ select CPU_ARM926EJS
+
+config TARGET_OTC570
+ bool "Support otc570"
+ select CPU_ARM926EJS
+
+config TARGET_CPU9260
+ bool "Support cpu9260"
+ select CPU_ARM926EJS
+
+config TARGET_PM9261
+ bool "Support pm9261"
+ select CPU_ARM926EJS
+
+config TARGET_PM9263
+ bool "Support pm9263"
+ select CPU_ARM926EJS
+
+config TARGET_PM9G45
+ bool "Support pm9g45"
+ select CPU_ARM926EJS
+
+config TARGET_CORVUS
+ select SUPPORT_SPL
+ bool "Support corvus"
+ select CPU_ARM926EJS
+
+config TARGET_TAURUS
+ select SUPPORT_SPL
+ bool "Support taurus"
+ select CPU_ARM926EJS
+
+config TARGET_STAMP9G20
+ bool "Support stamp9g20"
+ select CPU_ARM926EJS
+
+config ARCH_DAVINCI
+ bool "TI DaVinci"
+ select CPU_ARM926EJS
+ help
+ Support for TI's DaVinci platform.
+
+config KIRKWOOD
+ bool "Marvell Kirkwood"
+ select CPU_ARM926EJS
+
+config TARGET_DB_MV784MP_GP
+ bool "Support db-mv784mp-gp"
+ select CPU_V7
+
+config TARGET_MAXBCM
+ bool "Support maxbcm"
+ select CPU_V7
+
+config TARGET_DEVKIT3250
+ bool "Support devkit3250"
+ select CPU_ARM926EJS
+
+config TARGET_JADECPU
+ bool "Support jadecpu"
+ select CPU_ARM926EJS
+
+config TARGET_MX25PDK
+ bool "Support mx25pdk"
+ select CPU_ARM926EJS
+
+config TARGET_TX25
+ bool "Support tx25"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
++config TARGET_TX28
++ bool "Support tx28"
++ select CPU_ARM926EJS
++ select SUPPORT_SPL
++
++config TARGET_TX48
++ bool "Support tx48"
++ select CPU_V7
++ select SUPPORT_SPL
++
++config TARGET_TX51
++ bool "Support tx51"
++ select CPU_V7
++
++config TARGET_TX53
++ bool "Support tx53"
++ select CPU_V7
++
++config TARGET_TX6
++ bool "Support tx6"
++ select CPU_V7
++
+config TARGET_ZMX25
+ bool "Support zmx25"
+ select CPU_ARM926EJS
+
+config TARGET_APF27
+ bool "Support apf27"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_IMX27LITE
+ bool "Support imx27lite"
+ select CPU_ARM926EJS
+
+config TARGET_MAGNESIUM
+ bool "Support magnesium"
+ select CPU_ARM926EJS
+
+config TARGET_APX4DEVKIT
+ bool "Support apx4devkit"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_XFI3
+ bool "Support xfi3"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_M28EVK
+ bool "Support m28evk"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_MX23EVK
+ bool "Support mx23evk"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_MX28EVK
+ bool "Support mx28evk"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_MX23_OLINUXINO
+ bool "Support mx23_olinuxino"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_BG0900
+ bool "Support bg0900"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_SANSA_FUZE_PLUS
+ bool "Support sansa_fuze_plus"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config TARGET_SC_SPS_1
+ bool "Support sc_sps_1"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config ARCH_NOMADIK
+ bool "ST-Ericsson Nomadik"
+ select CPU_ARM926EJS
+
+config ORION5X
+ bool "Marvell Orion"
+ select CPU_ARM926EJS
+
+config TARGET_DKB
+ bool "Support dkb"
+ select CPU_ARM926EJS
+
+config TARGET_SPEAR300
+ bool "Support spear300"
+ select CPU_ARM926EJS
+
+config TARGET_SPEAR310
+ bool "Support spear310"
+ select CPU_ARM926EJS
+
+config TARGET_SPEAR320
+ bool "Support spear320"
+ select CPU_ARM926EJS
+
+config TARGET_SPEAR600
+ bool "Support spear600"
+ select CPU_ARM926EJS
+
+config TARGET_STV0991
+ bool "Support stv0991"
+ select CPU_V7
+
+config TARGET_X600
+ bool "Support x600"
+ select CPU_ARM926EJS
+ select SUPPORT_SPL
+
+config ARCH_VERSATILE
+ bool "ARM Ltd. Versatile family"
+ select CPU_ARM926EJS
+
+config TARGET_INTEGRATORCP_CM1136
+ bool "Support integratorcp_cm1136"
+ select CPU_ARM1136
+
+config TARGET_IMX31_PHYCORE
+ bool "Support imx31_phycore"
+ select CPU_ARM1136
+
+config TARGET_QONG
+ bool "Support qong"
+ select CPU_ARM1136
+
+config TARGET_MX31ADS
+ bool "Support mx31ads"
+ select CPU_ARM1136
+
+config TARGET_MX31PDK
+ bool "Support mx31pdk"
+ select CPU_ARM1136
+ select SUPPORT_SPL
+
+config TARGET_TT01
+ bool "Support tt01"
+ select CPU_ARM1136
+
+config TARGET_IMX31_LITEKIT
+ bool "Support imx31_litekit"
+ select CPU_ARM1136
+
+config TARGET_WOODBURN
+ bool "Support woodburn"
+ select CPU_ARM1136
+
+config TARGET_WOODBURN_SD
+ bool "Support woodburn_sd"
+ select CPU_ARM1136
+ select SUPPORT_SPL
+
+config TARGET_FLEA3
+ bool "Support flea3"
+ select CPU_ARM1136
+
+config TARGET_MX35PDK
+ bool "Support mx35pdk"
+ select CPU_ARM1136
+
+config TARGET_RPI
+ bool "Support rpi"
+ select CPU_ARM1176
+
+config TARGET_TNETV107X_EVM
+ bool "Support tnetv107x_evm"
+ select CPU_ARM1176
+
+config TARGET_INTEGRATORAP_CM946ES
+ bool "Support integratorap_cm946es"
+ select CPU_ARM946ES
+
+config TARGET_INTEGRATORCP_CM946ES
+ bool "Support integratorcp_cm946es"
+ select CPU_ARM946ES
+
+config TARGET_VEXPRESS_CA15_TC2
+ bool "Support vexpress_ca15_tc2"
+ select CPU_V7
+ select CPU_V7_HAS_NONSEC
+ select CPU_V7_HAS_VIRT
+
+config TARGET_VEXPRESS_CA5X2
+ bool "Support vexpress_ca5x2"
+ select CPU_V7
+
+config TARGET_VEXPRESS_CA9X4
+ bool "Support vexpress_ca9x4"
+ select CPU_V7
+
+config TARGET_KWB
+ bool "Support kwb"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_TSERIES
+ bool "Support tseries"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_CM_T335
+ bool "Support cm_t335"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_PEPPER
+ bool "Support pepper"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_AM335X_IGEP0033
+ bool "Support am335x_igep0033"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_PCM051
+ bool "Support pcm051"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_DRACO
+ bool "Support draco"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_DXR2
+ bool "Support dxr2"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_PXM2
+ bool "Support pxm2"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_RUT
+ bool "Support rut"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_PENGWYN
+ bool "Support pengwyn"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_AM335X_EVM
+ bool "Support am335x_evm"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_AM43XX_EVM
+ bool "Support am43xx_evm"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_TI814X_EVM
+ bool "Support ti814x_evm"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_TI816X_EVM
+ bool "Support ti816x_evm"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_SAMA5D3_XPLAINED
+ bool "Support sama5d3_xplained"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_SAMA5D3XEK
+ bool "Support sama5d3xek"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_SAMA5D4_XPLAINED
+ bool "Support sama5d4_xplained"
+ select CPU_V7
+
+config TARGET_SAMA5D4EK
+ bool "Support sama5d4ek"
+ select CPU_V7
+
+config TARGET_BCM28155_AP
+ bool "Support bcm28155_ap"
+ select CPU_V7
+
+config TARGET_BCMCYGNUS
+ bool "Support bcmcygnus"
+ select CPU_V7
+
+config TARGET_BCMNSP
+ bool "Support bcmnsp"
+ select CPU_V7
+
+config ARCH_EXYNOS
+ bool "Samsung EXYNOS"
+ select CPU_V7
+
+config ARCH_S5PC1XX
+ bool "Samsung S5PC1XX"
+ select CPU_V7
+
+config ARCH_HIGHBANK
+ bool "Calxeda Highbank"
+ select CPU_V7
+
+config ARCH_KEYSTONE
+ bool "TI Keystone"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_M53EVK
+ bool "Support m53evk"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_IMA3_MX53
+ bool "Support ima3-mx53"
+ select CPU_V7
+
+config TARGET_MX51EVK
+ bool "Support mx51evk"
+ select CPU_V7
+
+config TARGET_MX53ARD
+ bool "Support mx53ard"
+ select CPU_V7
+
+config TARGET_MX53EVK
+ bool "Support mx53evk"
+ select CPU_V7
+
+config TARGET_MX53LOCO
+ bool "Support mx53loco"
+ select CPU_V7
+
+config TARGET_MX53SMD
+ bool "Support mx53smd"
+ select CPU_V7
+
+config TARGET_MX51_EFIKAMX
+ bool "Support mx51_efikamx"
+ select CPU_V7
+
+config TARGET_VISION2
+ bool "Support vision2"
+ select CPU_V7
+
+config TARGET_UDOO
+ bool "Support udoo"
+ select CPU_V7
+
+config TARGET_WANDBOARD
+ bool "Support wandboard"
+ select CPU_V7
+
+config TARGET_TITANIUM
+ bool "Support titanium"
+ select CPU_V7
+
+config TARGET_NITROGEN6X
+ bool "Support nitrogen6x"
+ select CPU_V7
+
+config TARGET_CGTQMX6EVAL
+ bool "Support cgtqmx6eval"
+ select CPU_V7
+
+config TARGET_EMBESTMX6BOARDS
+ bool "Support embestmx6boards"
+ select CPU_V7
+
+config TARGET_ARISTAINETOS
+ bool "Support aristainetos"
+ select CPU_V7
+
+config TARGET_MX6QARM2
+ bool "Support mx6qarm2"
+ select CPU_V7
+
+config TARGET_MX6QSABREAUTO
+ bool "Support mx6qsabreauto"
+ select CPU_V7
+
+config TARGET_MX6SABRESD
+ bool "Support mx6sabresd"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_MX6SLEVK
+ bool "Support mx6slevk"
+ select CPU_V7
+
+config TARGET_MX6SXSABRESD
+ bool "Support mx6sxsabresd"
+ select CPU_V7
+
+config TARGET_GW_VENTANA
+ bool "Support gw_ventana"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_HUMMINGBOARD
+ bool "Support hummingboard"
+ select CPU_V7
+
+config TARGET_KOSAGI_NOVENA
+ bool "Support Kosagi Novena"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_TBS2910
+ bool "Support tbs2910"
+ select CPU_V7
+
+config TARGET_TQMA6
+ bool "TQ Systems TQMa6 board"
+ select CPU_V7
+
+config TARGET_OT1200
+ bool "Bachmann OT1200"
+ select CPU_V7
+
+config OMAP34XX
+ bool "OMAP34XX SoC"
+ select CPU_V7
+
+config OMAP44XX
+ bool "OMAP44XX SoC"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config OMAP54XX
+ bool "OMAP54XX SoC"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config RMOBILE
+ bool "Renesas ARM SoCs"
+ select CPU_V7
+
+config TARGET_CM_FX6
+ bool "Support cm_fx6"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_SOCFPGA_CYCLONE5
+ bool "Support socfpga_cyclone5"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config ARCH_SUNXI
+ bool "Support sunxi (Allwinner) SoCs"
+
+config TARGET_SNOWBALL
+ bool "Support snowball"
+ select CPU_V7
+
+config TARGET_U8500_HREF
+ bool "Support u8500_href"
+ select CPU_V7
+
+config TARGET_VF610TWR
+ bool "Support vf610twr"
+ select CPU_V7
+
+config ZYNQ
+ bool "Xilinx Zynq Platform"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TEGRA
+ bool "NVIDIA Tegra"
+ select SUPPORT_SPL
+ select SPL
+ select OF_CONTROL if !SPL_BUILD
+ select CPU_ARM720T if SPL_BUILD
+ select CPU_V7 if !SPL_BUILD
+
+config TARGET_VEXPRESS_AEMV8A
+ bool "Support vexpress_aemv8a"
+ select ARM64
+
+config TARGET_LS2085A_EMU
+ bool "Support ls2085a_emu"
+ select ARM64
+
+config TARGET_LS2085A_SIMU
+ bool "Support ls2085a_simu"
+ select ARM64
+
+config TARGET_LS1021AQDS
+ bool "Support ls1021aqds"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_LS1021ATWR
+ bool "Support ls1021atwr"
+ select CPU_V7
+ select SUPPORT_SPL
+
+config TARGET_BALLOON3
+ bool "Support balloon3"
+ select CPU_PXA
+
+config TARGET_H2200
+ bool "Support h2200"
+ select CPU_PXA
+
+config TARGET_PALMLD
+ bool "Support palmld"
+ select CPU_PXA
+
+config TARGET_PALMTC
+ bool "Support palmtc"
+ select CPU_PXA
+
+config TARGET_PALMTREO680
+ bool "Support palmtreo680"
+ select CPU_PXA
+ select SUPPORT_SPL
+
+config TARGET_PXA255_IDP
+ bool "Support pxa255_idp"
+ select CPU_PXA
+
+config TARGET_TRIZEPSIV
+ bool "Support trizepsiv"
+ select CPU_PXA
+
+config TARGET_VPAC270
+ bool "Support vpac270"
+ select CPU_PXA
+ select SUPPORT_SPL
+
+config TARGET_XAENIAX
+ bool "Support xaeniax"
+ select CPU_PXA
+
+config TARGET_ZIPITZ2
+ bool "Support zipitz2"
+ select CPU_PXA
+
+config TARGET_LP8X4X
+ bool "Support lp8x4x"
+ select CPU_PXA
+
+config TARGET_COLIBRI_PXA270
+ bool "Support colibri_pxa270"
+ select CPU_PXA
+
+config TARGET_JORNADA
+ bool "Support jornada"
+ select CPU_SA1100
+
+config ARCH_UNIPHIER
+ bool "Panasonic UniPhier platform"
+ select CPU_V7
+ select SUPPORT_SPL
+ select SPL
+ select OF_CONTROL if !SPL_BUILD
+
+endchoice
+
+source "arch/arm/cpu/arm926ejs/davinci/Kconfig"
+
+source "arch/arm/cpu/armv7/exynos/Kconfig"
+
+source "arch/arm/cpu/armv7/highbank/Kconfig"
+
+source "arch/arm/cpu/armv7/keystone/Kconfig"
+
+source "arch/arm/cpu/arm926ejs/kirkwood/Kconfig"
+
+source "arch/arm/cpu/arm926ejs/nomadik/Kconfig"
+
+source "arch/arm/cpu/armv7/omap3/Kconfig"
+
+source "arch/arm/cpu/armv7/omap4/Kconfig"
+
+source "arch/arm/cpu/armv7/omap5/Kconfig"
+
+source "arch/arm/cpu/arm926ejs/orion5x/Kconfig"
+
+source "arch/arm/cpu/armv7/rmobile/Kconfig"
+
+source "arch/arm/cpu/armv7/s5pc1xx/Kconfig"
+
+source "arch/arm/cpu/armv7/tegra-common/Kconfig"
+
+source "arch/arm/cpu/armv7/uniphier/Kconfig"
+
+source "arch/arm/cpu/arm926ejs/versatile/Kconfig"
+
+source "arch/arm/cpu/armv7/zynq/Kconfig"
+
+source "arch/arm/cpu/armv7/Kconfig"
+
+source "board/aristainetos/Kconfig"
+source "board/BuR/kwb/Kconfig"
+source "board/BuR/tseries/Kconfig"
+source "board/BuS/eb_cpux9k2/Kconfig"
+source "board/BuS/vl_ma2sc/Kconfig"
+source "board/CarMediaLab/flea3/Kconfig"
+source "board/Marvell/aspenite/Kconfig"
+source "board/Marvell/db-mv784mp-gp/Kconfig"
+source "board/Marvell/dkb/Kconfig"
+source "board/Marvell/gplugd/Kconfig"
+source "board/afeb9260/Kconfig"
+source "board/altera/socfpga/Kconfig"
+source "board/armadeus/apf27/Kconfig"
+source "board/armltd/integrator/Kconfig"
+source "board/armltd/vexpress/Kconfig"
+source "board/armltd/vexpress64/Kconfig"
+source "board/atmel/at91rm9200ek/Kconfig"
+source "board/atmel/at91sam9260ek/Kconfig"
+source "board/atmel/at91sam9261ek/Kconfig"
+source "board/atmel/at91sam9263ek/Kconfig"
+source "board/atmel/at91sam9m10g45ek/Kconfig"
+source "board/atmel/at91sam9n12ek/Kconfig"
+source "board/atmel/at91sam9rlek/Kconfig"
+source "board/atmel/at91sam9x5ek/Kconfig"
+source "board/atmel/sama5d3_xplained/Kconfig"
+source "board/atmel/sama5d3xek/Kconfig"
+source "board/atmel/sama5d4_xplained/Kconfig"
+source "board/atmel/sama5d4ek/Kconfig"
+source "board/bachmann/ot1200/Kconfig"
+source "board/balloon3/Kconfig"
+source "board/barco/titanium/Kconfig"
+source "board/bluegiga/apx4devkit/Kconfig"
+source "board/bluewater/snapper9260/Kconfig"
+source "board/boundary/nitrogen6x/Kconfig"
+source "board/broadcom/bcm28155_ap/Kconfig"
+source "board/broadcom/bcmcygnus/Kconfig"
+source "board/broadcom/bcmnsp/Kconfig"
+source "board/calao/sbc35_a9g20/Kconfig"
+source "board/calao/tny_a9260/Kconfig"
+source "board/calao/usb_a9263/Kconfig"
+source "board/cirrus/edb93xx/Kconfig"
+source "board/cm4008/Kconfig"
+source "board/cm41xx/Kconfig"
+source "board/compulab/cm_t335/Kconfig"
+source "board/compulab/cm_fx6/Kconfig"
+source "board/congatec/cgtqmx6eval/Kconfig"
+source "board/creative/xfi3/Kconfig"
+source "board/davedenx/qong/Kconfig"
+source "board/denx/m28evk/Kconfig"
+source "board/denx/m53evk/Kconfig"
+source "board/egnite/ethernut5/Kconfig"
+source "board/embest/mx6boards/Kconfig"
+source "board/esd/meesc/Kconfig"
+source "board/esd/otc570/Kconfig"
+source "board/esg/ima3-mx53/Kconfig"
+source "board/eukrea/cpu9260/Kconfig"
+source "board/eukrea/cpuat91/Kconfig"
+source "board/faraday/a320evb/Kconfig"
+source "board/freescale/ls2085a/Kconfig"
+source "board/freescale/ls1021aqds/Kconfig"
+source "board/freescale/ls1021atwr/Kconfig"
+source "board/freescale/mx23evk/Kconfig"
+source "board/freescale/mx25pdk/Kconfig"
+source "board/freescale/mx28evk/Kconfig"
+source "board/freescale/mx31ads/Kconfig"
+source "board/freescale/mx31pdk/Kconfig"
+source "board/freescale/mx35pdk/Kconfig"
+source "board/freescale/mx51evk/Kconfig"
+source "board/freescale/mx53ard/Kconfig"
+source "board/freescale/mx53evk/Kconfig"
+source "board/freescale/mx53loco/Kconfig"
+source "board/freescale/mx53smd/Kconfig"
+source "board/freescale/mx6qarm2/Kconfig"
+source "board/freescale/mx6qsabreauto/Kconfig"
+source "board/freescale/mx6sabresd/Kconfig"
+source "board/freescale/mx6slevk/Kconfig"
+source "board/freescale/mx6sxsabresd/Kconfig"
+source "board/freescale/vf610twr/Kconfig"
+source "board/gateworks/gw_ventana/Kconfig"
+source "board/genesi/mx51_efikamx/Kconfig"
+source "board/gumstix/pepper/Kconfig"
+source "board/h2200/Kconfig"
+source "board/hale/tt01/Kconfig"
+source "board/icpdas/lp8x4x/Kconfig"
+source "board/imx31_phycore/Kconfig"
+source "board/isee/igep0033/Kconfig"
+source "board/jornada/Kconfig"
+source "board/karo/tx25/Kconfig"
++source "board/karo/tx28/Kconfig"
++source "board/karo/tx48/Kconfig"
++source "board/karo/tx51/Kconfig"
++source "board/karo/tx53/Kconfig"
++source "board/karo/tx6/Kconfig"
+source "board/kosagi/novena/Kconfig"
+source "board/logicpd/imx27lite/Kconfig"
+source "board/logicpd/imx31_litekit/Kconfig"
+source "board/maxbcm/Kconfig"
+source "board/mpl/vcma9/Kconfig"
+source "board/olimex/mx23_olinuxino/Kconfig"
+source "board/palmld/Kconfig"
+source "board/palmtc/Kconfig"
+source "board/palmtreo680/Kconfig"
+source "board/phytec/pcm051/Kconfig"
+source "board/ppcag/bg0900/Kconfig"
+source "board/pxa255_idp/Kconfig"
+source "board/raspberrypi/rpi/Kconfig"
+source "board/ronetix/pm9261/Kconfig"
+source "board/ronetix/pm9263/Kconfig"
+source "board/ronetix/pm9g45/Kconfig"
+source "board/samsung/smdk2410/Kconfig"
+source "board/sandisk/sansa_fuze_plus/Kconfig"
+source "board/scb9328/Kconfig"
+source "board/schulercontrol/sc_sps_1/Kconfig"
+source "board/siemens/corvus/Kconfig"
+source "board/siemens/draco/Kconfig"
+source "board/siemens/pxm2/Kconfig"
+source "board/siemens/rut/Kconfig"
+source "board/siemens/taurus/Kconfig"
+source "board/silica/pengwyn/Kconfig"
+source "board/solidrun/hummingboard/Kconfig"
+source "board/spear/spear300/Kconfig"
+source "board/spear/spear310/Kconfig"
+source "board/spear/spear320/Kconfig"
+source "board/spear/spear600/Kconfig"
+source "board/spear/x600/Kconfig"
+source "board/st-ericsson/snowball/Kconfig"
+source "board/st-ericsson/u8500/Kconfig"
+source "board/st/stv0991/Kconfig"
+source "board/sunxi/Kconfig"
+source "board/syteco/jadecpu/Kconfig"
+source "board/syteco/zmx25/Kconfig"
+source "board/taskit/stamp9g20/Kconfig"
+source "board/tbs/tbs2910/Kconfig"
+source "board/ti/am335x/Kconfig"
+source "board/ti/am43xx/Kconfig"
+source "board/ti/ti814x/Kconfig"
+source "board/ti/ti816x/Kconfig"
+source "board/ti/tnetv107xevm/Kconfig"
+source "board/timll/devkit3250/Kconfig"
+source "board/toradex/colibri_pxa270/Kconfig"
+source "board/tqc/tqma6/Kconfig"
+source "board/trizepsiv/Kconfig"
+source "board/ttcontrol/vision2/Kconfig"
+source "board/udoo/Kconfig"
+source "board/vpac270/Kconfig"
+source "board/wandboard/Kconfig"
+source "board/woodburn/Kconfig"
+source "board/xaeniax/Kconfig"
+source "board/zipitz2/Kconfig"
+
+source "arch/arm/Kconfig.debug"
+
+endmenu
# SPDX-License-Identifier: GPL-2.0+
#
-CROSS_COMPILE ?= arm-linux-
-
ifndef CONFIG_STANDALONE_LOAD_ADDR
-ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TI814X),)
+ifneq ($(CONFIG_OMAP_COMMON),)
CONFIG_STANDALONE_LOAD_ADDR = 0x80300000
else
CONFIG_STANDALONE_LOAD_ADDR = 0xc100000
endif
LDFLAGS_FINAL += --gc-sections
-PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \
+ -fno-common -ffixed-r9
+PLATFORM_RELFLAGS += $(call cc-option, -msoft-float) \
+ $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
# Support generic board on ARM
__HAVE_ARCH_GENERIC_BOARD := y
-PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
+PLATFORM_CPPFLAGS += -D__ARM__
# Choose between ARM/Thumb instruction sets
ifeq ($(CONFIG_SYS_THUMB_BUILD),y)
-PF_CPPFLAGS_ARM := $(call cc-option, -mthumb -mthumb-interwork,\
+AFLAGS_IMPLICIT_IT := $(call as-option,-Wa$(comma)-mimplicit-it=always)
+PF_CPPFLAGS_ARM := $(AFLAGS_IMPLICIT_IT) \
+ $(call cc-option, -mthumb -mthumb-interwork,\
$(call cc-option,-marm,)\
$(call cc-option,-mno-thumb-interwork,)\
)
# Only test once
ifneq ($(CONFIG_SPL_BUILD),y)
-ALL-$(CONFIG_SYS_THUMB_BUILD) += checkthumb
+ifeq ($(CONFIG_SYS_THUMB_BUILD),y)
+archprepare: checkthumb
+
+checkthumb:
+ @if test "$(call cc-version)" -lt "0404"; then \
+ echo -n '*** Your GCC does not produce working '; \
+ echo 'binaries in THUMB mode.'; \
+ echo '*** Your board is configured for THUMB mode.'; \
+ false; \
+ fi
+endif
endif
- # Try if EABI is supported, else fall back to old API,
+ # Try if EABI is supported, else fall back to old ABI,
# i. e. for example:
# - with ELDK 4.2 (EABI supported), use:
# -mabi=aapcs-linux
# times. Also, the prefix needs to be different based on whether
# CONFIG_SPL_BUILD is defined or not. 'filter-out' the existing entry
# before adding the correct one.
-ifdef CONFIG_SPL_BUILD
-PLATFORM_LIBS := $(SPLTREE)/arch/arm/lib/eabi_compat.o \
- $(filter-out %/arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
-else
-PLATFORM_LIBS := $(OBJTREE)/arch/arm/lib/eabi_compat.o \
- $(filter-out %/arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
-endif
+PLATFORM_LIBS := arch/arm/lib/eabi_compat.o \
+ $(filter-out arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
endif
# needed for relocation
endif
endif
-# check that only R_ARM_RELATIVE relocations are generated
ifneq ($(CONFIG_SPL_BUILD),y)
-ALL-y += checkarmreloc
+# Check that only R_ARM_RELATIVE relocations are generated.
+ALL-y += checkarmreloc
+# The movt / movw can hardcode 16 bit parts of the addresses in the
+# instruction. Relocation is not supported for that case, so disable
+# such usage by requiring word relocations.
+PLATFORM_CPPFLAGS += $(call cc-option, -mword-relocations)
+endif
+
+# limit ourselves to the sections we want in the .bin.
+ifdef CONFIG_ARM64
+OBJCOPYFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rela.dyn
+else
+OBJCOPYFLAGS += -j .text -j .secure_text -j .rodata -j .hash -j .data -j .got.plt -j .u_boot_list -j .rel.dyn
+endif
+
+ifdef CONFIG_OF_EMBED
+OBJCOPYFLAGS += -j .dtb.init.rodata
+endif
+
+ifneq ($(CONFIG_IMX_CONFIG),)
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+ALL-y += SPL
+endif
+else
+ifeq ($(CONFIG_OF_SEPARATE),y)
+ALL-y += u-boot-dtb.imx
+else
+ALL-y += u-boot.imx
+endif
+endif
endif
/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
inline void lowlevel_init(void) {}
+ #define BOOT_CAUSE_MASK (RTC_PERSISTENT0_EXTERNAL_RESET | \
+ RTC_PERSISTENT0_ALARM_WAKE | \
+ RTC_PERSISTENT0_THERMAL_RESET)
+
+ static int wait_rtc_stat(u32 mask)
+ {
+ int timeout = 5000;
+ u32 val;
+ struct mxs_rtc_regs *rtc_regs = (void *)MXS_RTC_BASE;
+ u32 old_val = readl(&rtc_regs->hw_rtc_stat);
+
+ debug("stat=%x\n", old_val);
+
+ while ((val = readl(&rtc_regs->hw_rtc_stat)) & mask) {
+ if (val != old_val) {
+ old_val = val;
+ debug("stat: %x -> %x\n", old_val, val);
+ }
+ udelay(1);
+ if (timeout-- < 0)
+ break;
+ }
+ return !!(readl(&rtc_regs->hw_rtc_stat) & mask);
+ }
+
void reset_cpu(ulong ignored) __attribute__((noreturn));
void reset_cpu(ulong ignored)
(struct mxs_rtc_regs *)MXS_RTC_BASE;
struct mxs_lcdif_regs *lcdif_regs =
(struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+ u32 reg;
/*
* Shut down the LCD controller as it interferes with BootROM boot mode
*/
writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr);
- /* Wait 1 uS before doing the actual watchdog reset */
+ reg = readl(&rtc_regs->hw_rtc_persistent0);
+ if (reg & BOOT_CAUSE_MASK) {
+ writel(reg & ~BOOT_CAUSE_MASK, &rtc_regs->hw_rtc_persistent0);
+ wait_rtc_stat(RTC_STAT_NEW_REGS_PERSISTENT0);
+ }
+
+ /* Wait 1 mS before doing the actual watchdog reset */
writel(1, &rtc_regs->hw_rtc_watchdog);
writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
void mx28_fixup_vt(uint32_t start_addr)
{
/* ldr pc, [pc, #0x18] */
- const uint32_t ldr_pc = 0xe59ff018;
/* Jumptable location is 0x0 */
- uint32_t *vt = (uint32_t *)0x0;
- int i;
+ uint32_t *vt = (uint32_t *)0x20;
+ uint32_t cr = get_cr();
++<<<<<<< HEAD
+ for (i = 0; i < 8; i++) {
+ /* cppcheck-suppress nullPointer */
+ vt[i] = ldr_pc;
+ /* cppcheck-suppress nullPointer */
+ vt[i + 8] = start_addr + (4 * i);
+ }
++=======
+ memcpy(vt, (void *)start_addr + 0x20, 32);
+ set_cr(cr & ~CR_V);
++>>>>>>> karo-tx-uboot
}
#ifdef CONFIG_ARCH_MISC_INIT
}
#endif
+ #ifdef CONFIG_ARCH_CPU_INIT
int arch_cpu_init(void)
{
struct mxs_clkctrl_regs *clkctrl_regs =
return 0;
}
+ #endif
#if defined(CONFIG_DISPLAY_CPUINFO)
static const char *get_cpu_type(void)
}
#endif
+ #define pr_clk(n, c) { \
+ unsigned long clk = c; \
+ printf("%-5s %3lu.%03lu MHz\n", #n ":", clk / 1000000, \
+ clk / 1000 % 1000); \
+ }
+
int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- printf("CPU: %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
- printf("BUS: %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
- printf("EMI: %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
- printf("GPMI: %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+ pr_clk(CPU, mxc_get_clock(MXC_ARM_CLK));
+ pr_clk(APBH, mxc_get_clock(MXC_AHB_CLK));
+ pr_clk(APBX, mxc_get_clock(MXC_XBUS_CLK));
+ pr_clk(IO0, mxc_get_clock(MXC_IO0_CLK) * 1000);
+ pr_clk(IO1, mxc_get_clock(MXC_IO1_CLK) * 1000);
+ pr_clk(EMI, mxc_get_clock(MXC_EMI_CLK) * 1000000);
+ pr_clk(GPMI, mxc_get_clock(MXC_GPMI_CLK));
return 0;
}
udelay(10);
+ /*
+ * Enable pad output; must be done BEFORE enabling PLL
+ * according to i.MX28 Ref. Manual Rev. 1, 2010 p. 883
+ */
+ setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
/* Gate on ENET PLL */
writel(CLKCTRL_PLL2CTRL0_CLKGATE,
&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
- /* Enable pad output */
- setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
-
+ udelay(6000);
return 0;
}
#endif
#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
+#include <linux/compiler.h>
#include "mxs_init.h"
+DECLARE_GLOBAL_DATA_PTR;
+static gd_t gdata __section(".data");
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+static bd_t bdata __section(".data");
+#endif
+
/*
* This delay function is intended to be used only in early stage of boot, where
* clock are not set up yet. The timer used here is reset on every boot and
* takes a few seconds to roll. The boot doesn't take that long, so to keep the
* code simple, it doesn't take rolling into consideration.
*/
+ /*
+ * There's nothing to be taken into consideration for the rollover.
+ * Two's complement arithmetic used correctly does all that's needed
+ * automagically.
+ */
void early_delay(int delay)
{
struct mxs_digctl_regs *digctl_regs =
(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
+ u32 start = readl(&digctl_regs->hw_digctl_microseconds);
- uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
- st += delay;
- while (st > readl(&digctl_regs->hw_digctl_microseconds))
- ;
+ while (readl(&digctl_regs->hw_digctl_microseconds) - start < delay);
}
#define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
return i;
}
-void mxs_common_spl_init(const iomux_cfg_t *iomux_setup,
- const unsigned int iomux_size)
+static void mxs_spl_fixup_vectors(void)
+{
+ /*
+ * Copy our vector table to 0x0, since due to HAB, we cannot
+ * be loaded to 0x0. We want to have working vectoring though,
+ * thus this fixup. Our vectoring table is PIC, so copying is
+ * fine.
+ */
+ extern uint32_t _start;
+
+ /* cppcheck-suppress nullPointer */
+ memcpy(0x0, &_start, 0x60);
+}
+
+static void mxs_spl_console_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+ gd->bd = &bdata;
+ gd->baudrate = CONFIG_BAUDRATE;
+ serial_init();
+ gd->have_console = 1;
+#endif
+}
+
+void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
+ const iomux_cfg_t *iomux_setup,
+ const unsigned int iomux_size)
{
struct mxs_spl_data *data = (struct mxs_spl_data *)
((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
uint8_t bootmode = mxs_get_bootmode_index();
+ gd = &gdata;
+
+ mxs_spl_fixup_vectors();
mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
+
+ mxs_spl_console_init();
+
mxs_power_init();
mxs_mem_init();
mxs_power_wait_pswitch();
}
- /* Support aparatus */
+ /* Support apparatus */
inline void board_init_f(unsigned long bootflag)
{
for (;;)
writeb(CLKCTRL_FRAC_CLKGATE,
&clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
- early_delay(11000);
/* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
&clkctrl_regs->hw_clkctrl_emi);
+ while (readl(&clkctrl_regs->hw_clkctrl_emi) & CLKCTRL_EMI_BUSY_REF_EMI)
+ ;
/* Unbypass EMI */
writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
&clkctrl_regs->hw_clkctrl_clkseq_clr);
-
- early_delay(10000);
}
static void mxs_mem_setup_cpu_and_hbus(void)
&clkctrl_regs->hw_clkctrl_clkseq_set);
/* HBUS = 151MHz */
- writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
- writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
- &clkctrl_regs->hw_clkctrl_hbus_clr);
-
- early_delay(10000);
+ clrsetbits_le32(&clkctrl_regs->hw_clkctrl_hbus,
+ CLKCTRL_HBUS_DIV_MASK,
+ 3 << CLKCTRL_HBUS_DIV_OFFSET);
+ while (readl(&clkctrl_regs->hw_clkctrl_hbus) & CLKCTRL_HBUS_ASM_BUSY)
+ ;
/* CPU clock divider = 1 */
clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
- CLKCTRL_CPU_DIV_CPU_MASK, 1);
+ CLKCTRL_CPU_DIV_CPU_MASK,
+ 1 << CLKCTRL_CPU_DIV_CPU_OFFSET);
+ while (readl(&clkctrl_regs->hw_clkctrl_cpu) & CLKCTRL_CPU_BUSY_REF_CPU)
+ ;
/* Disable CPU bypass */
writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
&clkctrl_regs->hw_clkctrl_clkseq_clr);
-
- early_delay(15000);
}
- static void mxs_mem_setup_vdda(void)
+ void data_abort_memdetect_handler(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
- writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
- (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
- POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
- &power_regs->hw_power_vddactrl);
+ asm volatile("subs pc, lr, #4");
}
uint32_t mxs_mem_get_size(void)
{
uint32_t sz, da;
uint32_t *vt = (uint32_t *)0x20;
- /* The following is "subs pc, r14, #4", used as return from DABT. */
- const uint32_t data_abort_memdetect_handler = 0xe25ef004;
+ unsigned long cr;
+
+ /* move vector table to low memory */
+ asm volatile(
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "bic r7, %0, #(1 << 13)\n"
+ "mcr p15, 0, r7, c1, c0, 0\n"
+ : "=r"(cr) : : "r7");
/* Replace the DABT handler. */
da = vt[4];
- vt[4] = data_abort_memdetect_handler;
+ vt[4] = (uint32_t)data_abort_memdetect_handler;
sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
/* Restore the old DABT handler. */
vt[4] = da;
+ asm volatile("mcr p15, 0, %0, c1, c0, 0\n" : : "r"(cr));
return sz;
}
struct mxs_power_regs *power_regs =
(struct mxs_power_regs *)MXS_POWER_BASE;
+ /* We must wait before and after disabling the current limiter! */
+ early_delay(10000);
+
clrbits_le32(&power_regs->hw_power_vddmemctrl,
POWER_VDDMEMCTRL_ENABLE_ILIMIT);
+ early_delay(10000);
+
}
static void mx23_mem_init(void)
setbits_le32(MXS_DRAM_BASE + 0x20, 1 << 16);
clrbits_le32(MXS_DRAM_BASE + 0x40, 1 << 17);
- early_delay(20000);
+
+ /* Wait for EMI_STAT bit DRAM_HALTED */
+ for (;;) {
+ if (!(readl(MXS_EMI_BASE + 0x10) & (1 << 1)))
+ break;
+ early_delay(1000);
+ }
/* Adjust EMI port priority. */
clrsetbits_le32(0x80020000, 0x1f << 16, 0x2);
mxs_mem_init_clock();
- mxs_mem_setup_vdda();
-
#if defined(CONFIG_MX23)
mx23_mem_init();
#elif defined(CONFIG_MX28)
mx28_mem_init();
#endif
- early_delay(10000);
-
mxs_mem_setup_cpu_and_hbus();
}
#include "mxs_init.h"
+ #ifdef CONFIG_SYS_SPL_VDDD_VAL
+ #define VDDD_VAL CONFIG_SYS_SPL_VDDD_VAL
+ #else
+ #define VDDD_VAL 1350
+ #endif
+ #ifdef CONFIG_SYS_SPL_VDDIO_VAL
+ #define VDDIO_VAL CONFIG_SYS_SPL_VDDIO_VAL
+ #else
+ #define VDDIO_VAL 3300
+ #endif
+ #ifdef CONFIG_SYS_SPL_VDDA_VAL
+ #define VDDA_VAL CONFIG_SYS_SPL_VDDA_VAL
+ #else
+ #define VDDA_VAL 1800
+ #endif
+ #ifdef CONFIG_SYS_SPL_VDDMEM_VAL
+ #define VDDMEM_VAL CONFIG_SYS_SPL_VDDMEM_VAL
+ #else
+ #define VDDMEM_VAL 1700
+ #endif
+
+ #ifdef CONFIG_SYS_SPL_VDDD_BO_VAL
+ #define VDDD_BO_VAL CONFIG_SYS_SPL_VDDD_BO_VAL
+ #else
+ #define VDDD_BO_VAL 150
+ #endif
+ #ifdef CONFIG_SYS_SPL_VDDIO_BO_VAL
+ #define VDDIO_BO_VAL CONFIG_SYS_SPL_VDDIO_BO_VAL
+ #else
+ #define VDDIO_BO_VAL 150
+ #endif
+ #ifdef CONFIG_SYS_SPL_VDDA_BO_VAL
+ #define VDDA_BO_VAL CONFIG_SYS_SPL_VDDA_BO_VAL
+ #else
+ #define VDDA_BO_VAL 175
+ #endif
+ #ifdef CONFIG_SYS_SPL_VDDMEM_BO_VAL
+ #define VDDMEM_BO_VAL CONFIG_SYS_SPL_VDDMEM_BO_VAL
+ #else
+ #define VDDMEM_BO_VAL 25
+ #endif
+
+ #ifdef CONFIG_SYS_SPL_BATT_BO_LEVEL
+ #if CONFIG_SYS_SPL_BATT_BO_LEVEL < 2400 || CONFIG_SYS_SPL_BATT_BO_LEVEL > 3640
+ #error CONFIG_SYS_SPL_BATT_BO_LEVEL out of range
+ #endif
+ #define BATT_BO_VAL (((CONFIG_SYS_SPL_BATT_BO_LEVEL) - 2400) / 40)
+ #else
+ /* Brownout default at 3V */
+ #define BATT_BO_VAL ((3000 - 2400) / 40)
+ #endif
+
+ #ifdef CONFIG_SYS_SPL_FIXED_BATT_SUPPLY
+ static const int fixed_batt_supply = 1;
+ #else
+ static const int fixed_batt_supply;
+ #endif
+
+ static struct mxs_power_regs *power_regs = (void *)MXS_POWER_BASE;
+
+/**
+ * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL
+ *
+ * This function switches the CPU core clock from PLL to 24MHz XTAL
+ * oscilator. This is necessary if the PLL is being reconfigured to
+ * prevent crash of the CPU core.
+ */
static void mxs_power_clock2xtal(void)
{
struct mxs_clkctrl_regs *clkctrl_regs =
&clkctrl_regs->hw_clkctrl_clkseq_set);
}
+/**
+ * mxs_power_clock2pll() - Switch CPU core clock source to PLL
+ *
+ * This function switches the CPU core clock from 24MHz XTAL oscilator
+ * to PLL. This can only be called once the PLL has re-locked and once
+ * the PLL is stable after reconfiguration.
+ */
static void mxs_power_clock2pll(void)
{
struct mxs_clkctrl_regs *clkctrl_regs =
CLKCTRL_CLKSEQ_BYPASS_CPU);
}
-
- static void mxs_power_set_auto_restart(void)
+ static int mxs_power_wait_rtc_stat(u32 mask)
+ {
+ int timeout = 5000; /* 3 ms according to i.MX28 Ref. Manual */
+ u32 val;
+ struct mxs_rtc_regs *rtc_regs = (void *)MXS_RTC_BASE;
+
+ while ((val = readl(&rtc_regs->hw_rtc_stat)) & mask) {
+ early_delay(1);
+ if (timeout-- < 0)
+ break;
+ }
+ return !!(readl(&rtc_regs->hw_rtc_stat) & mask);
+ }
+
+/**
+ * mxs_power_set_auto_restart() - Set the auto-restart bit
+ *
+ * This function ungates the RTC block and sets the AUTO_RESTART
+ * bit to work around a design bug on MX28EVK Rev. A .
+ */
+ static int mxs_power_set_auto_restart(int on)
{
- struct mxs_rtc_regs *rtc_regs =
- (struct mxs_rtc_regs *)MXS_RTC_BASE;
-
- writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
- while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
- ;
+ struct mxs_rtc_regs *rtc_regs = (void *)MXS_RTC_BASE;
- writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
- while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
- ;
- /*
- * Due to the hardware design bug of mx28 EVK-A
- * we need to set the AUTO_RESTART bit.
- */
+ if (mxs_power_wait_rtc_stat(RTC_STAT_STALE_REGS_PERSISTENT0))
+ return 1;
- return;
+ /* Do nothing if flag already set */
+ if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
- while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
- ;
++ return 0;
+
+ if ((!(readl(&rtc_regs->hw_rtc_persistent0) &
+ RTC_PERSISTENT0_AUTO_RESTART) ^ !on) == 0)
+ return 0;
- setbits_le32(&rtc_regs->hw_rtc_persistent0,
- RTC_PERSISTENT0_AUTO_RESTART);
- writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
- writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
- while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
- ;
- while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
- ;
+ if (mxs_power_wait_rtc_stat(RTC_STAT_NEW_REGS_PERSISTENT0))
+ return 1;
+
+ clrsetbits_le32(&rtc_regs->hw_rtc_persistent0,
+ !on * RTC_PERSISTENT0_AUTO_RESTART,
+ !!on * RTC_PERSISTENT0_AUTO_RESTART);
+ if (mxs_power_wait_rtc_stat(RTC_STAT_NEW_REGS_PERSISTENT0))
+ return 1;
+
+ return 0;
}
+/**
+ * mxs_power_set_linreg() - Set linear regulators 25mV below DC-DC converter
+ *
+ * This function configures the VDDIO, VDDA and VDDD linear regulators output
+ * to be 25mV below the VDDIO, VDDA and VDDD output from the DC-DC switching
+ * converter. This is the recommended setting for the case where we use both
+ * linear regulators and DC-DC converter to power the VDDIO rail.
+ */
static void mxs_power_set_linreg(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
/* Set linear regulator 25mV below switching converter */
clrsetbits_le32(&power_regs->hw_power_vdddctrl,
POWER_VDDDCTRL_LINREG_OFFSET_MASK,
POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
}
+/**
+ * mxs_get_batt_volt() - Measure battery input voltage
+ *
+ * This function retrieves the battery input voltage and returns it.
+ */
static int mxs_get_batt_volt(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+
volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
volt *= 8;
return volt;
}
+/**
+ * mxs_is_batt_ready() - Test if the battery provides enough voltage to boot
+ *
+ * This function checks if the battery input voltage is higher than 3.6V and
+ * therefore allows the system to successfully boot using this power source.
+ */
static int mxs_is_batt_ready(void)
{
return (mxs_get_batt_volt() >= 3600);
}
+/**
+ * mxs_is_batt_good() - Test if battery is operational at all
+ *
+ * This function starts recharging the battery and tests if the input current
+ * provided by the 5V input recharging the battery is also sufficient to power
+ * the DC-DC converter.
+ */
static int mxs_is_batt_good(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t volt = mxs_get_batt_volt();
if ((volt >= 2400) && (volt <= 4300))
return 0;
}
+/**
+ * mxs_power_setup_5v_detect() - Start the 5V input detection comparator
+ *
+ * This function enables the 5V detection comparator and sets the 5V valid
+ * threshold to 4.4V . We use 4.4V threshold here to make sure that even
+ * under high load, the voltage drop on the 5V input won't be so critical
+ * to cause undervolt on the 4P2 linear regulator supplying the DC-DC
+ * converter and thus making the system crash.
+ */
static void mxs_power_setup_5v_detect(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
/* Start 5V detection */
clrsetbits_le32(&power_regs->hw_power_5vctrl,
POWER_5VCTRL_VBUSVALID_TRSH_MASK,
POWER_5VCTRL_PWRUP_VBUS_CMPS);
}
+/**
+ * mxs_src_power_init() - Preconfigure the power block
+ *
+ * This function configures reasonable values for the DC-DC control loop
+ * and battery monitor.
+ */
static void mxs_src_power_init(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
/* Improve efficieny and reduce transient ripple */
writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
- setbits_le32(&power_regs->hw_power_battmonitor,
+ if (!fixed_batt_supply) {
+ /* FIXME: This requires the LRADC to be set up! */
+ setbits_le32(&power_regs->hw_power_battmonitor,
POWER_BATTMONITOR_EN_BATADJ);
+ } else {
+ clrbits_le32(&power_regs->hw_power_battmonitor,
+ POWER_BATTMONITOR_EN_BATADJ);
+ }
/* Increase the RCSCALE level for quick DCDC response to dynamic load */
clrsetbits_le32(&power_regs->hw_power_loopctrl,
clrsetbits_le32(&power_regs->hw_power_minpwr,
POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
- /* 5V to battery handoff ... FIXME */
- setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
- early_delay(30);
- clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+ if (!fixed_batt_supply) {
+ /* 5V to battery handoff ... FIXME */
+ setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+ early_delay(30);
+ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+ }
}
+/**
+ * mxs_power_init_4p2_params() - Configure the parameters of the 4P2 regulator
+ *
+ * This function configures the necessary parameters for the 4P2 linear
+ * regulator to supply the DC-DC converter from 5V input.
+ */
static void mxs_power_init_4p2_params(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
/* Setup 4P2 parameters */
clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
}
+/**
+ * mxs_enable_4p2_dcdc_input() - Enable or disable the DCDC input from 4P2
+ * @xfer: Select if the input shall be enabled or disabled
+ *
+ * This function enables or disables the 4P2 input into the DC-DC converter.
+ */
static void mxs_enable_4p2_dcdc_input(int xfer)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
uint32_t prev_5v_brnout, prev_5v_droop;
POWER_CTRL_ENIRQ_VDD5V_DROOP);
}
+/**
+ * mxs_power_init_4p2_regulator() - Start the 4P2 regulator
+ *
+ * This function enables the 4P2 regulator and switches the DC-DC converter
+ * to use the 4P2 input.
+ */
static void mxs_power_init_4p2_regulator(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t tmp, tmp2;
setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
}
+/**
+ * mxs_power_init_dcdc_4p2_source() - Switch DC-DC converter to 4P2 source
+ *
+ * This function configures the DC-DC converter to be supplied from the 4P2
+ * linear regulator.
+ */
static void mxs_power_init_dcdc_4p2_source(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
if (!(readl(&power_regs->hw_power_dcdc4p2) &
POWER_DCDC4P2_ENABLE_DCDC)) {
hang();
}
}
+/**
+ * mxs_power_enable_4p2() - Power up the 4P2 regulator
+ *
+ * This function drives the process of powering up the 4P2 linear regulator
+ * and switching the DC-DC converter input over to the 4P2 linear regulator.
+ */
static void mxs_power_enable_4p2(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t vdddctrl, vddactrl, vddioctrl;
uint32_t tmp;
&power_regs->hw_power_charge_clr);
}
+/**
+ * mxs_boot_valid_5v() - Boot from 5V supply
+ *
+ * This function configures the power block to boot from valid 5V input.
+ * This is called only if the 5V is reliable and can properly supply the
+ * CPU. This function proceeds to configure the 4P2 converter to be supplied
+ * from the 5V input.
+ */
static void mxs_boot_valid_5v(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
/*
* Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
* disconnect event. FIXME
mxs_power_enable_4p2();
}
+/**
+ * mxs_powerdown() - Shut down the system
+ *
+ * This function powers down the CPU completely.
+ */
static void mxs_powerdown(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
&power_regs->hw_power_reset);
}
+/**
+ * mxs_batt_boot() - Configure the power block to boot from battery input
+ *
+ * This function configures the power block to boot from the battery voltage
+ * supply.
+ */
static void mxs_batt_boot(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
clrsetbits_le32(&power_regs->hw_power_5vctrl,
POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+
+ mxs_power_enable_4p2();
}
+/**
+ * mxs_handle_5v_conflict() - Test if the 5V input is reliable
+ *
+ * This function tests if the 5V input can reliably supply the system. If it
+ * can, then proceed to configuring the system to boot from 5V source, otherwise
+ * try booting from battery supply. If we can not boot from battery supply
+ * either, shut down the system.
+ */
static void mxs_handle_5v_conflict(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t tmp;
setbits_le32(&power_regs->hw_power_vddioctrl,
}
}
+/**
+ * mxs_5v_boot() - Configure the power block to boot from 5V input
+ *
+ * This function handles configuration of the power block when supplied by
+ * a 5V input.
+ */
static void mxs_5v_boot(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
/*
* NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
* but their implementation always returns 1 so we omit it here.
mxs_handle_5v_conflict();
}
-static void mxs_fixed_batt_boot(void)
+/**
+ * mxs_init_batt_bo() - Configure battery brownout threshold
+ *
+ * This function configures the battery input brownout threshold. The value
+ * at which the battery brownout happens is configured to 3.0V in the code.
+ */
+static void mxs_init_batt_bo(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_PWDN_5VBRNOUT |
+ POWER_5VCTRL_ENABLE_DCDC |
+ POWER_5VCTRL_ILIMIT_EQ_ZERO |
+ POWER_5VCTRL_PWDN_5VBRNOUT |
+ POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
+
+ writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+ clrbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_DISABLE_FET |
+ POWER_VDDDCTRL_ENABLE_LINREG |
+ POWER_VDDDCTRL_DISABLE_STEPPING);
+
+ clrbits_le32(&power_regs->hw_power_vddactrl,
+ POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+ POWER_VDDACTRL_DISABLE_STEPPING);
+
+ clrbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_DISABLE_FET |
+ POWER_VDDIOCTRL_DISABLE_STEPPING);
- /* Brownout at 3V */
+ /* Stop 5V detection */
+ writel(POWER_5VCTRL_PWRUP_VBUS_CMPS,
+ &power_regs->hw_power_5vctrl_clr);
+ }
+
+ static void mxs_init_batt_bo(void)
+ {
clrsetbits_le32(&power_regs->hw_power_battmonitor,
POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
- 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+ BATT_BO_VAL << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
}
+/**
+ * mxs_switch_vddd_to_dcdc_source() - Switch VDDD rail to DC-DC converter
+ *
+ * This function turns off the VDDD linear regulator and therefore makes
+ * the VDDD rail be supplied only by the DC-DC converter.
+ */
static void mxs_switch_vddd_to_dcdc_source(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
clrsetbits_le32(&power_regs->hw_power_vdddctrl,
POWER_VDDDCTRL_LINREG_OFFSET_MASK,
POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
POWER_VDDDCTRL_DISABLE_STEPPING);
}
+/**
+ * mxs_power_configure_power_source() - Configure power block source
+ *
+ * This function is the core of the power configuration logic. The function
+ * selects the power block input source and configures the whole power block
+ * accordingly. After the configuration is complete and the system is stable
+ * again, the function switches the CPU clock source back to PLL. Finally,
+ * the function switches the voltage rails to DC-DC converter.
+ */
static void mxs_power_configure_power_source(void)
{
- int batt_ready, batt_good;
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
struct mxs_lradc_regs *lradc_regs =
(struct mxs_lradc_regs *)MXS_LRADC_BASE;
mxs_src_power_init();
- if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
- batt_ready = mxs_is_batt_ready();
- if (batt_ready) {
- /* 5V source detected, good battery detected. */
- mxs_batt_boot();
- } else {
- batt_good = mxs_is_batt_good();
- if (!batt_good) {
- /* 5V source detected, bad battery detected. */
- writel(LRADC_CONVERSION_AUTOMATIC,
- &lradc_regs->hw_lradc_conversion_clr);
- clrbits_le32(&power_regs->hw_power_battmonitor,
- POWER_BATTMONITOR_BATT_VAL_MASK);
+ if (!fixed_batt_supply) {
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ if (mxs_is_batt_ready()) {
+ /* 5V source detected, good battery detected. */
+ mxs_batt_boot();
+ } else {
+ if (!mxs_is_batt_good()) {
+ /* 5V source detected, bad battery detected. */
+ writel(LRADC_CONVERSION_AUTOMATIC,
+ &lradc_regs->hw_lradc_conversion_clr);
+ clrbits_le32(&power_regs->hw_power_battmonitor,
+ POWER_BATTMONITOR_BATT_VAL_MASK);
+ }
+ mxs_5v_boot();
}
- mxs_5v_boot();
+ } else {
+ /* 5V not detected, booting from battery. */
+ mxs_batt_boot();
}
} else {
- /* 5V not detected, booting from battery. */
- mxs_batt_boot();
+ mxs_fixed_batt_boot();
}
mxs_power_clock2pll();
#endif
}
+/**
+ * mxs_enable_output_rail_protection() - Enable power rail protection
+ *
+ * This function enables overload protection on the power rails. This is
+ * triggered if the power rails' voltage drops rapidly due to overload and
+ * in such case, the supply to the powerrail is cut-off, protecting the
+ * CPU from damage. Note that under such condition, the system will likely
+ * crash or misbehave.
+ */
static void mxs_enable_output_rail_protection(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
POWER_VDDIOCTRL_PWDN_BRNOUT);
}
+/**
+ * mxs_get_vddio_power_source_off() - Get VDDIO rail power source
+ *
+ * This function tests if the VDDIO rail is supplied by linear regulator
+ * or by the DC-DC converter. Returns 1 if powered by linear regulator,
+ * returns 0 if powered by the DC-DC converter.
+ */
static int mxs_get_vddio_power_source_off(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t tmp;
- if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ if ((readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) &&
+ !(readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ILIMIT_EQ_ZERO)) {
+
tmp = readl(&power_regs->hw_power_vddioctrl);
if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
}
return 0;
-
}
+/**
+ * mxs_get_vddd_power_source_off() - Get VDDD rail power source
+ *
+ * This function tests if the VDDD rail is supplied by linear regulator
+ * or by the DC-DC converter. Returns 1 if powered by linear regulator,
+ * returns 0 if powered by the DC-DC converter.
+ */
static int mxs_get_vddd_power_source_off(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t tmp;
tmp = readl(&power_regs->hw_power_vdddctrl);
return 0;
}
+ static int mxs_get_vdda_power_source_off(void)
+ {
+ uint32_t tmp;
+
+ tmp = readl(&power_regs->hw_power_vddactrl);
+ if (tmp & POWER_VDDACTRL_DISABLE_FET) {
+ if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDACTRL_LINREG_OFFSET_0STEPS) {
+ return 1;
+ }
+ }
+
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ if (!(readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ENABLE_DCDC)) {
+ return 1;
+ }
+ }
+
+ if (!(tmp & POWER_VDDACTRL_ENABLE_LINREG)) {
+ if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW) {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
struct mxs_vddx_cfg {
uint32_t *reg;
uint8_t step_mV;
uint16_t lowest_mV;
+ uint16_t highest_mV;
int (*powered_by_linreg)(void);
uint32_t trg_mask;
uint32_t bo_irq;
uint32_t bo_offset_offset;
};
+ #define POWER_REG(n) &((struct mxs_power_regs *)MXS_POWER_BASE)->n
+
static const struct mxs_vddx_cfg mxs_vddio_cfg = {
- .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
- hw_power_vddioctrl),
+ .reg = POWER_REG(hw_power_vddioctrl),
#if defined(CONFIG_MX23)
.step_mV = 25,
#else
.step_mV = 50,
#endif
.lowest_mV = 2800,
+ .highest_mV = 3600,
.powered_by_linreg = mxs_get_vddio_power_source_off,
.trg_mask = POWER_VDDIOCTRL_TRG_MASK,
.bo_irq = POWER_CTRL_VDDIO_BO_IRQ,
};
static const struct mxs_vddx_cfg mxs_vddd_cfg = {
- .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
- hw_power_vdddctrl),
+ .reg = POWER_REG(hw_power_vdddctrl),
.step_mV = 25,
.lowest_mV = 800,
+ .highest_mV = 1575,
.powered_by_linreg = mxs_get_vddd_power_source_off,
.trg_mask = POWER_VDDDCTRL_TRG_MASK,
.bo_irq = POWER_CTRL_VDDD_BO_IRQ,
.bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
};
+ static const struct mxs_vddx_cfg mxs_vdda_cfg = {
+ .reg = POWER_REG(hw_power_vddactrl),
+ .step_mV = 50,
+ .lowest_mV = 2800,
+ .highest_mV = 3600,
+ .powered_by_linreg = mxs_get_vdda_power_source_off,
+ .trg_mask = POWER_VDDACTRL_TRG_MASK,
+ .bo_irq = POWER_CTRL_VDDA_BO_IRQ,
+ .bo_enirq = POWER_CTRL_ENIRQ_VDDA_BO,
+ .bo_offset_mask = POWER_VDDACTRL_BO_OFFSET_MASK,
+ .bo_offset_offset = POWER_VDDACTRL_BO_OFFSET_OFFSET,
+ };
+
#ifdef CONFIG_MX23
static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
- .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
- hw_power_vddmemctrl),
+ .reg = POWER_REG(hw_power_vddmemctrl),
.step_mV = 50,
- .lowest_mV = 1700,
+ .lowest_mV = 1500,
+ .highest_mV = 1700,
.powered_by_linreg = NULL,
.trg_mask = POWER_VDDMEMCTRL_TRG_MASK,
.bo_irq = 0,
};
#endif
+/**
+ * mxs_power_set_vddx() - Configure voltage on DC-DC converter rail
+ * @cfg: Configuration data of the DC-DC converter rail
+ * @new_target: New target voltage of the DC-DC converter rail
+ * @new_brownout: New brownout trigger voltage
+ *
+ * This function configures the output voltage on the DC-DC converter rail.
+ * The rail is selected by the @cfg argument. The new voltage target is
+ * selected by the @new_target and the voltage is specified in mV. The
+ * new brownout value is selected by the @new_brownout argument and the
+ * value is also in mV.
+ */
static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
uint32_t new_target, uint32_t new_brownout)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
uint32_t cur_target, diff, bo_int = 0;
- uint32_t powered_by_linreg = 0;
- int adjust_up, tmp;
+ int powered_by_linreg = 0;
+ int adjust_up;
+
+ if (new_target < cfg->lowest_mV)
+ new_target = cfg->lowest_mV;
+ if (new_target > cfg->highest_mV)
+ new_target = cfg->highest_mV;
- new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV);
+ new_brownout = DIV_ROUND_CLOSEST(new_target - new_brownout,
+ cfg->step_mV);
cur_target = readl(cfg->reg);
cur_target &= cfg->trg_mask;
if (powered_by_linreg ||
(readl(&power_regs->hw_power_sts) &
- POWER_STS_VDD5V_GT_VDDIO))
+ POWER_STS_VDD5V_GT_VDDIO)) {
early_delay(500);
- else {
- for (;;) {
- tmp = readl(&power_regs->hw_power_sts);
- if (tmp & POWER_STS_DC_OK)
- break;
+ } else {
+ while (!(readl(&power_regs->hw_power_sts) &
+ POWER_STS_DC_OK)) {
+
}
}
}
}
+/**
+ * mxs_setup_batt_detect() - Start the battery voltage measurement logic
+ *
+ * This function starts and configures the LRADC block. This allows the
+ * power initialization code to measure battery voltage and based on this
+ * knowledge, decide whether to boot at all, boot from battery or boot
+ * from 5V input.
+ */
static void mxs_setup_batt_detect(void)
{
mxs_lradc_init();
early_delay(10);
}
+/**
+ * mxs_ungate_power() - Ungate the POWER block
+ *
+ * This function ungates clock to the power block. In case the power block
+ * was still gated at this point, it will not be possible to configure the
+ * block and therefore the power initialization would fail. This function
+ * is only needed on i.MX233, on i.MX28 the power block is always ungated.
+ */
static void mxs_ungate_power(void)
{
#ifdef CONFIG_MX23
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr);
#endif
}
+ #ifdef CONFIG_CONFIG_MACH_MX28EVK
+ #define auto_restart 1
+ #else
+ #define auto_restart 0
+ #endif
+
+/**
+ * mxs_power_init() - The power block init main function
+ *
+ * This function calls all the power block initialization functions in
+ * proper sequence to start the power block.
+ */
void mxs_power_init(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
mxs_ungate_power();
mxs_power_clock2xtal();
- mxs_power_set_auto_restart();
+ if (mxs_power_set_auto_restart(auto_restart)) {
+ serial_puts("Inconsistent value in RTC_PERSISTENT0 register; power-on-reset required\n");
+ }
mxs_power_set_linreg();
- mxs_power_setup_5v_detect();
- mxs_setup_batt_detect();
+ if (!fixed_batt_supply) {
+ mxs_power_setup_5v_detect();
+ mxs_setup_batt_detect();
+ }
mxs_power_configure_power_source();
mxs_enable_output_rail_protection();
- mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
- mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
+ mxs_power_set_vddx(&mxs_vddio_cfg, VDDIO_VAL, VDDIO_BO_VAL);
+ mxs_power_set_vddx(&mxs_vddd_cfg, VDDD_VAL, VDDD_BO_VAL);
+ mxs_power_set_vddx(&mxs_vdda_cfg, VDDA_VAL, VDDA_BO_VAL);
#ifdef CONFIG_MX23
- mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
+ mxs_power_set_vddx(&mxs_vddmem_cfg, VDDMEM_VAL, VDDMEM_BO_VAL);
+
+ setbits_le32(&power_regs->hw_power_vddmemctrl,
+ POWER_VDDMEMCTRL_ENABLE_LINREG);
+ early_delay(500);
+ clrbits_le32(&power_regs->hw_power_vddmemctrl,
+ POWER_VDDMEMCTRL_ENABLE_ILIMIT);
+ #else
+ clrbits_le32(&power_regs->hw_power_vddmemctrl,
+ POWER_VDDMEMCTRL_ENABLE_LINREG);
#endif
writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
-
- writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
-
- early_delay(1000);
+ if (!fixed_batt_supply)
+ writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+ &power_regs->hw_power_5vctrl_set);
}
#ifdef CONFIG_SPL_MXS_PSWITCH_WAIT
+/**
+ * mxs_power_wait_pswitch() - Wait for power switch to be pressed
+ *
+ * This function waits until the power-switch was pressed to start booting
+ * the board.
+ */
void mxs_power_wait_pswitch(void)
{
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
;
}
* Based on code from LTIB:
* (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
- #define timestamp (gd->arch.tbl)
- #define lastdec (gd->arch.lastinc)
+ /* Enable this to verify that the code can correctly
+ * handle the timer rollover
+ */
+ /* #define DEBUG_TIMER_WRAP */
+
+ #ifdef DEBUG_TIMER_WRAP
+ /*
+ * Let the timer wrap 15 seconds after start to catch misbehaving
+ * timer related code early
+ */
+ #define TIMER_START (-time_to_tick(15 * CONFIG_SYS_HZ))
+ #else
+ #define TIMER_START 0UL
+ #endif
/*
* This driver uses 1kHz clock source.
return time * (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ);
}
- /* Calculate how many ticks happen in "us" microseconds */
- static inline unsigned long us_to_tick(unsigned long us)
- {
- return (us * MXS_INCREMENTER_HZ) / 1000000;
- }
-
int timer_init(void)
{
struct mxs_timrot_regs *timrot_regs =
TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
&timrot_regs->hw_timrot_timctrl0);
- /* Set fixed_count to maximal value */
++#ifndef DEBUG_TIMER_WRAP
+ /* Set fixed_count to maximum value */
#if defined(CONFIG_MX23)
writel(TIMER_LOAD_VAL - 1, &timrot_regs->hw_timrot_timcount0);
#elif defined(CONFIG_MX28)
writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
#endif
--
-#ifndef DEBUG_TIMER_WRAP
- /* Set fixed_count to maximum value */
- writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
-#else
++#else /* DEBUG_TIMER_WRAP */
+ /* Set fixed_count so that the counter will wrap after 20 seconds */
++#if defined(CONFIG_MX23)
++ writel(20 * MXS_INCREMENTER_HZ - 1, &timrot_regs->hw_timrot_timcount0);
++#elif defined(CONFIG_MX28)
+ writel(20 * MXS_INCREMENTER_HZ,
+ &timrot_regs->hw_timrot_fixed_count0);
++#endif
+ gd->arch.lastinc = TIMER_LOAD_VAL - 20 * MXS_INCREMENTER_HZ;
+
+ /* Make the usec counter roll over 30 seconds after startup */
+ writel(-30000000, MXS_HW_DIGCTL_MICROSECONDS);
-#endif
++#endif /* DEBUG_TIMER_WRAP */
+ writel(TIMROT_TIMCTRLn_UPDATE,
+ &timrot_regs->hw_timrot_timctrl0_clr);
+ #ifdef DEBUG_TIMER_WRAP
- /* Set fixed_count to maximal value for subsequent loads */
++ /* Set fixed_count to maximum value for subsequent loads */
++#if defined(CONFIG_MX23)
++ writel(20 * MXS_INCREMENTER_HZ - 1, &timrot_regs->hw_timrot_timcount0);
++#elif defined(CONFIG_MX28)
+ writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+ #endif
++#endif /* DEBUG_TIMER_WRAP */
+ gd->arch.timer_rate_hz = MXS_INCREMENTER_HZ;
+ gd->arch.tbl = TIMER_START;
+ gd->arch.tbu = 0;
return 0;
}
+ /* Note: This function works correctly for TIMER_LOAD_VAL == 0xffffffff!
+ * The rollover is handled automagically due to the properties of
+ * two's complement arithmetic.
+ * For any other value of TIMER_LOAD_VAL the calculations would have
+ * to be done modulus(TIMER_LOAD_VAL + 1).
+ */
unsigned long long get_ticks(void)
{
struct mxs_timrot_regs *timrot_regs =
(struct mxs_timrot_regs *)MXS_TIMROT_BASE;
- uint32_t now;
-
- /* Current tick value */
+ unsigned long now;
#if defined(CONFIG_MX23)
/* Upper bits are the valid ones. */
now = readl(&timrot_regs->hw_timrot_timcount0) >>
TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET;
-#else
+#elif defined(CONFIG_MX28)
- now = readl(&timrot_regs->hw_timrot_running_count0);
+ /* The timer is counting down, so subtract the register value from
+ * the counter period length (implicitly 2^32) to get an incrementing
+ * timestamp
+ */
+ now = -readl(&timrot_regs->hw_timrot_running_count0);
+#else
+#error "Don't know how to read timrot_regs"
#endif
+ ulong inc = now - gd->arch.lastinc;
- if (lastdec >= now) {
- /*
- * normal mode (non roll)
- * move stamp forward with absolut diff ticks
- */
- timestamp += (lastdec - now);
- } else {
- /* we have rollover of decrementer */
- timestamp += (TIMER_LOAD_VAL - now) + lastdec;
-
- }
- lastdec = now;
-
- return timestamp;
+ if (gd->arch.tbl + inc < gd->arch.tbl)
+ gd->arch.tbu++;
+ gd->arch.tbl += inc;
+ gd->arch.lastinc = now;
+ return ((unsigned long long)gd->arch.tbu << 32) | gd->arch.tbl;
}
ulong get_timer_masked(void)
ulong get_timer(ulong base)
{
- return get_timer_masked() - base;
+ /* NOTE: time_to_tick(base) is required to correctly handle rollover! */
+ return tick_to_time(get_ticks() - time_to_tick(base));
}
/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
void __udelay(unsigned long usec)
{
- uint32_t old, new, incr;
- uint32_t counter = 0;
-
- old = readl(MXS_HW_DIGCTL_MICROSECONDS);
-
- while (counter < usec) {
- new = readl(MXS_HW_DIGCTL_MICROSECONDS);
-
- /* Check if the timer wrapped. */
- if (new < old) {
- incr = 0xffffffff - old;
- incr += new;
- } else {
- incr = new - old;
- }
-
- /*
- * Check if we are close to the maximum time and the counter
- * would wrap if incremented. If that's the case, break out
- * from the loop as the requested delay time passed.
+ uint32_t start = readl(MXS_HW_DIGCTL_MICROSECONDS);
+
+ while (readl(MXS_HW_DIGCTL_MICROSECONDS) - start <= usec)
+ /* use '<=' to guarantee a delay of _at least_
+ * the given number of microseconds.
+ * No need for fancy rollover checks
+ * Two's complement arithmetic applied correctly
+ * does everything that's needed automagically!
*/
- if (counter + incr < counter)
- break;
-
- counter += incr;
- old = new;
- }
+ ;
}
ulong get_tbclk(void)
{
- return MXS_INCREMENTER_HZ;
+ return gd->arch.timer_rate_hz;
}
*/
#include <common.h>
+#include <dm.h>
#include <errno.h>
+#include <ns16550.h>
#include <spl.h>
#include <asm/arch/cpu.h>
#include <asm/arch/hardware.h>
#include <miiphy.h>
#include <cpsw.h>
#include <asm/errno.h>
+#include <linux/compiler.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/musb.h>
#include <asm/omap_musb.h>
+#include <asm/davinci_rtc.h>
DECLARE_GLOBAL_DATA_PTR;
-static const struct gpio_bank gpio_bank_am33xx[4] = {
+#ifdef CONFIG_DM_GPIO
+static const struct omap_gpio_platdata am33xx_gpio[] = {
+ { 0, AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
+ { 1, AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
+ { 2, AM33XX_GPIO2_BASE, METHOD_GPIO_24XX },
+ { 3, AM33XX_GPIO3_BASE, METHOD_GPIO_24XX },
+#ifdef CONFIG_AM43XX
+ { 4, AM33XX_GPIO4_BASE, METHOD_GPIO_24XX },
+ { 5, AM33XX_GPIO5_BASE, METHOD_GPIO_24XX },
+#endif
+};
+
+U_BOOT_DEVICES(am33xx_gpios) = {
+ { "gpio_omap", &am33xx_gpio[0] },
+ { "gpio_omap", &am33xx_gpio[1] },
+ { "gpio_omap", &am33xx_gpio[2] },
+ { "gpio_omap", &am33xx_gpio[3] },
+#ifdef CONFIG_AM43XX
+ { "gpio_omap", &am33xx_gpio[4] },
+ { "gpio_omap", &am33xx_gpio[5] },
+#endif
+};
+
+# ifndef CONFIG_OF_CONTROL
+/*
+ * TODO(sjg@chromium.org): When we can move SPL serial to DM, we can remove
+ * the CONFIGs. At the same time, we should move this to the board files.
+ */
+static const struct ns16550_platdata am33xx_serial[] = {
+ { CONFIG_SYS_NS16550_COM1, 2, CONFIG_SYS_NS16550_CLK },
+# ifdef CONFIG_SYS_NS16550_COM2
+ { CONFIG_SYS_NS16550_COM2, 2, CONFIG_SYS_NS16550_CLK },
+# ifdef CONFIG_SYS_NS16550_COM3
+ { CONFIG_SYS_NS16550_COM3, 2, CONFIG_SYS_NS16550_CLK },
+ { CONFIG_SYS_NS16550_COM4, 2, CONFIG_SYS_NS16550_CLK },
+ { CONFIG_SYS_NS16550_COM5, 2, CONFIG_SYS_NS16550_CLK },
+ { CONFIG_SYS_NS16550_COM6, 2, CONFIG_SYS_NS16550_CLK },
+# endif
+# endif
+};
+
+U_BOOT_DEVICES(am33xx_uarts) = {
+ { "serial_omap", &am33xx_serial[0] },
+# ifdef CONFIG_SYS_NS16550_COM2
+ { "serial_omap", &am33xx_serial[1] },
+# ifdef CONFIG_SYS_NS16550_COM3
+ { "serial_omap", &am33xx_serial[2] },
+ { "serial_omap", &am33xx_serial[3] },
+ { "serial_omap", &am33xx_serial[4] },
+ { "serial_omap", &am33xx_serial[5] },
+# endif
+# endif
+};
+# endif
+
+#else
+
+static const struct gpio_bank gpio_bank_am33xx[] = {
{ (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX },
+#ifdef CONFIG_AM43XX
+ { (void *)AM33XX_GPIO4_BASE, METHOD_GPIO_24XX },
+ { (void *)AM33XX_GPIO5_BASE, METHOD_GPIO_24XX },
+#endif
};
const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx;
-#ifdef CONFIG_HW_WATCHDOG
-void hw_watchdog_reset(void)
-{
- struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
- static int trg __attribute__((section(".data")));
-
- switch (trg) {
- case 0:
- case 1:
- if (readl(&wdtimer->wdtwwps) & (1 << 4))
- return;
- writel(trg ? 0x5555 : 0xaaaa, &wdtimer->wdtwspr);
- break;
- case 2:
- if (readl(&wdtimer->wdtwwps) & (1 << 2))
- return;
- /* 10 sec timeout */
- writel(-32768 * 10, &wdtimer->wdtwldr);
-
- if (readl(&wdtimer->wdtwwps) & (1 << 0))
- return;
- /* prescaler = 1 */
- writel(0, &wdtimer->wdtwclr);
- break;
-
- case 3:
- case 4:
- /* enable watchdog */
- if (readl(&wdtimer->wdtwwps) & (1 << 4))
- return;
- writel((trg & 1) ? 0xBBBB : 0x4444, &wdtimer->wdtwspr);
- break;
-
- default:
- /* retrigger watchdog */
- if (readl(&wdtimer->wdtwwps) & (1 << 3))
- return;
-
- writel(trg, &wdtimer->wdtwtgr);
- trg ^= 0x2;
- return;
- }
- trg++;
-}
-#endif
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
- /* Enable D-cache. I-cache is already enabled in start.S */
- dcache_enable();
-}
#endif
#if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
- int cpu_mmc_init(bd_t *bis)
+ int __cpu_mmc_init(bd_t *bis)
{
int ret;
return omap_mmc_init(1, 0, 0, -1, -1);
}
+ /* let platform code be able to override this! */
+ int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__cpu_mmc_init")));
#endif
-void setup_clocks_for_console(void)
-{
- /* Not yet implemented */
- return;
-}
-
/* AM33XX has two MUSB controllers which can be host or gadget */
#if (defined(CONFIG_MUSB_GADGET) || defined(CONFIG_MUSB_HOST)) && \
(defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1))
return 0;
}
-#ifdef CONFIG_SPL_BUILD
-void rtc32k_enable(void)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+/*
+ * In the case of non-SPL based booting we'll want to call these
+ * functions a tiny bit later as it will require gd to be set and cleared
+ * and that's not true in s_init in this case so we cannot do it there.
+ */
+int board_early_init_f(void)
{
- struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
+ prcm_init();
+ set_mux_conf_regs();
+
+ return 0;
+}
+
+/*
+ * This function is the place to do per-board things such as ramp up the
+ * MPU clock frequency.
+ */
+__weak void am33xx_spl_board_init(void)
+{
+ do_setup_dpll(&dpll_core_regs, &dpll_core_opp100);
+ do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100);
+}
+
+#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
+static void rtc32k_enable(void)
+{
+ struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
/*
* Unlock the RTC's registers. For more details please see the
* RTC_SS section of the TRM. In order to unlock we need to
* write these specific values (keys) in this order.
*/
- writel(0x83e70b13, &rtc->kick0r);
- writel(0x95a4f1e0, &rtc->kick1r);
+ writel(RTC_KICK0R_WE, &rtc->kick0r);
+ writel(RTC_KICK1R_WE, &rtc->kick1r);
/* Enable the RTC 32K OSC by setting bits 3 and 6. */
writel((1 << 3) | (1 << 6), &rtc->osc);
}
+#endif
-#define UART_RESET (0x1 << 1)
-#define UART_CLK_RUNNING_MASK 0x1
-#define UART_SMART_IDLE_EN (0x1 << 0x3)
-
-void uart_soft_reset(void)
+static void uart_soft_reset(void)
{
struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
u32 regval;
regval |= UART_SMART_IDLE_EN;
writel(regval, &uart_base->uartsyscfg);
}
+
+static void watchdog_disable(void)
+{
+ struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
+
+ writel(0xAAAA, &wdtimer->wdtwspr);
+ while (readl(&wdtimer->wdtwwps) != 0x0)
+ ;
+ writel(0x5555, &wdtimer->wdtwspr);
+ while (readl(&wdtimer->wdtwwps) != 0x0)
+ ;
+}
+
+void s_init(void)
+{
+ /*
+ * The ROM will only have set up sufficient pinmux to allow for the
+ * first 4KiB NOR to be read, we must finish doing what we know of
+ * the NOR mux in this space in order to continue.
+ */
+#ifdef CONFIG_NOR_BOOT
+ enable_norboot_pin_mux();
+#endif
+ /*
+ * Save the boot parameters passed from romcode.
+ * We cannot delay the saving further than this,
+ * to prevent overwrites.
+ */
+#ifdef CONFIG_SPL_BUILD
+ save_omap_boot_params();
+#endif
+ watchdog_disable();
+ set_uart_mux_conf();
+ setup_clocks_for_console();
+ uart_soft_reset();
+#if defined(CONFIG_NOR_BOOT) || defined(CONFIG_QSPI_BOOT)
+ gd->baudrate = CONFIG_BAUDRATE;
+ serial_init();
+ gd->have_console = 1;
+#elif defined(CONFIG_SPL_BUILD)
+ gd = &gdata;
+ preloader_console_init();
+#endif
+#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
+ /* Enable RTC32K clock */
+ rtc32k_enable();
+#endif
+#ifdef CONFIG_SPL_BUILD
+ board_early_init_f();
+ sdram_init();
+#endif
+}
#endif
#include <asm/arch/hardware.h>
#include <asm/io.h>
-
+ #define PRCM_MOD_EN 0x2
+ #define PRCM_FORCE_WAKEUP 0x2
+ #define PRCM_FUNCTL 0x0
+
+ #define PRCM_EMIF_CLK_ACTIVITY BIT(2)
+ #define PRCM_L3_GCLK_ACTIVITY BIT(4)
+
+ #define PLL_BYPASS_MODE 0x4
+ #define ST_MN_BYPASS 0x00000100
+ #define ST_DPLL_CLK 0x00000001
+ #define CLK_SEL_MASK 0x7ffff
+ #define CLK_DIV_MASK 0x1f
+ #define CLK_DIV2_MASK 0x7f
+ #define CLK_SEL_SHIFT 0x8
+ #define CLK_MODE_MASK 0x7
+ #define CLK_MODE_SEL 0x7
+ #define DPLL_CLKDCOLDO_GATE_CTRL 0x300
+
#define OSC (V_OSCK/1000000)
-#define MPUPLL_N (OSC-1)
+ #define MPUPLL_M CONFIG_SYS_MPUCLK
-#define COREPLL_N (OSC-1)
++#define MPUPLL_N (OSC - 1)
+ #define MPUPLL_M2 1
+
+ /* Core PLL Fdll = 1 GHZ, */
+ #define COREPLL_M 1000
-#define PERPLL_N (OSC-1)
++#define COREPLL_N (OSC - 1)
+
+ #define COREPLL_M4 10 /* CORE_CLKOUTM4 = 200 MHZ */
+ #define COREPLL_M5 8 /* CORE_CLKOUTM5 = 250 MHZ */
+ #define COREPLL_M6 4 /* CORE_CLKOUTM6 = 500 MHZ */
+
+ /*
+ * USB PHY clock is 960 MHZ. Since, this comes directly from Fdll, Fdll
+ * frequency needs to be set to 960 MHZ. Hence,
+ * For clkout = 192 MHZ, Fdll = 960 MHZ, divider values are given below
+ */
+ #define PERPLL_M 960
-#define DDRPLL_N (OSC-1)
++#define PERPLL_N (OSC - 1)
+ #define PERPLL_M2 5
+
+ /* DDR Freq is 266 MHZ for now */
+ /* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */
+ #define DDRPLL_M 266
-const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
-const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
-const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL;
-const struct cm_rtc *cmrtc = (struct cm_rtc *)CM_RTC;
-
-#ifdef CONFIG_SPL_BUILD
-#define enable_clk(reg, val) __enable_clk(#reg, ®, val)
++#define DDRPLL_N (OSC - 1)
+ #define DDRPLL_M2 1
+
+struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
+struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
+struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
+struct cm_rtc *const cmrtc = (struct cm_rtc *)CM_RTC;
+
+const struct dpll_regs dpll_mpu_regs = {
+ .cm_clkmode_dpll = CM_WKUP + 0x88,
+ .cm_idlest_dpll = CM_WKUP + 0x20,
+ .cm_clksel_dpll = CM_WKUP + 0x2C,
+ .cm_div_m2_dpll = CM_WKUP + 0xA8,
+};
+
+const struct dpll_regs dpll_core_regs = {
+ .cm_clkmode_dpll = CM_WKUP + 0x90,
+ .cm_idlest_dpll = CM_WKUP + 0x5C,
+ .cm_clksel_dpll = CM_WKUP + 0x68,
+ .cm_div_m4_dpll = CM_WKUP + 0x80,
+ .cm_div_m5_dpll = CM_WKUP + 0x84,
+ .cm_div_m6_dpll = CM_WKUP + 0xD8,
+};
+
+const struct dpll_regs dpll_per_regs = {
+ .cm_clkmode_dpll = CM_WKUP + 0x8C,
+ .cm_idlest_dpll = CM_WKUP + 0x70,
+ .cm_clksel_dpll = CM_WKUP + 0x9C,
+ .cm_div_m2_dpll = CM_WKUP + 0xAC,
+};
+
+const struct dpll_regs dpll_ddr_regs = {
+ .cm_clkmode_dpll = CM_WKUP + 0x94,
+ .cm_idlest_dpll = CM_WKUP + 0x34,
+ .cm_clksel_dpll = CM_WKUP + 0x40,
+ .cm_div_m2_dpll = CM_WKUP + 0xA0,
+};
+
+struct dpll_params dpll_mpu_opp100 = {
+ CONFIG_SYS_MPUCLK, OSC-1, 1, -1, -1, -1, -1};
+const struct dpll_params dpll_core_opp100 = {
+ 1000, OSC-1, -1, -1, 10, 8, 4};
+const struct dpll_params dpll_mpu = {
+ MPUPLL_M_300, OSC-1, 1, -1, -1, -1, -1};
+const struct dpll_params dpll_core = {
+ 50, OSC-1, -1, -1, 1, 1, 1};
+const struct dpll_params dpll_per = {
+ 960, OSC-1, 5, -1, -1, -1, -1};
+
+const struct dpll_params *get_dpll_mpu_params(void)
+{
+ return &dpll_mpu;
+}
-static void __enable_clk(const char *name, const void *reg, u32 mask)
+const struct dpll_params *get_dpll_core_params(void)
{
- unsigned long timeout = 10000000;
-
- writel(mask, reg);
- while (readl(reg) != mask)
- /* poor man's timeout, since timers not initialized */
- if (timeout-- == 0)
- /* no error message, since console not yet available */
- break;
+ return &dpll_core;
}
-static void enable_interface_clocks(void)
+const struct dpll_params *get_dpll_per_params(void)
{
- /* Enable all the Interconnect Modules */
- enable_clk(cmper->l3clkctrl, PRCM_MOD_EN);
- enable_clk(cmper->l4lsclkctrl, PRCM_MOD_EN);
- enable_clk(cmper->l4fwclkctrl, PRCM_MOD_EN);
- enable_clk(cmwkup->wkl4wkclkctrl, PRCM_MOD_EN);
- enable_clk(cmper->l3instrclkctrl, PRCM_MOD_EN);
- enable_clk(cmper->l4hsclkctrl, PRCM_MOD_EN);
-#ifdef CONFIG_HW_WATCHDOG
- enable_clk(cmwkup->wdtimer1ctrl, PRCM_MOD_EN);
-#endif
- /* GPIO0 */
- enable_clk(cmwkup->wkgpio0clkctrl, PRCM_MOD_EN);
+ return &dpll_per;
}
-/*
- * Force power domain wake up transition
- * Ensure that the corresponding interface clock is active before
- * using the peripheral
- */
-static void power_domain_wkup_transition(void)
+void setup_clocks_for_console(void)
{
- writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl);
- writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl);
- writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl);
- writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl);
- writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl);
+ clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
+ CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
+ CD_CLKCTRL_CLKTRCTRL_SHIFT);
+
+ clrsetbits_le32(&cmper->l4hsclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
+ CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
+ CD_CLKCTRL_CLKTRCTRL_SHIFT);
+
+ clrsetbits_le32(&cmwkup->wkup_uart0ctrl,
+ MODULE_CLKCTRL_MODULEMODE_MASK,
+ MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
+ MODULE_CLKCTRL_MODULEMODE_SHIFT);
+ clrsetbits_le32(&cmper->uart1clkctrl,
+ MODULE_CLKCTRL_MODULEMODE_MASK,
+ MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
+ MODULE_CLKCTRL_MODULEMODE_SHIFT);
+ clrsetbits_le32(&cmper->uart2clkctrl,
+ MODULE_CLKCTRL_MODULEMODE_MASK,
+ MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
+ MODULE_CLKCTRL_MODULEMODE_SHIFT);
+ clrsetbits_le32(&cmper->uart3clkctrl,
+ MODULE_CLKCTRL_MODULEMODE_MASK,
+ MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
+ MODULE_CLKCTRL_MODULEMODE_SHIFT);
+ clrsetbits_le32(&cmper->uart4clkctrl,
+ MODULE_CLKCTRL_MODULEMODE_MASK,
+ MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
+ MODULE_CLKCTRL_MODULEMODE_SHIFT);
+ clrsetbits_le32(&cmper->uart5clkctrl,
+ MODULE_CLKCTRL_MODULEMODE_MASK,
+ MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
+ MODULE_CLKCTRL_MODULEMODE_SHIFT);
}
-/*
- * Enable the peripheral clock for required peripherals
- */
-static void enable_per_clocks(void)
+void enable_basic_clocks(void)
{
- /* Enable the control module though RBL would have done it*/
- enable_clk(cmwkup->wkctrlclkctrl, PRCM_MOD_EN);
- /* Enable the timer2 clock */
- enable_clk(cmper->timer2clkctrl, PRCM_MOD_EN);
+ u32 *const clk_domains[] = {
+ &cmper->l3clkstctrl,
+ &cmper->l4fwclkstctrl,
+ &cmper->l3sclkstctrl,
+ &cmper->l4lsclkstctrl,
+ &cmwkup->wkclkstctrl,
+ &cmper->emiffwclkctrl,
+ &cmrtc->clkstctrl,
+ 0
+ };
+
+ u32 *const clk_modules_explicit_en[] = {
+ &cmper->l3clkctrl,
+ &cmper->l4lsclkctrl,
+ &cmper->l4fwclkctrl,
+ &cmwkup->wkl4wkclkctrl,
+ &cmper->l3instrclkctrl,
+ &cmper->l4hsclkctrl,
+ &cmwkup->wkgpio0clkctrl,
+ &cmwkup->wkctrlclkctrl,
+ &cmper->timer2clkctrl,
+ &cmper->gpmcclkctrl,
+ &cmper->elmclkctrl,
+ &cmper->mmc0clkctrl,
+ &cmper->mmc1clkctrl,
+ &cmwkup->wkup_i2c0ctrl,
+ &cmper->gpio1clkctrl,
+ &cmper->gpio2clkctrl,
+ &cmper->gpio3clkctrl,
+ &cmper->i2c1clkctrl,
+ &cmper->cpgmac0clkctrl,
+ &cmper->spi0clkctrl,
+ &cmrtc->rtcclkctrl,
+ &cmper->usb0clkctrl,
+ &cmper->emiffwclkctrl,
+ &cmper->emifclkctrl,
+ 0
+ };
+
+ do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
+
/* Select the Master osc 24 MHZ as Timer2 clock source */
writel(0x1, &cmdpll->clktimer2clk);
-
-#ifdef CONFIG_SYS_NS16550_COM1
- /* UART0 */
- enable_clk(cmwkup->wkup_uart0ctrl, PRCM_MOD_EN);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM2
- enable_clk(cmper->uart1clkctrl, PRCM_MOD_EN);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM3
- enable_clk(cmper->uart2clkctrl, PRCM_MOD_EN);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM4
- enable_clk(cmper->uart3clkctrl, PRCM_MOD_EN);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM5
- enable_clk(cmper->uart4clkctrl, PRCM_MOD_EN);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM6
- enable_clk(cmper->uart5clkctrl, PRCM_MOD_EN);
-#endif
- /* GPMC */
- enable_clk(cmper->gpmcclkctrl, PRCM_MOD_EN);
-
- /* ELM */
- enable_clk(cmper->elmclkctrl, PRCM_MOD_EN);
-
- /* Ethernet */
- enable_clk(cmper->cpswclkstctrl, PRCM_MOD_EN);
- enable_clk(cmper->cpgmac0clkctrl, PRCM_MOD_EN);
-
- /* MMC */
-#ifdef CONFIG_OMAP_MMC_DEV_0
- enable_clk(cmper->mmc0clkctrl, PRCM_MOD_EN);
-#endif
-#ifdef CONFIG_OMAP_MMC_DEV_1
- enable_clk(cmper->mmc1clkctrl, PRCM_MOD_EN);
-#endif
- /* LCD */
- enable_clk(cmper->lcdclkctrl, PRCM_MOD_EN);
-
- /* MMC1 */
- writel(PRCM_MOD_EN, &cmper->mmc1clkctrl);
- while (readl(&cmper->mmc1clkctrl) != PRCM_MOD_EN)
- ;
-
- /* i2c0 */
- enable_clk(cmwkup->wkup_i2c0ctrl, PRCM_MOD_EN);
-
- /* GPIO1-3 */
- enable_clk(cmper->gpio1clkctrl, PRCM_MOD_EN);
- enable_clk(cmper->gpio2clkctrl, PRCM_MOD_EN);
- enable_clk(cmper->gpio3clkctrl, PRCM_MOD_EN);
-
- /* i2c1 */
- enable_clk(cmper->i2c1clkctrl, PRCM_MOD_EN);
-
- /* spi0 */
- enable_clk(cmper->spi0clkctrl, PRCM_MOD_EN);
-
- /* rtc */
- enable_clk(cmrtc->rtcclkctrl, PRCM_MOD_EN);
-
- /* usb0 */
- enable_clk(cmper->usb0clkctrl, PRCM_MOD_EN);
}
-#endif /* CONFIG_SPL_BUILD */
-
+ void mpu_pll_config_val(int mpull_m)
+ {
+ u32 clkmode, clksel, div_m2;
+
+ clkmode = readl(&cmwkup->clkmoddpllmpu);
+ clksel = readl(&cmwkup->clkseldpllmpu);
+ div_m2 = readl(&cmwkup->divm2dpllmpu);
+
+ /* Set the PLL to bypass Mode */
+ writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu);
+ while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS)
+ ;
+
+ clksel &= ~CLK_SEL_MASK;
+ clksel |= (mpull_m << CLK_SEL_SHIFT) | MPUPLL_N;
+ writel(clksel, &cmwkup->clkseldpllmpu);
+
+ div_m2 &= ~CLK_DIV_MASK;
+ div_m2 |= MPUPLL_M2;
+ writel(div_m2, &cmwkup->divm2dpllmpu);
+
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
+ writel(clkmode, &cmwkup->clkmoddpllmpu);
+
+ while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK)
+ ;
+ }
+
+ void mpu_pll_config(void)
+ {
+ mpu_pll_config_val(CONFIG_SYS_MPUCLK);
+ }
+
+ static void core_pll_config_val(int m)
+ {
+ u32 clkmode, clksel, div_m4, div_m5, div_m6;
+
+ clkmode = readl(&cmwkup->clkmoddpllcore);
+ clksel = readl(&cmwkup->clkseldpllcore);
+ div_m4 = readl(&cmwkup->divm4dpllcore);
+ div_m5 = readl(&cmwkup->divm5dpllcore);
+ div_m6 = readl(&cmwkup->divm6dpllcore);
+
+ /* Set the PLL to bypass Mode */
+ writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore);
+
+ while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS)
+ ;
+
+ clksel &= ~CLK_SEL_MASK;
+ clksel |= ((m << CLK_SEL_SHIFT) | COREPLL_N);
+ writel(clksel, &cmwkup->clkseldpllcore);
+
+ div_m4 &= ~CLK_DIV_MASK;
+ div_m4 |= COREPLL_M4;
+ writel(div_m4, &cmwkup->divm4dpllcore);
+
+ div_m5 &= ~CLK_DIV_MASK;
+ div_m5 |= COREPLL_M5;
+ writel(div_m5, &cmwkup->divm5dpllcore);
+
+ div_m6 &= ~CLK_DIV_MASK;
+ div_m6 |= COREPLL_M6;
+ writel(div_m6, &cmwkup->divm6dpllcore);
+
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
+ writel(clkmode, &cmwkup->clkmoddpllcore);
+
+ while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK)
+ ;
+ }
+
+ static inline void core_pll_config(void)
+ {
+ core_pll_config_val(COREPLL_M);
+ }
+
+ static void per_pll_config_val(int m)
+ {
+ u32 clkmode, clksel, div_m2;
+
+ clkmode = readl(&cmwkup->clkmoddpllper);
+ clksel = readl(&cmwkup->clkseldpllper);
+ div_m2 = readl(&cmwkup->divm2dpllper);
+
+ /* Set the PLL to bypass Mode */
+ writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper);
+
+ while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS)
+ ;
+
+ clksel &= ~CLK_SEL_MASK;
+ clksel |= (m << CLK_SEL_SHIFT) | PERPLL_N;
+ writel(clksel, &cmwkup->clkseldpllper);
+
+ div_m2 &= ~CLK_DIV2_MASK;
+ div_m2 |= PERPLL_M2;
+ writel(div_m2, &cmwkup->divm2dpllper);
+
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
+ writel(clkmode, &cmwkup->clkmoddpllper);
+
+ while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
+ ;
+
+ writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper);
+ }
+
+ static inline void per_pll_config(void)
+ {
+ per_pll_config_val(PERPLL_M);
+ }
+
+ static void disp_pll_config_val(int m)
+ {
+ u32 clkmode, clksel, div_m2;
+
+ clkmode = readl(&cmwkup->clkmoddplldisp);
+ clksel = readl(&cmwkup->clkseldplldisp);
+ div_m2 = readl(&cmwkup->divm2dplldisp);
+
+ /* Set the PLL to bypass Mode */
+ writel(PLL_BYPASS_MODE, &cmwkup->clkmoddplldisp);
+
+ while (!(readl(&cmwkup->idlestdplldisp) & ST_MN_BYPASS))
+ ;
+
+ clksel &= ~CLK_SEL_MASK;
+ clksel |= (m << CLK_SEL_SHIFT) | DISPPLL_N;
+ writel(clksel, &cmwkup->clkseldplldisp);
+
+ div_m2 &= ~CLK_DIV2_MASK;
+ div_m2 |= DISPPLL_M2;
+ writel(div_m2, &cmwkup->divm2dplldisp);
+
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
+ writel(clkmode, &cmwkup->clkmoddplldisp);
+
+ while (!(readl(&cmwkup->idlestdplldisp) & ST_DPLL_CLK))
+ ;
+ }
+
+ static inline void disp_pll_config(void)
+ {
+ disp_pll_config_val(DISPPLL_M);
+ }
+
+ void ddr_pll_config(unsigned int ddrpll_m)
+ {
+ u32 clkmode, clksel, div_m2;
+
+ clkmode = readl(&cmwkup->clkmoddpllddr);
+ clksel = readl(&cmwkup->clkseldpllddr);
+ div_m2 = readl(&cmwkup->divm2dpllddr);
+
+ /* Set the PLL to bypass Mode */
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= PLL_BYPASS_MODE;
+ writel(clkmode, &cmwkup->clkmoddpllddr);
+
+ /* Wait till bypass mode is enabled */
+ while (!(readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS))
+ ;
+
+ clksel &= ~CLK_SEL_MASK;
+ clksel |= (ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N;
+ writel(clksel, &cmwkup->clkseldpllddr);
+
+ div_m2 &= ~CLK_DIV_MASK;
+ div_m2 |= DDRPLL_M2;
+ writel(div_m2, &cmwkup->divm2dpllddr);
+
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
+ writel(clkmode, &cmwkup->clkmoddpllddr);
+
+ /* Wait till dpll is locked */
+ while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK)
+ ;
+ }
+
-#ifdef CONFIG_SPL_BUILD
-void enable_emif_clocks(void)
-{
- /* Enable the EMIF_FW Functional clock */
- writel(PRCM_MOD_EN, &cmper->emiffwclkctrl);
- /* Enable EMIF0 Clock */
- writel(PRCM_MOD_EN, &cmper->emifclkctrl);
- /* Poll if module is functional */
- while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN)
- ;
-}
-
-/*
- * Configure the PLL/PRCM for necessary peripherals
- */
-void pll_init()
-{
- mpu_pll_config();
- core_pll_config();
- per_pll_config();
- disp_pll_config();
-
- /* Enable the required interconnect clocks */
- enable_interface_clocks();
-
- /* Power domain wake up transition */
- power_domain_wkup_transition();
-
- /* Enable the required peripherals */
- enable_per_clocks();
-}
-#endif
-
+ #define M(mn) (((mn) & CLK_SEL_MASK) >> CLK_SEL_SHIFT)
+ #define N(mn) ((mn) & CLK_DIV2_MASK)
+
+ unsigned long __clk_get_rate(u32 m_n, u32 div_m2)
+ {
+ unsigned long rate;
+
+ div_m2 &= CLK_DIV_MASK;
+ debug("M=%u N=%u M2=%u\n", M(m_n), N(m_n), div_m2);
+ rate = V_OSCK / 1000 * M(m_n) / (N(m_n) + 1) / div_m2;
+ debug("CLK = %lu.%03luMHz\n", rate / 1000, rate % 1000);
+ return rate * 1000;
+ }
+
+ unsigned long lcdc_clk_rate(void)
+ {
+ return clk_get_rate(cmwkup, disp);
+ }
+
+ unsigned long mpu_clk_rate(void)
+ {
+ return clk_get_rate(cmwkup, mpu);
+ }
+
+ enum {
+ CLK_MPU_PLL,
+ CLK_CORE_PLL,
+ CLK_PER_PLL,
+ CLK_DISP_PLL,
+ CLK_GPMC,
+ };
+
+ static struct clk_lookup {
+ const char *name;
+ unsigned int index;
+ } am33xx_clk_lookup[] = {
+ { "mpu", CLK_MPU_PLL, },
+ { "core", CLK_CORE_PLL, },
+ { "per", CLK_PER_PLL, },
+ { "lcdc", CLK_DISP_PLL, },
+ { "gpmc", CLK_GPMC, },
+ };
+
+ #define print_pll(dom, pll) { \
+ u32 __pll = clk_get_rate(dom, pll); \
+ printf("%-12s %4d.%03d MHz\n", #pll, \
+ __pll / 1000000, __pll / 1000 % 1000); \
+ }
+
+ #define print_pll2(dom, n, pll) { \
+ u32 __m_n = readl(&(dom)->clkseldpll##pll); \
+ u32 __div = readl(&(dom)->divm##n##dpll##pll); \
+ u32 __pll = __clk_get_rate(__m_n, __div); \
+ printf("%-12s %4d.%03d MHz\n", #pll "_m" #n, \
+ __pll / 1000000, __pll / 1000 % 1000); \
+ }
+
+ static void do_showclocks(void)
+ {
+ print_pll(cmwkup, mpu);
+ print_pll2(cmwkup, 4, core);
+ print_pll2(cmwkup, 5, core);
+ print_pll2(cmwkup, 6, core);
+ print_pll(cmwkup, ddr);
+ print_pll(cmwkup, per);
+ print_pll(cmwkup, disp);
+ }
+
+ int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc,
+ char *const argv[])
+ {
+ int i;
+ unsigned long freq;
+ unsigned long __attribute__((unused)) ref = ~0UL;
+
+ if (argc < 2) {
+ do_showclocks();
+ return CMD_RET_SUCCESS;
+ } else if (argc == 2 || argc > 4) {
+ return CMD_RET_USAGE;
+ }
+
+ freq = simple_strtoul(argv[2], NULL, 0);
+ if (freq < 1000) {
+ printf("Invalid clock frequency %lu\n", freq);
+ return CMD_RET_FAILURE;
+ }
+ if (argc > 3) {
+ ref = simple_strtoul(argv[3], NULL, 0);
+ }
+ for (i = 0; i < ARRAY_SIZE(am33xx_clk_lookup); i++) {
+ if (strcasecmp(argv[1], am33xx_clk_lookup[i].name) == 0) {
+ switch (am33xx_clk_lookup[i].index) {
+ case CLK_MPU_PLL:
+ mpu_pll_config_val(freq / 1000000);
+ break;
+ case CLK_CORE_PLL:
+ core_pll_config_val(freq / 1000000);
+ break;
+ case CLK_PER_PLL:
+ per_pll_config_val(freq / 1000000);
+ break;
+ case CLK_DISP_PLL:
+ disp_pll_config_val(freq / 1000000);
+ break;
+ default:
+ printf("Cannot change %s clock\n",
+ am33xx_clk_lookup[i].name);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("%s clock set to %lu.%03lu MHz\n",
+ am33xx_clk_lookup[i].name,
+ freq / 1000000, freq / 1000 % 1000);
+ return CMD_RET_SUCCESS;
+ }
+ }
+ if (i == ARRAY_SIZE(am33xx_clk_lookup)) {
+ printf("clock %s not found; supported clocks are:\n", argv[1]);
+ for (i = 0; i < ARRAY_SIZE(am33xx_clk_lookup); i++) {
+ printf("\t%s\n", am33xx_clk_lookup[i].name);
+ }
+ } else {
+ printf("Failed to set clock %s to %s MHz\n",
+ argv[1], argv[2]);
+ }
+ return CMD_RET_FAILURE;
+ }
+
+ U_BOOT_CMD(
+ clocks, 4, 0, do_clocks,
+ "display/set clocks",
+ " - display clock settings\n"
+ "clocks <clkname> <freq> - set clock <clkname> to <freq> Hz"
+ );
*/
static struct emif_reg_struct *emif_reg[2] = {
(struct emif_reg_struct *)EMIF4_0_CFG_BASE,
- (struct emif_reg_struct *)EMIF4_1_CFG_BASE};
+ (struct emif_reg_struct *)EMIF4_1_CFG_BASE,
+ };
/**
* Base addresses for DDR PHY cmd/data regs
*/
static struct ddr_cmd_regs *ddr_cmd_reg[2] = {
(struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR,
- (struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR2};
+ (struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR2,
+ };
static struct ddr_data_regs *ddr_data_reg[2] = {
(struct ddr_data_regs *)DDR_PHY_DATA_ADDR,
- (struct ddr_data_regs *)DDR_PHY_DATA_ADDR2};
+ (struct ddr_data_regs *)DDR_PHY_DATA_ADDR2,
+ };
/**
* Base address for ddr io control instances
*/
- static struct ddr_cmdtctrl *ioctrl_reg = {
- (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR};
+ static struct ddr_cmdtctrl *ioctrl_reg =
+ (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR;
- * Configure EMIF4D5 registers and MR registers
+static inline u32 get_mr(int nr, u32 cs, u32 mr_addr)
+{
+ u32 mr;
+
+ mr_addr |= cs << EMIF_REG_CS_SHIFT;
+ writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg);
+
+ mr = readl(&emif_reg[nr]->emif_lpddr2_mode_reg_data);
+ debug("get_mr: EMIF1 cs %d mr %08x val 0x%x\n", cs, mr_addr, mr);
+ if (((mr & 0x0000ff00) >> 8) == (mr & 0xff) &&
+ ((mr & 0x00ff0000) >> 16) == (mr & 0xff) &&
+ ((mr & 0xff000000) >> 24) == (mr & 0xff))
+ return mr & 0xff;
+ else
+ return mr;
+}
+
+static inline void set_mr(int nr, u32 cs, u32 mr_addr, u32 mr_val)
+{
+ mr_addr |= cs << EMIF_REG_CS_SHIFT;
+ writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg);
+ writel(mr_val, &emif_reg[nr]->emif_lpddr2_mode_reg_data);
+}
+
+static void configure_mr(int nr, u32 cs)
+{
+ u32 mr_addr;
+
+ while (get_mr(nr, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK)
+ ;
+ set_mr(nr, cs, LPDDR2_MR10, 0x56);
+
+ set_mr(nr, cs, LPDDR2_MR1, 0x43);
+ set_mr(nr, cs, LPDDR2_MR2, 0x2);
+
+ mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK;
+ set_mr(nr, cs, mr_addr, 0x2);
+}
+
+/*
- writel(0x1, &emif_reg[nr]->emif_iodft_tlgc);
++ * Configure EMIF4D5 registers and MR registers For details about these magic
++ * values please see the EMIF registers section of the TRM.
+ */
+void config_sdram_emif4d5(const struct emif_regs *regs, int nr)
+{
+ writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl);
+ writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl_shdw);
- writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
- writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
+ writel(regs->zq_config, &emif_reg[nr]->emif_zq_config);
+
+ writel(regs->temp_alert_config, &emif_reg[nr]->emif_temp_alert_config);
+ writel(regs->emif_rd_wr_lvl_rmp_win,
+ &emif_reg[nr]->emif_rd_wr_lvl_rmp_win);
+ writel(regs->emif_rd_wr_lvl_rmp_ctl,
+ &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
+ writel(regs->emif_rd_wr_lvl_ctl, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
+ writel(regs->emif_rd_wr_exec_thresh,
+ &emif_reg[nr]->emif_rd_wr_exec_thresh);
+
+ /*
+ * for most SOCs these registers won't need to be changed so only
+ * write to these registers if someone explicitly has set the
+ * register's value.
+ */
+ if(regs->emif_cos_config) {
+ writel(regs->emif_prio_class_serv_map, &emif_reg[nr]->emif_prio_class_serv_map);
+ writel(regs->emif_connect_id_serv_1_map, &emif_reg[nr]->emif_connect_id_serv_1_map);
+ writel(regs->emif_connect_id_serv_2_map, &emif_reg[nr]->emif_connect_id_serv_2_map);
+ writel(regs->emif_cos_config, &emif_reg[nr]->emif_cos_config);
+ }
+
++ /*
++ * Sequence to ensure that the PHY is in a known state prior to
++ * startting hardware leveling. Also acts as to latch some state from
++ * the EMIF into the PHY.
++ */
++ writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
++ writel(0x2411, &emif_reg[nr]->emif_iodft_tlgc);
++ writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
++
++ clrbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl,
++ EMIF_REG_INITREF_DIS_MASK);
++
+ writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
+ writel(regs->sdram_config, &cstat->secure_emif_sdram_config);
++ writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
++ writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
++
++ /* Perform hardware leveling. */
++ udelay(1000);
++ writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36) |
++ 0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
++ writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw) |
++ 0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw);
++
++ writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
++
++ /* Enable read leveling */
++ writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
++
++ /*
++ * Enable full read and write leveling. Wait for read and write
++ * leveling bit to clear RDWRLVLFULL_START bit 31
++ */
++ while((readl(&emif_reg[nr]->emif_rd_wr_lvl_ctl) & 0x80000000) != 0)
++ ;
++
++ /* Check the timeout register to see if leveling is complete */
++ if((readl(&emif_reg[nr]->emif_status) & 0x70) != 0)
++ puts("DDR3 H/W leveling incomplete with errors\n");
+
+ if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) {
+ configure_mr(nr, 0);
+ configure_mr(nr, 1);
+ }
+}
+
/**
* Configure SDRAM
*/
void config_sdram(const struct emif_regs *regs, int nr)
{
if (regs->zq_config) {
-- /*
-- * A value of 0x2800 for the REF CTRL will give us
-- * about 570us for a delay, which will be long enough
-- * to configure things.
-- */
-- writel(0x2800, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->zq_config, &emif_reg[nr]->emif_zq_config);
- writel(regs->sdram_config, &cstat->emif_sdram_config);
+ writel(regs->sdram_config, &cstat->secure_emif_sdram_config);
writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
}
++ writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
-- writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
}
/**
writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw);
}
- void __weak emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
- {
- }
-
+/*
- * Configure EXT PHY registers
++ * Configure EXT PHY registers for hardware leveling
+ */
+static void ext_phy_settings(const struct emif_regs *regs, int nr)
+{
- u32 *ext_phy_ctrl_base = 0;
- u32 *emif_ext_phy_ctrl_base = 0;
- const u32 *ext_phy_ctrl_const_regs;
- u32 i = 0;
- u32 size;
-
- ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1);
- emif_ext_phy_ctrl_base =
- (u32 *)&(emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
-
- /* Configure external phy control timing registers */
- for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) {
- writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++);
- /* Update shadow registers */
- writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++);
- }
-
+ /*
- * external phy 6-24 registers do not change with
- * ddr frequency
++ * Enable hardware leveling on the EMIF. For details about these
++ * magic values please see the EMIF registers section of the TRM.
+ */
- emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size);
-
- if (!size)
- return;
++ writel(0x08020080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
++ writel(0x08020080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1_shdw);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_22);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_22_shdw);
++ writel(0x00600020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_23);
++ writel(0x00600020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_23_shdw);
++ writel(0x40010080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_24);
++ writel(0x40010080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_24_shdw);
++ writel(0x08102040, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_25);
++ writel(0x08102040, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_25_shdw);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_26);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_26_shdw);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_27);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_27_shdw);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_28);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_28_shdw);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_29);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_29_shdw);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_30);
++ writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_30_shdw);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_31);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_31_shdw);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_32);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_32_shdw);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_33);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_33_shdw);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_34);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_34_shdw);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_35);
++ writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_35_shdw);
++ writel(0x000000FF, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
++ writel(0x000000FF, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw);
+
- for (i = 0; i < size; i++) {
- writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
- /* Update shadow registers */
- writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
- }
++ /*
++ * Sequence to ensure that the PHY is again in a known state after
++ * hardware leveling.
++ */
++ writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
++ writel(0x2411, &emif_reg[nr]->emif_iodft_tlgc);
++ writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
+}
+
/**
* Configure DDR PHY
*/
void config_ddr_phy(const struct emif_regs *regs, int nr)
{
- * disable initialization and refreshes for now until we
+ /*
++ * Disable initialization and refreshes for now until we
+ * finish programming EMIF regs.
++ * Also set time between rising edge of DDR_RESET to rising
++ * edge of DDR_CKE to > 500us per memory spec.
+ */
++#ifndef CONFIG_AM43XX
+ setbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl,
+ EMIF_REG_INITREF_DIS_MASK);
++#endif
++ if (regs->zq_config)
++ writel(0x80003100, &emif_reg[nr]->emif_sdram_ref_ctrl);
+
writel(regs->emif_ddr_phy_ctlr_1,
&emif_reg[nr]->emif_ddr_phy_ctrl_1);
writel(regs->emif_ddr_phy_ctlr_1,
&emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw);
+
+ if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5)
+ ext_phy_settings(regs, nr);
}
/**
*/
void config_cmd_ctrl(const struct cmd_control *cmd, int nr)
{
+ if (!cmd)
+ return;
+
writel(cmd->cmd0csratio, &ddr_cmd_reg[nr]->cm0csratio);
- writel(cmd->cmd0dldiff, &ddr_cmd_reg[nr]->cm0dldiff);
writel(cmd->cmd0iclkout, &ddr_cmd_reg[nr]->cm0iclkout);
writel(cmd->cmd1csratio, &ddr_cmd_reg[nr]->cm1csratio);
- writel(cmd->cmd1dldiff, &ddr_cmd_reg[nr]->cm1dldiff);
writel(cmd->cmd1iclkout, &ddr_cmd_reg[nr]->cm1iclkout);
writel(cmd->cmd2csratio, &ddr_cmd_reg[nr]->cm2csratio);
- writel(cmd->cmd2dldiff, &ddr_cmd_reg[nr]->cm2dldiff);
writel(cmd->cmd2iclkout, &ddr_cmd_reg[nr]->cm2iclkout);
}
{
int i;
+ if (!data)
+ return;
+
for (i = 0; i < DDR_DATA_REGS_NR; i++) {
writel(data->datardsratio0,
&(ddr_data_reg[nr]+i)->dt0rdsratio0);
&(ddr_data_reg[nr]+i)->dt0fwsratio0);
writel(data->datawrsratio0,
&(ddr_data_reg[nr]+i)->dt0wrsratio0);
- writel(data->datauserank0delay,
- &(ddr_data_reg[nr]+i)->dt0rdelays0);
- writel(data->datadldiff0,
- &(ddr_data_reg[nr]+i)->dt0dldiff0);
}
}
-void config_io_ctrl(unsigned long val)
+void config_io_ctrl(const struct ctrl_ioregs *ioregs)
{
- writel(val, &ioctrl_reg->cm0ioctl);
- writel(val, &ioctrl_reg->cm1ioctl);
- writel(val, &ioctrl_reg->cm2ioctl);
- writel(val, &ioctrl_reg->dt0ioctl);
- writel(val, &ioctrl_reg->dt1ioctl);
+ if (!ioregs)
+ return;
+
+ writel(ioregs->cm0ioctl, &ioctrl_reg->cm0ioctl);
+ writel(ioregs->cm1ioctl, &ioctrl_reg->cm1ioctl);
+ writel(ioregs->cm2ioctl, &ioctrl_reg->cm2ioctl);
+ writel(ioregs->dt0ioctl, &ioctrl_reg->dt0ioctl);
+ writel(ioregs->dt1ioctl, &ioctrl_reg->dt1ioctl);
+#ifdef CONFIG_AM43XX
+ writel(ioregs->dt2ioctrl, &ioctrl_reg->dt2ioctrl);
+ writel(ioregs->dt3ioctrl, &ioctrl_reg->dt3ioctrl);
+ writel(ioregs->emif_sdram_config_ext,
+ &ioctrl_reg->emif_sdram_config_ext);
+#endif
}
#include <asm/arch/sys_proto.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
+#include <power/tps65910.h>
+#include <linux/compiler.h>
struct ctrl_stat *cstat = (struct ctrl_stat *)CTRL_BASE;
/**
* get_board_rev() - setup to pass kernel board revision information
- * returns:(bit[0-3] sub version, higher bit[7-4] is higher version)
+ * returns: 0 for the ATAG REVISION tag value.
*/
-u32 get_board_rev(void)
+u32 __weak get_board_rev(void)
{
- return BOARD_REV_ID;
+ return 0;
}
/**
u32 get_device_type(void)
{
int mode;
- mode = readl(&cstat->statusreg) & (DEVICE_MASK);
+ mode = readl(&cstat->statusreg) & DEVICE_MASK;
return mode >>= 8;
}
u32 get_sysboot_value(void)
{
int mode;
- mode = readl(&cstat->statusreg) & (SYSBOOT_MASK);
+ mode = readl(&cstat->statusreg) & SYSBOOT_MASK;
return mode;
}
#ifdef CONFIG_DISPLAY_CPUINFO
static char *cpu_revs[] = {
- "1.0",
- "2.0",
- "2.1"};
-
+ "1.0",
+ "2.0",
+ "2.1",
+ };
static char *dev_types[] = {
- "TST",
- "EMU",
- "HS",
- "GP"};
+ "TST",
+ "EMU",
+ "HS",
+ "GP",
+ };
/**
* Print CPU information
break;
default:
cpu_s = "Unknown CPU type";
- break;
}
if (get_cpu_rev() < ARRAY_SIZE(cpu_revs))
return 0;
}
#endif /* CONFIG_DISPLAY_CPUINFO */
+
+#ifdef CONFIG_AM33XX
+int am335x_get_efuse_mpu_max_freq(struct ctrl_dev *cdev)
+{
+ int sil_rev;
+
+ sil_rev = readl(&cdev->deviceid) >> 28;
+
+ if (sil_rev == 1)
+ /* PG 2.0, efuse may not be set. */
+ return MPUPLL_M_800;
+ else if (sil_rev >= 2) {
+ /* Check what the efuse says our max speed is. */
+ int efuse_arm_mpu_max_freq;
+ efuse_arm_mpu_max_freq = readl(&cdev->efuse_sma);
+ switch ((efuse_arm_mpu_max_freq & DEVICE_ID_MASK)) {
+ case AM335X_ZCZ_1000:
+ return MPUPLL_M_1000;
+ case AM335X_ZCZ_800:
+ return MPUPLL_M_800;
+ case AM335X_ZCZ_720:
+ return MPUPLL_M_720;
+ case AM335X_ZCZ_600:
+ case AM335X_ZCE_600:
+ return MPUPLL_M_600;
+ case AM335X_ZCZ_300:
+ case AM335X_ZCE_300:
+ return MPUPLL_M_300;
+ }
+ }
+
+ /* PG 1.0 or otherwise unknown, use the PG1.0 max */
+ return MPUPLL_M_720;
+}
+
+int am335x_get_tps65910_mpu_vdd(int sil_rev, int frequency)
+{
+ /* For PG2.1 and later, we have one set of values. */
+ if (sil_rev >= 2) {
+ switch (frequency) {
+ case MPUPLL_M_1000:
+ return TPS65910_OP_REG_SEL_1_3_2_5;
+ case MPUPLL_M_800:
+ return TPS65910_OP_REG_SEL_1_2_6;
+ case MPUPLL_M_720:
+ return TPS65910_OP_REG_SEL_1_2_0;
+ case MPUPLL_M_600:
+ case MPUPLL_M_300:
+ return TPS65910_OP_REG_SEL_1_1_3;
+ }
+ }
+
+ /* Default to PG1.0/PG2.0 values. */
+ return TPS65910_OP_REG_SEL_1_1_3;
+}
+#endif
* to get size details from Current Cache Size ID Register(CCSIDR)
*/
static void set_csselr(u32 level, u32 type)
-{ u32 csselr = level << 1 | type;
+{
+ u32 csselr = level << 1 | type;
/* Write to Cache Size Selection Register(CSSELR) */
asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
u32 num_ways, u32 way_shift,
u32 log2_line_len)
{
- int way, set, setway;
+ int way, set;
+ u32 setway;
/*
* For optimal assembly code:
u32 num_ways, u32 way_shift,
u32 log2_line_len)
{
- int way, set, setway;
+ int way, set;
+ u32 setway;
/*
* For optimal assembly code:
static void v7_maint_dcache_all(u32 operation)
{
u32 level, cache_type, level_start_bit = 0;
-
u32 clidr = get_clidr();
for (level = 0; level < 7; level++) {
}
}
-static void v7_dcache_clean_inval_range(u32 start,
- u32 stop, u32 line_len)
+static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len)
{
u32 mva;
/* Invalidate TLB */
static void v7_inval_tlb(void)
{
- /* Invalidate entire unified TLB */
- asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0));
- /* Invalidate entire data TLB */
- asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0));
- /* Invalidate entire instruction TLB */
- asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0));
- /* Full system DSB - make sure that the invalidation is complete */
- CP15DSB;
- /* Full system ISB - make sure the instruction stream sees it */
- CP15ISB;
+ asm volatile (
+ /* Invalidate entire unified TLB */
+ "mcr p15, 0, %0, c8, c7, 0\n"
+ /* Invalidate entire data TLB */
+ "mcr p15, 0, %0, c8, c6, 0\n"
+ /* Invalidate entire instruction TLB */
+ "mcr p15, 0, %0, c8, c5, 0\n"
+ /* Full system DSB - make sure that the invalidation is complete */
+ "mcr p15, 0, %0, c7, c10, 4\n"
+ /* Full system ISB - make sure the instruction stream sees it */
+ "mcr p15, 0, %0, c7, c5, 4\n"
+ : : "r" (0));
}
void invalidate_dcache_all(void)
*/
void invalidate_dcache_range(unsigned long start, unsigned long stop)
{
-
v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE);
v7_outer_cache_inval_range(start, stop);
* Invalidate all instruction caches to PoU.
* Also flushes branch target cache.
*/
- asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
-
- /* Invalidate entire branch predictor array */
- asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0));
-
- /* Full system DSB - make sure that the invalidation is complete */
- CP15DSB;
-
- /* ISB - make sure the instruction stream sees it */
- CP15ISB;
+ asm volatile (
+ "mcr p15, 0, %0, c7, c5, 0\n"
+ /* Invalidate entire branch predictor array */
+ "mcr p15, 0, %0, c7, c5, 6\n"
+ /* Full system DSB - make sure that the invalidation is complete */
+ "mcr p15, 0, %0, c7, c10, 4\n"
+ /* ISB - make sure the instruction stream sees it */
+ "mcr p15, 0, %0, c7, c5, 4\n"
+ : : "r" (0));
}
#else
void invalidate_icache_all(void)
}
#endif
-/*
- * Stub implementations for outer cache operations
- */
-void __v7_outer_cache_enable(void)
-{
-}
-void v7_outer_cache_enable(void)
- __attribute__((weak, alias("__v7_outer_cache_enable")));
-
-void __v7_outer_cache_disable(void)
-{
-}
-void v7_outer_cache_disable(void)
- __attribute__((weak, alias("__v7_outer_cache_disable")));
-
-void __v7_outer_cache_flush_all(void)
-{
-}
-void v7_outer_cache_flush_all(void)
- __attribute__((weak, alias("__v7_outer_cache_flush_all")));
-
-void __v7_outer_cache_inval_all(void)
-{
-}
-void v7_outer_cache_inval_all(void)
- __attribute__((weak, alias("__v7_outer_cache_inval_all")));
-
-void __v7_outer_cache_flush_range(u32 start, u32 end)
-{
-}
-void v7_outer_cache_flush_range(u32 start, u32 end)
- __attribute__((weak, alias("__v7_outer_cache_flush_range")));
-
-void __v7_outer_cache_inval_range(u32 start, u32 end)
-{
-}
-void v7_outer_cache_inval_range(u32 start, u32 end)
- __attribute__((weak, alias("__v7_outer_cache_inval_range")));
+/* Stub implementations for outer cache operations */
+__weak void v7_outer_cache_enable(void) {}
+__weak void v7_outer_cache_disable(void) {}
+__weak void v7_outer_cache_flush_all(void) {}
+__weak void v7_outer_cache_inval_all(void) {}
+__weak void v7_outer_cache_flush_range(u32 start, u32 end) {}
+__weak void v7_outer_cache_inval_range(u32 start, u32 end) {}
/*
* Setup a temporary stack
*/
+ #ifndef CONFIG_SPL_BUILD
ldr sp, =CONFIG_SYS_INIT_SP_ADDR
+ #else
+ ldr sp, =CONFIG_SPL_STACK
+ #endif
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#ifdef CONFIG_SPL_BUILD
- ldr r8, =gdata
+ ldr r9, =gdata
#else
- sub sp, #GD_SIZE
+ sub sp, sp, #GD_SIZE
bic sp, sp, #7
- mov r8, sp
+ mov r9, sp
#endif
/*
* Save the old lr(passed in ip) and the current lr to stack
#define EMI_DIV_MAX 8
#define NFC_DIV_MAX 8
- #define MX5_CBCMR 0x00015154
- #define MX5_CBCDR 0x02888945
+ #define MXC_IPG_PER_CLK MXC_IPG_PERCLK
struct fixed_pll_mfd {
u32 ref_clk_hz;
u32 mfd;
};
- const struct fixed_pll_mfd fixed_mfd[] = {
+ static const struct fixed_pll_mfd fixed_mfd[] = {
{MXC_HCLK, 24 * 16},
};
#define PLL_FREQ_MAX(ref_clk) (4 * (ref_clk) * PLL_MFI_MAX)
#define PLL_FREQ_MIN(ref_clk) \
- ((2 * (ref_clk) * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
+ ((4 * (ref_clk) * PLL_MFI_MIN) / PLL_PD_MAX)
#define MAX_DDR_CLK 420000000
#define NFC_CLK_MAX 34000000
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
+ int clk_enable(struct clk *clk)
+ {
+ int ret = 0;
+
+ if (!clk)
+ return 0;
+
+ if (clk->usecount++ == 0) {
+ if (!clk->enable)
+ return 0;
+ ret = clk->enable(clk);
+ if (ret)
+ clk->usecount--;
+ }
+ return ret;
+ }
+
+ void clk_disable(struct clk *clk)
+ {
+ if (!clk)
+ return;
+
+ if (!(--clk->usecount)) {
+ if (clk->disable)
+ clk->disable(clk);
+ }
+ if (clk->usecount < 0) {
+ printf("%s: clk %p (%s) underflow\n", __func__, clk, clk->name);
+ hang();
+ }
+ }
+
+ int clk_get_usecount(struct clk *clk)
+ {
+ if (clk == NULL)
+ return 0;
+
+ return clk->usecount;
+ }
+
+ u32 clk_get_rate(struct clk *clk)
+ {
+ if (!clk)
+ return 0;
+
+ return clk->rate;
+ }
+
+ struct clk *clk_get_parent(struct clk *clk)
+ {
+ if (!clk)
+ return 0;
+
+ return clk->parent;
+ }
+
+ int clk_set_rate(struct clk *clk, unsigned long rate)
+ {
+ if (clk && clk->set_rate)
+ clk->set_rate(clk, rate);
+ return clk->rate;
+ }
+
+ long clk_round_rate(struct clk *clk, unsigned long rate)
+ {
+ if (clk == NULL || !clk->round_rate)
+ return 0;
+
+ return clk->round_rate(clk, rate);
+ }
+
+ int clk_set_parent(struct clk *clk, struct clk *parent)
+ {
+ debug("Setting parent of clk %p to %p (%p)\n", clk, parent,
+ clk ? clk->parent : NULL);
+
+ if (!clk || clk == parent)
+ return 0;
+
+ if (clk->set_parent) {
+ int ret;
+
+ ret = clk->set_parent(clk, parent);
+ if (ret)
+ return ret;
+ }
+ clk->parent = parent;
+ return 0;
+ }
+
void set_usboh3_clk(void)
{
clrsetbits_le32(&mxc_ccm->cscmr1,
MXC_CCM_CSCDR1_USBOH3_CLK_PODF(1));
}
-void enable_usboh3_clk(unsigned char enable)
+void enable_usboh3_clk(bool enable)
{
unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
MXC_CCM_CCGR2_USBOH3_60M(cg));
}
-#ifdef CONFIG_I2C_MXC
+ void ipu_clk_enable(void)
+ {
+ /* IPU root clock derived from AXI B */
+ clrsetbits_le32(&mxc_ccm->cbcmr, MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK,
+ MXC_CCM_CBCMR_IPU_HSP_CLK_SEL(1));
+
+ setbits_le32(&mxc_ccm->CCGR5,
+ MXC_CCM_CCGR5_IPU(MXC_CCM_CCGR_CG_MASK));
+
+ /* Handshake with IPU when certain clock rates are changed. */
+ clrbits_le32(&mxc_ccm->ccdr, MXC_CCM_CCDR_IPU_HS_MASK);
+
+ /* Handshake with IPU when LPM is entered as its enabled. */
+ clrbits_le32(&mxc_ccm->clpcr, MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS);
+ }
+
+ void ipu_clk_disable(void)
+ {
+ clrbits_le32(&mxc_ccm->CCGR5,
+ MXC_CCM_CCGR5_IPU(MXC_CCM_CCGR_CG_MASK));
+
+ /* Handshake with IPU when certain clock rates are changed. */
+ setbits_le32(&mxc_ccm->ccdr, MXC_CCM_CCDR_IPU_HS_MASK);
+
+ /* Handshake with IPU when LPM is entered as its enabled. */
+ setbits_le32(&mxc_ccm->clpcr, MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS);
+ }
+
+ void ipu_di_clk_enable(int di)
+ {
+ switch (di) {
+ case 0:
+ setbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_IPU_DI0(MXC_CCM_CCGR_CG_MASK));
+ break;
+ case 1:
+ setbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_IPU_DI1(MXC_CCM_CCGR_CG_MASK));
+ break;
+ default:
+ printf("%s: Invalid DI index %d\n", __func__, di);
+ }
+ }
+
+ void ipu_di_clk_disable(int di)
+ {
+ switch (di) {
+ case 0:
+ clrbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_IPU_DI0(MXC_CCM_CCGR_CG_MASK));
+ break;
+ case 1:
+ clrbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_IPU_DI1(MXC_CCM_CCGR_CG_MASK));
+ break;
+ default:
+ printf("%s: Invalid DI index %d\n", __func__, di);
+ }
+ }
+
+ #ifdef CONFIG_MX53
+ void ldb_clk_enable(int ldb)
+ {
+ switch (ldb) {
+ case 0:
+ setbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_LDB_DI0(MXC_CCM_CCGR_CG_MASK));
+ break;
+ case 1:
+ setbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_LDB_DI1(MXC_CCM_CCGR_CG_MASK));
+ break;
+ default:
+ printf("%s: Invalid LDB index %d\n", __func__, ldb);
+ }
+ }
+
+ void ldb_clk_disable(int ldb)
+ {
+ switch (ldb) {
+ case 0:
+ clrbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_LDB_DI0(MXC_CCM_CCGR_CG_MASK));
+ break;
+ case 1:
+ clrbits_le32(&mxc_ccm->CCGR6,
+ MXC_CCM_CCGR6_LDB_DI1(MXC_CCM_CCGR_CG_MASK));
+ break;
+ default:
+ printf("%s: Invalid LDB index %d\n", __func__, ldb);
+ }
+ }
+ #endif
+
+#ifdef CONFIG_SYS_I2C_MXC
/* i2c_num can be from 0, to 1 for i.MX51 and 2 for i.MX53 */
int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
{
}
#if defined(CONFIG_MX51)
-void enable_usb_phy1_clk(unsigned char enable)
+void enable_usb_phy1_clk(bool enable)
{
unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
MXC_CCM_CCGR2_USB_PHY(cg));
}
-void enable_usb_phy2_clk(unsigned char enable)
+void enable_usb_phy2_clk(bool enable)
{
/* i.MX51 has a single USB PHY clock, so do nothing here. */
}
#elif defined(CONFIG_MX53)
-void enable_usb_phy1_clk(unsigned char enable)
+void enable_usb_phy1_clk(bool enable)
{
unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
MXC_CCM_CCGR4_USB_PHY1(cg));
}
-void enable_usb_phy2_clk(unsigned char enable)
+void enable_usb_phy2_clk(bool enable)
{
unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
*/
static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq)
{
- uint32_t ctrl, op, mfd, mfn, mfi, pdf, ret;
+ uint32_t ctrl, op;
+ int mfd, mfn, mfi, pdf, ret;
uint64_t refclk, temp;
- int32_t mfn_abs;
+ uint32_t mfn_abs;
ctrl = readl(&pll->ctrl);
if (mfn >= 0x04000000) {
mfn |= 0xfc000000;
mfn_abs = -mfn;
- } else
+ } else {
mfn_abs = mfn;
-
+ }
refclk = infreq * 2;
if (ctrl & MXC_DPLLC_CTL_DPDCK0_2_EN)
refclk *= 2;
- do_div(refclk, pdf + 1);
temp = refclk * mfn_abs;
do_div(temp, mfd + 1);
ret = refclk * mfi;
- if ((int)mfn < 0)
+ if (mfn < 0)
ret -= temp;
else
ret += temp;
+ ret /= pdf + 1;
return ret;
}
return get_periph_clk() / (pdf + 1);
}
+ static u32 get_nfc_clk(void)
+ {
+ u32 parent_rate = get_emi_slow_clk();
+ u32 div = readl(&mxc_ccm->cbcdr);
+
+ div &= MXC_CCM_CBCDR_NFC_PODF_MASK;
+ div >>= MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+ div++;
+ return parent_rate / div;
+ }
+
static u32 get_ddr_clk(void)
{
u32 ret_val = 0;
return get_ahb_clk();
case MXC_DDR_CLK:
return get_ddr_clk();
+ case MXC_AXI_A_CLK:
+ return get_axi_a_clk();
+ case MXC_AXI_B_CLK:
+ return get_axi_b_clk();
+ case MXC_EMI_SLOW_CLK:
+ return get_emi_slow_clk();
+ case MXC_NFC_CLK:
+ return get_nfc_clk();
default:
break;
}
*/
static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
{
- u64 pd, mfi = 1, mfn, mfd, t1;
- u32 n_target = target;
- u32 n_ref = ref, i;
+ int pd, mfi = 1, mfn, mfd;
+ u64 t1;
+ size_t i;
/*
* Make sure targeted freq is in the valid range.
* Otherwise the following calculation might be wrong!!!
*/
- if (n_target < PLL_FREQ_MIN(ref) ||
- n_target > PLL_FREQ_MAX(ref)) {
- printf("Targeted peripheral clock should be"
- "within [%d - %d]\n",
+ if (target < PLL_FREQ_MIN(ref) ||
+ target > PLL_FREQ_MAX(ref)) {
+ printf("Targeted pll clock should be within [%d - %d]\n",
PLL_FREQ_MIN(ref) / SZ_DEC_1M,
PLL_FREQ_MAX(ref) / SZ_DEC_1M);
return -EINVAL;
if (i == ARRAY_SIZE(fixed_mfd))
return -EINVAL;
- /* Use n_target and n_ref to avoid overflow */
for (pd = 1; pd <= PLL_PD_MAX; pd++) {
- t1 = n_target * pd;
- do_div(t1, (4 * n_ref));
+ t1 = (u64)target * pd;
+ do_div(t1, (4 * ref));
mfi = t1;
if (mfi > PLL_MFI_MAX)
return -EINVAL;
/*
* Now got pd and mfi already
*
- * mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
+ * mfn = (((target * pd) / 4 - ref * mfi) * mfd) / ref;
*/
- t1 = n_target * pd;
+ t1 = (u64)target * pd;
do_div(t1, 4);
- t1 -= n_ref * mfi;
- t1 *= mfd;
- do_div(t1, n_ref);
+ t1 = (t1 - ref * mfi) * mfd;
+ do_div(t1, ref);
mfn = t1;
- debug("ref=%d, target=%d, pd=%d," "mfi=%d,mfn=%d, mfd=%d\n",
- ref, n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
- i = 1;
- if (mfn != 0)
+ if (mfn != 0) {
i = gcd(mfd, mfn);
- pll->pd = (u32)pd;
- pll->mfi = (u32)mfi;
- do_div(mfn, i);
- pll->mfn = (u32)mfn;
- do_div(mfd, i);
- pll->mfd = (u32)mfd;
+ mfn /= i;
+ mfd /= i;
+ } else {
+ mfd = 1;
+ }
+ debug("ref=%d, target=%d, pd=%d, mfi=%d, mfn=%d, mfd=%d\n",
+ ref, target, pd, mfi, mfn, mfd);
+ pll->pd = pd;
+ pll->mfi = mfi;
+ pll->mfn = mfn;
+ pll->mfd = mfd;
return 0;
}
#define CHANGE_PLL_SETTINGS(pll, pd, fi, fn, fd) \
{ \
- writel(0x1232, &pll->ctrl); \
- writel(0x2, &pll->config); \
- writel((((pd) - 1) << 0) | ((fi) << 4), \
- &pll->op); \
- writel(fn, &(pll->mfn)); \
- writel((fd) - 1, &pll->mfd); \
- writel((((pd) - 1) << 0) | ((fi) << 4), \
- &pll->hfs_op); \
- writel(fn, &pll->hfs_mfn); \
- writel((fd) - 1, &pll->hfs_mfd); \
- writel(0x1232, &pll->ctrl); \
- while (!readl(&pll->ctrl) & 0x1) \
+ __raw_writel(0x1232, &pll->ctrl); \
+ __raw_writel(0x2, &pll->config); \
+ __raw_writel((((pd) - 1) << 0) | ((fi) << 4), \
+ &pll->op); \
+ __raw_writel(fn, &(pll->mfn)); \
+ __raw_writel((fd) - 1, &pll->mfd); \
+ __raw_writel((((pd) - 1) << 0) | ((fi) << 4), \
+ &pll->hfs_op); \
+ __raw_writel(fn, &pll->hfs_mfn); \
+ __raw_writel((fd) - 1, &pll->hfs_mfd); \
+ __raw_writel(0x1232, &pll->ctrl); \
+ while (!__raw_readl(&pll->ctrl) & 0x1) \
;\
}
static int config_pll_clk(enum pll_clocks index, struct pll_param *pll_param)
{
- u32 ccsr = readl(&mxc_ccm->ccsr);
+ u32 ccsr = __raw_readl(&mxc_ccm->ccsr);
struct mxc_pll_reg *pll = mxc_plls[index];
switch (index) {
case PLL1_CLOCK:
/* Switch ARM to PLL2 clock */
- writel(ccsr | MXC_CCM_CCSR_PLL1_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr | 0x4, &mxc_ccm->ccsr);
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
pll_param->mfi, pll_param->mfn,
pll_param->mfd);
/* Switch back */
- writel(ccsr & ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr & ~0x4, &mxc_ccm->ccsr);
break;
case PLL2_CLOCK:
/* Switch to pll2 bypass clock */
- writel(ccsr | MXC_CCM_CCSR_PLL2_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr | 0x2, &mxc_ccm->ccsr);
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
pll_param->mfi, pll_param->mfn,
pll_param->mfd);
/* Switch back */
- writel(ccsr & ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr & ~0x2, &mxc_ccm->ccsr);
break;
case PLL3_CLOCK:
/* Switch to pll3 bypass clock */
- writel(ccsr | MXC_CCM_CCSR_PLL3_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr | 0x1, &mxc_ccm->ccsr);
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
pll_param->mfi, pll_param->mfn,
pll_param->mfd);
/* Switch back */
- writel(ccsr & ~MXC_CCM_CCSR_PLL3_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr & ~0x1, &mxc_ccm->ccsr);
break;
#ifdef CONFIG_MX53
case PLL4_CLOCK:
/* Switch to pll4 bypass clock */
- writel(ccsr | MXC_CCM_CCSR_PLL4_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr | 0x20, &mxc_ccm->ccsr);
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
pll_param->mfi, pll_param->mfn,
pll_param->mfd);
/* Switch back */
- writel(ccsr & ~MXC_CCM_CCSR_PLL4_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr & ~0x20, &mxc_ccm->ccsr);
break;
#endif
default:
return 0;
}
+ static int __adjust_core_voltage_stub(u32 freq)
+ {
+ return 0;
+ }
+ int adjust_core_voltage(u32 freq)
+ __attribute__((weak, alias("__adjust_core_voltage_stub")));
+
/* Config CPU clock */
static int config_core_clk(u32 ref, u32 freq)
{
int ret = 0;
struct pll_param pll_param;
+ u32 cur_freq = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK);
+
+ if (freq == cur_freq)
+ return 0;
memset(&pll_param, 0, sizeof(struct pll_param));
/* The case that periph uses PLL1 is not considered here */
ret = calc_pll_params(ref, freq, &pll_param);
if (ret != 0) {
- printf("Error:Can't find pll parameters: %d\n", ret);
+ printf("Error: Can't find pll parameters for %u.%03uMHz ref %u.%03uMHz\n",
+ freq / 1000000, freq / 1000 % 1000,
+ ref / 1000000, ref / 1000 % 1000);
return ret;
}
-
- return config_pll_clk(PLL1_CLOCK, &pll_param);
+ if (freq > cur_freq) {
+ ret = adjust_core_voltage(freq);
+ if (ret < 0) {
+ printf("Failed to adjust core voltage for changing ARM clk from %u.%03uMHz to %u.%03uMHz\n",
+ cur_freq / 1000000, cur_freq / 1000 % 1000,
+ freq / 1000000, freq / 1000 % 1000);
+ return ret;
+ }
+ ret = config_pll_clk(PLL1_CLOCK, &pll_param);
+ if (ret) {
+ adjust_core_voltage(cur_freq);
+ }
+ } else {
+ ret = config_pll_clk(PLL1_CLOCK, &pll_param);
+ if (ret) {
+ return ret;
+ }
+ ret = adjust_core_voltage(freq);
+ if (ret < 0) {
+ printf("Failed to adjust core voltage for changing ARM clk from %u.%03uMHz to %u.%03uMHz\n",
+ cur_freq / 1000000, cur_freq / 1000 % 1000,
+ freq / 1000000, freq / 1000 % 1000);
+ calc_pll_params(ref, cur_freq, &pll_param);
+ config_pll_clk(PLL1_CLOCK, &pll_param);
+ }
+ }
+ return ret;
}
static int config_nfc_clk(u32 nfc_clk)
MXC_CCM_CCGR5_EMI_ENFC(cg));
}
+#ifdef CONFIG_FSL_IIM
+void enable_efuse_prog_supply(bool enable)
+{
+ if (enable)
+ setbits_le32(&mxc_ccm->cgpr,
+ MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE);
+ else
+ clrbits_le32(&mxc_ccm->cgpr,
+ MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE);
+}
+#endif
+
/* Config main_bus_clock for periphs */
static int config_periph_clk(u32 ref, u32 freq)
{
/*
* Dump some core clockes.
*/
- int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+ #define pr_clk_val(c, v) { \
+ printf("%-11s %3lu.%03lu MHz\n", #c, \
+ (v) / 1000000, (v) / 1000 % 1000); \
+ }
+
+ #define pr_clk(c) { \
+ unsigned long __clk = mxc_get_clock(MXC_##c##_CLK); \
+ pr_clk_val(c, __clk); \
+ }
+
+ static int do_mx5_showclocks(void)
{
- u32 freq;
+ unsigned long freq;
freq = decode_pll(mxc_plls[PLL1_CLOCK], MXC_HCLK);
- printf("PLL1 %8d MHz\n", freq / 1000000);
+ pr_clk_val(PLL1, freq);
freq = decode_pll(mxc_plls[PLL2_CLOCK], MXC_HCLK);
- printf("PLL2 %8d MHz\n", freq / 1000000);
+ pr_clk_val(PLL2, freq);
freq = decode_pll(mxc_plls[PLL3_CLOCK], MXC_HCLK);
- printf("PLL3 %8d MHz\n", freq / 1000000);
+ pr_clk_val(PLL3, freq);
#ifdef CONFIG_MX53
freq = decode_pll(mxc_plls[PLL4_CLOCK], MXC_HCLK);
- printf("PLL4 %8d MHz\n", freq / 1000000);
+ pr_clk_val(PLL4, freq);
#endif
printf("\n");
- printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
- printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
- printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
- printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
+ pr_clk(AHB);
+ pr_clk(AXI_A);
+ pr_clk(AXI_B);
+ pr_clk(IPG);
+ pr_clk(IPG_PER);
+ pr_clk(DDR);
+ pr_clk(EMI_SLOW);
+ pr_clk(NFC);
#ifdef CONFIG_MXC_SPI
- printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000);
+ pr_clk(CSPI);
#endif
return 0;
}
+ static struct clk_lookup {
+ const char *name;
+ unsigned int index;
+ } mx5_clk_lookup[] = {
+ { "arm", MXC_ARM_CLK, },
+ };
+
+ int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int i;
+ unsigned long freq;
+ unsigned long ref = ~0UL;
+
+ if (argc < 2) {
+ do_mx5_showclocks();
+ return CMD_RET_SUCCESS;
+ } else if (argc == 2 || argc > 4) {
+ return CMD_RET_USAGE;
+ }
+
+ freq = simple_strtoul(argv[2], NULL, 0);
+ if (freq == 0) {
+ printf("Invalid clock frequency %lu\n", freq);
+ return CMD_RET_FAILURE;
+ }
+ if (argc > 3) {
+ ref = simple_strtoul(argv[3], NULL, 0);
+ }
+ for (i = 0; i < ARRAY_SIZE(mx5_clk_lookup); i++) {
+ if (strcasecmp(argv[1], mx5_clk_lookup[i].name) == 0) {
+ switch (mx5_clk_lookup[i].index) {
+ case MXC_ARM_CLK:
+ if (argc > 3)
+ return CMD_RET_USAGE;
+ ref = CONFIG_SYS_MX5_HCLK;
+ break;
+
+ case MXC_NFC_CLK:
+ if (argc > 3 && ref > 3) {
+ printf("Invalid clock selector value: %lu\n", ref);
+ return CMD_RET_FAILURE;
+ }
+ break;
+ }
+ printf("Setting %s clock to %lu MHz\n",
+ mx5_clk_lookup[i].name, freq);
+ if (mxc_set_clock(ref, freq, mx5_clk_lookup[i].index))
+ break;
+ freq = mxc_get_clock(mx5_clk_lookup[i].index);
+ printf("%s clock set to %lu.%03lu MHz\n",
+ mx5_clk_lookup[i].name,
+ freq / 1000000, freq / 1000 % 1000);
+ return CMD_RET_SUCCESS;
+ }
+ }
+ if (i == ARRAY_SIZE(mx5_clk_lookup)) {
+ printf("clock %s not found; supported clocks are:\n", argv[1]);
+ for (i = 0; i < ARRAY_SIZE(mx5_clk_lookup); i++) {
+ printf("\t%s\n", mx5_clk_lookup[i].name);
+ }
+ } else {
+ printf("Failed to set clock %s to %s MHz\n",
+ argv[1], argv[2]);
+ }
+ return CMD_RET_FAILURE;
+ }
+
/***************************************************/
U_BOOT_CMD(
- clocks, CONFIG_SYS_MAXARGS, 1, do_mx5_showclocks,
- "display clocks",
- ""
+ clocks, 4, 0, do_clocks,
+ "display/set clocks",
+ " - display clock settings\n"
+ "clocks <clkname> <freq> - set clock <clkname> to <freq> MHz"
);
/* reconfigure L2 cache aux control reg */
ldr r0, =0xC0 | /* tag RAM */ \
- 0x4 | /* data RAM */ \
- 1 << 24 | /* disable write allocate delay */ \
- 1 << 23 | /* disable write allocate combine */ \
- 1 << 22 /* disable write allocate */
+ 0x4 | /* data RAM */ \
+ 1 << 24 | /* disable write allocate delay */ \
+ 1 << 23 | /* disable write allocate combine */ \
+ 1 << 22 /* disable write allocate */
#if defined(CONFIG_MX51)
ldr r3, [r4, #ROM_SI_REV]
#endif
mcr 15, 1, r0, c9, c0, 2
+
+ /* enable L2 cache */
+ mrc 15, 0, r0, c1, c0, 1
+ orr r0, r0, #2
+ mcr 15, 0, r0, c1, c0, 1
+
.endm /* init_l2cc */
/* AIPS setup - Only setup MPROTx registers.
.endm /* init_m4if */
.macro setup_pll pll, freq
- ldr r0, =\pll
+ ldr r3, =\pll
adr r2, W_DP_\freq
bl setup_pll_func
.endm
setup_pll_func:
ldr r1, =0x00001232
- str r1, [r0, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */
+ str r1, [r3, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */
mov r1, #0x2
- str r1, [r0, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */
+ str r1, [r3, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */
ldr r1, [r2, #W_DP_OP]
- str r1, [r0, #PLL_DP_OP]
- str r1, [r0, #PLL_DP_HFS_OP]
+ str r1, [r3, #PLL_DP_OP]
+ str r1, [r3, #PLL_DP_HFS_OP]
ldr r1, [r2, #W_DP_MFD]
- str r1, [r0, #PLL_DP_MFD]
- str r1, [r0, #PLL_DP_HFS_MFD]
+ str r1, [r3, #PLL_DP_MFD]
+ str r1, [r3, #PLL_DP_HFS_MFD]
ldr r1, [r2, #W_DP_MFN]
- str r1, [r0, #PLL_DP_MFN]
- str r1, [r0, #PLL_DP_HFS_MFN]
+ str r1, [r3, #PLL_DP_MFN]
+ str r1, [r3, #PLL_DP_HFS_MFN]
ldr r1, =0x00001232
- str r1, [r0, #PLL_DP_CTL]
- 1: ldr r1, [r0, #PLL_DP_CTL]
+ str r1, [r3, #PLL_DP_CTL]
+ 1: ldr r1, [r3, #PLL_DP_CTL]
ands r1, r1, #0x1
beq 1b
.endm
.macro init_clock
- #if defined (CONFIG_MX51)
ldr r0, =CCM_BASE_ADDR
-
- /* Gate of clocks to the peripherals first */
+ #if defined (CONFIG_MX51)
+ /* Gate off clocks to the peripherals first */
ldr r1, =0x3FFFFFFF
str r1, [r0, #CLKCTL_CCGR0]
str r4, [r0, #CLKCTL_CCGR1]
str r1, [r0, #CLKCTL_CBCDR]
/* make sure divider effective */
1: ldr r1, [r0, #CLKCTL_CDHIPR]
- cmp r1, #0x0
+ tst r1, #0x7f
bne 1b
/* Switch ARM to step clock */
setup_pll PLL1_BASE_ADDR, 864
setup_pll_errata PLL1_BASE_ADDR, W_DP_MFN_800_DIT
#else
+ #if !defined(CONFIG_SYS_CPU_CLK) || CONFIG_SYS_CPU_CLK == 800
setup_pll PLL1_BASE_ADDR, 800
+ #elif CONFIG_SYS_CPU_CLK == 600
+ setup_pll PLL1_BASE_ADDR, 600
+ #else
+ #error Unsupported CONFIG_SYS_CPU_CLK value
+ #endif
#endif
setup_pll PLL3_BASE_ADDR, 665
/* Switch peripheral to PLL 3 */
- ldr r0, =CCM_BASE_ADDR
ldr r1, =0x000010C0 | CONFIG_SYS_DDR_CLKSEL
str r1, [r0, #CLKCTL_CBCMR]
ldr r1, =0x13239145
setup_pll PLL2_BASE_ADDR, 665
/* Switch peripheral to PLL2 */
- ldr r0, =CCM_BASE_ADDR
ldr r1, =0x19239145
str r1, [r0, #CLKCTL_CBCDR]
ldr r1, =0x000020C0 | CONFIG_SYS_DDR_CLKSEL
str r1, [r0, #CLKCTL_CSCDR1]
/* make sure divider effective */
1: ldr r1, [r0, #CLKCTL_CDHIPR]
- cmp r1, #0x0
+ tst r1, #0x7f
bne 1b
str r4, [r0, #CLKCTL_CCDR]
add r1, r1, #0x00000F0
str r1, [r0, #CLKCTL_CCOSR]
#else /* CONFIG_MX53 */
- ldr r0, =CCM_BASE_ADDR
-
- /* Gate of clocks to the peripherals first */
+ /* Gate off clocks to the peripherals first */
ldr r1, =0x3FFFFFFF
str r1, [r0, #CLKCTL_CCGR0]
str r4, [r0, #CLKCTL_CCGR1]
mov r1, #0x4
str r1, [r0, #CLKCTL_CCSR]
+ #if !defined(CONFIG_SYS_CPU_CLK) || CONFIG_SYS_CPU_CLK == 800
setup_pll PLL1_BASE_ADDR, 800
+ #elif CONFIG_SYS_CPU_CLK == 600
+ setup_pll PLL1_BASE_ADDR, 600
+ #else
+ #error Unsupported CONFIG_SYS_CPU_CLK value
+ #endif
- setup_pll PLL3_BASE_ADDR, 400
+ setup_pll PLL3_BASE_ADDR, 400
-
+ #ifndef CONFIG_TX53
- /* Switch peripheral to PLL3 */
- ldr r1, =0x00015154
- str r1, [r0, #CLKCTL_CBCMR]
- ldr r1, =0x02898945
- str r1, [r0, #CLKCTL_CBCDR]
- /* make sure change is effective */
+ /* Switch peripheral to PLL3 */
+ ldr r0, =CCM_BASE_ADDR
+ ldr r1, =0x00015154
+ str r1, [r0, #CLKCTL_CBCMR]
+ ldr r1, =0x02898945
+ str r1, [r0, #CLKCTL_CBCDR]
+ /* make sure change is effective */
1: ldr r1, [r0, #CLKCTL_CDHIPR]
- cmp r1, #0x0
+ tst r1, #0x7f
- bne 1b
+ bne 1b
- setup_pll PLL2_BASE_ADDR, 400
+ setup_pll PLL2_BASE_ADDR, 400
/* Switch peripheral to PLL2 */
- ldr r0, =CCM_BASE_ADDR
ldr r1, =0x00888945
str r1, [r0, #CLKCTL_CBCDR]
ldr r1, =0x00016154
str r1, [r0, #CLKCTL_CBCMR]
- /*change uart clk parent to pll2*/
+ /* change uart clk parent to pll2 */
ldr r1, [r0, #CLKCTL_CSCMR1]
- and r1, r1, #0xfcffffff
- orr r1, r1, #0x01000000
+ bic r1, #(0x3 << 24)
+ orr r1, r1, #(0x1 << 24)
str r1, [r0, #CLKCTL_CSCMR1]
/* make sure change is effective */
1: ldr r1, [r0, #CLKCTL_CDHIPR]
- cmp r1, #0x0
+ tst r1, #0x7f
bne 1b
+ setup_pll PLL3_BASE_ADDR, 216
+
setup_pll PLL4_BASE_ADDR, 455
+ #else /* CONFIG_TX53 */
+ /* Switch peripheral to PLL 3 */
+ ldr r1, [r0, #CLKCTL_CBCMR]
+ bic r1, #(0x3 << 12)
+ orr r1, r1, #(1 << 12)
+ str r1, [r0, #CLKCTL_CBCMR]
+
+ ldr r1, [r0, #CLKCTL_CBCDR]
+ orr r1, r1, #(1 << 25)
+ str r1, [r0, #CLKCTL_CBCDR]
+ 1:
+ /* make sure change is effective */
+ ldr r1, [r0, #CLKCTL_CDHIPR]
+ tst r1, #0x7f
+ bne 1b
+
+ #if CONFIG_SYS_SDRAM_CLK == 533
+ setup_pll PLL2_BASE_ADDR, 533
+ #elif CONFIG_SYS_SDRAM_CLK == 400
+ setup_pll PLL2_BASE_ADDR, 400
+ #elif CONFIG_SYS_SDRAM_CLK == 333
+ setup_pll PLL2_BASE_ADDR, 333
+ #else
+ #error Unsupported CONFIG_SYS_SDRAM_CLK
+ #endif
+
+ /* Switch peripheral to PLL2 */
+ ldr r1, [r0, #CLKCTL_CBCDR]
+ bic r1, #(1 << 25)
+ str r1, [r0, #CLKCTL_CBCDR]
+
+ ldr r1, [r0, #CLKCTL_CBCMR]
+ bic r1, #(3 << 12)
+ orr r1, #(2 << 12)
+ str r1, [r0, #CLKCTL_CBCMR]
+ #endif
+ setup_pll PLL3_BASE_ADDR, 216
+
/* Set the platform clock dividers */
ldr r0, =ARM_BASE_ADDR
ldr r1, =0x00000124
/* make uart div=6 */
ldr r1, [r0, #CLKCTL_CSCDR1]
- and r1, r1, #0xffffffc0
+ bic r1, #(0x3f << 0)
orr r1, r1, #0x0a
str r1, [r0, #CLKCTL_CSCDR1]
+ /* make sure divider effective */
+ 1: ldr r1, [r0, #CLKCTL_CDHIPR]
+ tst r1, #0x7f
+ bne 1b
/* Restore the default values in the Gate registers */
ldr r1, =0xFFFFFFFF
str r1, [r0, #CLKCTL_CCGR6]
str r1, [r0, #CLKCTL_CCGR7]
- mov r1, #0x00000
- str r1, [r0, #CLKCTL_CCDR]
+ mov r1, #0x00000
+ str r1, [r0, #CLKCTL_CCDR]
- /* for cko - for ARM div by 8 */
- mov r1, #0x000A0000
- add r1, r1, #0x00000F0
- str r1, [r0, #CLKCTL_CCOSR]
+ /* for cko - for ARM div by 8 */
+ mov r1, #0x000A0000
+ add r1, r1, #0x00000F0
+ str r1, [r0, #CLKCTL_CCOSR]
#endif /* CONFIG_MX53 */
.endm
-.macro setup_wdog
- ldr r0, =WDOG1_BASE_ADDR
- mov r1, #0x30
- strh r1, [r0]
-.endm
-
ENTRY(lowlevel_init)
mov r10, lr
mov r4, #0 /* Fix R4 to 0 */
W_DP_665: .word DP_OP_665
.word DP_MFD_665
.word DP_MFN_665
+ W_DP_600: .word DP_OP_600
+ .word DP_MFD_600
+ .word DP_MFN_600
#endif
W_DP_216: .word DP_OP_216
.word DP_MFD_216
W_DP_455: .word DP_OP_455
.word DP_MFD_455
.word DP_MFN_455
+ W_DP_533: .word DP_OP_533
+ .word DP_MFD_533
+ .word DP_MFN_533
#error "CPU_TYPE not defined"
#endif
+ #ifdef CONFIG_HW_WATCHDOG
+ #define wdog_base ((void *)WDOG1_BASE_ADDR)
+ #define WDOG_WCR 0x00
+ #define WCR_WDE (1 << 2)
+ #define WDOG_WSR 0x02
+
+ void hw_watchdog_reset(void)
+ {
+ if (readw(wdog_base + WDOG_WCR) & WCR_WDE) {
+ static u16 toggle = 0xaaaa;
+
+ writew(toggle, wdog_base + WDOG_WSR);
+ toggle ^= 0xffff;
+ }
+ }
+ #endif
+
u32 get_cpu_rev(void)
{
#ifdef CONFIG_MX51
#endif
#if defined(CONFIG_FEC_MXC)
- void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+ static void __imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
{
int i;
struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
for (i = 0; i < 6; i++)
mac[i] = readl(&fuse->mac_addr[i]) & 0xff;
}
+
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+ __attribute__((weak, alias("__imx_get_mac_from_fuse")));
+
#endif
-void set_chipselect_size(int const cs_size)
-{
- unsigned int reg;
- struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
- reg = readl(&iomuxc_regs->gpr1);
-
- switch (cs_size) {
- case CS0_128:
- reg &= ~0x7; /* CS0=128MB, CS1=0, CS2=0, CS3=0 */
- reg |= 0x5;
- break;
- case CS0_64M_CS1_64M:
- reg &= ~0x3F; /* CS0=64MB, CS1=64MB, CS2=0, CS3=0 */
- reg |= 0x1B;
- break;
- case CS0_64M_CS1_32M_CS2_32M:
- reg &= ~0x1FF; /* CS0=64MB, CS1=32MB, CS2=32MB, CS3=0 */
- reg |= 0x4B;
- break;
- case CS0_32M_CS1_32M_CS2_32M_CS3_32M:
- reg &= ~0xFFF; /* CS0=32MB, CS1=32MB, CS2=32MB, CS3=32MB */
- reg |= 0x249;
- break;
- default:
- printf("Unknown chip select size: %d\n", cs_size);
- break;
- }
-
- writel(reg, &iomuxc_regs->gpr1);
-}
-
-void cpu_cache_initialization(void)
-{
- printf("Enabling L2 cache\n");
- asm volatile(
- "mrc 15, 0, r0, c1, c0, 1\n"
- "orr r0, r0, #0x2\n"
- "mcr 15, 0, r0, c1, c0, 1\n"
- : : : "r0", "memory"
- );
-}
-
#ifdef CONFIG_MX53
void boot_mode_apply(unsigned cfg_val)
{
*/
#include <common.h>
+#include <div64.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
enum pll_clocks {
- PLL_SYS, /* System PLL */
- PLL_BUS, /* System Bus PLL*/
- PLL_USBOTG, /* OTG USB PLL */
- PLL_ENET, /* ENET PLL */
+ PLL_ARM, /* PLL1: ARM PLL */
- PLL_BUS, /* PLL2: System Bus PLL*/
++ PLL_528, /* PLL2: System Bus PLL*/
+ PLL_USBOTG, /* PLL3: OTG USB PLL */
+ PLL_AUDIO, /* PLL4: Audio PLL */
+ PLL_VIDEO, /* PLL5: Video PLL */
+ PLL_ENET, /* PLL6: ENET PLL */
+ PLL_USB2, /* PLL7: USB2 PLL */
+ PLL_MLB, /* PLL8: MLB PLL */
};
- struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ struct mxc_ccm_reg *const imx_ccm = (void *)CCM_BASE_ADDR;
+ struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
+
+ int clk_enable(struct clk *clk)
+ {
+ int ret = 0;
+
+ if (!clk)
+ return 0;
+ if (clk->usecount == 0) {
-debug("%s: Enabling %s clock\n", __func__, clk->name);
++ debug("%s: Enabling %s clock\n", __func__, clk->name);
+ ret = clk->enable(clk);
+ if (ret)
+ return ret;
+ clk->usecount++;
+ }
+ assert(clk->usecount > 0);
+ return ret;
+ }
+
+ void clk_disable(struct clk *clk)
+ {
+ if (!clk)
+ return;
+
+ assert(clk->usecount > 0);
+ if (!(--clk->usecount)) {
+ if (clk->disable) {
-debug("%s: Disabling %s clock\n", __func__, clk->name);
++ debug("%s: Disabling %s clock\n", __func__, clk->name);
+ clk->disable(clk);
+ }
+ }
+ }
+
+ int clk_get_usecount(struct clk *clk)
+ {
+ if (clk == NULL)
+ return 0;
+
+ return clk->usecount;
+ }
+
+ u32 clk_get_rate(struct clk *clk)
+ {
+ if (!clk)
+ return 0;
+
+ return clk->rate;
+ }
+
+ struct clk *clk_get_parent(struct clk *clk)
+ {
+ if (!clk)
+ return 0;
+
+ return clk->parent;
+ }
+
+ int clk_set_rate(struct clk *clk, unsigned long rate)
+ {
+ if (clk && clk->set_rate)
+ clk->set_rate(clk, rate);
+ return clk->rate;
+ }
+
+ long clk_round_rate(struct clk *clk, unsigned long rate)
+ {
+ if (clk == NULL || !clk->round_rate)
+ return 0;
+
+ return clk->round_rate(clk, rate);
+ }
+
+ int clk_set_parent(struct clk *clk, struct clk *parent)
+ {
+ debug("Setting parent of clk %p to %p (%p)\n", clk, parent,
+ clk ? clk->parent : NULL);
+
+ if (!clk || clk == parent)
+ return 0;
+
+ if (clk->set_parent) {
+ int ret;
+
+ ret = clk->set_parent(clk, parent);
+ if (ret)
+ return ret;
+ }
+ clk->parent = parent;
+ return 0;
+ }
#ifdef CONFIG_MXC_OCOTP
void enable_ocotp_clk(unsigned char enable)
}
#endif
+#ifdef CONFIG_NAND_MXS
+void setup_gpmi_io_clk(u32 cfg)
+{
+ /* Disable clocks per ERR007177 from MX6 errata */
+ clrbits_le32(&imx_ccm->CCGR4,
+ MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK);
+
+ clrbits_le32(&imx_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
+
+ clrsetbits_le32(&imx_ccm->cs2cdr,
+ MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
+ MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
+ cfg);
+
+ setbits_le32(&imx_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
+ setbits_le32(&imx_ccm->CCGR4,
+ MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK);
+}
+#endif
+
void enable_usboh3_clk(unsigned char enable)
{
u32 reg;
}
-#ifdef CONFIG_I2C_MXC
+#if defined(CONFIG_FEC_MXC) && !defined(CONFIG_MX6SX)
+void enable_enet_clk(unsigned char enable)
+{
+ u32 mask = MXC_CCM_CCGR1_ENET_CLK_ENABLE_MASK;
+
+ if (enable)
+ setbits_le32(&imx_ccm->CCGR1, mask);
+ else
+ clrbits_le32(&imx_ccm->CCGR1, mask);
+}
+#endif
+
+#ifdef CONFIG_MXC_UART
+void enable_uart_clk(unsigned char enable)
+{
+ u32 mask = MXC_CCM_CCGR5_UART_MASK | MXC_CCM_CCGR5_UART_SERIAL_MASK;
+
+ if (enable)
+ setbits_le32(&imx_ccm->CCGR5, mask);
+ else
+ clrbits_le32(&imx_ccm->CCGR5, mask);
+}
+#endif
+
+#ifdef CONFIG_SPI
+/* spi_num can be from 0 - 4 */
+int enable_cspi_clock(unsigned char enable, unsigned spi_num)
+{
+ u32 mask;
+
+ if (spi_num > 4)
+ return -EINVAL;
+
+ mask = MXC_CCM_CCGR_CG_MASK << (spi_num * 2);
+ if (enable)
+ setbits_le32(&imx_ccm->CCGR1, mask);
+ else
+ clrbits_le32(&imx_ccm->CCGR1, mask);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_MMC
+int enable_usdhc_clk(unsigned char enable, unsigned bus_num)
+{
+ u32 mask;
+
+ if (bus_num > 3)
+ return -EINVAL;
+
+ mask = MXC_CCM_CCGR_CG_MASK << (bus_num * 2 + 2);
+ if (enable)
+ setbits_le32(&imx_ccm->CCGR6, mask);
+ else
+ clrbits_le32(&imx_ccm->CCGR6, mask);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SYS_I2C_MXC
/* i2c_num can be from 0 - 2 */
int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
{
}
#endif
+/* spi_num can be from 0 - SPI_MAX_NUM */
+int enable_spi_clk(unsigned char enable, unsigned spi_num)
+{
+ u32 reg;
+ u32 mask;
+
+ if (spi_num > SPI_MAX_NUM)
+ return -EINVAL;
+
+ mask = MXC_CCM_CCGR_CG_MASK << (spi_num << 1);
+ reg = __raw_readl(&imx_ccm->CCGR1);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ __raw_writel(reg, &imx_ccm->CCGR1);
+ return 0;
+}
static u32 decode_pll(enum pll_clocks pll, u32 infreq)
{
u32 div;
switch (pll) {
- case PLL_SYS:
- div = __raw_readl(&imx_ccm->analog_pll_sys);
- div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
-
- return (infreq * div) >> 1;
- case PLL_BUS:
- div = __raw_readl(&imx_ccm->analog_pll_528);
+ case PLL_ARM:
+ div = __raw_readl(&anatop->pll_arm);
+ if (div & BM_ANADIG_PLL_ARM_BYPASS)
+ /* Assume the bypass clock is always derived from OSC */
+ return infreq;
+ div &= BM_ANADIG_PLL_ARM_DIV_SELECT;
+
+ return infreq * div / 2;
- case PLL_BUS:
++ case PLL_528:
+ div = __raw_readl(&anatop->pll_528);
- if (div & BM_ANADIG_PLL_SYS_BYPASS)
++ if (div & BM_ANADIG_PLL_528_BYPASS)
+ return infreq;
- div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
+ div &= BM_ANADIG_PLL_528_DIV_SELECT;
- return infreq * (20 + (div << 1));
+ return infreq * (20 + div * 2);
case PLL_USBOTG:
- div = __raw_readl(&imx_ccm->analog_usb1_pll_480_ctrl);
- div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
-
- return infreq * (20 + (div << 1));
+ div = __raw_readl(&anatop->usb1_pll_480_ctrl);
- if (div & BM_ANADIG_USB1_PLL_480_CTRL_BYPASS)
++ if (div & BM_ANADIG_USB_PLL_480_CTRL_BYPASS)
+ return infreq;
- div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
++ div &= BM_ANADIG_USB_PLL_480_CTRL_DIV_SELECT;
+
+ return infreq * (20 + div * 2);
+ case PLL_AUDIO:
+ div = __raw_readl(&anatop->pll_audio);
+ if (div & BM_ANADIG_PLL_AUDIO_BYPASS)
+ return infreq;
+ div &= BM_ANADIG_PLL_AUDIO_DIV_SELECT;
+
+ return infreq * div;
+ case PLL_VIDEO:
+ div = __raw_readl(&anatop->pll_video);
+ if (div & BM_ANADIG_PLL_VIDEO_BYPASS)
+ return infreq;
+ div &= BM_ANADIG_PLL_VIDEO_DIV_SELECT;
+
+ return infreq * div;
case PLL_ENET:
- div = __raw_readl(&imx_ccm->analog_pll_enet);
+ div = __raw_readl(&anatop->pll_enet);
+ if (div & BM_ANADIG_PLL_ENET_BYPASS)
+ return infreq;
div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
- return (div == 3 ? 125000000 : 25000000 * div * 2);
+ return 25000000 * (div + (div >> 1) + 1);
- default:
+ case PLL_USB2:
+ div = __raw_readl(&anatop->usb2_pll_480_ctrl);
- if (div & BM_ANADIG_USB2_PLL_480_CTRL_BYPASS)
++ if (div & BM_ANADIG_USB_PLL_480_CTRL_BYPASS)
+ return infreq;
- div &= BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT;
++ div &= BM_ANADIG_USB_PLL_480_CTRL_DIV_SELECT;
+
+ return infreq * (20 + div * 2);
+ case PLL_MLB:
+ div = __raw_readl(&anatop->pll_mlb);
+ if (div & BM_ANADIG_PLL_MLB_BYPASS)
+ return infreq;
+ /* unknown external clock provided on MLB_CLK pin */
return 0;
}
- /* NOTREACHED */
+ return 0;
}
- case PLL_BUS:
+static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num)
+{
+ u32 div;
+ u64 freq;
++ struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
+
+ switch (pll) {
- /* No PFD3 on PPL2 */
++ case PLL_528:
+ if (pfd_num == 3) {
- div = __raw_readl(&imx_ccm->analog_pfd_528);
- freq = (u64)decode_pll(PLL_BUS, MXC_HCLK);
++ /* No PFD3 on PLL2 */
+ return 0;
+ }
- div = __raw_readl(&imx_ccm->analog_pfd_480);
++ div = __raw_readl(&anatop->pfd_528);
++ freq = (u64)decode_pll(PLL_528, MXC_HCLK);
+ break;
+ case PLL_USBOTG:
- /* No PFD on other PLL */
++ div = __raw_readl(&anatop->pfd_480);
+ freq = (u64)decode_pll(PLL_USBOTG, MXC_HCLK);
+ break;
+ default:
++ /* No PFD on other PLL */
+ return 0;
+ }
+
+ return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >>
+ ANATOP_PFD_FRAC_SHIFT(pfd_num));
+}
static u32 get_mcu_main_clk(void)
{
reg = __raw_readl(&imx_ccm->cacrr);
reg &= MXC_CCM_CACRR_ARM_PODF_MASK;
reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET;
- freq = decode_pll(PLL_SYS, MXC_HCLK);
+ freq = decode_pll(PLL_ARM, MXC_HCLK);
return freq / (reg + 1);
}
case 2:
freq = MXC_HCLK;
break;
- default:
- break;
}
} else {
reg = __raw_readl(&imx_ccm->cbcmr);
switch (reg) {
case 0:
-- freq = decode_pll(PLL_BUS, MXC_HCLK);
++ freq = decode_pll(PLL_528, MXC_HCLK);
break;
case 1:
- freq = mxc_get_pll_pfd(PLL_BUS, 2);
- freq = PLL2_PFD2_FREQ;
++ freq = mxc_get_pll_pfd(PLL_528, 2);
break;
case 2:
- freq = mxc_get_pll_pfd(PLL_BUS, 0);
- freq = PLL2_PFD0_FREQ;
++ freq = mxc_get_pll_pfd(PLL_528, 0);
break;
case 3:
- freq = PLL2_PFD2_DIV_FREQ;
+ /* static / 2 divider */
- freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2;
- break;
- default:
++ freq = mxc_get_pll_pfd(PLL_528, 2) / 2;
break;
}
}
u32 reg, perclk_podf;
reg = __raw_readl(&imx_ccm->cscmr1);
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
+ if (reg & MXC_CCM_CSCMR1_PER_CLK_SEL_MASK)
+ return MXC_HCLK; /* OSC 24Mhz */
+#endif
perclk_podf = reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
return get_ipg_clk() / (perclk_podf + 1);
static u32 get_uart_clk(void)
{
u32 reg, uart_podf;
- u32 freq = PLL3_80M;
+ u32 freq = decode_pll(PLL_USBOTG, MXC_HCLK) / 6; /* static divider */
reg = __raw_readl(&imx_ccm->cscdr1);
-#ifdef CONFIG_MX6SL
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL)
freq = MXC_HCLK;
#endif
reg &= MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK;
cspi_podf = reg >> MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET;
- return PLL3_60M / (cspi_podf + 1);
+ return decode_pll(PLL_USBOTG, MXC_HCLK) / (8 * (cspi_podf + 1));
}
static u32 get_axi_clk(void)
if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
- root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
- root_freq = PLL2_PFD2_FREQ;
++ root_freq = mxc_get_pll_pfd(PLL_528, 2);
else
- root_freq = PLL3_PFD1_FREQ;
+ root_freq = mxc_get_pll_pfd(PLL_USBOTG, 1);
} else
root_freq = get_periph_clk();
static u32 get_emi_slow_clk(void)
{
- u32 emi_clk_sel, emi_slow_pof, cscmr1, root_freq = 0;
+ u32 emi_clk_sel, emi_slow_podf, cscmr1, root_freq = 0;
cscmr1 = __raw_readl(&imx_ccm->cscmr1);
emi_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
emi_clk_sel >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET;
- emi_slow_pof = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
- emi_slow_pof >>= MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
+ emi_slow_podf = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
+ emi_slow_podf >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET;
switch (emi_clk_sel) {
case 0:
root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
break;
case 2:
- root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
- root_freq = PLL2_PFD2_FREQ;
++ root_freq = mxc_get_pll_pfd(PLL_528, 2);
break;
case 3:
- root_freq = mxc_get_pll_pfd(PLL_BUS, 0);
- root_freq = PLL2_PFD0_FREQ;
++ root_freq = mxc_get_pll_pfd(PLL_528, 0);
break;
}
- return root_freq / (emi_slow_pof + 1);
+ return root_freq / (emi_slow_podf + 1);
}
- root_freq = PLL2_PFD0_FREQ;
+ static u32 get_nfc_clk(void)
+ {
+ u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
+ u32 podf = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
+ u32 pred = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
+ int nfc_clk_sel = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK) >>
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
+ u32 root_freq;
+
+ switch (nfc_clk_sel) {
+ case 0:
- root_freq = decode_pll(PLL_BUS, MXC_HCLK);
++ root_freq = mxc_get_pll_pfd(PLL_528, 0);
+ break;
+ case 1:
- root_freq = PLL2_PFD2_FREQ;
++ root_freq = decode_pll(PLL_528, MXC_HCLK);
+ break;
+ case 2:
+ root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
+ break;
+ case 3:
- root_freq = PLL2_PFD0_FREQ;
++ root_freq = mxc_get_pll_pfd(PLL_528, 2);
+ break;
+ }
+
+ return root_freq / (pred + 1) / (podf + 1);
+ }
+
+ #define CS2CDR_ENFC_MASK (MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK | \
+ MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK | \
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK)
+
+ static int set_nfc_clk(u32 ref, u32 freq_khz)
+ {
+ u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
+ u32 podf;
+ u32 pred;
+ int nfc_clk_sel;
+ u32 root_freq;
+ u32 min_err = ~0;
+ u32 nfc_val = ~0;
+ u32 freq = freq_khz * 1000;
+
+ for (nfc_clk_sel = 0; nfc_clk_sel < 4; nfc_clk_sel++) {
+ u32 act_freq;
+ u32 err;
+
+ if (ref < 4 && ref != nfc_clk_sel)
+ continue;
+
+ switch (nfc_clk_sel) {
+ case 0:
- root_freq = decode_pll(PLL_BUS, MXC_HCLK);
++ root_freq = mxc_get_pll_pfd(PLL_528, 0);
+ break;
+ case 1:
- root_freq = PLL2_PFD2_FREQ;
++ root_freq = decode_pll(PLL_528, MXC_HCLK);
+ break;
+ case 2:
+ root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
+ break;
+ case 3:
- podf = min(DIV_ROUND_UP(root_freq, freq), 1 << 6);
- pred = min(DIV_ROUND_UP(root_freq / podf, freq), 8);
++ root_freq = mxc_get_pll_pfd(PLL_528, 2);
+ break;
+ }
+ if (root_freq < freq)
+ continue;
+
-#ifdef CONFIG_MX6SL
++ podf = min(DIV_ROUND_UP(root_freq, freq), 1U << 6);
++ pred = min(DIV_ROUND_UP(root_freq / podf, freq), 8U);
+ act_freq = root_freq / pred / podf;
+ err = (freq - act_freq) * 100 / freq;
+ debug("root=%d[%u] freq=%u pred=%u podf=%u act=%u err=%d\n",
+ nfc_clk_sel, root_freq, freq, pred, podf, act_freq, err);
+ if (act_freq > freq)
+ continue;
+ if (err < min_err) {
+ nfc_val = (podf - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
+ nfc_val |= (pred - 1) << MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
+ nfc_val |= nfc_clk_sel << MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
+ min_err = err;
+ if (err == 0)
+ break;
+ }
+ }
+
+ if (nfc_val == ~0 || min_err > 10)
+ return -EINVAL;
+
+ if ((cs2cdr & CS2CDR_ENFC_MASK) != nfc_val) {
+ debug("changing cs2cdr from %08x to %08x\n", cs2cdr,
+ (cs2cdr & ~CS2CDR_ENFC_MASK) | nfc_val);
+ __raw_writel((cs2cdr & ~CS2CDR_ENFC_MASK) | nfc_val,
+ &imx_ccm->cs2cdr);
+ } else {
+ debug("Leaving cs2cdr unchanged [%08x]\n", cs2cdr);
+ }
+ return 0;
+ }
+
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
static u32 get_mmdc_ch0_clk(void)
{
u32 cbcmr = __raw_readl(&imx_ccm->cbcmr);
switch ((cbcmr & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) >>
MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET) {
case 0:
-- freq = decode_pll(PLL_BUS, MXC_HCLK);
++ freq = decode_pll(PLL_528, MXC_HCLK);
break;
case 1:
- freq = mxc_get_pll_pfd(PLL_BUS, 2);
- freq = PLL2_PFD2_FREQ;
++ freq = mxc_get_pll_pfd(PLL_528, 2);
break;
case 2:
- freq = mxc_get_pll_pfd(PLL_BUS, 0);
- freq = PLL2_PFD0_FREQ;
++ freq = mxc_get_pll_pfd(PLL_528, 0);
break;
case 3:
- freq = PLL2_PFD2_DIV_FREQ;
+ /* static / 2 divider */
- freq = mxc_get_pll_pfd(PLL_BUS, 2) / 2;
++ freq = mxc_get_pll_pfd(PLL_528, 2) / 2;
}
return freq / (podf + 1);
}
#endif
+#ifdef CONFIG_MX6SX
+/* qspi_num can be from 0 - 1 */
+void enable_qspi_clk(int qspi_num)
+{
+ u32 reg = 0;
+ /* Enable QuadSPI clock */
+ switch (qspi_num) {
+ case 0:
+ /* disable the clock gate */
+ clrbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_QSPI1_MASK);
+
+ /* set 50M : (50 = 396 / 2 / 4) */
+ reg = readl(&imx_ccm->cscmr1);
+ reg &= ~(MXC_CCM_CSCMR1_QSPI1_PODF_MASK |
+ MXC_CCM_CSCMR1_QSPI1_CLK_SEL_MASK);
+ reg |= ((1 << MXC_CCM_CSCMR1_QSPI1_PODF_OFFSET) |
+ (2 << MXC_CCM_CSCMR1_QSPI1_CLK_SEL_OFFSET));
+ writel(reg, &imx_ccm->cscmr1);
+
+ /* enable the clock gate */
+ setbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_QSPI1_MASK);
+ break;
+ case 1:
+ /*
+ * disable the clock gate
+ * QSPI2 and GPMI_BCH_INPUT_GPMI_IO share the same clock gate,
+ * disable both of them.
+ */
+ clrbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
+
+ /* set 50M : (50 = 396 / 2 / 4) */
+ reg = readl(&imx_ccm->cs2cdr);
+ reg &= ~(MXC_CCM_CS2CDR_QSPI2_CLK_PODF_MASK |
+ MXC_CCM_CS2CDR_QSPI2_CLK_PRED_MASK |
+ MXC_CCM_CS2CDR_QSPI2_CLK_SEL_MASK);
+ reg |= (MXC_CCM_CS2CDR_QSPI2_CLK_PRED(0x1) |
+ MXC_CCM_CS2CDR_QSPI2_CLK_SEL(0x3));
+ writel(reg, &imx_ccm->cs2cdr);
+
+ /*enable the clock gate*/
+ setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_QSPI2_ENFC_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+#ifdef CONFIG_FEC_MXC
+int enable_fec_anatop_clock(enum enet_freq freq)
+{
+ u32 reg = 0;
+ s32 timeout = 100000;
+
+ struct anatop_regs __iomem *anatop =
+ (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
+
+ if (freq < ENET_25MHZ || freq > ENET_125MHZ)
+ return -EINVAL;
+
+ reg = readl(&anatop->pll_enet);
+ reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
+ reg |= freq;
+
+ if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) ||
+ (!(reg & BM_ANADIG_PLL_ENET_LOCK))) {
+ reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;
+ writel(reg, &anatop->pll_enet);
+ while (timeout--) {
+ if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK)
+ break;
+ }
+ if (timeout < 0)
+ return -ETIMEDOUT;
+ }
+
+ /* Enable FEC clock */
+ reg |= BM_ANADIG_PLL_ENET_ENABLE;
+ reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
+ writel(reg, &anatop->pll_enet);
+
+#ifdef CONFIG_MX6SX
+ /*
+ * Set enet ahb clock to 200MHz
+ * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB
+ */
+ reg = readl(&imx_ccm->chsccdr);
+ reg &= ~(MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_MASK
+ | MXC_CCM_CHSCCDR_ENET_PODF_MASK
+ | MXC_CCM_CHSCCDR_ENET_CLK_SEL_MASK);
+ /* PLL2 PFD2 */
+ reg |= (4 << MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_OFFSET);
+ /* Div = 2*/
+ reg |= (1 << MXC_CCM_CHSCCDR_ENET_PODF_OFFSET);
+ reg |= (0 << MXC_CCM_CHSCCDR_ENET_CLK_SEL_OFFSET);
+ writel(reg, &imx_ccm->chsccdr);
+
+ /* Enable enet system clock */
+ reg = readl(&imx_ccm->CCGR3);
+ reg |= MXC_CCM_CCGR3_ENET_MASK;
+ writel(reg, &imx_ccm->CCGR3);
+#endif
+ return 0;
+}
+#endif
+
static u32 get_usdhc_clk(u32 port)
{
u32 root_freq = 0, usdhc_podf = 0, clk_sel = 0;
}
if (clk_sel)
- root_freq = mxc_get_pll_pfd(PLL_BUS, 0);
- root_freq = PLL2_PFD0_FREQ;
++ root_freq = mxc_get_pll_pfd(PLL_528, 0);
else
- root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
- root_freq = PLL2_PFD2_FREQ;
++ root_freq = mxc_get_pll_pfd(PLL_528, 2);
return root_freq / (usdhc_podf + 1);
}
u32 imx_get_fecclk(void)
{
- return decode_pll(PLL_ENET, MXC_HCLK);
+ return mxc_get_clock(MXC_IPG_CLK);
}
-int enable_sata_clock(void)
+static int enable_enet_pll(uint32_t en)
{
- struct mxc_ccm_reg *const imx_ccm
- = (struct mxc_ccm_reg *) CCM_BASE_ADDR;
+ u32 reg;
s32 timeout = 100000;
- u32 reg = 0;
- /* Enable sata clock */
- reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
- reg |= MXC_CCM_CCGR5_SATA_MASK;
- writel(reg, &imx_ccm->CCGR5);
-
/* Enable PLLs */
- reg = readl(&imx_ccm->analog_pll_enet);
- reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN;
- writel(reg, &imx_ccm->analog_pll_enet);
- reg |= BM_ANADIG_PLL_SYS_ENABLE;
+ reg = readl(&anatop->pll_enet);
+ reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;
+ writel(reg, &anatop->pll_enet);
+ reg |= BM_ANADIG_PLL_ENET_ENABLE;
while (timeout--) {
- if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_SYS_LOCK)
+ if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK)
break;
}
if (timeout <= 0)
return -EIO;
- reg &= ~BM_ANADIG_PLL_SYS_BYPASS;
- writel(reg, &imx_ccm->analog_pll_enet);
+ reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
+ writel(reg, &anatop->pll_enet);
- reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
+ reg |= en;
- writel(reg, &imx_ccm->analog_pll_enet);
+ writel(reg, &anatop->pll_enet);
+ return 0;
+}
+
+#ifndef CONFIG_MX6SX
+static void ungate_sata_clock(void)
+{
+ struct mxc_ccm_reg *const imx_ccm =
+ (struct mxc_ccm_reg *)CCM_BASE_ADDR;
- return 0 ;
+ /* Enable SATA clock. */
+ setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
+}
+#endif
+
+static void ungate_pcie_clock(void)
+{
+ struct mxc_ccm_reg *const imx_ccm =
+ (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ /* Enable PCIe clock. */
+ setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_PCIE_MASK);
+}
+
+#ifndef CONFIG_MX6SX
+int enable_sata_clock(void)
+{
+ ungate_sata_clock();
+ return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA);
+}
+
+void disable_sata_clock(void)
+{
+ struct mxc_ccm_reg *const imx_ccm =
+ (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ clrbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
+}
+#endif
+
+int enable_pcie_clock(void)
+{
+ struct anatop_regs *anatop_regs =
+ (struct anatop_regs *)ANATOP_BASE_ADDR;
+ struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ u32 lvds1_clk_sel;
+
+ /*
+ * Here be dragons!
+ *
+ * The register ANATOP_MISC1 is not documented in the Freescale
+ * MX6RM. The register that is mapped in the ANATOP space and
+ * marked as ANATOP_MISC1 is actually documented in the PMU section
+ * of the datasheet as PMU_MISC1.
+ *
+ * Switch LVDS clock source to SATA (0xb) on mx6q/dl or PCI (0xa) on
+ * mx6sx, disable clock INPUT and enable clock OUTPUT. This is important
+ * for PCI express link that is clocked from the i.MX6.
+ */
+#define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12)
+#define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10)
+#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK 0x0000001F
+#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_PCIE_REF 0xa
+#define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_SATA_REF 0xb
+
+ if (is_cpu_type(MXC_CPU_MX6SX))
+ lvds1_clk_sel = ANADIG_ANA_MISC1_LVDS1_CLK_SEL_PCIE_REF;
+ else
+ lvds1_clk_sel = ANADIG_ANA_MISC1_LVDS1_CLK_SEL_SATA_REF;
+
+ clrsetbits_le32(&anatop_regs->ana_misc1,
+ ANADIG_ANA_MISC1_LVDSCLK1_IBEN |
+ ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK,
+ ANADIG_ANA_MISC1_LVDSCLK1_OBEN | lvds1_clk_sel);
+
+ /* PCIe reference clock sourced from AXI. */
+ clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL);
+
+ /* Party time! Ungate the clock to the PCIe. */
+#ifndef CONFIG_MX6SX
+ ungate_sata_clock();
+#endif
+ ungate_pcie_clock();
+
+ return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA |
+ BM_ANADIG_PLL_ENET_ENABLE_PCIE);
+}
+
+#ifdef CONFIG_SECURE_BOOT
+void hab_caam_clock_enable(unsigned char enable)
+{
+ u32 reg;
+
+ /* CG4 ~ CG6, CAAM clocks */
+ reg = __raw_readl(&imx_ccm->CCGR0);
+ if (enable)
+ reg |= (MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK |
+ MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
+ MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK);
+ else
+ reg &= ~(MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK |
+ MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
+ MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK);
+ __raw_writel(reg, &imx_ccm->CCGR0);
+
+ /* EMI slow clk */
+ reg = __raw_readl(&imx_ccm->CCGR6);
+ if (enable)
+ reg |= MXC_CCM_CCGR6_EMI_SLOW_MASK;
+ else
+ reg &= ~MXC_CCM_CCGR6_EMI_SLOW_MASK;
+ __raw_writel(reg, &imx_ccm->CCGR6);
+}
+#endif
+
+static void enable_pll3(void)
+{
+ struct anatop_regs __iomem *anatop =
+ (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
+
+ /* make sure pll3 is enabled */
+ if ((readl(&anatop->usb1_pll_480_ctrl) &
- BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0) {
++ BM_ANADIG_USB_PLL_480_CTRL_LOCK) == 0) {
+ /* enable pll's power */
- writel(BM_ANADIG_USB1_PLL_480_CTRL_POWER,
++ writel(BM_ANADIG_USB_PLL_480_CTRL_POWER,
+ &anatop->usb1_pll_480_ctrl_set);
+ writel(0x80, &anatop->ana_misc2_clr);
+ /* wait for pll lock */
+ while ((readl(&anatop->usb1_pll_480_ctrl) &
- BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0)
++ BM_ANADIG_USB_PLL_480_CTRL_LOCK) == 0)
+ ;
+ /* disable bypass */
- writel(BM_ANADIG_USB1_PLL_480_CTRL_BYPASS,
++ writel(BM_ANADIG_USB_PLL_480_CTRL_BYPASS,
+ &anatop->usb1_pll_480_ctrl_clr);
+ /* enable pll output */
- writel(BM_ANADIG_USB1_PLL_480_CTRL_ENABLE,
++ writel(BM_ANADIG_USB_PLL_480_CTRL_ENABLE,
+ &anatop->usb1_pll_480_ctrl_set);
+ }
+}
+
+void enable_thermal_clk(void)
+{
+ enable_pll3();
}
+ void ipu_clk_enable(void)
+ {
+ u32 reg = readl(&imx_ccm->CCGR3);
+ reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK;
+ writel(reg, &imx_ccm->CCGR3);
+ }
+
+ void ipu_clk_disable(void)
+ {
+ u32 reg = readl(&imx_ccm->CCGR3);
+ reg &= ~MXC_CCM_CCGR3_IPU1_IPU_MASK;
+ writel(reg, &imx_ccm->CCGR3);
+ }
+
+ void ipu_di_clk_enable(int di)
+ {
+ switch (di) {
+ case 0:
+ setbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK);
+ break;
+ case 1:
+ setbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_IPU1_IPU_DI1_MASK);
+ break;
+ default:
+ printf("%s: Invalid DI index %d\n", __func__, di);
+ }
+ }
+
+ void ipu_di_clk_disable(int di)
+ {
+ switch (di) {
+ case 0:
+ clrbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK);
+ break;
+ case 1:
+ clrbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_IPU1_IPU_DI1_MASK);
+ break;
+ default:
+ printf("%s: Invalid DI index %d\n", __func__, di);
+ }
+ }
+
+ void ldb_clk_enable(int ldb)
+ {
+ switch (ldb) {
+ case 0:
+ setbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_LDB_DI0_MASK);
+ break;
+ case 1:
+ setbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_LDB_DI1_MASK);
+ break;
+ default:
+ printf("%s: Invalid LDB index %d\n", __func__, ldb);
+ }
+ }
+
+ void ldb_clk_disable(int ldb)
+ {
+ switch (ldb) {
+ case 0:
+ clrbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_LDB_DI0_MASK);
+ break;
+ case 1:
+ clrbits_le32(&imx_ccm->CCGR3,
+ MXC_CCM_CCGR3_LDB_DI1_MASK);
+ break;
+ default:
+ printf("%s: Invalid LDB index %d\n", __func__, ldb);
+ }
+ }
+
+ void ocotp_clk_enable(void)
+ {
+ u32 reg = readl(&imx_ccm->CCGR2);
+ reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
+ writel(reg, &imx_ccm->CCGR2);
+ }
+
+ void ocotp_clk_disable(void)
+ {
+ u32 reg = readl(&imx_ccm->CCGR2);
+ reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
+ writel(reg, &imx_ccm->CCGR2);
+ }
+
unsigned int mxc_get_clock(enum mxc_clock clk)
{
switch (clk) {
return get_usdhc_clk(3);
case MXC_SATA_CLK:
return get_ahb_clk();
- break;
+ case MXC_NFC_CLK:
+ return get_nfc_clk();
+ default:
+ printf("Unsupported MXC CLK: %d\n", clk);
}
- return -1;
+ return 0;
}
+ static inline int gcd(int m, int n)
+ {
+ int t;
+ while (m > 0) {
+ if (n > m) {
+ t = m;
+ m = n;
+ n = t;
+ } /* swap */
+ m -= n;
+ }
+ return n;
+ }
+
+ /* Config CPU clock */
+ static int set_arm_clk(u32 ref, u32 freq_khz)
+ {
+ int d;
+ int div = 0;
+ int mul = 0;
+ u32 min_err = ~0;
+ u32 reg;
+
+ if (freq_khz > ref / 1000 * 108 / 2 || freq_khz < ref / 1000 * 54 / 8 / 2) {
+ printf("Frequency %u.%03uMHz is out of range: %u.%03u..%u.%03u\n",
+ freq_khz / 1000, freq_khz % 1000,
+ 54 * ref / 1000000 / 8 / 2, 54 * ref / 1000 / 8 / 2 % 1000,
+ 108 * ref / 1000000 / 2, 108 * ref / 1000 / 2 % 1000);
+ return -EINVAL;
+ }
+
+ for (d = DIV_ROUND_UP(648000, freq_khz); d <= 8; d++) {
+ int m = freq_khz * 2 * d / (ref / 1000);
+ u32 f;
+ u32 err;
+
+ if (m > 108) {
+ debug("%s@%d: d=%d m=%d\n", __func__, __LINE__,
+ d, m);
+ break;
+ }
+
+ f = ref * m / d / 2;
+ if (f > freq_khz * 1000) {
+ debug("%s@%d: d=%d m=%d f=%u freq=%u\n", __func__, __LINE__,
+ d, m, f, freq_khz);
+ if (--m < 54)
+ return -EINVAL;
+ f = ref * m / d / 2;
+ }
+ err = freq_khz * 1000 - f;
+ debug("%s@%d: d=%d m=%d f=%u freq=%u err=%d\n", __func__, __LINE__,
+ d, m, f, freq_khz, err);
+ if (err < min_err) {
+ mul = m;
+ div = d;
+ min_err = err;
+ if (err == 0)
+ break;
+ }
+ }
+ if (min_err == ~0)
+ return -EINVAL;
+ debug("Setting M=%3u D=%2u for %u.%03uMHz (actual: %u.%03uMHz)\n",
+ mul, div, freq_khz / 1000, freq_khz % 1000,
+ ref * mul / 2 / div / 1000000, ref * mul / 2 / div / 1000 % 1000);
+
+ reg = readl(&anatop->pll_arm);
+ debug("anadig_pll_arm=%08x -> %08x\n",
+ reg, (reg & ~0x7f) | mul);
+
+ reg |= 1 << 16;
+ writel(reg, &anatop->pll_arm); /* bypass PLL */
+
+ reg = (reg & ~0x7f) | mul;
+ writel(reg, &anatop->pll_arm);
+
+ writel(div - 1, &imx_ccm->cacrr);
+
+ reg &= ~(1 << 16);
+ writel(reg, &anatop->pll_arm); /* disable PLL bypass */
+
+ return 0;
+ }
+
/*
- * Dump some core clockes.
+ * This function assumes the expected core clock has to be changed by
+ * modifying the PLL. This is NOT true always but for most of the times,
+ * it is. So it assumes the PLL output freq is the same as the expected
+ * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
+ * In the latter case, it will try to increase the presc value until
+ * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
+ * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
+ * on the targeted PLL and reference input clock to the PLL. Lastly,
+ * it sets the register based on these values along with the dividers.
+ * Note 1) There is no value checking for the passed-in divider values
+ * so the caller has to make sure those values are sensible.
+ * 2) Also adjust the NFC divider such that the NFC clock doesn't
+ * exceed NFC_CLK_MAX.
+ * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
+ * 177MHz for higher voltage, this function fixes the max to 133MHz.
+ * 4) This function should not have allowed diag_printf() calls since
+ * the serial driver has been stoped. But leave then here to allow
+ * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
*/
- int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
- {
- u32 freq;
- freq = decode_pll(PLL_SYS, MXC_HCLK);
- printf("PLL_SYS %8d MHz\n", freq / 1000000);
- freq = decode_pll(PLL_BUS, MXC_HCLK);
- printf("PLL_BUS %8d MHz\n", freq / 1000000);
- freq = decode_pll(PLL_USBOTG, MXC_HCLK);
- printf("PLL_OTG %8d MHz\n", freq / 1000000);
- freq = decode_pll(PLL_ENET, MXC_HCLK);
- printf("PLL_NET %8d MHz\n", freq / 1000000);
+ int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk)
+ {
+ int ret;
+
+ freq *= 1000;
+
+ switch (clk) {
+ case MXC_ARM_CLK:
+ ret = set_arm_clk(ref, freq);
+ break;
+
+ case MXC_NFC_CLK:
+ ret = set_nfc_clk(ref, freq);
+ break;
+
+ default:
+ printf("Warning: Unsupported or invalid clock type: %d\n",
+ clk);
+ return -EINVAL;
+ }
+
+ return ret;
+ }
+
+ /*
+ * Dump some core clocks.
+ */
+ #define print_pll(pll) { \
+ u32 __pll = decode_pll(pll, MXC_HCLK); \
+ printf("%-12s %4d.%03d MHz\n", #pll, \
+ __pll / 1000000, __pll / 1000 % 1000); \
+ }
+
+ #define MXC_IPG_PER_CLK MXC_IPG_PERCLK
- print_pll(PLL_BUS);
+ #define print_clk(clk) { \
+ u32 __clk = mxc_get_clock(MXC_##clk##_CLK); \
+ printf("%-12s %4d.%03d MHz\n", #clk, \
+ __clk / 1000000, __clk / 1000 % 1000); \
+ }
+
+ #define print_pfd(pll, pfd) { \
+ u32 __pfd = readl(&anatop->pfd_##pll); \
+ if (__pfd & (0x80 << 8 * pfd)) { \
+ printf("PFD_%s[%d] OFF\n", #pll, pfd); \
+ } else { \
+ __pfd = (__pfd >> 8 * pfd) & 0x3f; \
+ printf("PFD_%s[%d] %4d.%03d MHz\n", #pll, pfd, \
+ pll * 18 / __pfd, \
+ pll * 18 * 1000 / __pfd % 1000); \
+ } \
+ }
+
+ static void do_mx6_showclocks(void)
+ {
+ print_pll(PLL_ARM);
++ print_pll(PLL_528);
+ print_pll(PLL_USBOTG);
+ print_pll(PLL_AUDIO);
+ print_pll(PLL_VIDEO);
+ print_pll(PLL_ENET);
+ print_pll(PLL_USB2);
printf("\n");
- printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
- printf("UART %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000);
- #ifdef CONFIG_MXC_SPI
- printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000);
- #endif
- printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
- printf("AXI %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000);
- printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
- printf("USDHC1 %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000);
- printf("USDHC2 %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000);
- printf("USDHC3 %8d kHz\n", mxc_get_clock(MXC_ESDHC3_CLK) / 1000);
- printf("USDHC4 %8d kHz\n", mxc_get_clock(MXC_ESDHC4_CLK) / 1000);
- printf("EMI SLOW %8d kHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK) / 1000);
- printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
- return 0;
+ print_pfd(480, 0);
+ print_pfd(480, 1);
+ print_pfd(480, 2);
+ print_pfd(480, 3);
+ print_pfd(528, 0);
+ print_pfd(528, 1);
+ print_pfd(528, 2);
+ printf("\n");
+
+ print_clk(IPG);
+ print_clk(UART);
+ print_clk(CSPI);
+ print_clk(AHB);
+ print_clk(AXI);
+ print_clk(DDR);
+ print_clk(ESDHC);
+ print_clk(ESDHC2);
+ print_clk(ESDHC3);
+ print_clk(ESDHC4);
+ print_clk(EMI_SLOW);
+ print_clk(NFC);
+ print_clk(IPG_PER);
+ print_clk(ARM);
+ }
+
+ static struct clk_lookup {
+ const char *name;
+ unsigned int index;
+ } mx6_clk_lookup[] = {
+ { "arm", MXC_ARM_CLK, },
+ { "nfc", MXC_NFC_CLK, },
+ };
+
+ int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int i;
+ unsigned long freq;
+ unsigned long ref = ~0UL;
+
+ if (argc < 2) {
+ do_mx6_showclocks();
+ return CMD_RET_SUCCESS;
+ } else if (argc == 2 || argc > 4) {
+ return CMD_RET_USAGE;
+ }
+
+ freq = simple_strtoul(argv[2], NULL, 0);
+ if (freq == 0) {
+ printf("Invalid clock frequency %lu\n", freq);
+ return CMD_RET_FAILURE;
+ }
+ if (argc > 3) {
+ ref = simple_strtoul(argv[3], NULL, 0);
+ }
+ for (i = 0; i < ARRAY_SIZE(mx6_clk_lookup); i++) {
+ if (strcasecmp(argv[1], mx6_clk_lookup[i].name) == 0) {
+ switch (mx6_clk_lookup[i].index) {
+ case MXC_ARM_CLK:
+ if (argc > 3)
+ return CMD_RET_USAGE;
- ref = CONFIG_SYS_MX6_HCLK;
++ ref = MXC_HCLK;
+ break;
+
+ case MXC_NFC_CLK:
+ if (argc > 3 && ref > 3) {
+ printf("Invalid clock selector value: %lu\n", ref);
+ return CMD_RET_FAILURE;
+ }
+ break;
+ }
+ printf("Setting %s clock to %lu MHz\n",
+ mx6_clk_lookup[i].name, freq);
+ if (mxc_set_clock(ref, freq, mx6_clk_lookup[i].index))
+ break;
+ freq = mxc_get_clock(mx6_clk_lookup[i].index);
+ printf("%s clock set to %lu.%03lu MHz\n",
+ mx6_clk_lookup[i].name,
+ freq / 1000000, freq / 1000 % 1000);
+ return CMD_RET_SUCCESS;
+ }
+ }
+ if (i == ARRAY_SIZE(mx6_clk_lookup)) {
+ printf("clock %s not found; supported clocks are:\n", argv[1]);
+ for (i = 0; i < ARRAY_SIZE(mx6_clk_lookup); i++) {
+ printf("\t%s\n", mx6_clk_lookup[i].name);
+ }
+ } else {
+ printf("Failed to set clock %s to %s MHz\n",
+ argv[1], argv[2]);
+ }
+ return CMD_RET_FAILURE;
}
+#ifndef CONFIG_MX6SX
+void enable_ipu_clock(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ int reg;
+ reg = readl(&mxc_ccm->CCGR3);
+ reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK;
+ writel(reg, &mxc_ccm->CCGR3);
+}
+#endif
/***************************************************/
U_BOOT_CMD(
- clocks, CONFIG_SYS_MAXARGS, 1, do_mx6_showclocks,
- "display clocks",
- ""
+ clocks, 4, 0, do_clocks,
+ "display/set clocks",
+ " - display clock settings\n"
+ "clocks <clkname> <freq> - set clock <clkname> to <freq> MHz"
);
*/
#include <common.h>
-#include <div64.h>
+#include <asm/armv7.h>
+#include <asm/bootm.h>
+#include <asm/pl310.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
+ #include <asm/arch/crm_regs.h>
+ #include <asm/arch/regs-ocotp.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/imx-common/boot_mode.h>
#include <asm/imx-common/dma.h>
#include <stdbool.h>
-#ifdef CONFIG_VIDEO_IPUV3
+#include <asm/arch/mxc_hdmi.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/bootm.h>
+#include <dm.h>
+#include <imx_thermal.h>
++#include <div64.h>
+ #include <ipu.h>
-#endif
+
+ DECLARE_GLOBAL_DATA_PTR;
+
++#define __data __attribute__((section(".data")))
++
+ #ifdef CONFIG_MX6_TEMPERATURE_MIN
+ #define TEMPERATURE_MIN CONFIG_MX6_TEMPERATURE_MIN
+ #else
+ #define TEMPERATURE_MIN (-40)
+ #endif
+ #ifdef CONFIG_MX6_TEMPERATURE_HOT
+ #define TEMPERATURE_HOT CONFIG_MX6_TEMPERATURE_HOT
+ #else
+ #define TEMPERATURE_HOT 80
+ #endif
+ #ifdef CONFIG_MX6_TEMPERATURE_MAX
+ #define TEMPERATURE_MAX CONFIG_MX6_TEMPERATURE_MAX
+ #else
+ #define TEMPERATURE_MAX 125
+ #endif
+ #define TEMP_AVG_COUNT 5
+ #define TEMP_WARN_THRESHOLD 5
-#define __data __attribute__((section(".data")))
+enum ldo_reg {
+ LDO_ARM,
+ LDO_SOC,
+ LDO_PU,
+};
struct scu_regs {
u32 ctrl;
u32 fpga_rev;
};
-#ifdef CONFIG_HW_WATCHDOG
-#define wdog_base ((void *)WDOG1_BASE_ADDR)
-#define WDOG_WCR 0x00
-#define WCR_WDE (1 << 2)
-#define WDOG_WSR 0x02
+#if defined(CONFIG_IMX6_THERMAL)
+static const struct imx_thermal_plat imx6_thermal_plat = {
+ .regs = (void *)ANATOP_BASE_ADDR,
+ .fuse_bank = 1,
+ .fuse_word = 6,
+};
-void hw_watchdog_reset(void)
-{
- if (readw(wdog_base + WDOG_WCR) & WCR_WDE) {
- static u16 __data toggle = 0xaaaa;
- static int __data first = 1;
+U_BOOT_DEVICE(imx6_thermal) = {
+ .name = "imx_thermal",
+ .platdata = &imx6_thermal_plat,
+};
+#endif
- if (first) {
- printf("Watchdog active\n");
- first = 0;
- }
- writew(toggle, wdog_base + WDOG_WSR);
- toggle ^= 0xffff;
- }
+u32 get_nr_cpus(void)
+{
+ struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
+ return readl(&scu->config) & 3;
}
-#endif
u32 get_cpu_rev(void)
{
if (type != MXC_CPU_MX6SL) {
reg = readl(&anatop->digprog);
+ struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
+ u32 cfg = readl(&scu->config) & 3;
type = ((reg >> 16) & 0xff);
if (type == MXC_CPU_MX6DL) {
- struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
- u32 cfg = readl(&scu->config) & 3;
-
if (!cfg)
type = MXC_CPU_MX6SOLO;
}
+
+ if (type == MXC_CPU_MX6Q) {
+ if (cfg == 1)
+ type = MXC_CPU_MX6D;
+ }
+
}
reg &= 0xff; /* mx6 silicon revision */
return (type << 12) | (reg + 0x10);
if (type == MXC_CPU_MX6SOLO)
cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF);
+ if (type == MXC_CPU_MX6D)
+ cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF);
+
return cpurev;
}
#endif
void init_aips(void)
{
struct aipstz_regs *aips1, *aips2;
+#ifdef CONFIG_MX6SX
+ struct aipstz_regs *aips3;
+#endif
aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;
aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;
+#ifdef CONFIG_MX6SX
+ aips3 = (struct aipstz_regs *)AIPS3_BASE_ADDR;
+#endif
/*
* Set all MPROTx to be non-bufferable, trusted for R/W,
writel(0x00000000, &aips2->opacr2);
writel(0x00000000, &aips2->opacr3);
writel(0x00000000, &aips2->opacr4);
+
+#ifdef CONFIG_MX6SX
+ /*
+ * Set all MPROTx to be non-bufferable, trusted for R/W,
+ * not forced to user-mode.
+ */
+ writel(0x77777777, &aips3->mprot0);
+ writel(0x77777777, &aips3->mprot1);
+
+ /*
+ * Set all OPACRx to be non-bufferable, not require
+ * supervisor privilege level for access,allow for
+ * write access and untrusted master access.
+ */
+ writel(0x00000000, &aips3->opacr0);
+ writel(0x00000000, &aips3->opacr1);
+ writel(0x00000000, &aips3->opacr2);
+ writel(0x00000000, &aips3->opacr3);
+ writel(0x00000000, &aips3->opacr4);
+#endif
+}
+
+static void clear_ldo_ramp(void)
+{
+ struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
+ int reg;
+
+ /* ROM may modify LDO ramp up time according to fuse setting, so in
+ * order to be in the safe side we neeed to reset these settings to
+ * match the reset value: 0'b00
+ */
+ reg = readl(&anatop->ana_misc2);
+ reg &= ~(0x3f << 24);
+ writel(reg, &anatop->ana_misc2);
}
/*
- * Set the VDDSOC
+ * Set the PMU_REG_CORE register
*
- * Mask out the REG_CORE[22:18] bits (REG2_TRIG) and set
- * them to the specified millivolt level.
+ * Set LDO_SOC/PU/ARM regulators to the specified millivolt level.
* Possible values are from 0.725V to 1.450V in steps of
* 0.025V (25mV).
*/
-static void set_vddsoc(u32 mv)
+static int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
{
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
- u32 val, reg = readl(&anatop->reg_core);
+ u32 val, step, old, reg = readl(&anatop->reg_core);
+ u8 shift;
if (mv < 725)
val = 0x00; /* Power gated off */
else
val = (mv - 700) / 25;
+ clear_ldo_ramp();
+
+ switch (ldo) {
+ case LDO_SOC:
+ shift = 18;
+ break;
+ case LDO_PU:
+ shift = 9;
+ break;
+ case LDO_ARM:
+ shift = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ old = (reg & (0x1F << shift)) >> shift;
+ step = abs(val - old);
+ if (step == 0)
+ return 0;
+
+ reg = (reg & ~(0x1F << shift)) | (val << shift);
+ writel(reg, &anatop->reg_core);
+
/*
- * Mask out the REG_CORE[22:18] bits (REG2_TRIG)
- * and set them to the calculated value (0.7V + val * 0.25V)
+ * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per
+ * step
*/
- reg = (reg & ~(0x1F << 18)) | (val << 18);
- writel(reg, &anatop->reg_core);
+ udelay(3 * step);
+
+ return 0;
}
+ static u32 __data thermal_calib;
+
+ #define FACTOR0 10000000
+ #define FACTOR1 15976
+ #define FACTOR2 4297157
+
+ int raw_to_celsius(unsigned int raw, unsigned int raw_25c, unsigned int raw_hot,
+ unsigned int hot_temp)
+ {
+ int temperature;
+
+ if (raw_hot != 0 && hot_temp != 0) {
+ unsigned int raw_n40c, ratio;
+
+ ratio = ((raw_25c - raw_hot) * 100) / (hot_temp - 25);
+ raw_n40c = raw_25c + (13 * ratio) / 20;
+ if (raw <= raw_n40c)
+ temperature = (raw_n40c - raw) * 100 / ratio - 40;
+ else
+ temperature = TEMPERATURE_MIN;
+ } else {
+ u64 temp64 = FACTOR0;
+ unsigned int c1, c2;
+ /*
+ * Derived from linear interpolation:
+ * slope = 0.4297157 - (0.0015976 * 25C fuse)
+ * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
+ * (Nmeas - n1) / (Tmeas - t1) = slope
+ * We want to reduce this down to the minimum computation necessary
+ * for each temperature read. Also, we want Tmeas in millicelsius
+ * and we don't want to lose precision from integer division. So...
+ * Tmeas = (Nmeas - n1) / slope + t1
+ * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
+ * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
+ * Let constant c1 = (-1000 / slope)
+ * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
+ * Let constant c2 = n1 *c1 + 1000 * t1
+ * milli_Tmeas = c2 - Nmeas * c1
+ */
+ temp64 *= 1000;
+ do_div(temp64, FACTOR1 * raw_25c - FACTOR2);
+ c1 = temp64;
+ c2 = raw_25c * c1 + 1000 * 25;
+ temperature = (c2 - raw * c1) / 1000;
+ }
+ return temperature;
+ }
+
+ int read_cpu_temperature(void)
+ {
+ unsigned int reg, tmp, i;
+ unsigned int raw_25c, raw_hot, hot_temp;
+ int temperature;
+ struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
+ struct mx6_ocotp_regs *const ocotp_regs = (void *)OCOTP_BASE_ADDR;
+
+ if (!thermal_calib) {
+ ocotp_clk_enable();
+ writel(1, &ocotp_regs->hw_ocotp_read_ctrl);
+ thermal_calib = readl(&ocotp_regs->hw_ocotp_ana1);
+ writel(0, &ocotp_regs->hw_ocotp_read_ctrl);
+ ocotp_clk_disable();
+ }
+
+ if (thermal_calib == 0 || thermal_calib == 0xffffffff)
+ return TEMPERATURE_MIN;
+
+ /* Fuse data layout:
+ * [31:20] sensor value @ 25C
+ * [19:8] sensor value of hot
+ * [7:0] hot temperature value */
+ raw_25c = thermal_calib >> 20;
+ raw_hot = (thermal_calib & 0xfff00) >> 8;
+ hot_temp = thermal_calib & 0xff;
+
+ /* now we only using single measure, every time we measure
+ * the temperature, we will power on/off the anadig module
+ */
+ writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr);
+ writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
+
+ /* write measure freq */
+ writel(327, &anatop->tempsense1);
+ writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr);
+ writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
+ writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set);
+
+ /* average the temperature value over multiple readings */
+ for (i = 0; i < TEMP_AVG_COUNT; i++) {
+ static int failed;
+ int limit = 100;
+
+ while ((readl(&anatop->tempsense0) &
+ BM_ANADIG_TEMPSENSE0_FINISHED) == 0) {
+ udelay(10000);
+ if (--limit < 0)
+ break;
+ }
+ if ((readl(&anatop->tempsense0) &
+ BM_ANADIG_TEMPSENSE0_FINISHED) == 0) {
+ if (!failed) {
+ printf("Failed to read temp sensor\n");
+ failed = 1;
+ }
+ return 0;
+ }
+ failed = 0;
+ reg = (readl(&anatop->tempsense0) &
+ BM_ANADIG_TEMPSENSE0_TEMP_VALUE) >>
+ BP_ANADIG_TEMPSENSE0_TEMP_VALUE;
+ if (i == 0)
+ tmp = reg;
+ else
+ tmp = (tmp * i + reg) / (i + 1);
+ writel(BM_ANADIG_TEMPSENSE0_FINISHED,
+ &anatop->tempsense0_clr);
+ }
+
+ temperature = raw_to_celsius(tmp, raw_25c, raw_hot, hot_temp);
+
+ /* power down anatop thermal sensor */
+ writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set);
+ writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr);
+
+ return temperature;
+ }
+
+ int check_cpu_temperature(int boot)
+ {
+ static int __data max_temp;
+ int boot_limit = getenv_ulong("max_boot_temp", 10, TEMPERATURE_HOT);
+ int tmp = read_cpu_temperature();
+ bool first = true;
+
+ if (tmp < TEMPERATURE_MIN || tmp > TEMPERATURE_MAX) {
+ printf("Temperature: can't get valid data!\n");
+ return tmp;
+ }
+
+ if (!boot) {
+ if (tmp > boot_limit) {
+ printf("CPU is %d C, too hot, resetting...\n", tmp);
+ udelay(100000);
+ reset_cpu(0);
+ }
+ if (tmp > max_temp) {
+ if (tmp > boot_limit - TEMP_WARN_THRESHOLD)
+ printf("WARNING: CPU temperature %d C\n", tmp);
+ max_temp = tmp;
+ }
+ } else {
+ printf("Temperature: %d C, calibration data 0x%x\n",
+ tmp, thermal_calib);
+ while (tmp >= boot_limit) {
+ if (first) {
+ printf("CPU is %d C, too hot to boot, waiting...\n",
+ tmp);
+ first = false;
+ }
+ if (ctrlc())
+ break;
+ udelay(50000);
+ tmp = read_cpu_temperature();
+ if (tmp > boot_limit - TEMP_WARN_THRESHOLD && tmp != max_temp)
+ printf("WARNING: CPU temperature %d C\n", tmp);
+ max_temp = tmp;
+ }
+ }
+ return tmp;
+ }
+
static void imx_set_wdog_powerdown(bool enable)
{
struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
writew(enable, &wdog2->wmcr);
}
-#ifdef CONFIG_ARCH_CPU_INIT
+static void set_ahb_rate(u32 val)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ u32 reg, div;
+
+ div = get_periph_clk() / val - 1;
+ reg = readl(&mxc_ccm->cbcdr);
+
+ writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) |
+ (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr);
+}
+
+static void clear_mmdc_ch_mask(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ /* Clear MMDC channel mask */
+ writel(0, &mxc_ccm->ccdr);
+}
+
+#ifdef CONFIG_MX6SL
+static void set_preclk_from_osc(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ u32 reg;
+
+ reg = readl(&mxc_ccm->cscmr1);
+ reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
+ writel(reg, &mxc_ccm->cscmr1);
+}
+#endif
+
int arch_cpu_init(void)
{
init_aips();
- set_vddsoc(1200); /* Set VDDSOC to 1.2V */
+ /* Need to clear MMDC_CHx_MASK to make warm reset work. */
+ clear_mmdc_ch_mask();
+
+ /*
+ * When low freq boot is enabled, ROM will not set AHB
+ * freq, so we need to ensure AHB freq is 132MHz in such
+ * scenario.
+ */
+ if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
+ set_ahb_rate(132000000);
+
+ /* Set perclk to source from OSC 24MHz */
+#if defined(CONFIG_MX6SL)
+ set_preclk_from_osc();
+#endif
imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
- #ifdef CONFIG_APBH_DMA
- /* Start APBH DMA */
+ #ifdef CONFIG_VIDEO_IPUV3
+ gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3H;
+ #endif
+ #ifdef CONFIG_APBH_DMA
+ /* Timer is required for Initializing APBH DMA */
+ timer_init();
mxs_dma_init();
#endif
+
+ return 0;
+}
+
+int board_postclk_init(void)
+{
+ set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */
+
return 0;
}
-#endif
#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
{
+#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
+ enum dcache_option option = DCACHE_WRITETHROUGH;
+#else
+ enum dcache_option option = DCACHE_WRITEBACK;
+#endif
+
+ /* Avoid random hang when download by usb */
+ invalidate_dcache_all();
+
/* Enable D-cache. I-cache is already enabled in start.S */
dcache_enable();
+
+ /* Enable caching on OCRAM and ROM */
+ mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR,
+ ROMCP_ARB_END_ADDR,
+ option);
+ mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR,
+ IRAM_SIZE,
+ option);
}
#endif
u32 value = readl(&fuse->mac_addr_high);
mac[0] = (value >> 8);
- mac[1] = value ;
+ mac[1] = value;
value = readl(&fuse->mac_addr_low);
- mac[2] = value >> 24 ;
- mac[3] = value >> 16 ;
- mac[4] = value >> 8 ;
- mac[5] = value ;
-
+ mac[2] = value >> 24;
+ mac[3] = value >> 16;
+ mac[4] = value >> 8;
+ mac[5] = value;
}
#endif
/*
* cfg_val will be used for
* Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
- * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0]
- * to SBMR1, which will determine the boot device.
+ * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
+ * instead of SBMR1 to determine the boot device.
*/
const struct boot_mode soc_boot_modes[] = {
{"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
/* reserved value should start rom usb */
{"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)},
{"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)},
- {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
- {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
- {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
- {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
+ {"ecspi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
+ {"ecspi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
+ {"ecspi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
+ {"ecspi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
/* 4 bit bus width */
{"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
{"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
void s_init(void)
{
+ struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
+ struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ u32 mask480;
+ u32 mask528;
+ u32 reg, periph1, periph2;
+
+ if (is_cpu_type(MXC_CPU_MX6SX))
+ return;
+
+ /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
+ * to make sure PFD is working right, otherwise, PFDs may
+ * not output clock after reset, MX6DL and MX6SL have added 396M pfd
+ * workaround in ROM code, as bus clock need it
+ */
+
+ mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
+ ANATOP_PFD_CLKGATE_MASK(1) |
+ ANATOP_PFD_CLKGATE_MASK(2) |
+ ANATOP_PFD_CLKGATE_MASK(3);
+ mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
+ ANATOP_PFD_CLKGATE_MASK(3);
+
+ reg = readl(&ccm->cbcmr);
+ periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
+ >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET);
+ periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
+ >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
+
+ /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */
+ if ((periph2 != 0x2) && (periph1 != 0x2))
+ mask528 |= ANATOP_PFD_CLKGATE_MASK(0);
+
+ if ((periph2 != 0x1) && (periph1 != 0x1) &&
+ (periph2 != 0x3) && (periph1 != 0x3))
+ mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
+
+ writel(mask480, &anatop->pfd_480_set);
+ writel(mask528, &anatop->pfd_528_set);
+ writel(mask480, &anatop->pfd_480_clr);
+ writel(mask528, &anatop->pfd_528_clr);
+}
+
+#ifdef CONFIG_IMX_HDMI
+void imx_enable_hdmi_phy(void)
+{
+ struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+ u8 reg;
+ reg = readb(&hdmi->phy_conf0);
+ reg |= HDMI_PHY_CONF0_PDZ_MASK;
+ writeb(reg, &hdmi->phy_conf0);
+ udelay(3000);
+ reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
+ writeb(reg, &hdmi->phy_conf0);
+ udelay(3000);
+ reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
+ writeb(reg, &hdmi->phy_conf0);
+ writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
+}
+
+void imx_setup_hdmi(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+ int reg;
+
+ /* Turn on HDMI PHY clock */
+ reg = readl(&mxc_ccm->CCGR2);
+ reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK|
+ MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
+ writel(reg, &mxc_ccm->CCGR2);
+ writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
+ reg = readl(&mxc_ccm->chsccdr);
+ reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK|
+ MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK|
+ MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+ reg |= (CHSCCDR_PODF_DIVIDE_BY_3
+ << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
+ |(CHSCCDR_IPU_PRE_CLK_540M_PFD
+ << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+ writel(reg, &mxc_ccm->chsccdr);
+}
+#endif
+
+#ifndef CONFIG_SYS_L2CACHE_OFF
+#define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002
+void v7_outer_cache_enable(void)
+{
+ struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE;
+ unsigned int val;
+
+#if defined CONFIG_MX6SL
+ struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+ val = readl(&iomux->gpr[11]);
+ if (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM) {
+ /* L2 cache configured as OCRAM, reset it */
+ val &= ~IOMUXC_GPR11_L2CACHE_AS_OCRAM;
+ writel(val, &iomux->gpr[11]);
+ }
+#endif
+
+ /* Must disable the L2 before changing the latency parameters */
+ clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
+
+ writel(0x132, &pl310->pl310_tag_latency_ctrl);
+ writel(0x132, &pl310->pl310_data_latency_ctrl);
+
+ val = readl(&pl310->pl310_prefetch_ctrl);
+
+ /* Turn on the L2 I/D prefetch */
+ val |= 0x30000000;
+
+ /*
+ * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0
+ * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2
+ * But according to ARM PL310 errata: 752271
+ * ID: 752271: Double linefill feature can cause data corruption
+ * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2
+ * Workaround: The only workaround to this erratum is to disable the
+ * double linefill feature. This is the default behavior.
+ */
+
+#ifndef CONFIG_MX6Q
+ val |= 0x40800000;
+#endif
+ writel(val, &pl310->pl310_prefetch_ctrl);
+
+ val = readl(&pl310->pl310_power_ctrl);
+ val |= L2X0_DYNAMIC_CLK_GATING_EN;
+ val |= L2X0_STNDBY_MODE_EN;
+ writel(val, &pl310->pl310_power_ctrl);
+
+ setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
+}
+
+void v7_outer_cache_disable(void)
+{
+ struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE;
+
+ clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
}
+#endif /* !CONFIG_SYS_L2CACHE_OFF */
*/
#include <common.h>
+#include <ahci.h>
#include <spl.h>
#include <asm/omap_common.h>
#include <asm/arch/omap.h>
#include <asm/arch/mmc_host_def.h>
#include <asm/arch/sys_proto.h>
+#include <watchdog.h>
+#include <scsi.h>
DECLARE_GLOBAL_DATA_PTR;
* used. But it not correct to assume that romcode structure
* encoding would be same as u-boot. So use the defined offsets.
*/
- gd->arch.omap_boot_params.omap_bootdevice = boot_device =
- *((u8 *)(rom_params + BOOT_DEVICE_OFFSET));
+ boot_device = *((u8 *)(rom_params + BOOT_DEVICE_OFFSET));
+
+#if defined(BOOT_DEVICE_NAND_I2C)
+ /*
+ * Re-map NAND&I2C boot-device to the "normal" NAND boot-device.
+ * Otherwise the SPL boot IF can't handle this device correctly.
+ * Somehow booting with Hynix 4GBit NAND H27U4G8 on Siemens
+ * Draco leads to this boot-device passed to SPL from the BootROM.
+ */
+ if (boot_device == BOOT_DEVICE_NAND_I2C)
+ boot_device = BOOT_DEVICE_NAND;
+#endif
+ gd->arch.omap_boot_params.omap_bootdevice = boot_device;
gd->arch.omap_boot_params.ch_flags =
*((u8 *)(rom_params + CH_FLAGS_OFFSET));
if ((boot_device >= MMC_BOOT_DEVICES_START) &&
(boot_device <= MMC_BOOT_DEVICES_END)) {
-#if !defined(CONFIG_AM33XX) && !defined(CONFIG_TI81XX)
+#if !defined(CONFIG_AM33XX) && !defined(CONFIG_TI81XX) && \
+ !defined(CONFIG_AM43XX)
if ((omap_hw_init_context() ==
OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)) {
gd->arch.omap_boot_params.omap_bootmode =
*((u32 *)(dev_data + BOOT_MODE_OFFSET));
}
}
+
+#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)
+ /*
+ * We get different values for QSPI_1 and QSPI_4 being used, but
+ * don't actually care about this difference. Rather than
+ * mangle the later code, if we're coming in as QSPI_4 just
+ * change to the QSPI_1 value.
+ */
+ if (gd->arch.omap_boot_params.omap_bootdevice == 11)
+ gd->arch.omap_boot_params.omap_bootdevice = BOOT_DEVICE_SPI;
+#endif
}
#ifdef CONFIG_SPL_BUILD
u32 spl_boot_device(void)
{
- return (u32) (gd->arch.omap_boot_params.omap_bootdevice);
+ return gd->arch.omap_boot_params.omap_bootdevice;
}
u32 spl_boot_mode(void)
{
- return gd->arch.omap_boot_params.omap_bootmode;
+ u32 val = gd->arch.omap_boot_params.omap_bootmode;
+
+ if (val == MMCSD_MODE_RAW)
+ return MMCSD_MODE_RAW;
+ else if (val == MMCSD_MODE_FS)
+ return MMCSD_MODE_FS;
+ else
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ return MMCSD_MODE_EMMCBOOT;
+#else
+ return MMCSD_MODE_UNDEFINED;
+#endif
}
void spl_board_init(void)
#if defined(CONFIG_AM33XX) && defined(CONFIG_SPL_MUSB_NEW_SUPPORT)
arch_misc_init();
#endif
+#if defined(CONFIG_HW_WATCHDOG)
+ hw_watchdog_init();
+#endif
+#ifdef CONFIG_AM33XX
+ am33xx_spl_board_init();
+#endif
}
int board_mmc_init(bd_t *bis)
image_entry((u32 *)&gd->arch.omap_boot_params);
}
#endif
+
+#ifdef CONFIG_SCSI_AHCI_PLAT
+void arch_preboot_os(void)
+{
+ ahci_reset(DWC_AHSATA_BASE);
+}
+#endif
#include <common.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
+#if !defined(CONFIG_MX25) && !defined(CONFIG_VF610)
+#include <asm/arch/sys_proto.h>
+#endif
#include <asm/imx-common/iomux-v3.h>
static void *base = (void *)IOMUXC_BASE_ADDR;
(pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
+#if defined CONFIG_MX6SL
+ /* Check whether LVE bit needs to be set */
+ if (pad_ctrl & PAD_CTL_LVE) {
+ pad_ctrl &= ~PAD_CTL_LVE;
+ pad_ctrl |= PAD_CTL_LVE_BIT;
+ }
+#endif
++#ifdef DEBUG
++ printf("PAD[%2d]=%016llx mux[%03x]=%02x pad[%03x]=%05x%c inp[%03x]=%d\n",
++ i, pad, mux_ctrl_ofs, mux_mode, pad_ctrl_ofs, pad_ctrl,
++ pad & PAD_CTRL_VALID ? ' ' : '!', sel_input_ofs, sel_input);
++#endif
+
if (mux_ctrl_ofs)
__raw_writel(mux_mode, base + mux_ctrl_ofs);
__raw_writel(sel_input, base + sel_input_ofs);
#ifdef CONFIG_IOMUX_SHARE_CONF_REG
- if (!(pad_ctrl & NO_PAD_CTRL))
+ if (pad & PAD_CTRL_VALID)
__raw_writel((mux_mode << PAD_MUX_MODE_SHIFT) | pad_ctrl,
base + pad_ctrl_ofs);
#else
- if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
+ if ((pad & PAD_CTRL_VALID) && pad_ctrl_ofs)
__raw_writel(pad_ctrl, base + pad_ctrl_ofs);
#endif
}
+/* configures a list of pads within declared with IOMUX_PADS macro */
void imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list,
unsigned count)
{
iomux_v3_cfg_t const *p = pad_list;
+ int stride;
int i;
- for (i = 0; i < count; i++) {
-#ifdef DEBUG
- u32 mux_ctrl_ofs = (*p & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
- u32 mux_mode = (*p & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
- u32 sel_input_ofs =
- (*p & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
- u32 sel_input =
- (*p & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
- u32 pad_ctrl_ofs =
- (*p & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
- u32 pad_ctrl = (*p & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
-
- printf("PAD[%2d]=%016llx mux[%03x]=%02x pad[%03x]=%05x%c inp[%03x]=%d\n",
- i, *p, mux_ctrl_ofs, mux_mode, pad_ctrl_ofs, pad_ctrl,
- *p & PAD_CTRL_VALID ? ' ' : '!', sel_input_ofs, sel_input);
+#if defined(CONFIG_MX6QDL)
+ stride = 2;
+ if (!is_cpu_type(MXC_CPU_MX6Q) && !is_cpu_type(MXC_CPU_MX6D))
+ p += 1;
+#else
+ stride = 1;
#endif
- imx_iomux_v3_setup_pad(*p++);
+ for (i = 0; i < count; i++) {
+ imx_iomux_v3_setup_pad(*p);
+ p += stride;
}
}
- int num_bits, int value)
+
+void imx_iomux_set_gpr_register(int group, int start_bit,
- int i = 0;
- u32 reg;
- reg = readl(base + group * 4);
- while (num_bits) {
- reg &= ~(1<<(start_bit + i));
- i++;
- num_bits--;
- }
- reg |= (value << start_bit);
++ int num_bits, int value)
+{
++ u32 reg = readl(base + group * 4);
++
++ reg &= ~(((1 << num_bits) - 1) << start_bit);
++ reg |= value << start_bit;
+ writel(reg, base + group * 4);
+}
#include <div64.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
/* General purpose timers registers */
struct mxc_gpt {
/* General purpose timers bitfields */
#define GPTCR_SWR (1 << 15) /* Software reset */
+#define GPTCR_24MEN (1 << 10) /* Enable 24MHz clock input */
#define GPTCR_FRR (1 << 9) /* Freerun / restart */
-#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */
+#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source 32khz */
+#define GPTCR_CLKSOURCE_OSC (5 << 6) /* Clock source OSC */
+#define GPTCR_CLKSOURCE_PRE (1 << 6) /* Clock source PRECLK */
+#define GPTCR_CLKSOURCE_MASK (0x7 << 6)
#define GPTCR_TEN 1 /* Timer enable */
+#define GPTPR_PRESCALER24M_SHIFT 12
+#define GPTPR_PRESCALER24M_MASK (0xF << GPTPR_PRESCALER24M_SHIFT)
+
DECLARE_GLOBAL_DATA_PTR;
+static inline int gpt_has_clk_source_osc(void)
+{
+#if defined(CONFIG_MX6)
+ if (((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) &&
+ (is_soc_rev(CHIP_REV_1_0) > 0)) || is_cpu_type(MXC_CPU_MX6DL) ||
+ is_cpu_type(MXC_CPU_MX6SOLO) || is_cpu_type(MXC_CPU_MX6SX))
+ return 1;
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static inline ulong gpt_get_clk(void)
+{
+#ifdef CONFIG_MXC_GPT_HCLK
+ if (gpt_has_clk_source_osc())
+ return MXC_HCLK >> 3;
+ else
+ return mxc_get_clock(MXC_IPG_PERCLK);
+#else
+ return MXC_CLK32;
+#endif
+}
static inline unsigned long long tick_to_time(unsigned long long tick)
{
+ ulong gpt_clk = gpt_get_clk();
+
tick *= CONFIG_SYS_HZ;
- do_div(tick, MXC_CLK32);
+ do_div(tick, gpt_clk);
+
return tick;
}
+ static inline unsigned long time_to_tick(unsigned long time)
+ {
+ unsigned long long ticks = (unsigned long long)time;
+
+ ticks *= MXC_CLK32;
+ do_div(ticks, CONFIG_SYS_HZ);
+ return ticks;
+ }
+
static inline unsigned long long us_to_tick(unsigned long long usec)
{
- usec = usec * MXC_CLK32 + 999999;
+ ulong gpt_clk = gpt_get_clk();
+
+ usec = usec * gpt_clk + 999999;
do_div(usec, 1000000);
return usec;
for (i = 0; i < 100; i++)
__raw_writel(0, &cur_gpt->control);
- __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */
-
- /* Freerun Mode, PERCLK1 input */
i = __raw_readl(&cur_gpt->control);
- __raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control);
+ i &= ~GPTCR_CLKSOURCE_MASK;
+
+#ifdef CONFIG_MXC_GPT_HCLK
+ if (gpt_has_clk_source_osc()) {
+ i |= GPTCR_CLKSOURCE_OSC | GPTCR_TEN;
+
+ /* For DL/S, SX, set 24Mhz OSC Enable bit and prescaler */
+ if (is_cpu_type(MXC_CPU_MX6DL) ||
+ is_cpu_type(MXC_CPU_MX6SOLO) ||
+ is_cpu_type(MXC_CPU_MX6SX)) {
+ i |= GPTCR_24MEN;
+
+ /* Produce 3Mhz clock */
+ __raw_writel((7 << GPTPR_PRESCALER24M_SHIFT),
+ &cur_gpt->prescaler);
+ }
+ } else {
+ i |= GPTCR_CLKSOURCE_PRE | GPTCR_TEN;
+ }
+#else
+ __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */
+ i |= GPTCR_CLKSOURCE_32 | GPTCR_TEN;
+#endif
+ __raw_writel(i, &cur_gpt->control);
gd->arch.tbl = __raw_readl(&cur_gpt->counter);
gd->arch.tbu = 0;
+ gd->arch.timer_rate_hz = MXC_CLK32;
return 0;
}
{
/*
* get_ticks() returns a long long (64 bit), it wraps in
- * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
+ * 2^64 / GPT_CLK = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
* 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
* 5 * 10^6 days - long enough.
*/
+ /*
+ * LW: get_ticks() returns a long long with the top 32 bits always ZERO!
+ * Thus the calculation above is not true.
+ * A 64bit timer value would only make sense if it was
+ * consistently used throughout the code. Thus also the parameter
+ * to get_timer() and its return value would need to be 64bit wide!
+ */
return tick_to_time(get_ticks());
}
ulong get_timer(ulong base)
{
- return get_timer_masked() - base;
+ return tick_to_time(get_ticks() - time_to_tick(base));
}
/* delay x useconds AND preserve advance timstamp value */
void __udelay(unsigned long usec)
{
- unsigned long long tmp;
- ulong tmo;
+ unsigned long start = __raw_readl(&cur_gpt->counter);
+ unsigned long ticks;
+
+ if (usec == 0)
+ return;
- tmo = us_to_tick(usec);
- tmp = get_ticks() + tmo; /* get current timestamp */
+ ticks = us_to_tick(usec);
+ if (ticks == 0)
+ ticks++;
- while (get_ticks() < tmp) /* loop till event */
- /*NOP*/;
+ while (__raw_readl(&cur_gpt->counter) - start < ticks)
+ /* loop till event */;
}
/*
*/
ulong get_tbclk(void)
{
- return gd->arch.timer_rate_hz;
+ return gpt_get_clk();
}
#ifndef _CLOCKS_AM33XX_H_
#define _CLOCKS_AM33XX_H_
+/* MAIN PLL Fdll supported frequencies */
+#define MPUPLL_M_1000 1000
+#define MPUPLL_M_800 800
+#define MPUPLL_M_720 720
+#define MPUPLL_M_600 600
+#define MPUPLL_M_550 550
+#define MPUPLL_M_300 300
+
/* MAIN PLL Fdll = 550 MHz, by default */
#ifndef CONFIG_SYS_MPUCLK
-#define CONFIG_SYS_MPUCLK 550
+#define CONFIG_SYS_MPUCLK MPUPLL_M_550
#endif
-extern void pll_init(void);
-extern void enable_emif_clocks(void);
+ #define DISPPLL_M 200
+ #define DISPPLL_N (OSC - 1)
+ #define DISPPLL_M2 1
+
+#define UART_RESET (0x1 << 1)
+#define UART_CLK_RUNNING_MASK 0x1
+#define UART_SMART_IDLE_EN (0x1 << 0x3)
+
+#define CM_DLL_CTRL_NO_OVERRIDE 0x0
+#define CM_DLL_READYST 0x4
+
extern void enable_dmm_clocks(void);
+extern const struct dpll_params dpll_core_opp100;
+extern struct dpll_params dpll_mpu_opp100;
#endif /* endif _CLOCKS_AM33XX_H_ */
#include <asm/arch/hardware.h>
- #define BIT(x) (1 << x)
- #define CL_BIT(x) (0 << x)
+ #define BIT(x) (1 << (x))
+ #define CL_BIT(x) (0 << (x))
/* Timer register bits */
#define TCLR_ST BIT(0) /* Start=1 Stop=0 */
#define TCLR_AR BIT(1) /* Auto reload */
#define TCLR_PRE BIT(5) /* Pre-scaler enable */
- #define TCLR_PTV_SHIFT (2) /* Pre-scaler shift value */
+ #define TCLR_PTV_SHIFT 2 /* Pre-scaler shift value */
#define TCLR_PRE_DISABLE CL_BIT(5) /* Pre-scalar disable */
+#define TCLR_CE BIT(6) /* compare mode enable */
+#define TCLR_SCPWM BIT(7) /* pwm outpin behaviour */
+#define TCLR_TCM BIT(8) /* edge detection of input pin*/
+#define TCLR_TRG_SHIFT (10) /* trigmode on pwm outpin */
+#define TCLR_PT BIT(12) /* pulse/toggle mode of outpin*/
+#define TCLR_CAPTMODE BIT(13) /* capture mode */
+#define TCLR_GPOCFG BIT(14) /* 0=output,1=input */
+#define TCFG_RESET BIT(0) /* software reset */
+#define TCFG_EMUFREE BIT(1) /* behaviour of tmr on debug */
+#define TCFG_IDLEMOD_SHIFT (2) /* power management */
/* device type */
#define DEVICE_MASK (BIT(8) | BIT(9) | BIT(10))
#define TST_DEVICE 0x0
#define AM335X 0xB944
#define TI81XX 0xB81E
#define DEVICE_ID (CTRL_BASE + 0x0600)
+#define DEVICE_ID_MASK 0x1FFF
+
+/* MPU max frequencies */
+#define AM335X_ZCZ_300 0x1FEF
+#define AM335X_ZCZ_600 0x1FAF
+#define AM335X_ZCZ_720 0x1F2F
+#define AM335X_ZCZ_800 0x1E2F
+#define AM335X_ZCZ_1000 0x1C2F
+#define AM335X_ZCE_300 0x1FDF
+#define AM335X_ZCE_600 0x1F9F
/* This gives the status of the boot mode pins on the evm */
- #define SYSBOOT_MASK (BIT(0) | BIT(1) | BIT(2)\
- | BIT(3) | BIT(4))
+ #define SYSBOOT_MASK (BIT(0) | BIT(1) | BIT(2) | \
+ BIT(3) | BIT(4))
-/* Reset control */
-#ifdef CONFIG_AM33XX
-#define PRM_RSTCTRL (PRCM_BASE + 0x0F00)
-#elif defined(CONFIG_TI814X)
-#define PRM_RSTCTRL (PRCM_BASE + 0x00A0)
-#endif
-#define PRM_RSTST (PRM_RSTCTRL + 8)
#define PRM_RSTCTRL_RESET 0x01
#define PRM_RSTST_WARM_RESET_MASK 0x232
+/*
+ * Watchdog:
+ * Using the prescaler, the OMAP watchdog could go for many
+ * months before firing. These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX (24 * 60 * 60) /* 1 day */
+#define TIMER_MARGIN_DEFAULT 60 /* 60 secs */
+#define TIMER_MARGIN_MIN 1
+
+#define PTV 0 /* prescale */
+#define GET_WLDR_VAL(secs) (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+#define WDT_WWPS_PEND_WCLR BIT(0)
+#define WDT_WWPS_PEND_WLDR BIT(2)
+#define WDT_WWPS_PEND_WTGR BIT(3)
+#define WDT_WWPS_PEND_WSPR BIT(4)
+
+#define WDT_WCLR_PRE BIT(5)
+#define WDT_WCLR_PTV_OFF 2
+
#ifndef __KERNEL_STRICT_NAMES
#ifndef __ASSEMBLY__
-struct gpmc_cs {
- u32 config1; /* 0x00 */
- u32 config2; /* 0x04 */
- u32 config3; /* 0x08 */
- u32 config4; /* 0x0C */
- u32 config5; /* 0x10 */
- u32 config6; /* 0x14 */
- u32 config7; /* 0x18 */
- u32 nand_cmd; /* 0x1C */
- u32 nand_adr; /* 0x20 */
- u32 nand_dat; /* 0x24 */
- u8 res[8]; /* blow up to 0x30 byte */
-};
-
-struct bch_res_0_3 {
- u32 bch_result_x[4];
-};
-struct gpmc {
- u32 res1[4];
- u32 sysconfig; /* 0x10 */
- u32 res2;
- u32 irqstatus; /* 0x18 */
- u32 irqenable; /* 0x1C */
- u32 res3[8];
- u32 timeout_control; /* 0x40 */
- u32 res4[3];
- u32 config; /* 0x50 */
- u32 status; /* 0x54 */
- u32 res5[2]; /* 0x58 */
- struct gpmc_cs cs[8]; /* 0x60, 0x90, .. */
- u32 pref_config1; /* 0x1E0 */
- u32 pref_config2; /* 0x1E4 */
- u32 res6; /* 0x1E8 */
- u32 pref_control; /* 0x1EC */
- u32 pref_status; /* 0x1F0 */
- u32 ecc_config; /* 0x1F4 */
- u32 ecc_control; /* 0x1F8 */
- u32 ecc_size_config; /* 0x1FC */
- u32 ecc1_result; /* 0x200 */
- u32 ecc2_result; /* 0x204 */
- u32 ecc3_result; /* 0x208 */
- u32 ecc4_result; /* 0x20C */
- u32 ecc5_result; /* 0x210 */
- u32 ecc6_result; /* 0x214 */
- u32 ecc7_result; /* 0x218 */
- u32 ecc8_result; /* 0x21C */
- u32 ecc9_result; /* 0x220 */
- u32 res7[3]; /* 0x224 */
- u32 testmomde_ctrl; /* 0x230 */
- u32 res8[3]; /* 0x234 */
- struct bch_res_0_3 bch_result_0_3[2]; /* 0x240 */
-};
+#ifndef CONFIG_AM43XX
/* Encapsulating core pll registers */
struct cm_wkuppll {
unsigned int wkclkstctrl; /* offset 0x00 */
unsigned int wkctrlclkctrl; /* offset 0x04 */
unsigned int wkgpio0clkctrl; /* offset 0x08 */
unsigned int wkl4wkclkctrl; /* offset 0x0c */
- unsigned int resv2[4];
+ unsigned int timer0clkctrl; /* offset 0x10 */
+ unsigned int resv2[3];
unsigned int idlestdpllmpu; /* offset 0x20 */
unsigned int resv3[2];
unsigned int clkseldpllmpu; /* offset 0x2c */
unsigned int idlestdpllddr; /* offset 0x34 */
unsigned int resv5[2];
unsigned int clkseldpllddr; /* offset 0x40 */
- unsigned int resv6[4];
+ unsigned int autoidledplldisp; /* offset 0x44 */
+ unsigned int idlestdplldisp; /* offset 0x48 */
+ unsigned int resv6[2];
unsigned int clkseldplldisp; /* offset 0x54 */
unsigned int resv7[1];
unsigned int idlestdpllcore; /* offset 0x5c */
unsigned int resv11[1];
unsigned int wkup_uart0ctrl; /* offset 0xB4 */
unsigned int wkup_i2c0ctrl; /* offset 0xB8 */
- unsigned int resv12[6];
- unsigned int wdtimer1ctrl;
+ unsigned int wkup_adctscctrl; /* offset 0xBC */
+ unsigned int resv12;
+ unsigned int timer1clkctrl; /* offset 0xC4 */
+ unsigned int resv13[4];
unsigned int divm6dpllcore; /* offset 0xD8 */
};
unsigned int resv1;
unsigned int cpgmac0clkctrl; /* offset 0x14 */
unsigned int lcdclkctrl; /* offset 0x18 */
- unsigned int usb0clkctrl; /* offset 0x1C */
+ unsigned int usb0clkctrl; /* offset 0x1c */
unsigned int resv2;
unsigned int tptc0clkctrl; /* offset 0x24 */
unsigned int emifclkctrl; /* offset 0x28 */
unsigned int tpccclkctrl; /* offset 0xBC */
unsigned int dcan0clkctrl; /* offset 0xC0 */
unsigned int dcan1clkctrl; /* offset 0xC4 */
- unsigned int resv6[2];
+ unsigned int resv6;
+ unsigned int epwmss1clkctrl; /* offset 0xCC */
unsigned int emiffwclkctrl; /* offset 0xD0 */
- unsigned int resv7[2];
+ unsigned int epwmss0clkctrl; /* offset 0xD4 */
+ unsigned int epwmss2clkctrl; /* offset 0xD8 */
unsigned int l3instrclkctrl; /* offset 0xDC */
unsigned int l3clkctrl; /* Offset 0xE0 */
- unsigned int resv8[4];
+ unsigned int resv8[2];
+ unsigned int timer5clkctrl; /* offset 0xEC */
+ unsigned int timer6clkctrl; /* offset 0xF0 */
unsigned int mmc1clkctrl; /* offset 0xF4 */
unsigned int mmc2clkctrl; /* offset 0xF8 */
unsigned int resv9[8];
unsigned int l4hsclkctrl; /* offset 0x120 */
unsigned int resv10[8];
unsigned int cpswclkstctrl; /* offset 0x144 */
+ unsigned int lcdcclkstctrl; /* offset 0x148 */
};
/* Encapsulating Display pll registers */
struct cm_dpll {
- unsigned int resv1[2];
+ unsigned int resv1;
+ unsigned int clktimer7clk; /* offset 0x04 */
unsigned int clktimer2clk; /* offset 0x08 */
+ unsigned int clktimer3clk; /* offset 0x0C */
+ unsigned int clktimer4clk; /* offset 0x10 */
+ unsigned int resv2;
+ unsigned int clktimer5clk; /* offset 0x18 */
+ unsigned int clktimer6clk; /* offset 0x1C */
+ unsigned int resv3[2];
+ unsigned int clktimer1clk; /* offset 0x28 */
+ unsigned int resv4[2];
+ unsigned int clklcdcpixelclk; /* offset 0x34 */
+};
+#else
+/* Encapsulating core pll registers */
+struct cm_wkuppll {
+ unsigned int resv0[136];
+ unsigned int wkl4wkclkctrl; /* offset 0x220 */
+ unsigned int resv1[55];
+ unsigned int wkclkstctrl; /* offset 0x300 */
+ unsigned int resv2[15];
+ unsigned int wkup_i2c0ctrl; /* offset 0x340 */
+ unsigned int resv3;
+ unsigned int wkup_uart0ctrl; /* offset 0x348 */
+ unsigned int resv4[5];
+ unsigned int wkctrlclkctrl; /* offset 0x360 */
+ unsigned int resv5;
+ unsigned int wkgpio0clkctrl; /* offset 0x368 */
+
+ unsigned int resv6[109];
+ unsigned int clkmoddpllcore; /* offset 0x520 */
+ unsigned int idlestdpllcore; /* offset 0x524 */
+ unsigned int resv61;
+ unsigned int clkseldpllcore; /* offset 0x52C */
+ unsigned int resv7[2];
+ unsigned int divm4dpllcore; /* offset 0x538 */
+ unsigned int divm5dpllcore; /* offset 0x53C */
+ unsigned int divm6dpllcore; /* offset 0x540 */
+
+ unsigned int resv8[7];
+ unsigned int clkmoddpllmpu; /* offset 0x560 */
+ unsigned int idlestdpllmpu; /* offset 0x564 */
+ unsigned int resv9;
+ unsigned int clkseldpllmpu; /* offset 0x56c */
+ unsigned int divm2dpllmpu; /* offset 0x570 */
+
+ unsigned int resv10[11];
+ unsigned int clkmoddpllddr; /* offset 0x5A0 */
+ unsigned int idlestdpllddr; /* offset 0x5A4 */
+ unsigned int resv11;
+ unsigned int clkseldpllddr; /* offset 0x5AC */
+ unsigned int divm2dpllddr; /* offset 0x5B0 */
+
+ unsigned int resv12[11];
+ unsigned int clkmoddpllper; /* offset 0x5E0 */
+ unsigned int idlestdpllper; /* offset 0x5E4 */
+ unsigned int resv13;
+ unsigned int clkseldpllper; /* offset 0x5EC */
+ unsigned int divm2dpllper; /* offset 0x5F0 */
+ unsigned int resv14[8];
+ unsigned int clkdcoldodpllper; /* offset 0x614 */
+
+ unsigned int resv15[2];
+ unsigned int clkmoddplldisp; /* offset 0x620 */
+ unsigned int resv16[2];
+ unsigned int clkseldplldisp; /* offset 0x62C */
+ unsigned int divm2dplldisp; /* offset 0x630 */
};
+/*
+ * Encapsulating peripheral functional clocks
+ * pll registers
+ */
+struct cm_perpll {
+ unsigned int l3clkstctrl; /* offset 0x00 */
+ unsigned int resv0[7];
+ unsigned int l3clkctrl; /* Offset 0x20 */
+ unsigned int resv1[7];
+ unsigned int l3instrclkctrl; /* offset 0x40 */
+ unsigned int resv2[3];
+ unsigned int ocmcramclkctrl; /* offset 0x50 */
+ unsigned int resv3[9];
+ unsigned int tpccclkctrl; /* offset 0x78 */
+ unsigned int resv4;
+ unsigned int tptc0clkctrl; /* offset 0x80 */
+
+ unsigned int resv5[7];
+ unsigned int l4hsclkctrl; /* offset 0x0A0 */
+ unsigned int resv6;
+ unsigned int l4fwclkctrl; /* offset 0x0A8 */
+ unsigned int resv7[85];
+ unsigned int l3sclkstctrl; /* offset 0x200 */
+ unsigned int resv8[7];
+ unsigned int gpmcclkctrl; /* offset 0x220 */
+ unsigned int resv9[5];
+ unsigned int mcasp0clkctrl; /* offset 0x238 */
+ unsigned int resv10;
+ unsigned int mcasp1clkctrl; /* offset 0x240 */
+ unsigned int resv11;
+ unsigned int mmc2clkctrl; /* offset 0x248 */
+ unsigned int resv12[3];
+ unsigned int qspiclkctrl; /* offset 0x258 */
+ unsigned int resv121;
+ unsigned int usb0clkctrl; /* offset 0x260 */
+ unsigned int resv13[103];
+ unsigned int l4lsclkstctrl; /* offset 0x400 */
+ unsigned int resv14[7];
+ unsigned int l4lsclkctrl; /* offset 0x420 */
+ unsigned int resv15;
+ unsigned int dcan0clkctrl; /* offset 0x428 */
+ unsigned int resv16;
+ unsigned int dcan1clkctrl; /* offset 0x430 */
+ unsigned int resv17[13];
+ unsigned int elmclkctrl; /* offset 0x468 */
+
+ unsigned int resv18[3];
+ unsigned int gpio1clkctrl; /* offset 0x478 */
+ unsigned int resv19;
+ unsigned int gpio2clkctrl; /* offset 0x480 */
+ unsigned int resv20;
+ unsigned int gpio3clkctrl; /* offset 0x488 */
+ unsigned int resv41;
+ unsigned int gpio4clkctrl; /* offset 0x490 */
+ unsigned int resv42;
+ unsigned int gpio5clkctrl; /* offset 0x498 */
+ unsigned int resv21[3];
+
+ unsigned int i2c1clkctrl; /* offset 0x4A8 */
+ unsigned int resv22;
+ unsigned int i2c2clkctrl; /* offset 0x4B0 */
+ unsigned int resv23[3];
+ unsigned int mmc0clkctrl; /* offset 0x4C0 */
+ unsigned int resv24;
+ unsigned int mmc1clkctrl; /* offset 0x4C8 */
+
+ unsigned int resv25[13];
+ unsigned int spi0clkctrl; /* offset 0x500 */
+ unsigned int resv26;
+ unsigned int spi1clkctrl; /* offset 0x508 */
+ unsigned int resv27[9];
+ unsigned int timer2clkctrl; /* offset 0x530 */
+ unsigned int resv28;
+ unsigned int timer3clkctrl; /* offset 0x538 */
+ unsigned int resv29;
+ unsigned int timer4clkctrl; /* offset 0x540 */
+ unsigned int resv30[5];
+ unsigned int timer7clkctrl; /* offset 0x558 */
+
+ unsigned int resv31[9];
+ unsigned int uart1clkctrl; /* offset 0x580 */
+ unsigned int resv32;
+ unsigned int uart2clkctrl; /* offset 0x588 */
+ unsigned int resv33;
+ unsigned int uart3clkctrl; /* offset 0x590 */
+ unsigned int resv34;
+ unsigned int uart4clkctrl; /* offset 0x598 */
+ unsigned int resv35;
+ unsigned int uart5clkctrl; /* offset 0x5A0 */
+ unsigned int resv36[87];
+
+ unsigned int emifclkstctrl; /* offset 0x700 */
+ unsigned int resv361[7];
+ unsigned int emifclkctrl; /* offset 0x720 */
+ unsigned int resv37[3];
+ unsigned int emiffwclkctrl; /* offset 0x730 */
+ unsigned int resv371;
+ unsigned int otfaemifclkctrl; /* offset 0x738 */
+ unsigned int resv38[57];
+ unsigned int lcdclkctrl; /* offset 0x820 */
+ unsigned int resv39[183];
+ unsigned int cpswclkstctrl; /* offset 0xB00 */
+ unsigned int resv40[7];
+ unsigned int cpgmac0clkctrl; /* offset 0xB20 */
+};
+
+struct cm_device_inst {
+ unsigned int cm_clkout1_ctrl;
+ unsigned int cm_dll_ctrl;
+};
+
+struct cm_dpll {
+ unsigned int resv1;
+ unsigned int clktimer2clk; /* offset 0x04 */
+};
+#endif /* CONFIG_AM43XX */
+
/* Control Module RTC registers */
struct cm_rtc {
unsigned int rtcclkctrl; /* offset 0x0 */
unsigned int twpc; /* offset 0x48 */
unsigned int tmar; /* offset 0x4c */
unsigned int tcar1; /* offset 0x50 */
- unsigned int tscir; /* offset 0x54 */
+ unsigned int tsicr; /* offset 0x54 */
unsigned int tcar2; /* offset 0x58 */
};
-/* RTC Registers */
-struct rtc_regs {
- unsigned int res[21];
- unsigned int osc; /* offset 0x54 */
- unsigned int res2[5];
- unsigned int kick0r; /* offset 0x6c */
- unsigned int kick1r; /* offset 0x70 */
-};
-
/* UART Registers */
struct uart_sys {
unsigned int resv1[21];
unsigned int resv1[16];
unsigned int statusreg; /* ofset 0x40 */
unsigned int resv2[51];
- unsigned int secure_emif_sdram_config; /* offset 0x0110 */
+ unsigned int emif_sdram_config; /* offset 0x0110 */
+ unsigned int resv3[319];
+ unsigned int dev_attr;
};
/* AM33XX GPIO registers */
#define OMAP_GPIO_SETDATAOUT 0x0194
/* Control Device Register */
+
+ /* Control Device Register */
+#define MREQPRIO_0_SAB_INIT1_MASK 0xFFFFFF8F
+#define MREQPRIO_0_SAB_INIT0_MASK 0xFFFFFFF8
+#define MREQPRIO_1_DSS_MASK 0xFFFFFF8F
+
struct ctrl_dev {
unsigned int deviceid; /* offset 0x00 */
unsigned int resv1[7];
unsigned int macid1h; /* offset 0x3c */
unsigned int resv4[4];
unsigned int miisel; /* offset 0x50 */
+ unsigned int resv5[7];
+ unsigned int mreqprio_0; /* offset 0x70 */
+ unsigned int mreqprio_1; /* offset 0x74 */
+ unsigned int resv6[97];
+ unsigned int efuse_sma; /* offset 0x1FC */
+};
+
+/* Bandwidth Limiter Portion of the L3Fast Configuration Register */
+#define BW_LIMITER_BW_FRAC_MASK 0xFFFFFFE0
+#define BW_LIMITER_BW_INT_MASK 0xFFFFFFF0
+#define BW_LIMITER_BW_WATERMARK_MASK 0xFFFFF800
+
+struct l3f_cfg_bwlimiter {
+ u32 padding0[2];
+ u32 modena_init0_bw_fractional;
+ u32 modena_init0_bw_integer;
+ u32 modena_init0_watermark_0;
+};
+
+/* gmii_sel register defines */
+#define GMII1_SEL_MII 0x0
+#define GMII1_SEL_RMII 0x1
+#define GMII1_SEL_RGMII 0x2
+#define GMII2_SEL_MII 0x0
+#define GMII2_SEL_RMII 0x4
+#define GMII2_SEL_RGMII 0x8
+#define RGMII1_IDMODE BIT(4)
+#define RGMII2_IDMODE BIT(5)
+#define RMII1_IO_CLK_EN BIT(6)
+#define RMII2_IO_CLK_EN BIT(7)
+
+#define MII_MODE_ENABLE (GMII1_SEL_MII | GMII2_SEL_MII)
+#define RMII_MODE_ENABLE (GMII1_SEL_RMII | GMII2_SEL_RMII)
+#define RGMII_MODE_ENABLE (GMII1_SEL_RGMII | GMII2_SEL_RGMII)
+#define RGMII_INT_DELAY (RGMII1_IDMODE | RGMII2_IDMODE)
+#define RMII_CHIPCKL_ENABLE (RMII1_IO_CLK_EN | RMII2_IO_CLK_EN)
+
+/* PWMSS */
+struct pwmss_regs {
+ unsigned int idver;
+ unsigned int sysconfig;
+ unsigned int clkconfig;
+ unsigned int clkstatus;
+};
+#define ECAP_CLK_EN BIT(0)
+#define ECAP_CLK_STOP_REQ BIT(1)
+
+struct pwmss_ecap_regs {
+ unsigned int tsctr;
+ unsigned int ctrphs;
+ unsigned int cap1;
+ unsigned int cap2;
+ unsigned int cap3;
+ unsigned int cap4;
+ unsigned int resv1[4];
+ unsigned short ecctl1;
+ unsigned short ecctl2;
};
-void init_timer(void);
+/* Capture Control register 2 */
+#define ECTRL2_SYNCOSEL_MASK (0x03 << 6)
+#define ECTRL2_MDSL_ECAP BIT(9)
+#define ECTRL2_CTRSTP_FREERUN BIT(4)
+#define ECTRL2_PLSL_LOW BIT(10)
+#define ECTRL2_SYNC_EN BIT(5)
-unsigned long lcdc_clk_rate(void);
+ #define clk_get_rate(c,p) \
+ __clk_get_rate(readl(&(c)->clkseldpll##p), \
+ readl(&(c)->divm2dpll##p))
+
+ unsigned long __clk_get_rate(u32 m_n, u32 div_m2);
+
+ unsigned long mpu_clk_rate(void);
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL_STRICT_NAMES */
+ /* Ethernet MAC ID from EFuse */
+ #define MAC_ID0_LO (CTRL_BASE + 0x630)
+ #define MAC_ID0_HI (CTRL_BASE + 0x634)
+ #define MAC_ID1_LO (CTRL_BASE + 0x638)
+ #define MAC_ID1_HI (CTRL_BASE + 0x63c)
+ #define MAC_MII_SEL (CTRL_BASE + 0x650)
+
#endif /* _AM33XX_CPU_H */
/* AM335X EMIF Register values */
#define VTP_CTRL_READY (0x1 << 5)
#define VTP_CTRL_ENABLE (0x1 << 6)
- #define VTP_CTRL_START_EN (0x1)
+ #define VTP_CTRL_FILTER_SHIFT 1
+ #define VTP_CTRL_FILTER_MASK (0x7 << VTP_CTRL_FILTER_SHIFT)
+ #define VTP_CTRL_FILTER(n) (((n) << VTP_CTRL_FILTER_SHIFT) & VTP_CTRL_FILTER_MASK)
+ #define VTP_CTRL_START_EN (0x1 << 0)
+ #define PHY_DLL_LOCK_DIFF 0x0
+#ifdef CONFIG_AM43XX
+#define DDR_CKE_CTRL_NORMAL 0x3
+#else
#define DDR_CKE_CTRL_NORMAL 0x1
+#endif
#define PHY_EN_DYN_PWRDN (0x1 << 20)
/* Micron MT47H128M16RT-25E */
#define MT47H128M16RT25E_EMIF_TIM3 0x0000033F
#define MT47H128M16RT25E_EMIF_SDCFG 0x41805332
#define MT47H128M16RT25E_EMIF_SDREF 0x0000081a
-#define MT47H128M16RT25E_DLL_LOCK_DIFF 0x0
#define MT47H128M16RT25E_RATIO 0x80
-#define MT47H128M16RT25E_INVERT_CLKOUT 0x00
#define MT47H128M16RT25E_RD_DQS 0x12
-#define MT47H128M16RT25E_WR_DQS 0x00
-#define MT47H128M16RT25E_PHY_WRLVL 0x00
-#define MT47H128M16RT25E_PHY_GATELVL 0x00
#define MT47H128M16RT25E_PHY_WR_DATA 0x40
#define MT47H128M16RT25E_PHY_FIFO_WE 0x80
-#define MT47H128M16RT25E_PHY_RANK0_DELAY 0x1
#define MT47H128M16RT25E_IOCTRL_VALUE 0x18B
/* Micron MT41J128M16JT-125 */
-#define MT41J128MJT125_EMIF_READ_LATENCY 0x06
+#define MT41J128MJT125_EMIF_READ_LATENCY 0x100006
#define MT41J128MJT125_EMIF_TIM1 0x0888A39B
#define MT41J128MJT125_EMIF_TIM2 0x26337FDA
#define MT41J128MJT125_EMIF_TIM3 0x501F830F
#define MT41J128MJT125_EMIF_SDCFG 0x61C04AB2
#define MT41J128MJT125_EMIF_SDREF 0x0000093B
#define MT41J128MJT125_ZQ_CFG 0x50074BE4
-#define MT41J128MJT125_DLL_LOCK_DIFF 0x1
#define MT41J128MJT125_RATIO 0x40
#define MT41J128MJT125_INVERT_CLKOUT 0x1
#define MT41J128MJT125_RD_DQS 0x3B
#define MT41J128MJT125_PHY_FIFO_WE 0x100
#define MT41J128MJT125_IOCTRL_VALUE 0x18B
+/* Micron MT41K128M16JT-187E */
+#define MT41K128MJT187E_EMIF_READ_LATENCY 0x06
+#define MT41K128MJT187E_EMIF_TIM1 0x0888B3DB
+#define MT41K128MJT187E_EMIF_TIM2 0x36337FDA
+#define MT41K128MJT187E_EMIF_TIM3 0x501F830F
+#define MT41K128MJT187E_EMIF_SDCFG 0x61C04AB2
+#define MT41K128MJT187E_EMIF_SDREF 0x0000093B
+#define MT41K128MJT187E_ZQ_CFG 0x50074BE4
+#define MT41K128MJT187E_RATIO 0x40
+#define MT41K128MJT187E_INVERT_CLKOUT 0x1
+#define MT41K128MJT187E_RD_DQS 0x3B
+#define MT41K128MJT187E_WR_DQS 0x85
+#define MT41K128MJT187E_PHY_WR_DATA 0xC1
+#define MT41K128MJT187E_PHY_FIFO_WE 0x100
+#define MT41K128MJT187E_IOCTRL_VALUE 0x18B
+
+/* Micron MT41J64M16JT-125 */
+#define MT41J64MJT125_EMIF_SDCFG 0x61C04A32
+
+/* Micron MT41J256M16JT-125 */
+#define MT41J256MJT125_EMIF_SDCFG 0x61C04B32
+
/* Micron MT41J256M8HX-15E */
-#define MT41J256M8HX15E_EMIF_READ_LATENCY 0x06
+#define MT41J256M8HX15E_EMIF_READ_LATENCY 0x100006
#define MT41J256M8HX15E_EMIF_TIM1 0x0888A39B
#define MT41J256M8HX15E_EMIF_TIM2 0x26337FDA
#define MT41J256M8HX15E_EMIF_TIM3 0x501F830F
#define MT41J256M8HX15E_EMIF_SDCFG 0x61C04B32
#define MT41J256M8HX15E_EMIF_SDREF 0x0000093B
#define MT41J256M8HX15E_ZQ_CFG 0x50074BE4
-#define MT41J256M8HX15E_DLL_LOCK_DIFF 0x1
#define MT41J256M8HX15E_RATIO 0x40
#define MT41J256M8HX15E_INVERT_CLKOUT 0x1
#define MT41J256M8HX15E_RD_DQS 0x3B
#define MT41K256M16HA125E_EMIF_SDCFG 0x61C05332
#define MT41K256M16HA125E_EMIF_SDREF 0xC30
#define MT41K256M16HA125E_ZQ_CFG 0x50074BE4
-#define MT41K256M16HA125E_DLL_LOCK_DIFF 0x1
#define MT41K256M16HA125E_RATIO 0x80
#define MT41K256M16HA125E_INVERT_CLKOUT 0x0
#define MT41K256M16HA125E_RD_DQS 0x38
#define MT41K256M16HA125E_IOCTRL_VALUE 0x18B
/* Micron MT41J512M8RH-125 on EVM v1.5 */
-#define MT41J512M8RH125_EMIF_READ_LATENCY 0x06
+#define MT41J512M8RH125_EMIF_READ_LATENCY 0x100006
#define MT41J512M8RH125_EMIF_TIM1 0x0888A39B
#define MT41J512M8RH125_EMIF_TIM2 0x26517FDA
#define MT41J512M8RH125_EMIF_TIM3 0x501F84EF
#define MT41J512M8RH125_EMIF_SDCFG 0x61C04BB2
#define MT41J512M8RH125_EMIF_SDREF 0x0000093B
#define MT41J512M8RH125_ZQ_CFG 0x50074BE4
-#define MT41J512M8RH125_DLL_LOCK_DIFF 0x1
#define MT41J512M8RH125_RATIO 0x80
#define MT41J512M8RH125_INVERT_CLKOUT 0x0
#define MT41J512M8RH125_RD_DQS 0x3B
#define MT41J512M8RH125_IOCTRL_VALUE 0x18B
/* Samsung K4B2G1646E-BIH9 */
-#define K4B2G1646EBIH9_EMIF_READ_LATENCY 0x06
-#define K4B2G1646EBIH9_EMIF_TIM1 0x0888A39B
-#define K4B2G1646EBIH9_EMIF_TIM2 0x2A04011A
-#define K4B2G1646EBIH9_EMIF_TIM3 0x501F820F
-#define K4B2G1646EBIH9_EMIF_SDCFG 0x61C24AB2
-#define K4B2G1646EBIH9_EMIF_SDREF 0x0000093B
+#define K4B2G1646EBIH9_EMIF_READ_LATENCY 0x100007
+#define K4B2G1646EBIH9_EMIF_TIM1 0x0AAAE51B
+#define K4B2G1646EBIH9_EMIF_TIM2 0x2A1D7FDA
+#define K4B2G1646EBIH9_EMIF_TIM3 0x501F83FF
+#define K4B2G1646EBIH9_EMIF_SDCFG 0x61C052B2
+#define K4B2G1646EBIH9_EMIF_SDREF 0x00000C30
#define K4B2G1646EBIH9_ZQ_CFG 0x50074BE4
-#define K4B2G1646EBIH9_DLL_LOCK_DIFF 0x1
-#define K4B2G1646EBIH9_RATIO 0x40
-#define K4B2G1646EBIH9_INVERT_CLKOUT 0x1
-#define K4B2G1646EBIH9_RD_DQS 0x3B
-#define K4B2G1646EBIH9_WR_DQS 0x85
-#define K4B2G1646EBIH9_PHY_FIFO_WE 0x100
-#define K4B2G1646EBIH9_PHY_WR_DATA 0xC1
+#define K4B2G1646EBIH9_RATIO 0x80
+#define K4B2G1646EBIH9_INVERT_CLKOUT 0x0
+#define K4B2G1646EBIH9_RD_DQS 0x35
+#define K4B2G1646EBIH9_WR_DQS 0x3A
+#define K4B2G1646EBIH9_PHY_FIFO_WE 0x97
+#define K4B2G1646EBIH9_PHY_WR_DATA 0x76
#define K4B2G1646EBIH9_IOCTRL_VALUE 0x18B
+#define LPDDR2_ADDRCTRL_IOCTRL_VALUE 0x294
+#define LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
+#define LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
+#define LPDDR2_DATA0_IOCTRL_VALUE 0x20000294
+#define LPDDR2_DATA1_IOCTRL_VALUE 0x20000294
+#define LPDDR2_DATA2_IOCTRL_VALUE 0x20000294
+#define LPDDR2_DATA3_IOCTRL_VALUE 0x20000294
+
+#define DDR3_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
+#define DDR3_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
+#define DDR3_ADDRCTRL_IOCTRL_VALUE 0x84
+#define DDR3_DATA0_IOCTRL_VALUE 0x84
+#define DDR3_DATA1_IOCTRL_VALUE 0x84
+#define DDR3_DATA2_IOCTRL_VALUE 0x84
+#define DDR3_DATA3_IOCTRL_VALUE 0x84
+
/**
* Configure DMM
*/
* Configure SDRAM
*/
void config_sdram(const struct emif_regs *regs, int nr);
+void config_sdram_emif4d5(const struct emif_regs *regs, int nr);
/**
* Set SDRAM timings
struct ddr_cmd_regs {
unsigned int resv0[7];
unsigned int cm0csratio; /* offset 0x01C */
- unsigned int resv1[2];
- unsigned int cm0dldiff; /* offset 0x028 */
+ unsigned int resv1[3];
unsigned int cm0iclkout; /* offset 0x02C */
unsigned int resv2[8];
unsigned int cm1csratio; /* offset 0x050 */
- unsigned int resv3[2];
- unsigned int cm1dldiff; /* offset 0x05C */
+ unsigned int resv3[3];
unsigned int cm1iclkout; /* offset 0x060 */
unsigned int resv4[8];
unsigned int cm2csratio; /* offset 0x084 */
- unsigned int resv5[2];
- unsigned int cm2dldiff; /* offset 0x090 */
+ unsigned int resv5[3];
unsigned int cm2iclkout; /* offset 0x094 */
unsigned int resv6[3];
};
* correspond to DATA1 registers defined here.
*/
struct ddr_regs {
- unsigned int resv0[7];
- unsigned int cm0csratio; /* offset 0x01C */
+ unsigned int resv0[3];
+ unsigned int cm0config; /* offset 0x00C */
+ unsigned int cm0configclk; /* offset 0x010 */
unsigned int resv1[2];
- unsigned int cm0dldiff; /* offset 0x028 */
+ unsigned int cm0csratio; /* offset 0x01C */
+ unsigned int resv2[3];
unsigned int cm0iclkout; /* offset 0x02C */
- unsigned int resv2[8];
+ unsigned int resv3[4];
+ unsigned int cm1config; /* offset 0x040 */
+ unsigned int cm1configclk; /* offset 0x044 */
+ unsigned int resv4[2];
unsigned int cm1csratio; /* offset 0x050 */
- unsigned int resv3[2];
- unsigned int cm1dldiff; /* offset 0x05C */
+ unsigned int resv5[3];
unsigned int cm1iclkout; /* offset 0x060 */
- unsigned int resv4[8];
+ unsigned int resv6[4];
+ unsigned int cm2config; /* offset 0x074 */
+ unsigned int cm2configclk; /* offset 0x078 */
+ unsigned int resv7[2];
unsigned int cm2csratio; /* offset 0x084 */
- unsigned int resv5[2];
- unsigned int cm2dldiff; /* offset 0x090 */
+ unsigned int resv8[3];
unsigned int cm2iclkout; /* offset 0x094 */
- unsigned int resv6[12];
+ unsigned int resv9[12];
unsigned int dt0rdsratio0; /* offset 0x0C8 */
- unsigned int resv7[4];
+ unsigned int resv10[4];
unsigned int dt0wdsratio0; /* offset 0x0DC */
- unsigned int resv8[4];
+ unsigned int resv11[4];
unsigned int dt0wiratio0; /* offset 0x0F0 */
- unsigned int resv9;
+ unsigned int resv12;
unsigned int dt0wimode0; /* offset 0x0F8 */
unsigned int dt0giratio0; /* offset 0x0FC */
- unsigned int resv10;
+ unsigned int resv13;
unsigned int dt0gimode0; /* offset 0x104 */
unsigned int dt0fwsratio0; /* offset 0x108 */
- unsigned int resv11[4];
+ unsigned int resv14[4];
unsigned int dt0dqoffset; /* offset 0x11C */
unsigned int dt0wrsratio0; /* offset 0x120 */
- unsigned int resv12[4];
+ unsigned int resv15[4];
unsigned int dt0rdelays0; /* offset 0x134 */
unsigned int dt0dldiff0; /* offset 0x138 */
};
unsigned long cmd0csratio;
unsigned long cmd0csforce;
unsigned long cmd0csdelay;
- unsigned long cmd0dldiff;
unsigned long cmd0iclkout;
unsigned long cmd1csratio;
unsigned long cmd1csforce;
unsigned long cmd1csdelay;
- unsigned long cmd1dldiff;
unsigned long cmd1iclkout;
unsigned long cmd2csratio;
unsigned long cmd2csforce;
unsigned long cmd2csdelay;
- unsigned long cmd2dldiff;
unsigned long cmd2iclkout;
};
unsigned long datagiratio0;
unsigned long datafwsratio0;
unsigned long datawrsratio0;
- unsigned long datauserank0delay;
- unsigned long datadldiff0;
};
/**
unsigned int resv2[12];
unsigned int dt0ioctl;
unsigned int dt1ioctl;
+ unsigned int dt2ioctrl;
+ unsigned int dt3ioctrl;
+ unsigned int resv3[4];
+ unsigned int emif_sdram_config_ext;
+};
+
+struct ctrl_ioregs {
+ unsigned int cm0ioctl;
+ unsigned int cm1ioctl;
+ unsigned int cm2ioctl;
+ unsigned int dt0ioctl;
+ unsigned int dt1ioctl;
+ unsigned int dt2ioctrl;
+ unsigned int dt3ioctrl;
+ unsigned int emif_sdram_config_ext;
};
/**
* Configure DDR io control registers
*/
-void config_io_ctrl(unsigned long val);
+void config_io_ctrl(const struct ctrl_ioregs *ioregs);
struct ddr_ctrl {
unsigned int ddrioctrl;
unsigned int ddrckectrl;
};
-void config_ddr(unsigned int pll, unsigned int ioctrl,
+void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs,
const struct ddr_data *data, const struct cmd_control *ctrl,
const struct emif_regs *regs, int nr);
+void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size);
#endif /* _DDR_DEFS_H */
#define AM33XX_GPIO1_BASE 0x4804C000
#define AM33XX_GPIO2_BASE 0x481AC000
#define AM33XX_GPIO3_BASE 0x481AE000
+#define AM33XX_GPIO4_BASE 0x48320000
+#define AM33XX_GPIO5_BASE 0x48322000
+ #define AM33XX_GPIO_NR(bank, pin) (((bank) << 5) | (pin))
+
+/* GPIO CTRL register */
+#define GPIO_CTRL_DISABLEMODULE_SHIFT 0
+#define GPIO_CTRL_DISABLEMODULE_MASK (1 << 0)
+#define GPIO_CTRL_ENABLEMODULE GPIO_CTRL_DISABLEMODULE_MASK
+
+/* GPIO OUTPUT ENABLE register */
+#define GPIO_OE_ENABLE(x) (1 << x)
+
+/* GPIO SETDATAOUT register */
+#define GPIO_SETDATAOUT(x) (1 << x)
#endif /* _GPIO_AM33xx_H */
*/
#define OMAP_HSMMC1_BASE 0x48060100
#define OMAP_HSMMC2_BASE 0x481D8100
+ #define OMAP_HSMMC3_BASE 0x47810100
#if defined(CONFIG_TI814X)
#undef MMC_CLOCK_REFERENCE
#define MMC_CLOCK_REFERENCE 192 /* MHz */
+#elif defined(CONFIG_TI816X)
+#undef MMC_CLOCK_REFERENCE
+#define MMC_CLOCK_REFERENCE 48 /* MHz */
#endif
#endif /* MMC_HOST_DEF_H */
#ifndef __ASSEMBLY__
struct exynos4_sysreg {
- unsigned char res1[0x210];
+ unsigned int res1[0x210 / 4];
unsigned int display_ctrl;
unsigned int display_ctrl2;
unsigned int camera_control;
};
struct exynos5_sysreg {
- unsigned char res1[0x214];
+ unsigned int res1[0x214 / 4];
unsigned int disp1blk_cfg;
unsigned int disp2blk_cfg;
unsigned int hdcp_e_fuse;
unsigned int reserved;
unsigned int ispblk_cfg;
unsigned int usb20phy_cfg;
- unsigned char res2[0x29c];
+ unsigned int res2[0x29c / 4];
unsigned int mipi_dphy;
unsigned int dptx_dphy;
unsigned int phyclk_sel;
void set_usbhost_mode(unsigned int mode);
void set_system_display_ctrl(void);
+int exynos_lcd_early_init(const void *blob);
#endif /* _EXYNOS4_SYSTEM_H */
MXC_NFC_CLK,
MXC_PERIPH_CLK,
MXC_I2C_CLK,
+ MXC_AXI_A_CLK,
+ MXC_AXI_B_CLK,
+ MXC_EMI_SLOW_CLK,
+ };
+
+
+ struct clk {
+ const char *name;
+ int id;
+ /* Source clock this clk depends on */
+ struct clk *parent;
+ /* Secondary clock to enable/disable with this clock */
+ struct clk *secondary;
+ /* Current clock rate */
+ unsigned long rate;
+ /* Reference count of clock enable/disable */
+ __s8 usecount;
+ /* Register bit position for clock's enable/disable control. */
+ u8 enable_shift;
+ /* Register address for clock's enable/disable control. */
+ void *enable_reg;
+ u32 flags;
+ /*
+ * Function ptr to recalculate the clock's rate based on parent
+ * clock's rate
+ */
+ void (*recalc) (struct clk *);
+ /*
+ * Function ptr to set the clock to a new rate. The rate must match a
+ * supported rate returned from round_rate. Leave blank if clock is not
+ * programmable
+ */
+ int (*set_rate) (struct clk *, unsigned long);
+ /*
+ * Function ptr to round the requested clock rate to the nearest
+ * supported rate that is less than or equal to the requested rate.
+ */
+ unsigned long (*round_rate) (struct clk *, unsigned long);
+ /*
+ * Function ptr to enable the clock. Leave blank if clock can not
+ * be gated.
+ */
+ int (*enable) (struct clk *);
+ /*
+ * Function ptr to disable the clock. Leave blank if clock can not
+ * be gated.
+ */
+ void (*disable) (struct clk *);
+ /* Function ptr to set the parent clock of the clock. */
+ int (*set_parent) (struct clk *, struct clk *);
};
u32 imx_get_uartclk(void);
u32 imx_get_fecclk(void);
unsigned int mxc_get_clock(enum mxc_clock clk);
- int mxc_set_clock(u32 ref, u32 freq, u32 clk_type);
+ int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk);
+ int adjust_core_voltage(u32 freq);
void set_usb_phy_clk(void);
-void enable_usb_phy1_clk(unsigned char enable);
-void enable_usb_phy2_clk(unsigned char enable);
+void enable_usb_phy1_clk(bool enable);
+void enable_usb_phy2_clk(bool enable);
void set_usboh3_clk(void);
-void enable_usboh3_clk(unsigned char enable);
+void enable_usboh3_clk(bool enable);
void mxc_set_sata_internal_clock(void);
int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
void enable_nfc_clk(unsigned char enable);
+void enable_efuse_prog_supply(bool enable);
+ void ipu_clk_enable(void);
+ void ipu_clk_disable(void);
+ void ipu_di_clk_enable(int di);
+ void ipu_di_clk_disable(int di);
+ #ifdef CONFIG_MX53
+ void ldb_clk_enable(int ldb);
+ void ldb_clk_disable(int ldb);
+ #else
+ static inline void ldb_clk_enable(int ldb)
+ {
+ }
+ static inline void ldb_clk_disable(int ldb)
+ {
+ }
+ #endif /* CONFIG_MX53 */
#endif /* __ASM_ARCH_CLOCK_H */
#define MXC_CCM_CSCDR1_UART_CLK_PODF_RD(r) ((r) & 0x7)
/* Define the bits in register CCDR */
- #define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
+ #define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 21)
+/* Define the bits in register CGPR */
+#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (1 << 4)
+
/* Define the bits in register CCGRx */
#define MXC_CCM_CCGR_CG_MASK 0x3
#define MXC_CCM_CCGR_CG_OFF 0x0
#endif
/* Define the bits in register CLPCR */
- #define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
+ #define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
#define MXC_DPLLC_CTL_HFSM (1 << 7)
#define MXC_DPLLC_CTL_DPDCK0_2_EN (1 << 12)
#if defined(CONFIG_MX51)
#define IRAM_BASE_ADDR 0x1FFE0000 /* internal ram */
#define IPU_SOC_BASE_ADDR 0x40000000
- #define IPU_SOC_OFFSET 0x1E000000
- #define SPBA0_BASE_ADDR 0x70000000
- #define AIPS1_BASE_ADDR 0x73F00000
- #define AIPS2_BASE_ADDR 0x83F00000
- #define CSD0_BASE_ADDR 0x90000000
- #define CSD1_BASE_ADDR 0xA0000000
- #define NFC_BASE_ADDR_AXI 0xCFFF0000
- #define CS1_BASE_ADDR 0xB8000000
+ #define SPBA0_BASE_ADDR 0x70000000
+ #define AIPS1_BASE_ADDR 0x73F00000
+ #define AIPS2_BASE_ADDR 0x83F00000
+ #define CSD0_BASE_ADDR 0x90000000
+ #define CSD1_BASE_ADDR 0xA0000000
+ #define NFC_BASE_ADDR_AXI 0xCFFF0000
+ #define CS1_BASE_ADDR 0xB8000000
#elif defined(CONFIG_MX53)
- #define IPU_SOC_BASE_ADDR 0x18000000
- #define IPU_SOC_OFFSET 0x06000000
- #define SPBA0_BASE_ADDR 0x50000000
- #define AIPS1_BASE_ADDR 0x53F00000
- #define AIPS2_BASE_ADDR 0x63F00000
- #define CSD0_BASE_ADDR 0x70000000
- #define CSD1_BASE_ADDR 0xB0000000
- #define NFC_BASE_ADDR_AXI 0xF7FF0000
- #define IRAM_BASE_ADDR 0xF8000000
- #define CS1_BASE_ADDR 0xF4000000
+ #define IPU_SOC_BASE_ADDR 0x00000000
+ #define SPBA0_BASE_ADDR 0x50000000
+ #define AIPS1_BASE_ADDR 0x53F00000
+ #define AIPS2_BASE_ADDR 0x63F00000
+ #define CSD0_BASE_ADDR 0x70000000
+ #define CSD1_BASE_ADDR 0xB0000000
+ #define NFC_BASE_ADDR_AXI 0xF7FF0000
+ #define IRAM_BASE_ADDR 0xF8000000
+ #define CS1_BASE_ADDR 0xF4000000
#define SATA_BASE_ADDR 0x10000000
#else
#error "CPU_TYPE not defined"
#define MMC_SDHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000)
#define MMC_SDHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000)
#define UART3_BASE (SPBA0_BASE_ADDR + 0x0000C000)
- #define CSPI1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000)
+ #define CSPI1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000)
#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000)
#define MMC_SDHC3_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000)
#define MMC_SDHC4_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000)
#define GPC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D8000)
#if defined(CONFIG_MX53)
- #define GPIO5_BASE_ADDR (AIPS1_BASE_ADDR + 0x000DC000)
- #define GPIO6_BASE_ADDR (AIPS1_BASE_ADDR + 0x000E0000)
- #define GPIO7_BASE_ADDR (AIPS1_BASE_ADDR + 0x000E4000)
+ #define GPIO5_BASE_ADDR (AIPS1_BASE_ADDR + 0x000DC000)
+ #define GPIO6_BASE_ADDR (AIPS1_BASE_ADDR + 0x000E0000)
+ #define GPIO7_BASE_ADDR (AIPS1_BASE_ADDR + 0x000E4000)
#define I2C3_BASE_ADDR (AIPS1_BASE_ADDR + 0x000EC000)
- #define UART4_BASE_ADDR (AIPS1_BASE_ADDR + 0x000F0000)
+ #define UART4_BASE_ADDR (AIPS1_BASE_ADDR + 0x000F0000)
#endif
/*
* AIPS 2
#define IIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000)
#define CSU_BASE_ADDR (AIPS2_BASE_ADDR + 0x0009C000)
#define ARM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A0000)
- #define OWIRE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000)
+ #define OWIRE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000)
#define FIRI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A8000)
#define CSPI2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000)
#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000)
#define SAHARA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F8000)
#if defined(CONFIG_MX53)
- #define UART5_BASE_ADDR (AIPS2_BASE_ADDR + 0x00090000)
+ #define UART5_BASE_ADDR (AIPS2_BASE_ADDR + 0x00090000)
#endif
/*
*/
#define WBED 1
-/*
- * WEIM WCR
- */
-#define BCM 1
-#define GBCD(x) (((x) & 0x3) << 1)
-#define INTEN (1 << 4)
-#define INTPOL (1 << 5)
-#define WDOG_EN (1 << 8)
-#define WDOG_LIMIT(x) (((x) & 0x3) << 9)
-
-#define CS0_128 0
-#define CS0_64M_CS1_64M 1
-#define CS0_64M_CS1_32M_CS2_32M 2
-#define CS0_32M_CS1_32M_CS2_32M_CS3_32M 3
-
/*
* CSPI register definitions
*/
#define MXC_CSPICTRL_CHAN 18
/* Bit position inside CON register to be associated with SS */
-#define MXC_CSPICON_POL 4
-#define MXC_CSPICON_PHA 0
-#define MXC_CSPICON_SSPOL 12
+#define MXC_CSPICON_PHA 0 /* SCLK phase control */
+#define MXC_CSPICON_POL 4 /* SCLK polarity */
+#define MXC_CSPICON_SSPOL 12 /* SS polarity */
+#define MXC_CSPICON_CTL 20 /* inactive state of SCLK */
#define MXC_SPI_BASE_ADDRESSES \
CSPI1_BASE_ADDR, \
CSPI2_BASE_ADDR, \
/*
* Number of GPIO pins per port
*/
- #define GPIO_NUM_PIN 32
+ #define GPIO_NUM_PIN 32
#define IIM_SREV 0x24
#define ROM_SI_REV 0x48
#define DP_MFD_665 (96 - 1)
#define DP_MFN_665 89
+ #define DP_OP_600 ((6 << 4) + ((1 - 1) << 0))
+ #define DP_MFD_600 (4 - 1)
+ #define DP_MFN_600 1
+
#define DP_OP_532 ((5 << 4) + ((1 - 1) << 0))
#define DP_MFD_532 (24 - 1)
#define DP_MFN_532 13
- #define DP_OP_400 ((8 << 4) + ((2 - 1) << 0))
- #define DP_MFD_400 (3 - 1)
- #define DP_MFN_400 1
+ #define DP_OP_533 ((5 << 4) + ((1 - 1) << 0))
+ #define DP_MFD_533 (9 - 1)
+ #define DP_MFN_533 5
#define DP_OP_455 ((9 << 4) + ((2 - 1) << 0))
#define DP_MFD_455 (48 - 1)
#define DP_MFN_455 23
+ #define DP_OP_400 ((8 << 4) + ((2 - 1) << 0))
+ #define DP_MFD_400 (3 - 1)
+ #define DP_MFN_400 1
+
+ #define DP_OP_333 ((6 << 4) + ((2 - 1) << 0))
+ #define DP_MFD_333 (16 - 1)
+ #define DP_MFN_333 15
+
#define DP_OP_216 ((6 << 4) + ((3 - 1) << 0))
#define DP_MFD_216 (4 - 1)
#define DP_MFN_216 3
- #define CHIP_REV_1_0 0x10
- #define CHIP_REV_1_1 0x11
- #define CHIP_REV_2_0 0x20
- #define CHIP_REV_2_5 0x25
- #define CHIP_REV_3_0 0x30
+ #define CHIP_REV_1_0 0x10
+ #define CHIP_REV_1_1 0x11
+ #define CHIP_REV_2_0 0x20
+ #define CHIP_REV_2_5 0x25
+ #define CHIP_REV_3_0 0x30
- #define BOARD_REV_1_0 0x0
- #define BOARD_REV_2_0 0x1
+ #define BOARD_REV_1_0 0x0
+ #define BOARD_REV_2_0 0x1
#define BOARD_VER_OFFSET 0x8
- #define IMX_IIM_BASE (IIM_BASE_ADDR)
+ #define IMX_IIM_BASE IIM_BASE_ADDR
#if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__))
#include <asm/types.h>
#if defined(CONFIG_MX51)
struct iomuxc {
- u32 gpr0;
- u32 gpr1;
+ u32 gpr[2];
u32 omux0;
u32 omux1;
u32 omux2;
};
#elif defined(CONFIG_MX53)
struct iomuxc {
- u32 gpr0;
- u32 gpr1;
- u32 gpr2;
+ u32 gpr[3];
u32 omux0;
u32 omux1;
u32 omux2;
struct iim_regs {
u32 stat;
u32 statm;
- u32 err;
+ u32 err;
u32 emask;
u32 fctl;
u32 ua;
u32 sdat;
u32 prev;
u32 srev;
- u32 prg_p;
+ u32 preg_p;
u32 scs0;
u32 scs1;
u32 scs2;
#ifndef _SYS_PROTO_H_
#define _SYS_PROTO_H_
-#define MXC_CPU_MX51 0x51
-#define MXC_CPU_MX53 0x53
-#define MXC_CPU_MX6SL 0x60
-#define MXC_CPU_MX6DL 0x61
-#define MXC_CPU_MX6SOLO 0x62
-#define MXC_CPU_MX6Q 0x63
+#include "../arch-imx/cpu.h"
#define is_soc_rev(rev) ((get_cpu_rev() & 0xFF) - rev)
u32 get_cpu_rev(void);
unsigned imx_ddr_size(void);
void sdelay(unsigned long);
void set_chipselect_size(int const);
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
/*
* Initializes on-chip ethernet controllers.
MXC_I2C_CLK,
};
+enum enet_freq {
+ ENET_25MHZ,
+ ENET_50MHZ,
+ ENET_100MHZ,
+ ENET_125MHZ,
+};
+ struct clk {
+ const char *name;
+ int id;
+ /* Source clock this clk depends on */
+ struct clk *parent;
+ /* Secondary clock to enable/disable with this clock */
+ struct clk *secondary;
+ /* Current clock rate */
+ unsigned long rate;
+ /* Reference count of clock enable/disable */
+ __s8 usecount;
+ /* Register bit position for clock's enable/disable control. */
+ u8 enable_shift;
+ /* Register address for clock's enable/disable control. */
+ void *enable_reg;
+ u32 flags;
+ /*
+ * Function ptr to recalculate the clock's rate based on parent
+ * clock's rate
+ */
+ void (*recalc) (struct clk *);
+ /*
+ * Function ptr to set the clock to a new rate. The rate must match a
+ * supported rate returned from round_rate. Leave blank if clock is not
+ * programmable
+ */
+ int (*set_rate) (struct clk *, unsigned long);
+ /*
+ * Function ptr to round the requested clock rate to the nearest
+ * supported rate that is less than or equal to the requested rate.
+ */
+ unsigned long (*round_rate) (struct clk *, unsigned long);
+ /*
+ * Function ptr to enable the clock. Leave blank if clock can not
+ * be gated.
+ */
+ int (*enable) (struct clk *);
+ /*
+ * Function ptr to disable the clock. Leave blank if clock can not
+ * be gated.
+ */
+ void (*disable) (struct clk *);
+ /* Function ptr to set the parent clock of the clock. */
+ int (*set_parent) (struct clk *, struct clk *);
+ };
+
u32 imx_get_uartclk(void);
u32 imx_get_fecclk(void);
unsigned int mxc_get_clock(enum mxc_clock clk);
+ int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk);
+void setup_gpmi_io_clk(u32 cfg);
+void hab_caam_clock_enable(unsigned char enable);
void enable_ocotp_clk(unsigned char enable);
void enable_usboh3_clk(unsigned char enable);
+void enable_uart_clk(unsigned char enable);
+int enable_cspi_clock(unsigned char enable, unsigned spi_num);
+int enable_usdhc_clk(unsigned char enable, unsigned bus_num);
int enable_sata_clock(void);
+void disable_sata_clock(void);
+int enable_pcie_clock(void);
int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
-
+int enable_spi_clk(unsigned char enable, unsigned spi_num);
+void enable_ipu_clock(void);
+int enable_fec_anatop_clock(enum enet_freq freq);
+void enable_enet_clk(unsigned char enable);
+void enable_qspi_clk(int qspi_num);
+void enable_thermal_clk(void);
+ void ipu_clk_enable(void);
+ void ipu_clk_disable(void);
+ void ipu_di_clk_enable(int di);
+ void ipu_di_clk_disable(int di);
+ void ldb_clk_enable(int ldb);
+ void ldb_clk_disable(int ldb);
+ void ocotp_clk_enable(void);
+ void ocotp_clk_disable(void);
#endif /* __ASM_ARCH_CLOCK_H */
u32 CCGR6; /* 0x0080 */
u32 CCGR7;
u32 cmeor;
- u32 resv[0xfdd];
- u32 analog_pll_sys; /* 0x4000 */
- u32 analog_pll_sys_set;
- u32 analog_pll_sys_clr;
- u32 analog_pll_sys_tog;
- u32 analog_usb1_pll_480_ctrl; /* 0x4010 */
- u32 analog_usb1_pll_480_ctrl_set;
- u32 analog_usb1_pll_480_ctrl_clr;
- u32 analog_usb1_pll_480_ctrl_tog;
- u32 analog_reserved0[4];
- u32 analog_pll_528; /* 0x4030 */
- u32 analog_pll_528_set;
- u32 analog_pll_528_clr;
- u32 analog_pll_528_tog;
- u32 analog_pll_528_ss; /* 0x4040 */
- u32 analog_reserved1[3];
- u32 analog_pll_528_num; /* 0x4050 */
- u32 analog_reserved2[3];
- u32 analog_pll_528_denom; /* 0x4060 */
- u32 analog_reserved3[3];
- u32 analog_pll_audio; /* 0x4070 */
- u32 analog_pll_audio_set;
- u32 analog_pll_audio_clr;
- u32 analog_pll_audio_tog;
- u32 analog_pll_audio_num; /* 0x4080*/
- u32 analog_reserved4[3];
- u32 analog_pll_audio_denom; /* 0x4090 */
- u32 analog_reserved5[3];
- u32 analog_pll_video; /* 0x40a0 */
- u32 analog_pll_video_set;
- u32 analog_pll_video_clr;
- u32 analog_pll_video_tog;
- u32 analog_pll_video_num; /* 0x40b0 */
- u32 analog_reserved6[3];
- u32 analog_pll_video_denom; /* 0x40c0 */
- u32 analog_reserved7[7];
- u32 analog_pll_enet; /* 0x40e0 */
- u32 analog_pll_enet_set;
- u32 analog_pll_enet_clr;
- u32 analog_pll_enet_tog;
- u32 analog_pfd_480; /* 0x40f0 */
- u32 analog_pfd_480_set;
- u32 analog_pfd_480_clr;
- u32 analog_pfd_480_tog;
- u32 analog_pfd_528; /* 0x4100 */
- u32 analog_pfd_528_set;
- u32 analog_pfd_528_clr;
- u32 analog_pfd_528_tog;
};
-
-struct anatop_regs {
- mxs_reg_32(pll_arm); /* 0x000 */
- mxs_reg_32(usb1_pll_480_ctrl); /* 0x010 */
- mxs_reg_32(usb2_pll_480_ctrl); /* 0x020 */
- mxs_reg_32(pll_528); /* 0x030 */
- reg_32(pll_528_ss); /* 0x040 */
- reg_32(pll_528_num); /* 0x050 */
- reg_32(pll_528_denom); /* 0x060 */
- mxs_reg_32(pll_audio); /* 0x070 */
- reg_32(pll_audio_num); /* 0x080 */
- reg_32(pll_audio_denom); /* 0x090 */
- mxs_reg_32(pll_video); /* 0x0a0 */
- reg_32(pll_video_num); /* 0x0b0 */
- reg_32(pll_video_denom); /* 0x0c0 */
- mxs_reg_32(pll_mlb); /* 0x0d0 */
- mxs_reg_32(pll_enet); /* 0x0e0 */
- mxs_reg_32(pfd_480); /* 0x0f0 */
- mxs_reg_32(pfd_528); /* 0x100 */
- mxs_reg_32(reg_1p1); /* 0x110 */
- mxs_reg_32(reg_3p0); /* 0x120 */
- mxs_reg_32(reg_2p5); /* 0x130 */
- mxs_reg_32(reg_core); /* 0x140 */
- mxs_reg_32(ana_misc0); /* 0x150 */
- mxs_reg_32(ana_misc1); /* 0x160 */
- mxs_reg_32(ana_misc2); /* 0x170 */
- mxs_reg_32(tempsense0); /* 0x180 */
- mxs_reg_32(tempsense1); /* 0x190 */
- mxs_reg_32(usb1_vbus_detect); /* 0x1a0 */
- mxs_reg_32(usb1_chrg_detect); /* 0x1b0 */
- mxs_reg_32(usb1_vbus_det_stat); /* 0x1c0 */
- mxs_reg_32(usb1_chrg_det_stat); /* 0x1d0 */
- mxs_reg_32(usb1_loopback); /* 0x1e0 */
- mxs_reg_32(usb1_misc); /* 0x1f0 */
- mxs_reg_32(usb2_vbus_detect); /* 0x200 */
- mxs_reg_32(usb2_chrg_detect); /* 0x210 */
- mxs_reg_32(usb2_vbus_det_stat); /* 0x220 */
- mxs_reg_32(usb2_chrg_det_stat); /* 0x230 */
- mxs_reg_32(usb2_loopback); /* 0x240 */
- mxs_reg_32(usb2_misc); /* 0x250 */
- reg_32(digprog); /* 0x260 */
- reg_32(rsrvd); /* 0x270 */
- reg_32(digprog_sololite); /* 0x280 */
-};
#endif
/* Define the bits in register CCR */
#define MXC_CCM_CCR_RBC_EN (1 << 27)
- #define MXC_CCM_CCR_REG_BYPASS_CNT_MASK (0x3F << 21)
+ #define MXC_CCM_CCR_REG_BYPASS_CNT_MASK (0x3F << CCR_REG_BYPASS_CNT_OFFSET)
#define MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET 21
- #define MXC_CCM_CCR_WB_COUNT_MASK 0x7
+ #define MXC_CCM_CCR_WB_COUNT_MASK (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET)
#define MXC_CCM_CCR_WB_COUNT_OFFSET (1 << 16)
#define MXC_CCM_CCR_COSC_EN (1 << 12)
-#define MXC_CCM_CCR_OSCNT_MASK (0xFF << MXC_CCM_CCR_OSCNT_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCR_OSCNT_MASK 0x7F
+#else
+#define MXC_CCM_CCR_OSCNT_MASK 0xFF
+#endif
#define MXC_CCM_CCR_OSCNT_OFFSET 0
/* Define the bits in register CCDR */
/* Define the bits in register CACRR */
#define MXC_CCM_CACRR_ARM_PODF_OFFSET 0
- #define MXC_CCM_CACRR_ARM_PODF_MASK 0x7
+ #define MXC_CCM_CACRR_ARM_PODF_MASK (0x7 << MXC_CCM_CACRR_ARM_PODF_OFFSET)
/* Define the bits in register CBCDR */
- #define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK (0x7 << 27)
+ #define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK (0x7 << MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET)
#define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET 27
#define MXC_CCM_CBCDR_PERIPH2_CLK2_SEL (1 << 26)
#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (1 << 25)
- #define MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK (0x7 << 19)
+#ifndef CONFIG_MX6SX
+ #define MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK (0x7 << MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET)
#define MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET 19
- #define MXC_CCM_CBCDR_AXI_PODF_MASK (0x7 << 16)
+#endif
+ #define MXC_CCM_CBCDR_AXI_PODF_MASK (0x7 << MXC_CCM_CBCDR_AXI_PODF_OFFSET)
#define MXC_CCM_CBCDR_AXI_PODF_OFFSET 16
- #define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
+ #define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << MXC_CCM_CBCDR_AHB_PODF_OFFSET)
#define MXC_CCM_CBCDR_AHB_PODF_OFFSET 10
- #define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
+ #define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << MXC_CCM_CBCDR_IPG_PODF_OFFSET)
#define MXC_CCM_CBCDR_IPG_PODF_OFFSET 8
#define MXC_CCM_CBCDR_AXI_ALT_SEL (1 << 7)
#define MXC_CCM_CBCDR_AXI_SEL (1 << 6)
- #define MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK (0x7 << 3)
+ #define MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK (0x7 << MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET)
#define MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET 3
- #define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_MASK (0x7 << 0)
+ #define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_MASK (0x7 << MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET)
#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET 0
/* Define the bits in register CBCMR */
- #define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << 29)
+ #define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET)
#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET 29
- #define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << 26)
+ #define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET)
#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET 26
- #define MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK (0x7 << 23)
+ #define MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK (0x7 << MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET)
#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET 23
- #define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << 21)
+ #define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET)
#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET 21
#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20)
- #define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18)
+ #define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET)
#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET 18
- #define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16)
+#ifndef CONFIG_MX6SX
+ #define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET)
#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET 16
- #define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
+ #define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET)
#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET 14
- #define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12)
+#endif
+ #define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET)
#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET 12
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CBCMR_VDOAXI_CLK_SEL (1 << 11)
+#endif
#define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10)
- #define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << 8)
+ #define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET)
#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET 8
- #define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << 4)
+ #define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET)
#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET 4
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL (1 << 1)
#define MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL (1 << 0)
+#endif
/* Define the bits in register CSCMR1 */
- #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK (0x3 << 29)
+ #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK (0x3 << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET)
#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET 29
- #define MXC_CCM_CSCMR1_QSPI1_PODF_MASK (0x7 << 26)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CSCMR1_ACLK_EMI_MASK (0x3 << 27)
++#define MXC_CCM_CSCMR1_QSPI1_PODF_MASK (0x7 << MXC_CCM_CSCMR1_QSPI1_PODF_OFFSET)
+#define MXC_CCM_CSCMR1_QSPI1_PODF_OFFSET 26
+#else
+ #define MXC_CCM_CSCMR1_ACLK_EMI_MASK (0x3 << MXC_CCM_CSCMR1_ACLK_EMI_OFFSET)
#define MXC_CCM_CSCMR1_ACLK_EMI_OFFSET 27
- #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << 23)
+#endif
+ #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET)
#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET 23
- #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20)
+/* ACLK_EMI_PODF is LCFIF2_PODF on MX6SX */
+ #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET)
#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET 20
#define MXC_CCM_CSCMR1_USDHC4_CLK_SEL (1 << 19)
#define MXC_CCM_CSCMR1_USDHC3_CLK_SEL (1 << 18)
#define MXC_CCM_CSCMR1_USDHC2_CLK_SEL (1 << 17)
#define MXC_CCM_CSCMR1_USDHC1_CLK_SEL (1 << 16)
- #define MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK (0x3 << 14)
+ #define MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK (0x3 << MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET)
#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET 14
- #define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
+ #define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET)
#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET 12
- #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 10)
+ #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET)
#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET 10
- #define MXC_CCM_CSCMR1_QSPI1_CLK_SEL_MASK (0x7 << 7)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CSCMR1_PER_CLK_SEL_MASK (1 << 6)
++#define MXC_CCM_CSCMR1_QSPI1_CLK_SEL_MASK (0x7 << MXC_CCM_CSCMR1_QSPI1_CLK_SEL_OFFSET)
+#define MXC_CCM_CSCMR1_QSPI1_CLK_SEL_OFFSET 7
+#endif
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
- #define MXC_CCM_CSCMR1_PERCLK_PODF_MASK 0x3F
++#define MXC_CCM_CSCMR1_PER_CLK_SEL_MASK (1 << MXC_CCM_CSCMR1_PER_CLK_SEL_OFFSET)
+#define MXC_CCM_CSCMR1_PER_CLK_SEL_OFFSET 6
+#endif
+ #define MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET 0
+ #define MXC_CCM_CSCMR1_PERCLK_PODF_MASK (0x3F << MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET)
/* Define the bits in register CSCMR2 */
- #define MXC_CCM_CSCMR2_VID_CLK_SEL_MASK (0x7 << 21)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK (0x3 << 19)
++#define MXC_CCM_CSCMR2_VID_CLK_SEL_MASK (0x7 << MXC_CCM_CSCMR2_VID_CLK_SEL_OFFSET)
+#define MXC_CCM_CSCMR2_VID_CLK_SEL_OFFSET 21
+#endif
+ #define MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK (0x3 << MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET)
#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET 19
#define MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV (1 << 11)
#define MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV (1 << 10)
- #define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3 << 8)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK (0x3F << 2)
++#define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3 << MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET)
+#define MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET 8
- #define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3F << 2)
++#define MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK (0x3F << MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET)
+#define MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET 2
+#else
+ #define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3F << MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET)
#define MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET 2
+#endif
/* Define the bits in register CSCDR1 */
- #define MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK (0x7 << 25)
+#ifndef CONFIG_MX6SX
+ #define MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK (0x7 << MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET)
#define MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET 25
- #define MXC_CCM_CSCDR1_USDHC4_PODF_MASK (0x7 << 22)
+#endif
+ #define MXC_CCM_CSCDR1_USDHC4_PODF_MASK (0x7 << MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET)
#define MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET 22
- #define MXC_CCM_CSCDR1_USDHC3_PODF_MASK (0x7 << 19)
+ #define MXC_CCM_CSCDR1_USDHC3_PODF_MASK (0x7 << MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET)
#define MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET 19
- #define MXC_CCM_CSCDR1_USDHC2_PODF_MASK (0x7 << 16)
+ #define MXC_CCM_CSCDR1_USDHC2_PODF_MASK (0x7 << MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET)
#define MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET 16
- #define MXC_CCM_CSCDR1_USDHC1_PODF_MASK (0x7 << 11)
+ #define MXC_CCM_CSCDR1_USDHC1_PODF_MASK (0x7 << MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET)
#define MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET 11
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET 8
- #define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
+ #define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET 6
- #define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
+ #define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET)
+#endif
#ifdef CONFIG_MX6SL
- #define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK 0x1F
- #define MXC_CCM_CSCDR1_UART_CLK_SEL (1 << 6)
+ #define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x1F << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET)
+ #define MXC_CCM_CSCDR1_UART_CLK_SEL (1 << MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET)
#else
- #define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK 0x3F
+ #define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x3F << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CSCDR1_UART_CLK_SEL (1 << 6)
++#define MXC_CCM_CSCDR1_UART_CLK_SEL (1 << MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET)
+#endif
#endif
+ #define MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET 6
#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET 0
/* Define the bits in register CS1CDR */
- #define MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK (0x3F << 25)
+ #define MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK (0x3F << MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET)
#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET 25
- #define MXC_CCM_CS1CDR_SSI3_CLK_PRED_MASK (0x7 << 22)
++#define MXC_CCM_CS1CDR_SSI3_CLK_PRED_MASK (0x7 << MXC_CCM_CS1CDR_SSI3_CLK_PRED_OFFSET)
+#define MXC_CCM_CS1CDR_SSI3_CLK_PRED_OFFSET 22
- #define MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK (0x3F << 16)
+ #define MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK (0x3F << MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET)
#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET 16
- #define MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK (0x3 << 9)
+ #define MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK (0x3 << MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET)
#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET 9
- #define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
+ #define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET)
#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET 6
- #define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK 0x3F
+ #define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F << MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET)
#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET 0
/* Define the bits in register CS2CDR */
- #define MXC_CCM_CS2CDR_QSPI2_CLK_PODF_MASK (0x3F << 21)
- #define MXC_CCM_CS2CDR_QSPI2_CLK_PODF_OFFSET 21
- #define MXC_CCM_CS2CDR_QSPI2_CLK_PODF(v) (((v) & 0x3f) << 21)
- #define MXC_CCM_CS2CDR_QSPI2_CLK_PRED_MASK (0x7 << 18)
- #define MXC_CCM_CS2CDR_QSPI2_CLK_PRED_OFFSET 18
- #define MXC_CCM_CS2CDR_QSPI2_CLK_PRED(v) (((v) & 0x7) << 18)
- #define MXC_CCM_CS2CDR_QSPI2_CLK_SEL_MASK (0x7 << 15)
- #define MXC_CCM_CS2CDR_QSPI2_CLK_SEL_OFFSET 15
- #define MXC_CCM_CS2CDR_QSPI2_CLK_SEL(v) (((v) & 0x7) << 15)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK (0x3F << 21)
++#define MXC_CCM_CS2CDR_QSPI2_CLK_PODF_MASK (0x3F << MXC_CCM_CS2CDR_QSPI2_CLK_PODF_OFFSET)
++#define MXC_CCM_CS2CDR_QSPI2_CLK_PODF_OFFSET 21
++#define MXC_CCM_CS2CDR_QSPI2_CLK_PODF(v) (((v) & 0x3f) << MXC_CCM_CS2CDR_QSPI2_CLK_PODF_OFFSET)
++#define MXC_CCM_CS2CDR_QSPI2_CLK_PRED_MASK (0x7 << MXC_CCM_CS2CDR_QSPI2_CLK_PRED_OFFSET)
++#define MXC_CCM_CS2CDR_QSPI2_CLK_PRED_OFFSET 18
++#define MXC_CCM_CS2CDR_QSPI2_CLK_PRED(v) (((v) & 0x7) << MXC_CCM_CS2CDR_QSPI2_CLK_PRED_OFFSET)
++#define MXC_CCM_CS2CDR_QSPI2_CLK_SEL_MASK (0x7 << MXC_CCM_CS2CDR_QSPI2_CLK_SEL_OFFSET)
++#define MXC_CCM_CS2CDR_QSPI2_CLK_SEL_OFFSET 15
++#define MXC_CCM_CS2CDR_QSPI2_CLK_SEL(v) (((v) & 0x7) << MXC_CCM_CS2CDR_QSPI2_CLK_SEL_OFFSET)
+#else
+ #define MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK (0x3F << MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET)
#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET 21
- #define MXC_CCM_CS2CDR_ENFC_CLK_PODF(v) (((v) & 0x3f) << 21)
- #define MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK (0x7 << 18)
+ #define MXC_CCM_CS2CDR_ENFC_CLK_PODF(v) (((v) & 0x3f) << MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET)
+ #define MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK (0x7 << MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET)
#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET 18
- #define MXC_CCM_CS2CDR_ENFC_CLK_PRED(v) (((v) & 0x7) << 18)
- #define MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK (0x3 << 16)
+ #define MXC_CCM_CS2CDR_ENFC_CLK_PRED(v) (((v) & 0x7) << MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET)
+ #define MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK (0x3 << MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET)
#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET 16
- #define MXC_CCM_CS2CDR_ENFC_CLK_SEL(v) (((v) & 0x3) << 16)
+ #define MXC_CCM_CS2CDR_ENFC_CLK_SEL(v) (((v) & 0x3) << MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET)
+#endif
- #define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK (0x7 << 12)
+ #define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK (0x7 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET 12
- #define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK (0x7 << 9)
+ #define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK (0x7 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET 9
- #define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
+ #define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET)
#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET 6
- #define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK 0x3F
+ #define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F << MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET)
#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET 0
/* Define the bits in register CDCDR */
- #define MXC_CCM_CDCDR_HSI_TX_PODF_MASK (0x7 << 29)
+#ifndef CONFIG_MX6SX
+ #define MXC_CCM_CDCDR_HSI_TX_PODF_MASK (0x7 << MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET)
#define MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET 29
--#define MXC_CCM_CDCDR_HSI_TX_CLK_SEL (1 << 28)
++#define MXC_CCM_CDCDR_HSI_TX_CLK_SEL_MASK (1 << MXC_CCM_CDCDR_HSI_TX_CLK_SEL_OFFSET)
++#define MXC_CCM_CDCDR_HSI_TX_CLK_SEL_OFFSET 28
+#endif
- #define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
+ #define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET 25
- #define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x7 << 22)
+ #define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x7 << MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET 19
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET 22
- #define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK (0x3 << 20)
+ #define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK (0x3 << MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET)
#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET 20
- #define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 12)
+ #define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET 12
- #define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x7 << 9)
+ #define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x7 << MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET 9
- #define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_MASK (0x3 << 7)
+ #define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_MASK (0x3 << MXC_CCM_CDCDR_SPDIF1_CLK_SEL_OFFSET)
#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_OFFSET 7
/* Define the bits in register CHSCCDR */
- #define MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_MASK (0x7 << 15)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CHSCCDR_ENET_PODF_MASK (0x7 << 12)
++#define MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_OFFSET)
+#define MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_OFFSET 15
- #define MXC_CCM_CHSCCDR_ENET_CLK_SEL_MASK (0x7 << 9)
++#define MXC_CCM_CHSCCDR_ENET_PODF_MASK (0x7 << MXC_CCM_CHSCCDR_ENET_PODF_OFFSET)
+#define MXC_CCM_CHSCCDR_ENET_PODF_OFFSET 12
- #define MXC_CCM_CHSCCDR_M4_PRE_CLK_SEL_MASK (0x7 << 6)
++#define MXC_CCM_CHSCCDR_ENET_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_ENET_CLK_SEL_OFFSET)
+#define MXC_CCM_CHSCCDR_ENET_CLK_SEL_OFFSET 9
- #define MXC_CCM_CHSCCDR_M4_PODF_MASK (0x7 << 3)
++#define MXC_CCM_CHSCCDR_M4_PRE_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_M4_PRE_CLK_SEL_OFFSET)
+#define MXC_CCM_CHSCCDR_M4_PRE_CLK_SEL_OFFSET 6
- #define MXC_CCM_CHSCCDR_M4_CLK_SEL_MASK (0x7)
++#define MXC_CCM_CHSCCDR_M4_PODF_MASK (0x7 << MXC_CCM_CHSCCDR_M4_PODF_OFFSET)
+#define MXC_CCM_CHSCCDR_M4_PODF_OFFSET 3
- #define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK (0x7 << 15)
++#define MXC_CCM_CHSCCDR_M4_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_M4_CLK_SEL_OFFSET)
+#define MXC_CCM_CHSCCDR_M4_CLK_SEL_OFFSET 0
+#else
+ #define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_DI1_PRE_CLK_SEL_OFFSET)
#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET 15
- #define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK (0x7 << 12)
+ #define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK (0x7 << MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET)
#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET 12
- #define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK (0x7 << 9)
+ #define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET)
#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET 9
- #define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
+ #define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_DI0_PRE_CLK_SEL_OFFSET)
#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET 6
- #define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << 3)
+ #define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET 3
- #define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7)
+ #define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)
#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET 0
+#endif
- #define CHSCCDR_CLK_SEL_LDB_DI0 3
- #define CHSCCDR_PODF_DIVIDE_BY_3 2
- #define CHSCCDR_IPU_PRE_CLK_540M_PFD 5
-
/* Define the bits in register CSCDR2 */
- #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << 19)
+ #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET)
#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET 19
- #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15)
- #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_OFFSET 15
- #define MXC_CCM_CHSCCDR_IPU2_DI1_PODF_MASK (0x7 << 12)
- #define MXC_CCM_CHSCCDR_IPU2_DI1_PODF_OFFSET 12
- #define MXC_CCM_CHSCCDR_IPU2_DI1_CLK_SEL_MASK (0x7 << 9)
- #define MXC_CCM_CHSCCDR_IPU2_DI1_CLK_SEL_OFFSET 9
+/* All IPU2_DI1 are LCDIF1 on MX6SX */
- #define MXC_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
- #define MXC_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL_OFFSET 6
- #define MXC_CCM_CHSCCDR_IPU2_DI0_PODF_MASK (0x7 << 3)
- #define MXC_CCM_CHSCCDR_IPU2_DI0_PODF_OFFSET 3
- #define MXC_CCM_CHSCCDR_IPU2_DI0_CLK_SEL_MASK 0x7
- #define MXC_CCM_CHSCCDR_IPU2_DI0_CLK_SEL_OFFSET 0
+ #define MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << MXC_CCM_CSCDR2_DI1_PRE_CLK_SEL_OFFSET)
+ #define MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_OFFSET 15
+ #define MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK (0x7 << MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET)
+ #define MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET 12
+ #define MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_MASK (0x7 << MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_OFFSET)
+ #define MXC_CCM_CSCDR2_IPU2_DI1_CLK_SEL_OFFSET 9
+/* All IPU2_DI0 are LCDIF2 on MX6SX */
+ #define MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_MASK (0x7 << MXC_CCM_CSCDR2_DI0_PRE_CLK_SEL_OFFSET)
+ #define MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_OFFSET 6
+ #define MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK (0x7 << MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET)
+ #define MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET 3
+ #define MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_MASK (0x7 << MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_OFFSET)
+ #define MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_OFFSET 0
/* Define the bits in register CSCDR3 */
- #define MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK (0x7 << 16)
+ #define MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK (0x7 << MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET)
#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET 16
- #define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK (0x3 << 14)
+ #define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK (0x3 << MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET)
#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET 14
- #define MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK (0x7 << 11)
+ #define MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK (0x7 << MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET)
#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET 11
- #define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK (0x3 << 9)
+ #define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK (0x3 << MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET)
#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET 9
/* Define the bits in register CDHIPR */
#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CDHIPR_MMDC_CH0_PODF_BUSY (1 << 4)
+#endif
#define MXC_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY (1 << 3)
#define MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY (1 << 2)
#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 1)
- #define MXC_CCM_CDHIPR_AXI_PODF_BUSY 1
+ #define MXC_CCM_CDHIPR_AXI_PODF_BUSY (1 << 0)
/* Define the bits in register CLPCR */
#define MXC_CCM_CLPCR_MASK_L2CC_IDLE (1 << 27)
#define MXC_CCM_CLPCR_MASK_SCU_IDLE (1 << 26)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CLPCR_MASK_CORE3_WFI (1 << 25)
#define MXC_CCM_CLPCR_MASK_CORE2_WFI (1 << 24)
#define MXC_CCM_CLPCR_MASK_CORE1_WFI (1 << 23)
+#endif
#define MXC_CCM_CLPCR_MASK_CORE0_WFI (1 << 22)
#define MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS (1 << 21)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS (1 << 19)
#define MXC_CCM_CLPCR_WB_CORE_AT_LPM (1 << 17)
-#define MXC_CCM_CLPCR_WB_PER_AT_LPM (1 << 17)
+#endif
+#define MXC_CCM_CLPCR_WB_PER_AT_LPM (1 << 16)
#define MXC_CCM_CLPCR_COSC_PWRDOWN (1 << 11)
- #define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
+ #define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET)
#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET 9
#define MXC_CCM_CLPCR_VSTBY (1 << 8)
#define MXC_CCM_CLPCR_DIS_REF_OSC (1 << 7)
#define MXC_CCM_CLPCR_SBYOS (1 << 6)
#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (1 << 5)
- #define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
+#ifndef CONFIG_MX6SX
+ #define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET)
#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET 3
#define MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY (1 << 2)
- #define MXC_CCM_CLPCR_LPM_MASK 0x3
+#endif
+ #define MXC_CCM_CLPCR_LPM_MASK (0x3 << MXC_CCM_CLPCR_LPM_OFFSET)
#define MXC_CCM_CLPCR_LPM_OFFSET 0
/* Define the bits in register CISR */
#define MXC_CCM_CISR_ARM_PODF_LOADED (1 << 26)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CISR_MMDC_CH0_PODF_LOADED (1 << 23)
+#endif
#define MXC_CCM_CISR_PERIPH_CLK_SEL_LOADED (1 << 22)
#define MXC_CCM_CISR_MMDC_CH1_PODF_LOADED (1 << 21)
#define MXC_CCM_CISR_AHB_PODF_LOADED (1 << 20)
#define MXC_CCM_CISR_PERIPH2_CLK_SEL_LOADED (1 << 19)
#define MXC_CCM_CISR_AXI_PODF_LOADED (1 << 17)
#define MXC_CCM_CISR_COSC_READY (1 << 6)
- #define MXC_CCM_CISR_LRF_PLL 1
+ #define MXC_CCM_CISR_LRF_PLL (1 << 0)
/* Define the bits in register CIMR */
#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (1 << 26)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED (1 << 23)
+#endif
#define MXC_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED (1 << 22)
#define MXC_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED (1 << 21)
#define MXC_CCM_CIMR_MASK_AHB_PODF_LOADED (1 << 20)
-#define MXC_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED (1 << 22)
+#define MXC_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED (1 << 19)
#define MXC_CCM_CIMR_MASK_AXI_PODF_LOADED (1 << 17)
#define MXC_CCM_CIMR_MASK_COSC_READY (1 << 6)
- #define MXC_CCM_CIMR_MASK_LRF_PLL 1
+ #define MXC_CCM_CIMR_MASK_LRF_PLL (1 << 0)
/* Define the bits in register CCOSR */
#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (1 << 24)
- #define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21)
+ #define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << MXC_CCM_CCOSR_CKO2_DIV_OFFSET)
#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET 21
#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET 16
- #define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16)
+ #define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << MXC_CCM_CCOSR_CKO2_SEL_OFFSET)
+#define MXC_CCM_CCOSR_CLK_OUT_SEL (0x1 << 8)
#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7)
- #define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4)
+ #define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << MXC_CCM_CCOSR_CKOL_DIV_OFFSET)
#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET 4
- #define MXC_CCM_CCOSR_CKOL_SEL_MASK 0xF
+ #define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF << MXC_CCM_CCOSR_CKOL_SEL_OFFSET)
#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET 0
/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_FAST_PLL_EN (1 << 16)
#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (1 << 4)
#define MXC_CCM_CGPR_MMDC_EXT_CLK_DIS (1 << 2)
- #define MXC_CCM_CGPR_PMIC_DELAY_SCALER 1
+ #define MXC_CCM_CGPR_PMIC_DELAY_SCALER (1 << 0)
/* Define the bits in registers CCGRx */
#define MXC_CCM_CCGR_CG_MASK 3
#define MXC_CCM_CCGR0_DCIC1_MASK (3 << MXC_CCM_CCGR0_DCIC1_OFFSET)
#define MXC_CCM_CCGR0_DCIC2_OFFSET 26
#define MXC_CCM_CCGR0_DCIC2_MASK (3 << MXC_CCM_CCGR0_DCIC2_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR0_AIPS_TZ3_OFFSET 30
+#define MXC_CCM_CCGR0_AIPS_TZ3_MASK (3 << MXC_CCM_CCGR0_AIPS_TZ3_OFFSET)
+#else
#define MXC_CCM_CCGR0_DTCP_OFFSET 28
#define MXC_CCM_CCGR0_DTCP_MASK (3 << MXC_CCM_CCGR0_DTCP_OFFSET)
+#endif
#define MXC_CCM_CCGR1_ECSPI1S_OFFSET 0
#define MXC_CCM_CCGR1_ECSPI1S_MASK (3 << MXC_CCM_CCGR1_ECSPI1S_OFFSET)
#define MXC_CCM_CCGR1_ECSPI4S_MASK (3 << MXC_CCM_CCGR1_ECSPI4S_OFFSET)
#define MXC_CCM_CCGR1_ECSPI5S_OFFSET 8
#define MXC_CCM_CCGR1_ECSPI5S_MASK (3 << MXC_CCM_CCGR1_ECSPI5S_OFFSET)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR1_ENET_CLK_ENABLE_OFFSET 10
#define MXC_CCM_CCGR1_ENET_CLK_ENABLE_MASK (3 << MXC_CCM_CCGR1_ENET_CLK_ENABLE_OFFSET)
+#endif
#define MXC_CCM_CCGR1_EPIT1S_OFFSET 12
#define MXC_CCM_CCGR1_EPIT1S_MASK (3 << MXC_CCM_CCGR1_EPIT1S_OFFSET)
#define MXC_CCM_CCGR1_EPIT2S_OFFSET 14
#define MXC_CCM_CCGR1_EPIT2S_MASK (3 << MXC_CCM_CCGR1_EPIT2S_OFFSET)
#define MXC_CCM_CCGR1_ESAIS_OFFSET 16
#define MXC_CCM_CCGR1_ESAIS_MASK (3 << MXC_CCM_CCGR1_ESAIS_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR1_WAKEUP_OFFSET 18
+#define MXC_CCM_CCGR1_WAKEUP_MASK (3 << MXC_CCM_CCGR1_WAKEUP_OFFSET)
+#endif
#define MXC_CCM_CCGR1_GPT_BUS_OFFSET 20
#define MXC_CCM_CCGR1_GPT_BUS_MASK (3 << MXC_CCM_CCGR1_GPT_BUS_OFFSET)
#define MXC_CCM_CCGR1_GPT_SERIAL_OFFSET 22
#define MXC_CCM_CCGR1_GPT_SERIAL_MASK (3 << MXC_CCM_CCGR1_GPT_SERIAL_OFFSET)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR1_GPU2D_OFFSET 24
#define MXC_CCM_CCGR1_GPU2D_MASK (3 << MXC_CCM_CCGR1_GPU2D_OFFSET)
+#endif
#define MXC_CCM_CCGR1_GPU3D_OFFSET 26
#define MXC_CCM_CCGR1_GPU3D_MASK (3 << MXC_CCM_CCGR1_GPU3D_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR1_OCRAM_S_OFFSET 28
+#define MXC_CCM_CCGR1_OCRAM_S_MASK (3 << MXC_CCM_CCGR1_OCRAM_S_OFFSET)
+#define MXC_CCM_CCGR1_CANFD_OFFSET 30
+#define MXC_CCM_CCGR1_CANFD_MASK (3 << MXC_CCM_CCGR1_CANFD_OFFSET)
+#endif
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_OFFSET 0
#define MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK (3 << MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_OFFSET)
+#else
+#define MXC_CCM_CCGR2_CSI_OFFSET 2
+#define MXC_CCM_CCGR2_CSI_MASK (3 << MXC_CCM_CCGR2_CSI_OFFSET)
+#endif
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_OFFSET 4
#define MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK (3 << MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_OFFSET)
+#endif
#define MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET 6
#define MXC_CCM_CCGR2_I2C1_SERIAL_MASK (3 << MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET)
#define MXC_CCM_CCGR2_I2C2_SERIAL_OFFSET 8
#define MXC_CCM_CCGR2_IPMUX3_MASK (3 << MXC_CCM_CCGR2_IPMUX3_OFFSET)
#define MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS_OFFSET 22
#define MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS_MASK (3 << MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR2_LCD_OFFSET 28
+#define MXC_CCM_CCGR2_LCD_MASK (3 << MXC_CCM_CCGR2_LCD_OFFSET)
+#define MXC_CCM_CCGR2_PXP_OFFSET 30
+#define MXC_CCM_CCGR2_PXP_MASK (3 << MXC_CCM_CCGR2_PXP_OFFSET)
+#else
#define MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG_OFFSET 24
#define MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG_MASK (3 << MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG_OFFSET)
#define MXC_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK_OFFSET 26
#define MXC_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK_MASK (3 << MXC_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK_OFFSET)
+#endif
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR3_M4_OFFSET 2
+#define MXC_CCM_CCGR3_M4_MASK (3 << MXC_CCM_CCGR3_M4_OFFSET)
+#define MXC_CCM_CCGR3_ENET_OFFSET 4
+#define MXC_CCM_CCGR3_ENET_MASK (3 << MXC_CCM_CCGR3_ENET_OFFSET)
+#define MXC_CCM_CCGR3_QSPI_OFFSET 14
+#define MXC_CCM_CCGR3_QSPI_MASK (3 << MXC_CCM_CCGR3_QSPI_OFFSET)
+#else
#define MXC_CCM_CCGR3_IPU1_IPU_OFFSET 0
#define MXC_CCM_CCGR3_IPU1_IPU_MASK (3 << MXC_CCM_CCGR3_IPU1_IPU_OFFSET)
#define MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET 2
#define MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK (3 << MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET)
#define MXC_CCM_CCGR3_IPU1_IPU_DI1_OFFSET 4
#define MXC_CCM_CCGR3_IPU1_IPU_DI1_MASK (3 << MXC_CCM_CCGR3_IPU1_IPU_DI1_OFFSET)
+#endif
#define MXC_CCM_CCGR3_IPU2_IPU_OFFSET 6
#define MXC_CCM_CCGR3_IPU2_IPU_MASK (3 << MXC_CCM_CCGR3_IPU2_IPU_OFFSET)
#define MXC_CCM_CCGR3_IPU2_IPU_DI0_OFFSET 8
#define MXC_CCM_CCGR3_IPU2_IPU_DI1_MASK (3 << MXC_CCM_CCGR3_IPU2_IPU_DI1_OFFSET)
#define MXC_CCM_CCGR3_LDB_DI0_OFFSET 12
#define MXC_CCM_CCGR3_LDB_DI0_MASK (3 << MXC_CCM_CCGR3_LDB_DI0_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR3_QSPI1_OFFSET 14
+#define MXC_CCM_CCGR3_QSPI1_MASK (3 << MXC_CCM_CCGR3_QSPI1_OFFSET)
+#else
#define MXC_CCM_CCGR3_LDB_DI1_OFFSET 14
#define MXC_CCM_CCGR3_LDB_DI1_MASK (3 << MXC_CCM_CCGR3_LDB_DI1_OFFSET)
#define MXC_CCM_CCGR3_MIPI_CORE_CFG_OFFSET 16
#define MXC_CCM_CCGR3_MIPI_CORE_CFG_MASK (3 << MXC_CCM_CCGR3_MIPI_CORE_CFG_OFFSET)
+#endif
#define MXC_CCM_CCGR3_MLB_OFFSET 18
#define MXC_CCM_CCGR3_MLB_MASK (3 << MXC_CCM_CCGR3_MLB_OFFSET)
#define MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0_OFFSET 20
#define MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0_MASK (3 << MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0_OFFSET)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1_OFFSET 22
#define MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1_MASK (3 << MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1_OFFSET)
+#endif
#define MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0_OFFSET 24
#define MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0_MASK (3 << MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0_OFFSET)
#define MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1_OFFSET 26
#define MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1_MASK (3 << MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1_OFFSET)
#define MXC_CCM_CCGR3_OCRAM_OFFSET 28
#define MXC_CCM_CCGR3_OCRAM_MASK (3 << MXC_CCM_CCGR3_OCRAM_OFFSET)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR3_OPENVGAXICLK_OFFSET 30
#define MXC_CCM_CCGR3_OPENVGAXICLK_MASK (3 << MXC_CCM_CCGR3_OPENVGAXICLK_OFFSET)
+#endif
#define MXC_CCM_CCGR4_PCIE_OFFSET 0
#define MXC_CCM_CCGR4_PCIE_MASK (3 << MXC_CCM_CCGR4_PCIE_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR4_QSPI2_ENFC_OFFSET 10
+#define MXC_CCM_CCGR4_QSPI2_ENFC_MASK (3 << MXC_CCM_CCGR4_QSPI2_ENFC_OFFSET)
+#else
#define MXC_CCM_CCGR4_PL301_MX6QFAST1_S133_OFFSET 8
#define MXC_CCM_CCGR4_PL301_MX6QFAST1_S133_MASK (3 << MXC_CCM_CCGR4_PL301_MX6QFAST1_S133_OFFSET)
+#endif
#define MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET 12
#define MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK (3 << MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET)
#define MXC_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE_OFFSET 14
#define MXC_CCM_CCGR5_ROM_OFFSET 0
#define MXC_CCM_CCGR5_ROM_MASK (3 << MXC_CCM_CCGR5_ROM_OFFSET)
+#ifndef CONFIG_MX6SX
#define MXC_CCM_CCGR5_SATA_OFFSET 4
#define MXC_CCM_CCGR5_SATA_MASK (3 << MXC_CCM_CCGR5_SATA_OFFSET)
+#endif
#define MXC_CCM_CCGR5_SDMA_OFFSET 6
#define MXC_CCM_CCGR5_SDMA_MASK (3 << MXC_CCM_CCGR5_SDMA_OFFSET)
#define MXC_CCM_CCGR5_SPBA_OFFSET 12
#define MXC_CCM_CCGR5_UART_MASK (3 << MXC_CCM_CCGR5_UART_OFFSET)
#define MXC_CCM_CCGR5_UART_SERIAL_OFFSET 26
#define MXC_CCM_CCGR5_UART_SERIAL_MASK (3 << MXC_CCM_CCGR5_UART_SERIAL_OFFSET)
+#ifdef CONFIG_MX6SX
+#define MXC_CCM_CCGR5_SAI1_OFFSET 20
+#define MXC_CCM_CCGR5_SAI1_MASK (3 << MXC_CCM_CCGR5_SAI1_OFFSET)
+#define MXC_CCM_CCGR5_SAI2_OFFSET 30
+#define MXC_CCM_CCGR5_SAI2_MASK (3 << MXC_CCM_CCGR5_SAI2_OFFSET)
+#endif
- #define MXC_CCM_CCGR6_USBOH3_OFFSET 0
- #define MXC_CCM_CCGR6_USBOH3_MASK (3 << MXC_CCM_CCGR6_USBOH3_OFFSET)
- #define MXC_CCM_CCGR6_USDHC1_OFFSET 2
- #define MXC_CCM_CCGR6_USDHC1_MASK (3 << MXC_CCM_CCGR6_USDHC1_OFFSET)
- #define MXC_CCM_CCGR6_USDHC2_OFFSET 4
- #define MXC_CCM_CCGR6_USDHC2_MASK (3 << MXC_CCM_CCGR6_USDHC2_OFFSET)
- #define MXC_CCM_CCGR6_USDHC3_OFFSET 6
- #define MXC_CCM_CCGR6_USDHC3_MASK (3 << MXC_CCM_CCGR6_USDHC3_OFFSET)
- #define MXC_CCM_CCGR6_USDHC4_OFFSET 8
- #define MXC_CCM_CCGR6_USDHC4_MASK (3 << MXC_CCM_CCGR6_USDHC4_OFFSET)
- #define MXC_CCM_CCGR6_EMI_SLOW_OFFSET 10
- #define MXC_CCM_CCGR6_EMI_SLOW_MASK (3 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET)
+ #define MXC_CCM_CCGR6_USBOH3_OFFSET 0
+ #define MXC_CCM_CCGR6_USBOH3_MASK (3 << MXC_CCM_CCGR6_USBOH3_OFFSET)
+ #define MXC_CCM_CCGR6_USDHC1_OFFSET 2
+ #define MXC_CCM_CCGR6_USDHC1_MASK (3 << MXC_CCM_CCGR6_USDHC1_OFFSET)
+ #define MXC_CCM_CCGR6_USDHC2_OFFSET 4
+ #define MXC_CCM_CCGR6_USDHC2_MASK (3 << MXC_CCM_CCGR6_USDHC2_OFFSET)
+ #define MXC_CCM_CCGR6_USDHC3_OFFSET 6
+ #define MXC_CCM_CCGR6_USDHC3_MASK (3 << MXC_CCM_CCGR6_USDHC3_OFFSET)
+ #define MXC_CCM_CCGR6_USDHC4_OFFSET 8
+ #define MXC_CCM_CCGR6_USDHC4_MASK (3 << MXC_CCM_CCGR6_USDHC4_OFFSET)
+ #define MXC_CCM_CCGR6_EMI_SLOW_OFFSET 10
+ #define MXC_CCM_CCGR6_EMI_SLOW_MASK (3 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET)
+ #define MXC_CCM_CCGR6_VDOAXICLK_OFFSET 12
+ #define MXC_CCM_CCGR6_VDOAXICLK_MASK (3 << MXC_CCM_CCGR6_VDOAXICLK_OFFSET)
+
+ #define ANATOP_PFD_480_PFD0_FRAC_SHIFT 0
+ #define ANATOP_PFD_480_PFD0_FRAC_MASK (0x3f << ANATOP_PFD_480_PFD0_FRAC_SHIFT)
+ #define ANATOP_PFD_480_PFD0_STABLE_SHIFT 6
+ #define ANATOP_PFD_480_PFD0_STABLE_MASK (1 << ANATOP_PFD_480_PFD0_STABLE_SHIFT)
+ #define ANATOP_PFD_480_PFD0_CLKGATE_SHIFT 7
+ #define ANATOP_PFD_480_PFD0_CLKGATE_MASK (1 << ANATOP_PFD_480_PFD0_CLKGATE_SHIFT)
+ #define ANATOP_PFD_480_PFD1_FRAC_SHIFT 8
+ #define ANATOP_PFD_480_PFD1_FRAC_MASK (0x3f << ANATOP_PFD_480_PFD1_FRAC_SHIFT)
+ #define ANATOP_PFD_480_PFD1_STABLE_SHIFT 14
+ #define ANATOP_PFD_480_PFD1_STABLE_MASK (1 << ANATOP_PFD_480_PFD1_STABLE_SHIFT)
+ #define ANATOP_PFD_480_PFD1_CLKGATE_SHIFT 15
+ #define ANATOP_PFD_480_PFD1_CLKGATE_MASK (0x3f << ANATOP_PFD_480_PFD1_CLKGATE_SHIFT)
+ #define ANATOP_PFD_480_PFD2_FRAC_SHIFT 16
+ #define ANATOP_PFD_480_PFD2_FRAC_MASK (1 << ANATOP_PFD_480_PFD2_FRAC_SHIFT)
+ #define ANATOP_PFD_480_PFD2_STABLE_SHIFT 22
+ #define ANATOP_PFD_480_PFD2_STABLE_MASK (1 << ANATOP_PFD_480_PFD2_STABLE_SHIFT)
+ #define ANATOP_PFD_480_PFD2_CLKGATE_SHIFT 23
+ #define ANATOP_PFD_480_PFD2_CLKGATE_MASK (0x3f << ANATOP_PFD_480_PFD2_CLKGATE_SHIFT)
+ #define ANATOP_PFD_480_PFD3_FRAC_SHIFT 24
+ #define ANATOP_PFD_480_PFD3_FRAC_MASK (1 << ANATOP_PFD_480_PFD3_FRAC_SHIFT)
+ #define ANATOP_PFD_480_PFD3_STABLE_SHIFT 30
+ #define ANATOP_PFD_480_PFD3_STABLE_MASK (1 << ANATOP_PFD_480_PFD3_STABLE_SHIFT)
+ #define ANATOP_PFD_480_PFD3_CLKGATE_SHIFT 31
+
+ #define BM_ANADIG_PLL_ARM_LOCK (1 << 31)
+ #define BM_ANADIG_PLL_ARM_PLL_SEL (1 << 19)
+ #define BM_ANADIG_PLL_ARM_LVDS_24MHZ_SEL (1 << 18)
+ #define BM_ANADIG_PLL_ARM_LVDS_SEL (1 << 17)
+ #define BM_ANADIG_PLL_ARM_BYPASS (1 << 16)
+ #define BP_ANADIG_PLL_ARM_BYPASS_CLK_SRC 14
+ #define BM_ANADIG_PLL_ARM_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_ARM_BYPASS_CLK_SRC)
-#define BF_ANADIG_PLL_ARM_BYPASS_CLK_SRC(v) \
- (((v) << BP_ANADIG_PLL_ARM_BYPASS_CLK_SRC) & BM_ANADIG_PLL_ARM_BYPASS_CLK_SRC)
-#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__OSC_24M BF_ANADIG_PLL_ARM_BYPASS_CLK_SRC(0)
-#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__ANACLK_1 BF_ANADIG_PLL_ARM_BYPASS_CLK_SRC(1)
-#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__ANACLK_2 BF_ANADIG_PLL_ARM_BYPASS_CLK_SRC(2)
-#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__XOR BF_ANADIG_PLL_ARM_BYPASS_CLK_SRC(3)
++#define BF_ANADIG_PLL_ARM_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_ARM_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_ARM_BYPASS_CLK_SRC)
++#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_PLL_ARM_BYPASS_CLK_SRC__XOR 0x3
+ #define BM_ANADIG_PLL_ARM_ENABLE (1 << 13)
+ #define BM_ANADIG_PLL_ARM_POWERDOWN (1 << 12)
+ #define BM_ANADIG_PLL_ARM_HOLD_RING_OFF (1 << 11)
+ #define BM_ANADIG_PLL_ARM_DOUBLE_CP (1 << 10)
+ #define BM_ANADIG_PLL_ARM_HALF_CP (1 << 9)
+ #define BM_ANADIG_PLL_ARM_DOUBLE_LF (1 << 8)
+ #define BM_ANADIG_PLL_ARM_HALF_LF (1 << 7)
+ #define BP_ANADIG_PLL_ARM_DIV_SELECT 0
+ #define BM_ANADIG_PLL_ARM_DIV_SELECT (0x7F << BP_ANADIG_PLL_ARM_DIV_SELECT)
-#define BF_ANADIG_PLL_ARM_DIV_SELECT(v) \
- (((v) << BP_ANADIG_PLL_ARM_DIV_SELECT) & \
++#define BF_ANADIG_PLL_ARM_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_ARM_DIV_SELECT) & \
+ BM_ANADIG_PLL_ARM_DIV_SELECT)
+
-#define BM_ANADIG_USB1_PLL_480_CTRL_LOCK (1 << 31)
-#define BM_ANADIG_USB1_PLL_480_CTRL_BYPASS (1 << 16)
-#define BP_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC 14
-#define BM_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC (0x3 << BP_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC)
-#define BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(v) \
- (((v) << BP_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC) & \
- BM_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC)
-#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__OSC_24M BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(0)
-#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_1 BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(1)
-#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_2 BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(2)
-#define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__XOR BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(3)
-#define BM_ANADIG_USB1_PLL_480_CTRL_ENABLE (1 << 13)
-#define BM_ANADIG_USB1_PLL_480_CTRL_POWER (1 << 12)
-#define BM_ANADIG_USB1_PLL_480_CTRL_HOLD_RING_OFF (1 << 11)
-#define BM_ANADIG_USB1_PLL_480_CTRL_DOUBLE_CP (1 << 10)
-#define BM_ANADIG_USB1_PLL_480_CTRL_HALF_CP (1 << 9)
-#define BM_ANADIG_USB1_PLL_480_CTRL_DOUBLE_LF (1 << 8)
-#define BM_ANADIG_USB1_PLL_480_CTRL_HALF_LF (1 << 7)
-#define BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS (1 << 6)
-#define BP_ANADIG_USB1_PLL_480_CTRL_CONTROL0 2
-#define BM_ANADIG_USB1_PLL_480_CTRL_CONTROL0 (0x7 << BP_ANADIG_USB1_PLL_480_CTRL_CONTROL0)
-#define BF_ANADIG_USB1_PLL_480_CTRL_CONTROL0(v) \
- (((v) << BP_ANADIG_USB1_PLL_480_CTRL_CONTROL0) & \
- BM_ANADIG_USB1_PLL_480_CTRL_CONTROL0)
-#define BP_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT 0
-#define BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT (0x3 << BP_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT)
-#define BF_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT(v) \
- (((v) << BP_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT) & \
- BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT)
-
-#define BM_ANADIG_USB2_PLL_480_CTRL_LOCK (1 << 31)
-#define BM_ANADIG_USB2_PLL_480_CTRL_BYPASS (1 << 16)
-#define BP_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC 14
-#define BM_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC (0x3 << BP_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC)
-#define BF_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC(v) \
- (((v) << BP_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC) & \
- BM_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC)
-#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__OSC_24M BF_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC(0)
-#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_1 BF_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC(1)
-#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_2 BF_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC(2)
-#define BV_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC__XOR BF_ANADIG_USB2_PLL_480_CTRL_BYPASS_CLK_SRC(3)
-#define BM_ANADIG_USB2_PLL_480_CTRL_ENABLE (1 << 13)
-#define BM_ANADIG_USB2_PLL_480_CTRL_POWER (1 << 12)
-#define BM_ANADIG_USB2_PLL_480_CTRL_HOLD_RING_OFF (1 << 11)
-#define BM_ANADIG_USB2_PLL_480_CTRL_DOUBLE_CP (1 << 10)
-#define BM_ANADIG_USB2_PLL_480_CTRL_HALF_CP (1 << 9)
-#define BM_ANADIG_USB2_PLL_480_CTRL_DOUBLE_LF (1 << 8)
-#define BM_ANADIG_USB2_PLL_480_CTRL_HALF_LF (1 << 7)
-#define BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS (1 << 6)
-#define BP_ANADIG_USB2_PLL_480_CTRL_CONTROL0 2
-#define BM_ANADIG_USB2_PLL_480_CTRL_CONTROL0 (0x7 << BP_ANADIG_USB2_PLL_480_CTRL_CONTROL0)
-#define BF_ANADIG_USB2_PLL_480_CTRL_CONTROL0(v) \
- (((v) << BP_ANADIG_USB2_PLL_480_CTRL_CONTROL0) & \
- BM_ANADIG_USB2_PLL_480_CTRL_CONTROL0)
-#define BP_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT 0
-#define BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT (0x3 << BP_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT)
-#define BF_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT(v) \
- (((v) << BP_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT) & \
- BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT)
-
-#define BM_ANADIG_PLL_SYS_LOCK (1 << 31)
-#define BM_ANADIG_PLL_SYS_PLL_SEL (1 << 19)
-#define BM_ANADIG_PLL_SYS_LVDS_24MHZ_SEL (1 << 18)
-#define BM_ANADIG_PLL_SYS_LVDS_SEL (1 << 17)
-#define BM_ANADIG_PLL_SYS_BYPASS (1 << 16)
-#define BP_ANADIG_PLL_SYS_BYPASS_CLK_SRC 14
-#define BM_ANADIG_PLL_SYS_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_SYS_BYPASS_CLK_SRC)
-#define BF_ANADIG_PLL_SYS_BYPASS_CLK_SRC(v) \
- (((v) << BP_ANADIG_PLL_SYS_BYPASS_CLK_SRC) & BM_ANADIG_PLL_SYS_BYPASS_CLK_SRC)
-#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__OSC_24M 0x0
-#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__ANACLK_1 0x1
-#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__ANACLK_2 0x2
-#define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__XOR 0x3
-#define BM_ANADIG_PLL_SYS_ENABLE (1 << 13)
-#define BM_ANADIG_PLL_SYS_POWERDOWN (1 << 12)
-#define BM_ANADIG_PLL_SYS_HOLD_RING_OFF (1 << 11)
-#define BM_ANADIG_PLL_SYS_DOUBLE_CP (1 << 10)
-#define BM_ANADIG_PLL_SYS_HALF_CP (1 << 9)
-#define BM_ANADIG_PLL_SYS_DOUBLE_LF (1 << 8)
-#define BM_ANADIG_PLL_SYS_HALF_LF (1 << 7)
-#define BP_ANADIG_PLL_SYS_DIV_SELECT 0
-#define BM_ANADIG_PLL_SYS_DIV_SELECT (0x7F << BP_ANADIG_PLL_SYS_DIV_SELECT)
-#define BF_ANADIG_PLL_SYS_DIV_SELECT(v) \
- (((v) << BP_ANADIG_PLL_SYS_DIV_SELECT) & BM_ANADIG_PLL_SYS_DIV_SELECT)
++#define BM_ANADIG_PLL_528_CTRL_LOCK (1 << 31)
++#define BM_ANADIG_PLL_528_PFD_OFFSET_EN (1 << 18)
++#define BM_ANADIG_PLL_528_DITHER_ENABLE (1 << 17)
++#define BM_ANADIG_PLL_528_CTRL_BYPASS (1 << 16)
++#define BP_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC 14
++#define BM_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC)
++#define BV_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_PLL_528_CTRL_BYPASS_CLK_SRC__XOR 0x3
++#define BM_ANADIG_PLL_528_CTRL_ENABLE (1 << 13)
++#define BM_ANADIG_PLL_528_CTRL_POWER (1 << 12)
++#define BM_ANADIG_PLL_528_CTRL_HOLD_RING_OFF (1 << 11)
++#define BM_ANADIG_PLL_528_CTRL_DOUBLE_CP (1 << 10)
++#define BM_ANADIG_PLL_528_CTRL_HALF_CP (1 << 9)
++#define BM_ANADIG_PLL_528_CTRL_DOUBLE_LF (1 << 8)
++#define BM_ANADIG_PLL_528_CTRL_HALF_LF (1 << 7)
++#define BM_ANADIG_PLL_528_CTRL_EN_USB_CLKS (1 << 6)
++#define BP_ANADIG_PLL_528_CTRL_CONTROL0 2
++#define BM_ANADIG_PLL_528_CTRL_CONTROL0 (0x7 << BP_ANADIG_PLL_528_CTRL_CONTROL0)
++#define BF_ANADIG_PLL_528_CTRL_CONTROL0(v) \
++ (((v) << BP_ANADIG_PLL_528_CTRL_CONTROL0) & \
++ BM_ANADIG_PLL_528_CTRL_CONTROL0)
++#define BP_ANADIG_PLL_528_CTRL_DIV_SELECT 0
++#define BM_ANADIG_PLL_528_CTRL_DIV_SELECT (0x3 << BP_ANADIG_PLL_528_CTRL_DIV_SELECT)
++#define BF_ANADIG_PLL_528_CTRL_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_528_CTRL_DIV_SELECT) & \
++ BM_ANADIG_PLL_528_CTRL_DIV_SELECT)
+
+ #define BM_ANADIG_PLL_AUDIO_LOCK (1 << 31)
+ #define BM_ANADIG_PLL_AUDIO_SSC_EN (1 << 21)
+ #define BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT 19
+ #define BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT (0x3 << BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT)
+ #define BF_ANADIG_PLL_AUDIO_TEST_DIV_SELECT(v) \
+ (((v) << BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT) & BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT)
+ #define BM_ANADIG_PLL_AUDIO_PFD_OFFSET_EN (1 << 18)
+ #define BM_ANADIG_PLL_AUDIO_DITHER_ENABLE (1 << 17)
+ #define BM_ANADIG_PLL_AUDIO_BYPASS (1 << 16)
+ #define BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC 14
+ #define BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC)
-#define BF_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC(v) \
++#define BF_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC(v) \
+ (((v) << BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC) & BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC)
+ #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__OSC_24M 0x0
+ #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_1 0x1
+ #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_2 0x2
+ #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__XOR 0x3
+ #define BM_ANADIG_PLL_AUDIO_ENABLE (1 << 13)
+ #define BM_ANADIG_PLL_AUDIO_POWERDOWN (1 << 12)
+ #define BM_ANADIG_PLL_AUDIO_HOLD_RING_OFF (1 << 11)
+ #define BM_ANADIG_PLL_AUDIO_DOUBLE_CP (1 << 10)
+ #define BM_ANADIG_PLL_AUDIO_HALF_CP (1 << 9)
+ #define BM_ANADIG_PLL_AUDIO_DOUBLE_LF (1 << 8)
+ #define BM_ANADIG_PLL_AUDIO_HALF_LF (1 << 7)
+ #define BP_ANADIG_PLL_AUDIO_DIV_SELECT 0
+ #define BM_ANADIG_PLL_AUDIO_DIV_SELECT (0x7F << BP_ANADIG_PLL_AUDIO_DIV_SELECT)
-#define BF_ANADIG_PLL_AUDIO_DIV_SELECT(v) \
- (((v) << BP_ANADIG_PLL_AUDIO_DIV_SELECT) & BM_ANADIG_PLL_AUDIO_DIV_SELECT)
++#define BF_ANADIG_PLL_AUDIO_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_DIV_SELECT) & \
++ BM_ANADIG_PLL_AUDIO_DIV_SELECT)
+
+ #define BP_ANADIG_PLL_AUDIO_NUM_A 0
-#define BM_ANADIG_PLL_AUDIO_NUM_A 0x3FFFFFFF
-#define BF_ANADIG_PLL_AUDIO_NUM_A(v) \
- (((v) << BP_ANADIG_PLL_AUDIO_NUM_A) & BM_ANADIG_PLL_AUDIO_NUM_A)
++#define BM_ANADIG_PLL_AUDIO_NUM_A (0x3FFFFFFF << BP_ANADIG_PLL_AUDIO_NUM_A)
++#define BF_ANADIG_PLL_AUDIO_NUM_A(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_NUM_A) & \
++ BM_ANADIG_PLL_AUDIO_NUM_A)
+
+ #define BP_ANADIG_PLL_AUDIO_DENOM_B 0
-#define BM_ANADIG_PLL_AUDIO_DENOM_B 0x3FFFFFFF
-#define BF_ANADIG_PLL_AUDIO_DENOM_B(v) \
- (((v) << BP_ANADIG_PLL_AUDIO_DENOM_B) & BM_ANADIG_PLL_AUDIO_DENOM_B)
++#define BM_ANADIG_PLL_AUDIO_DENOM_B (0x3FFFFFFF << BP_ANADIG_PLL_AUDIO_DENOM_B)
++#define BF_ANADIG_PLL_AUDIO_DENOM_B(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_DENOM_B) & \
++ BM_ANADIG_PLL_AUDIO_DENOM_B)
+
+ #define BM_ANADIG_PLL_VIDEO_LOCK (1 << 31)
+ #define BM_ANADIG_PLL_VIDEO_SSC_EN (1 << 21)
+ #define BP_ANADIG_PLL_VIDEO_TEST_DIV_SELECT 19
+ #define BM_ANADIG_PLL_VIDEO_TEST_DIV_SELECT (0x3 << BP_ANADIG_PLL_VIDEO_TEST_DIV_SELECT)
-#define BF_ANADIG_PLL_VIDEO_TEST_DIV_SELECT(v) \
- (((v) << BP_ANADIG_PLL_VIDEO_TEST_DIV_SELECT) & BM_ANADIG_PLL_VIDEO_TEST_DIV_SELECT)
++#define BF_ANADIG_PLL_VIDEO_TEST_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_TEST_DIV_SELECT) & \
++ BM_ANADIG_PLL_VIDEO_TEST_DIV_SELECT)
+ #define BM_ANADIG_PLL_VIDEO_PFD_OFFSET_EN (1 << 18)
+ #define BM_ANADIG_PLL_VIDEO_DITHER_ENABLE (1 << 17)
+ #define BM_ANADIG_PLL_VIDEO_BYPASS (1 << 16)
+ #define BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC 14
+ #define BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
-#define BF_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC(v) \
- (((v) << BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC) & BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
+ #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__OSC_24M 0x0
+ #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_1 0x1
+ #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_2 0x2
+ #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__XOR 0x3
+ #define BM_ANADIG_PLL_VIDEO_ENABLE (1 << 13)
+ #define BM_ANADIG_PLL_VIDEO_POWERDOWN (1 << 12)
+ #define BM_ANADIG_PLL_VIDEO_HOLD_RING_OFF (1 << 11)
+ #define BM_ANADIG_PLL_VIDEO_DOUBLE_CP (1 << 10)
+ #define BM_ANADIG_PLL_VIDEO_HALF_CP (1 << 9)
+ #define BM_ANADIG_PLL_VIDEO_DOUBLE_LF (1 << 8)
+ #define BM_ANADIG_PLL_VIDEO_HALF_LF (1 << 7)
+ #define BP_ANADIG_PLL_VIDEO_DIV_SELECT 0
+ #define BM_ANADIG_PLL_VIDEO_DIV_SELECT (0x7F << BP_ANADIG_PLL_VIDEO_DIV_SELECT)
-#define BF_ANADIG_PLL_VIDEO_DIV_SELECT(v) \
- (((v) << BP_ANADIG_PLL_VIDEO_DIV_SELECT) & BM_ANADIG_PLL_VIDEO_DIV_SELECT)
++#define BF_ANADIG_PLL_VIDEO_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_DIV_SELECT) & \
++ BM_ANADIG_PLL_VIDEO_DIV_SELECT)
+
+ #define BP_ANADIG_PLL_VIDEO_NUM_A 0
+ #define BM_ANADIG_PLL_VIDEO_NUM_A (0x3FFFFFFF << BP_ANADIG_PLL_VIDEO_NUM_A)
-#define BF_ANADIG_PLL_VIDEO_NUM_A(v) \
- (((v) << BP_ANADIG_PLL_VIDEO_NUM_A) & BM_ANADIG_PLL_VIDEO_NUM_A)
++#define BF_ANADIG_PLL_VIDEO_NUM_A(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_NUM_A) & \
++ BM_ANADIG_PLL_VIDEO_NUM_A)
+
+ #define BP_ANADIG_PLL_VIDEO_DENOM_B 0
+ #define BM_ANADIG_PLL_VIDEO_DENOM_B (0x3FFFFFFF << BP_ANADIG_PLL_VIDEO_DENOM_B)
-#define BF_ANADIG_PLL_VIDEO_DENOM_B(v) \
- (((v) << BP_ANADIG_PLL_VIDEO_DENOM_B) & BM_ANADIG_PLL_VIDEO_DENOM_B)
++#define BF_ANADIG_PLL_VIDEO_DENOM_B(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_DENOM_B) & \
++ BM_ANADIG_PLL_VIDEO_DENOM_B)
+
+ #define BM_ANADIG_PLL_MLB_LOCK (1 << 31)
+ #define BP_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG 26
+ #define BM_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG (0x7 << BP_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG)
-#define BF_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG(v) \
- (((v) << BP_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG) & BM_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG)
++#define BF_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG(v) \
++ (((v) << BP_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG) & \
++ BM_ANADIG_PLL_MLB_MLB_FLT_RES_DLY_CFG)
+ #define BP_ANADIG_PLL_MLB_RX_CLK_DLY_CFG 23
+ #define BM_ANADIG_PLL_MLB_RX_CLK_DLY_CFG (0x7 << BP_ANADIG_PLL_MLB_RX_CLK_DLY_CFG)
-#define BF_ANADIG_PLL_MLB_RX_CLK_DLY_CFG(v) \
- (((v) << BP_ANADIG_PLL_MLB_RX_CLK_DLY_CFG) & BM_ANADIG_PLL_MLB_RX_CLK_DLY_CFG)
++#define BF_ANADIG_PLL_MLB_RX_CLK_DLY_CFG(v) \
++ (((v) << BP_ANADIG_PLL_MLB_RX_CLK_DLY_CFG) & \
++ BM_ANADIG_PLL_MLB_RX_CLK_DLY_CFG)
+ #define BP_ANADIG_PLL_MLB_VDDD_DLY_CFG 20
+ #define BM_ANADIG_PLL_MLB_VDDD_DLY_CFG (0x7 << BP_ANADIG_PLL_MLB_VDDD_DLY_CFG)
-#define BF_ANADIG_PLL_MLB_VDDD_DLY_CFG(v) \
- (((v) << BP_ANADIG_PLL_MLB_VDDD_DLY_CFG) & BM_ANADIG_PLL_MLB_VDDD_DLY_CFG)
++#define BF_ANADIG_PLL_MLB_VDDD_DLY_CFG(v) \
++ (((v) << BP_ANADIG_PLL_MLB_VDDD_DLY_CFG) & \
++ BM_ANADIG_PLL_MLB_VDDD_DLY_CFG)
+ #define BP_ANADIG_PLL_MLB_VDDA_DLY_CFG 17
+ #define BM_ANADIG_PLL_MLB_VDDA_DLY_CFG (0x7 << BP_ANADIG_PLL_MLB_VDDA_DLY_CFG)
-#define BF_ANADIG_PLL_MLB_VDDA_DLY_CFG(v) \
- (((v) << BP_ANADIG_PLL_MLB_VDDA_DLY_CFG) & BM_ANADIG_PLL_MLB_VDDA_DLY_CFG)
++#define BF_ANADIG_PLL_MLB_VDDA_DLY_CFG(v) \
++ (((v) << BP_ANADIG_PLL_MLB_VDDA_DLY_CFG) & \
++ BM_ANADIG_PLL_MLB_VDDA_DLY_CFG)
+ #define BM_ANADIG_PLL_MLB_BYPASS (1 << 16)
+ #define BP_ANADIG_PLL_MLB_PHASE_SEL 12
+ #define BM_ANADIG_PLL_MLB_PHASE_SEL (0x7 << BP_ANADIG_PLL_MLB_PHASE_SEL)
-#define BF_ANADIG_PLL_MLB_PHASE_SEL(v) \
- (((v) << BP_ANADIG_PLL_MLB_PHASE_SEL) & BM_ANADIG_PLL_MLB_PHASE_SEL)
++#define BF_ANADIG_PLL_MLB_PHASE_SEL(v) \
++ (((v) << BP_ANADIG_PLL_MLB_PHASE_SEL) & \
++ BM_ANADIG_PLL_MLB_PHASE_SEL)
+ #define BM_ANADIG_PLL_MLB_HOLD_RING_OFF (1 << 11)
+
+ #define BM_ANADIG_PLL_ENET_LOCK (1 << 31)
+ #define BM_ANADIG_PLL_ENET_ENABLE_SATA (1 << 20)
+ #define BM_ANADIG_PLL_ENET_ENABLE_PCIE (1 << 19)
+ #define BM_ANADIG_PLL_ENET_PFD_OFFSET_EN (1 << 18)
+ #define BM_ANADIG_PLL_ENET_DITHER_ENABLE (1 << 17)
+ #define BM_ANADIG_PLL_ENET_BYPASS (1 << 16)
+ #define BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC 14
+ #define BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
-#define BF_ANADIG_PLL_ENET_BYPASS_CLK_SRC(v) \
- (((v) << BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC) & BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_ENET_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
+ #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__OSC_24M 0x0
+ #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_1 0x1
+ #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_2 0x2
+ #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__XOR 0x3
+ #define BM_ANADIG_PLL_ENET_ENABLE (1 << 13)
+ #define BM_ANADIG_PLL_ENET_POWERDOWN (1 << 12)
+ #define BM_ANADIG_PLL_ENET_HOLD_RING_OFF (1 << 11)
+ #define BM_ANADIG_PLL_ENET_DOUBLE_CP (1 << 10)
+ #define BM_ANADIG_PLL_ENET_HALF_CP (1 << 9)
+ #define BM_ANADIG_PLL_ENET_DOUBLE_LF (1 << 8)
+ #define BM_ANADIG_PLL_ENET_HALF_LF (1 << 7)
+ #define BP_ANADIG_PLL_ENET_DIV_SELECT 0
+ #define BM_ANADIG_PLL_ENET_DIV_SELECT (0x3 << BP_ANADIG_PLL_ENET_DIV_SELECT)
-#define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \
- (((v) << BP_ANADIG_PLL_ENET_DIV_SELECT) & BM_ANADIG_PLL_ENET_DIV_SELECT)
++#define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_ENET_DIV_SELECT) & \
++ BM_ANADIG_PLL_ENET_DIV_SELECT)
+
+ #define BM_ANADIG_PFD_480_PFD3_CLKGATE (1 << 31)
+ #define BM_ANADIG_PFD_480_PFD3_STABLE (1 << 30)
+ #define BP_ANADIG_PFD_480_PFD3_FRAC 24
+ #define BM_ANADIG_PFD_480_PFD3_FRAC (0x3F << BP_ANADIG_PFD_480_PFD3_FRAC)
+ #define BF_ANADIG_PFD_480_PFD3_FRAC(v) \
- (((v) << BP_ANADIG_PFD_480_PFD3_FRAC) & BM_ANADIG_PFD_480_PFD3_FRAC)
++ (((v) << BP_ANADIG_PFD_480_PFD3_FRAC) & \
++ BM_ANADIG_PFD_480_PFD3_FRAC)
+
+ #define BP_ANADIG_ANA_MISC0_CLKGATE_DELAY 26
+ #define BM_ANADIG_ANA_MISC0_CLKGATE_DELAY (0x7 << BP_ANADIG_ANA_MISC0_CLKGATE_DELAY)
-#define BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(v) \
- (((v) << BP_ANADIG_ANA_MISC0_CLKGATE_DELAY) & BM_ANADIG_ANA_MISC0_CLKGATE_DELAY)
++#define BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(v) \
++ (((v) << BP_ANADIG_ANA_MISC0_CLKGATE_DELAY) & \
++ BM_ANADIG_ANA_MISC0_CLKGATE_DELAY)
+ #define BM_ANADIG_ANA_MISC0_CLKGATE_CTRL (1 << 25)
+ #define BP_ANADIG_ANA_MISC0_ANAMUX 21
+ #define BM_ANADIG_ANA_MISC0_ANAMUX (0xf << BP_ANADIG_ANA_MISC0_ANAMUX)
-#define BF_ANADIG_ANA_MISC0_ANAMUX(v) \
- (((v) << BP_ANADIG_ANA_MISC0_ANAMUX) & BM_ANADIG_ANA_MISC0_ANAMUX)
++#define BF_ANADIG_ANA_MISC0_ANAMUX(v) \
++ (((v) << BP_ANADIG_ANA_MISC0_ANAMUX) & \
++ BM_ANADIG_ANA_MISC0_ANAMUX)
+ #define BM_ANADIG_ANA_MISC0_ANAMUX_EN (1 << 20)
+ #define BP_ANADIG_ANA_MISC0_WBCP_VPW_THRESH 18
+ #define BM_ANADIG_ANA_MISC0_WBCP_VPW_THRESH (0x3 << BP_ANADIG_ANA_MISC0_WBCP_VPW_THRESH)
+ #define BF_ANADIG_ANA_MISC0_WBCP_VPW_THRESH(v) \
- (((v) << BP_ANADIG_ANA_MISC0_WBCP_VPW_THRESH) & BM_ANADIG_ANA_MISC0_WBCP_VPW_THRESH)
++ (((v) << BP_ANADIG_ANA_MISC0_WBCP_VPW_THRESH) & \
++ BM_ANADIG_ANA_MISC0_WBCP_VPW_THRESH)
+ #define BM_ANADIG_ANA_MISC0_OSC_XTALOK_EN (1 << 17)
-#define BM_ANADIG_ANA_MISC0_OSC_XTALOK (1 << 16)
-#define BP_ANADIG_ANA_MISC0_OSC_I 14
-#define BM_ANADIG_ANA_MISC0_OSC_I 0x0000C000
-#define BF_ANADIG_ANA_MISC0_OSC_I(v) \
- (((v) << BP_ANADIG_ANA_MISC0_OSC_I) & BM_ANADIG_ANA_MISC0_OSC_I)
++#define BM_ANADIG_ANA_MISC0_OSC_XTALOK (1 << 16)
++#define BP_ANADIG_ANA_MISC0_OSC_I 14
++#define BM_ANADIG_ANA_MISC0_OSC_I (0x3 << BP_ANADIG_ANA_MISC0_OSC_I)
++#define BF_ANADIG_ANA_MISC0_OSC_I(v) \
++ (((v) << BP_ANADIG_ANA_MISC0_OSC_I) & \
++ BM_ANADIG_ANA_MISC0_OSC_I)
+ #define BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN (1 << 13)
-#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG (1 << 12)
++#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG (1 << 12)
+ #define BP_ANADIG_ANA_MISC0_REFTOP_BIAS_TST 8
-#define BM_ANADIG_ANA_MISC0_REFTOP_BIAS_TST 0x00000300
++#define BM_ANADIG_ANA_MISC0_REFTOP_BIAS_TST (0x3 << BP_ANADIG_ANA_MISC0_REFTOP_BIAS_TST)
+ #define BF_ANADIG_ANA_MISC0_REFTOP_BIAS_TST(v) \
- (((v) << BP_ANADIG_ANA_MISC0_REFTOP_BIAS_TST) & BM_ANADIG_ANA_MISC0_REFTOP_BIAS_TST)
-#define BM_ANADIG_ANA_MISC0_REFTOP_VBGUP (1 << 7)
++ (((v) << BP_ANADIG_ANA_MISC0_REFTOP_BIAS_TST) & \
++ BM_ANADIG_ANA_MISC0_REFTOP_BIAS_TST)
++#define BM_ANADIG_ANA_MISC0_REFTOP_VBGUP (1 << 7)
+ #define BP_ANADIG_ANA_MISC0_REFTOP_VBGADJ 4
+ #define BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ (0x7 << BP_ANADIG_ANA_MISC0_REFTOP_VBGADJ)
-#define BF_ANADIG_ANA_MISC0_REFTOP_VBGADJ(v) \
- (((v) << BM_ANADIG_ANA_MISC0_REFTOP_VBGUP) & BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ)
-#define BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF (1 << 3)
-#define BM_ANADIG_ANA_MISC0_REFTOP_LOWPOWER (1 << 2)
-#define BM_ANADIG_ANA_MISC0_REFTOP_PWDVBGUP (1 << 1)
++#define BF_ANADIG_ANA_MISC0_REFTOP_VBGADJ(v) \
++ (((v) << BP_ANADIG_ANA_MISC0_REFTOP_VBGADJ) & \
++ BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ)
++#define BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF (1 << 3)
++#define BM_ANADIG_ANA_MISC0_REFTOP_LOWPOWER (1 << 2)
++#define BM_ANADIG_ANA_MISC0_REFTOP_PWDVBGUP (1 << 1)
+ #define BM_ANADIG_ANA_MISC0_REFTOP_PWD (1 << 0)
+
-#define BM_ANADIG_ANA_MISC1_IRQ_DIG_BO (1 << 31)
-#define BM_ANADIG_ANA_MISC1_IRQ_ANA_BO 0x40000000
-#define BM_ANADIG_ANA_MISC1_IRQ_TEMPSENSE_BO 0x20000000
++#define BM_ANADIG_ANA_MISC1_IRQ_DIG_BO (1 << 31)
++#define BM_ANADIG_ANA_MISC1_IRQ_ANA_BO (1 << 30)
++#define BM_ANADIG_ANA_MISC1_IRQ_TEMPSENSE_BO (1 << 29)
+ #define BM_ANADIG_ANA_MISC1_LVDSCLK2_IBEN (1 << 13)
-#define BM_ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12)
-#define BM_ANADIG_ANA_MISC1_LVDSCLK2_OBEN (1 << 11)
-#define BM_ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10)
++#define BM_ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12)
++#define BM_ANADIG_ANA_MISC1_LVDSCLK2_OBEN (1 << 11)
++#define BM_ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10)
+ #define BP_ANADIG_ANA_MISC1_LVDS2_CLK_SEL 5
-#define BM_ANADIG_ANA_MISC1_LVDS2_CLK_SEL 0x000003E0
-#define BF_ANADIG_ANA_MISC1_LVDS2_CLK_SEL(v) \
- (((v) << BP_ANADIG_ANA_MISC1_LVDS2_CLK_SEL) & BM_ANADIG_ANA_MISC1_LVDS2_CLK_SEL)
++#define BM_ANADIG_ANA_MISC1_LVDS2_CLK_SEL (0x1f << BP_ANADIG_ANA_MISC1_LVDS2_CLK_SEL)
++#define BF_ANADIG_ANA_MISC1_LVDS2_CLK_SEL(v) \
++ (((v) << BP_ANADIG_ANA_MISC1_LVDS2_CLK_SEL) & \
++ BM_ANADIG_ANA_MISC1_LVDS2_CLK_SEL)
+ #define BP_ANADIG_ANA_MISC1_LVDS1_CLK_SEL 0
-#define BM_ANADIG_ANA_MISC1_LVDS1_CLK_SEL 0x0000001F
-#define BF_ANADIG_ANA_MISC1_LVDS1_CLK_SEL(v) \
- (((v) << 0) & BM_ANADIG_ANA_MISC1_LVDS1_CLK_SEL)
-
-#define BP_ANADIG_ANA_MISC2_CONTROL3 30
-#define BM_ANADIG_ANA_MISC2_CONTROL3 0xC0000000
-#define BF_ANADIG_ANA_MISC2_CONTROL3(v) \
- (((v) << BP_ANADIG_ANA_MISC2_CONTROL3) & BM_ANADIG_ANA_MISC2_CONTROL3)
++#define BM_ANADIG_ANA_MISC1_LVDS1_CLK_SEL (0x1F << BP_ANADIG_ANA_MISC1_LVDS1_CLK_SEL)
++#define BF_ANADIG_ANA_MISC1_LVDS1_CLK_SEL(v) \
++ (((v) << BP_ANADIG_ANA_MISC1_LVDS1_CLK_SEL) & \
++ BM_ANADIG_ANA_MISC1_LVDS1_CLK_SEL)
++
++#define BP_ANADIG_ANA_MISC2_CONTROL3 30
++#define BM_ANADIG_ANA_MISC2_CONTROL3 (0x3 << BP_ANADIG_ANA_MISC2_CONTROL3)
++#define BF_ANADIG_ANA_MISC2_CONTROL3(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_CONTROL3) & \
++ BM_ANADIG_ANA_MISC2_CONTROL3)
+ #define BP_ANADIG_ANA_MISC2_REG2_STEP_TIME 28
-#define BM_ANADIG_ANA_MISC2_REG2_STEP_TIME 0x30000000
-#define BF_ANADIG_ANA_MISC2_REG2_STEP_TIME(v) \
- (((v) << BP_ANADIG_ANA_MISC2_REG2_STEP_TIME) & BM_ANADIG_ANA_MISC2_REG2_STEP_TIME)
++#define BM_ANADIG_ANA_MISC2_REG2_STEP_TIME (0x3 << BP_ANADIG_ANA_MISC2_REG2_STEP_TIME)
++#define BF_ANADIG_ANA_MISC2_REG2_STEP_TIME(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_REG2_STEP_TIME) & \
++ BM_ANADIG_ANA_MISC2_REG2_STEP_TIME)
+ #define BP_ANADIG_ANA_MISC2_REG1_STEP_TIME 26
-#define BM_ANADIG_ANA_MISC2_REG1_STEP_TIME 0x0C000000
-#define BF_ANADIG_ANA_MISC2_REG1_STEP_TIME(v) \
- (((v) << BP_ANADIG_ANA_MISC2_REG1_STEP_TIME) & BM_ANADIG_ANA_MISC2_REG1_STEP_TIME)
++#define BM_ANADIG_ANA_MISC2_REG1_STEP_TIME (0x3 << BP_ANADIG_ANA_MISC2_REG1_STEP_TIME)
++#define BF_ANADIG_ANA_MISC2_REG1_STEP_TIME(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_REG1_STEP_TIME) & \
++ BM_ANADIG_ANA_MISC2_REG1_STEP_TIME)
+ #define BP_ANADIG_ANA_MISC2_REG0_STEP_TIME 24
-#define BM_ANADIG_ANA_MISC2_REG0_STEP_TIME 0x03000000
-#define BF_ANADIG_ANA_MISC2_REG0_STEP_TIME(v) \
- (((v) << BP_ANADIG_ANA_MISC2_REG0_STEP_TIME) & BM_ANADIG_ANA_MISC2_REG0_STEP_TIME)
-#define BM_ANADIG_ANA_MISC2_CONTROL2 0x00800000
-#define BM_ANADIG_ANA_MISC2_REG2_OK 0x00400000
-#define BM_ANADIG_ANA_MISC2_REG2_ENABLE_BO (1 << 21)
++#define BM_ANADIG_ANA_MISC2_REG0_STEP_TIME (0x3 << BP_ANADIG_ANA_MISC2_REG0_STEP_TIME)
++#define BF_ANADIG_ANA_MISC2_REG0_STEP_TIME(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_REG0_STEP_TIME) & \
++ BM_ANADIG_ANA_MISC2_REG0_STEP_TIME)
++#define BM_ANADIG_ANA_MISC2_CONTROL2 (1 << 23)
++#define BM_ANADIG_ANA_MISC2_REG2_OK (1 << 22)
++#define BM_ANADIG_ANA_MISC2_REG2_ENABLE_BO (1 << 21)
+ #define BM_ANADIG_ANA_MISC2_REG2_BO_STATUS (1 << 19)
+ #define BP_ANADIG_ANA_MISC2_REG2_BO_OFFSET 16
-#define BM_ANADIG_ANA_MISC2_REG2_BO_OFFSET 0x00070000
-#define BF_ANADIG_ANA_MISC2_REG2_BO_OFFSET(v) \
- (((v) << BP_ANADIG_ANA_MISC2_REG2_BO_OFFSET) & BM_ANADIG_ANA_MISC2_REG2_BO_OFFSET)
-#define BM_ANADIG_ANA_MISC2_CONTROL1 (1 << 15)
-#define BM_ANADIG_ANA_MISC2_REG1_OK (1 << 14)
++#define BM_ANADIG_ANA_MISC2_REG2_BO_OFFSET (0x7 << BP_ANADIG_ANA_MISC2_REG2_BO_OFFSET)
++#define BF_ANADIG_ANA_MISC2_REG2_BO_OFFSET(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_REG2_BO_OFFSET) & \
++ BM_ANADIG_ANA_MISC2_REG2_BO_OFFSET)
++#define BM_ANADIG_ANA_MISC2_CONTROL1 (1 << 15)
++#define BM_ANADIG_ANA_MISC2_REG1_OK (1 << 14)
+ #define BM_ANADIG_ANA_MISC2_REG1_ENABLE_BO (1 << 13)
-#define BM_ANADIG_ANA_MISC2_REG1_BO_STATUS (1 << 11)
++#define BM_ANADIG_ANA_MISC2_REG1_BO_STATUS (1 << 11)
+ #define BP_ANADIG_ANA_MISC2_REG1_BO_OFFSET 8
-#define BM_ANADIG_ANA_MISC2_REG1_BO_OFFSET 0x00000700
-#define BF_ANADIG_ANA_MISC2_REG1_BO_OFFSET(v) \
- (((v) << BP_ANADIG_ANA_MISC2_REG1_BO_OFFSET) & BM_ANADIG_ANA_MISC2_REG1_BO_OFFSET)
++#define BM_ANADIG_ANA_MISC2_REG1_BO_OFFSET (0x7 << BP_ANADIG_ANA_MISC2_REG1_BO_OFFSET
++#define BF_ANADIG_ANA_MISC2_REG1_BO_OFFSET(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_REG1_BO_OFFSET) & \
++ BM_ANADIG_ANA_MISC2_REG1_BO_OFFSET)
+ #define BM_ANADIG_ANA_MISC2_CONTROL0 (1 << 7)
+ #define BM_ANADIG_ANA_MISC2_REG0_OK (1 << 6)
+ #define BM_ANADIG_ANA_MISC2_REG0_ENABLE_BO (1 << 5)
+ #define BM_ANADIG_ANA_MISC2_REG0_BO_STATUS (1 << 3)
+ #define BP_ANADIG_ANA_MISC2_REG0_BO_OFFSET 0
+ #define BM_ANADIG_ANA_MISC2_REG0_BO_OFFSET (0x7 << BP_ANADIG_ANA_MISC2_REG0_BO_OFFSET)
-#define BF_ANADIG_ANA_MISC2_REG0_BO_OFFSET(v) \
- (((v) << BP_ANADIG_ANA_MISC2_REG0_BO_OFFSET) & BM_ANADIG_ANA_MISC2_REG0_BO_OFFSET)
-
-#define BP_ANADIG_TEMPSENSE0_ALARM_VALUE 20
-#define BM_ANADIG_TEMPSENSE0_ALARM_VALUE (0xFFF << BP_ANADIG_TEMPSENSE0_ALARM_VALUE)
-#define BF_ANADIG_TEMPSENSE0_ALARM_VALUE(v) \
- (((v) << BP_ANADIG_TEMPSENSE0_ALARM_VALUE) & BM_ANADIG_TEMPSENSE0_ALARM_VALUE)
-#define BP_ANADIG_TEMPSENSE0_TEMP_VALUE 8
-#define BM_ANADIG_TEMPSENSE0_TEMP_VALUE (0xFFF << BP_ANADIG_TEMPSENSE0_TEMP_VALUE)
-#define BF_ANADIG_TEMPSENSE0_TEMP_VALUE(v) \
- (((v) << BP_ANADIG_TEMPSENSE0_TEMP_VALUE) & BM_ANADIG_TEMPSENSE0_TEMP_VALUE)
-#define BM_ANADIG_TEMPSENSE0_TEST (1 << 6)
-#define BP_ANADIG_TEMPSENSE0_VBGADJ 3
-#define BM_ANADIG_TEMPSENSE0_VBGADJ (0x7 << BP_ANADIG_TEMPSENSE0_VBGADJ)
++#define BF_ANADIG_ANA_MISC2_REG0_BO_OFFSET(v) \
++ (((v) << BP_ANADIG_ANA_MISC2_REG0_BO_OFFSET) & \
++ BM_ANADIG_ANA_MISC2_REG0_BO_OFFSET)
++
++#define BP_ANADIG_TEMPSENSE0_ALARM_VALUE 20
++#define BM_ANADIG_TEMPSENSE0_ALARM_VALUE (0xFFF << BP_ANADIG_TEMPSENSE0_ALARM_VALUE)
++#define BF_ANADIG_TEMPSENSE0_ALARM_VALUE(v) \
++ (((v) << BP_ANADIG_TEMPSENSE0_ALARM_VALUE) & \
++ BM_ANADIG_TEMPSENSE0_ALARM_VALUE)
++#define BP_ANADIG_TEMPSENSE0_TEMP_VALUE 8
++#define BM_ANADIG_TEMPSENSE0_TEMP_VALUE (0xFFF << BP_ANADIG_TEMPSENSE0_TEMP_VALUE)
++#define BF_ANADIG_TEMPSENSE0_TEMP_VALUE(v) \
++ (((v) << BP_ANADIG_TEMPSENSE0_TEMP_VALUE) & \
++ BM_ANADIG_TEMPSENSE0_TEMP_VALUE)
++#define BM_ANADIG_TEMPSENSE0_TEST (1 << 6)
++#define BP_ANADIG_TEMPSENSE0_VBGADJ 3
++#define BM_ANADIG_TEMPSENSE0_VBGADJ (0x7 << BP_ANADIG_TEMPSENSE0_VBGADJ)
+ #define BF_ANADIG_TEMPSENSE0_VBGADJ(v) \
- (((v) << BP_ANADIG_TEMPSENSE0_VBGADJ) & BM_ANADIG_TEMPSENSE0_VBGADJ)
-#define BM_ANADIG_TEMPSENSE0_FINISHED (1 << 2)
-#define BM_ANADIG_TEMPSENSE0_MEASURE_TEMP (1 << 1)
-#define BM_ANADIG_TEMPSENSE0_POWER_DOWN (1 << 0)
-
-#define BP_ANADIG_TEMPSENSE1_MEASURE_FREQ 0
-#define BM_ANADIG_TEMPSENSE1_MEASURE_FREQ (0xFFFF << BP_ANADIG_TEMPSENSE1_MEASURE_FREQ)
-#define BF_ANADIG_TEMPSENSE1_MEASURE_FREQ(v) \
- (((v) << BP_ANADIG_TEMPSENSE1_MEASURE_FREQ) & BM_ANADIG_TEMPSENSE1_MEASURE_FREQ)
-
-#ifdef CONFIG_MX6Q
-#define PLL2_PFD0_FREQ 352000000
-#define PLL2_PFD1_FREQ 594000000
++ (((v) << BP_ANADIG_TEMPSENSE0_VBGADJ) & \
++ BM_ANADIG_TEMPSENSE0_VBGADJ)
++#define BM_ANADIG_TEMPSENSE0_FINISHED (1 << 2)
++#define BM_ANADIG_TEMPSENSE0_MEASURE_TEMP (1 << 1)
++#define BM_ANADIG_TEMPSENSE0_POWER_DOWN (1 << 0)
++
++#define BP_ANADIG_TEMPSENSE1_MEASURE_FREQ 0
++#define BM_ANADIG_TEMPSENSE1_MEASURE_FREQ (0xFFFF << BP_ANADIG_TEMPSENSE1_MEASURE_FREQ)
++#define BF_ANADIG_TEMPSENSE1_MEASURE_FREQ(v) \
++ (((v) << BP_ANADIG_TEMPSENSE1_MEASURE_FREQ) & \
++ BM_ANADIG_TEMPSENSE1_MEASURE_FREQ)
++
++#define MXC_CCM_CCGR6_USBOH3_OFFSET 0
++#define MXC_CCM_CCGR6_USBOH3_MASK (3 << MXC_CCM_CCGR6_USBOH3_OFFSET)
++#define MXC_CCM_CCGR6_USDHC1_OFFSET 2
++#define MXC_CCM_CCGR6_USDHC1_MASK (3 << MXC_CCM_CCGR6_USDHC1_OFFSET)
++#define MXC_CCM_CCGR6_USDHC2_OFFSET 4
++#define MXC_CCM_CCGR6_USDHC2_MASK (3 << MXC_CCM_CCGR6_USDHC2_OFFSET)
++#define MXC_CCM_CCGR6_USDHC3_OFFSET 6
++#define MXC_CCM_CCGR6_USDHC3_MASK (3 << MXC_CCM_CCGR6_USDHC3_OFFSET)
++#define MXC_CCM_CCGR6_USDHC4_OFFSET 8
++#define MXC_CCM_CCGR6_USDHC4_MASK (3 << MXC_CCM_CCGR6_USDHC4_OFFSET)
++#define MXC_CCM_CCGR6_EMI_SLOW_OFFSET 10
++#define MXC_CCM_CCGR6_EMI_SLOW_MASK (3 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET)
+#ifdef CONFIG_MX6SX
- #define MXC_CCM_CCGR6_PWM8_OFFSET 16
- #define MXC_CCM_CCGR6_PWM8_MASK (3 << MXC_CCM_CCGR6_PWM8_OFFSET)
- #define MXC_CCM_CCGR6_VADC_OFFSET 20
- #define MXC_CCM_CCGR6_VADC_MASK (3 << MXC_CCM_CCGR6_VADC_OFFSET)
- #define MXC_CCM_CCGR6_GIS_OFFSET 22
- #define MXC_CCM_CCGR6_GIS_MASK (3 << MXC_CCM_CCGR6_GIS_OFFSET)
- #define MXC_CCM_CCGR6_I2C4_OFFSET 24
- #define MXC_CCM_CCGR6_I2C4_MASK (3 << MXC_CCM_CCGR6_I2C4_OFFSET)
- #define MXC_CCM_CCGR6_PWM5_OFFSET 26
- #define MXC_CCM_CCGR6_PWM5_MASK (3 << MXC_CCM_CCGR6_PWM5_OFFSET)
- #define MXC_CCM_CCGR6_PWM6_OFFSET 28
- #define MXC_CCM_CCGR6_PWM6_MASK (3 << MXC_CCM_CCGR6_PWM6_OFFSET)
- #define MXC_CCM_CCGR6_PWM7_OFFSET 30
- #define MXC_CCM_CCGR6_PWM7_MASK (3 << MXC_CCM_CCGR6_PWM7_OFFSET)
++#define MXC_CCM_CCGR6_PWM8_OFFSET 16
++#define MXC_CCM_CCGR6_PWM8_MASK (3 << MXC_CCM_CCGR6_PWM8_OFFSET)
++#define MXC_CCM_CCGR6_VADC_OFFSET 20
++#define MXC_CCM_CCGR6_VADC_MASK (3 << MXC_CCM_CCGR6_VADC_OFFSET)
++#define MXC_CCM_CCGR6_GIS_OFFSET 22
++#define MXC_CCM_CCGR6_GIS_MASK (3 << MXC_CCM_CCGR6_GIS_OFFSET)
++#define MXC_CCM_CCGR6_I2C4_OFFSET 24
++#define MXC_CCM_CCGR6_I2C4_MASK (3 << MXC_CCM_CCGR6_I2C4_OFFSET)
++#define MXC_CCM_CCGR6_PWM5_OFFSET 26
++#define MXC_CCM_CCGR6_PWM5_MASK (3 << MXC_CCM_CCGR6_PWM5_OFFSET)
++#define MXC_CCM_CCGR6_PWM6_OFFSET 28
++#define MXC_CCM_CCGR6_PWM6_MASK (3 << MXC_CCM_CCGR6_PWM6_OFFSET)
++#define MXC_CCM_CCGR6_PWM7_OFFSET 30
++#define MXC_CCM_CCGR6_PWM7_MASK (3 << MXC_CCM_CCGR6_PWM7_OFFSET)
#else
- #define MXC_CCM_CCGR6_VDOAXICLK_OFFSET 12
- #define MXC_CCM_CCGR6_VDOAXICLK_MASK (3 << MXC_CCM_CCGR6_VDOAXICLK_OFFSET)
-#define PLL2_PFD0_FREQ 306580000
-#define PLL2_PFD1_FREQ 528000000
-#endif
-#define PLL2_PFD2_FREQ 396000000
-#define PLL2_PFD2_DIV_FREQ (PLL2_PFD2_FREQ / 2)
-#define PLL3_PFD0_FREQ 720000000
-#define PLL3_PFD1_FREQ 540000000
-#define PLL3_PFD2_FREQ 508200000
-#define PLL3_PFD3_FREQ 454700000
-#define PLL3_80M 80000000
-#define PLL3_60M 60000000
++#define MXC_CCM_CCGR6_VDOAXICLK_OFFSET 12
++#define MXC_CCM_CCGR6_VDOAXICLK_MASK (3 << MXC_CCM_CCGR6_VDOAXICLK_OFFSET)
+#endif
+
- #define BM_ANADIG_PLL_SYS_LOCK 0x80000000
- #define BP_ANADIG_PLL_SYS_RSVD0 20
- #define BM_ANADIG_PLL_SYS_RSVD0 0x7FF00000
- #define BF_ANADIG_PLL_SYS_RSVD0(v) \
- (((v) << 20) & BM_ANADIG_PLL_SYS_RSVD0)
- #define BM_ANADIG_PLL_SYS_PLL_SEL 0x00080000
- #define BM_ANADIG_PLL_SYS_LVDS_24MHZ_SEL 0x00040000
- #define BM_ANADIG_PLL_SYS_LVDS_SEL 0x00020000
- #define BM_ANADIG_PLL_SYS_BYPASS 0x00010000
- #define BP_ANADIG_PLL_SYS_BYPASS_CLK_SRC 14
- #define BM_ANADIG_PLL_SYS_BYPASS_CLK_SRC 0x0000C000
- #define BF_ANADIG_PLL_SYS_BYPASS_CLK_SRC(v) \
- (((v) << 14) & BM_ANADIG_PLL_SYS_BYPASS_CLK_SRC)
- #define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__OSC_24M 0x0
- #define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__ANACLK_1 0x1
- #define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__ANACLK_2 0x2
- #define BV_ANADIG_PLL_SYS_BYPASS_CLK_SRC__XOR 0x3
- #define BM_ANADIG_PLL_SYS_ENABLE 0x00002000
- #define BM_ANADIG_PLL_SYS_POWERDOWN 0x00001000
- #define BM_ANADIG_PLL_SYS_HOLD_RING_OFF 0x00000800
- #define BM_ANADIG_PLL_SYS_DOUBLE_CP 0x00000400
- #define BM_ANADIG_PLL_SYS_HALF_CP 0x00000200
- #define BM_ANADIG_PLL_SYS_DOUBLE_LF 0x00000100
- #define BM_ANADIG_PLL_SYS_HALF_LF 0x00000080
- #define BP_ANADIG_PLL_SYS_DIV_SELECT 0
- #define BM_ANADIG_PLL_SYS_DIV_SELECT 0x0000007F
- #define BF_ANADIG_PLL_SYS_DIV_SELECT(v) \
- (((v) << 0) & BM_ANADIG_PLL_SYS_DIV_SELECT)
-
- #define BM_ANADIG_USB1_PLL_480_CTRL_LOCK 0x80000000
- #define BP_ANADIG_USB1_PLL_480_CTRL_RSVD1 17
- #define BM_ANADIG_USB1_PLL_480_CTRL_RSVD1 0x7FFE0000
- #define BF_ANADIG_USB1_PLL_480_CTRL_RSVD1(v) \
- (((v) << 17) & BM_ANADIG_USB1_PLL_480_CTRL_RSVD1)
- #define BM_ANADIG_USB1_PLL_480_CTRL_BYPASS 0x00010000
- #define BP_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC 14
- #define BM_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC 0x0000C000
- #define BF_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC(v) \
- (((v) << 14) & BM_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC)
- #define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__OSC_24M 0x0
- #define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_1 0x1
- #define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_2 0x2
- #define BV_ANADIG_USB1_PLL_480_CTRL_BYPASS_CLK_SRC__XOR 0x3
- #define BM_ANADIG_USB1_PLL_480_CTRL_ENABLE 0x00002000
- #define BM_ANADIG_USB1_PLL_480_CTRL_POWER 0x00001000
- #define BM_ANADIG_USB1_PLL_480_CTRL_HOLD_RING_OFF 0x00000800
- #define BM_ANADIG_USB1_PLL_480_CTRL_DOUBLE_CP 0x00000400
- #define BM_ANADIG_USB1_PLL_480_CTRL_HALF_CP 0x00000200
- #define BM_ANADIG_USB1_PLL_480_CTRL_DOUBLE_LF 0x00000100
- #define BM_ANADIG_USB1_PLL_480_CTRL_HALF_LF 0x00000080
- #define BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS 0x00000040
- #define BM_ANADIG_USB1_PLL_480_CTRL_RSVD0 0x00000020
- #define BP_ANADIG_USB1_PLL_480_CTRL_CONTROL0 2
- #define BM_ANADIG_USB1_PLL_480_CTRL_CONTROL0 0x0000001C
- #define BF_ANADIG_USB1_PLL_480_CTRL_CONTROL0(v) \
- (((v) << 2) & BM_ANADIG_USB1_PLL_480_CTRL_CONTROL0)
- #define BP_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT 0
- #define BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT 0x00000003
- #define BF_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT(v) \
- (((v) << 0) & BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT)
-
- #define BM_ANADIG_PLL_528_LOCK 0x80000000
- #define BP_ANADIG_PLL_528_RSVD1 19
- #define BM_ANADIG_PLL_528_RSVD1 0x7FF80000
- #define BF_ANADIG_PLL_528_RSVD1(v) \
- (((v) << 19) & BM_ANADIG_PLL_528_RSVD1)
- #define BM_ANADIG_PLL_528_PFD_OFFSET_EN 0x00040000
- #define BM_ANADIG_PLL_528_DITHER_ENABLE 0x00020000
- #define BM_ANADIG_PLL_528_BYPASS 0x00010000
- #define BP_ANADIG_PLL_528_BYPASS_CLK_SRC 14
- #define BM_ANADIG_PLL_528_BYPASS_CLK_SRC 0x0000C000
- #define BF_ANADIG_PLL_528_BYPASS_CLK_SRC(v) \
- (((v) << 14) & BM_ANADIG_PLL_528_BYPASS_CLK_SRC)
- #define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__OSC_24M 0x0
- #define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__ANACLK_1 0x1
- #define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__ANACLK_2 0x2
- #define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__XOR 0x3
- #define BM_ANADIG_PLL_528_ENABLE 0x00002000
- #define BM_ANADIG_PLL_528_POWERDOWN 0x00001000
- #define BM_ANADIG_PLL_528_HOLD_RING_OFF 0x00000800
- #define BM_ANADIG_PLL_528_DOUBLE_CP 0x00000400
- #define BM_ANADIG_PLL_528_HALF_CP 0x00000200
- #define BM_ANADIG_PLL_528_DOUBLE_LF 0x00000100
- #define BM_ANADIG_PLL_528_HALF_LF 0x00000080
- #define BP_ANADIG_PLL_528_RSVD0 1
- #define BM_ANADIG_PLL_528_RSVD0 0x0000007E
- #define BF_ANADIG_PLL_528_RSVD0(v) \
- (((v) << 1) & BM_ANADIG_PLL_528_RSVD0)
- #define BM_ANADIG_PLL_528_DIV_SELECT 0x00000001
-
- #define BP_ANADIG_PLL_528_SS_STOP 16
- #define BM_ANADIG_PLL_528_SS_STOP 0xFFFF0000
- #define BF_ANADIG_PLL_528_SS_STOP(v) \
- (((v) << 16) & BM_ANADIG_PLL_528_SS_STOP)
- #define BM_ANADIG_PLL_528_SS_ENABLE 0x00008000
- #define BP_ANADIG_PLL_528_SS_STEP 0
- #define BM_ANADIG_PLL_528_SS_STEP 0x00007FFF
- #define BF_ANADIG_PLL_528_SS_STEP(v) \
- (((v) << 0) & BM_ANADIG_PLL_528_SS_STEP)
-
- #define BP_ANADIG_PLL_528_NUM_RSVD0 30
- #define BM_ANADIG_PLL_528_NUM_RSVD0 0xC0000000
- #define BF_ANADIG_PLL_528_NUM_RSVD0(v) \
- (((v) << 30) & BM_ANADIG_PLL_528_NUM_RSVD0)
- #define BP_ANADIG_PLL_528_NUM_A 0
- #define BM_ANADIG_PLL_528_NUM_A 0x3FFFFFFF
- #define BF_ANADIG_PLL_528_NUM_A(v) \
- (((v) << 0) & BM_ANADIG_PLL_528_NUM_A)
-
- #define BP_ANADIG_PLL_528_DENOM_RSVD0 30
- #define BM_ANADIG_PLL_528_DENOM_RSVD0 0xC0000000
- #define BF_ANADIG_PLL_528_DENOM_RSVD0(v) \
- (((v) << 30) & BM_ANADIG_PLL_528_DENOM_RSVD0)
- #define BP_ANADIG_PLL_528_DENOM_B 0
- #define BM_ANADIG_PLL_528_DENOM_B 0x3FFFFFFF
- #define BF_ANADIG_PLL_528_DENOM_B(v) \
- (((v) << 0) & BM_ANADIG_PLL_528_DENOM_B)
-
- #define BM_ANADIG_PLL_AUDIO_LOCK 0x80000000
- #define BP_ANADIG_PLL_AUDIO_RSVD0 22
- #define BM_ANADIG_PLL_AUDIO_RSVD0 0x7FC00000
- #define BF_ANADIG_PLL_AUDIO_RSVD0(v) \
- (((v) << 22) & BM_ANADIG_PLL_AUDIO_RSVD0)
- #define BM_ANADIG_PLL_AUDIO_SSC_EN 0x00200000
- #define BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT 19
- #define BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT 0x00180000
- #define BF_ANADIG_PLL_AUDIO_TEST_DIV_SELECT(v) \
- (((v) << 19) & BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT)
- #define BM_ANADIG_PLL_AUDIO_PFD_OFFSET_EN 0x00040000
- #define BM_ANADIG_PLL_AUDIO_DITHER_ENABLE 0x00020000
- #define BM_ANADIG_PLL_AUDIO_BYPASS 0x00010000
- #define BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC 14
- #define BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC 0x0000C000
- #define BF_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC(v) \
- (((v) << 14) & BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC)
- #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__OSC_24M 0x0
- #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_1 0x1
- #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_2 0x2
- #define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__XOR 0x3
- #define BM_ANADIG_PLL_AUDIO_ENABLE 0x00002000
- #define BM_ANADIG_PLL_AUDIO_POWERDOWN 0x00001000
- #define BM_ANADIG_PLL_AUDIO_HOLD_RING_OFF 0x00000800
- #define BM_ANADIG_PLL_AUDIO_DOUBLE_CP 0x00000400
- #define BM_ANADIG_PLL_AUDIO_HALF_CP 0x00000200
- #define BM_ANADIG_PLL_AUDIO_DOUBLE_LF 0x00000100
- #define BM_ANADIG_PLL_AUDIO_HALF_LF 0x00000080
- #define BP_ANADIG_PLL_AUDIO_DIV_SELECT 0
- #define BM_ANADIG_PLL_AUDIO_DIV_SELECT 0x0000007F
- #define BF_ANADIG_PLL_AUDIO_DIV_SELECT(v) \
- (((v) << 0) & BM_ANADIG_PLL_AUDIO_DIV_SELECT)
-
- #define BP_ANADIG_PLL_AUDIO_NUM_RSVD0 30
- #define BM_ANADIG_PLL_AUDIO_NUM_RSVD0 0xC0000000
- #define BF_ANADIG_PLL_AUDIO_NUM_RSVD0(v) \
- (((v) << 30) & BM_ANADIG_PLL_AUDIO_NUM_RSVD0)
- #define BP_ANADIG_PLL_AUDIO_NUM_A 0
- #define BM_ANADIG_PLL_AUDIO_NUM_A 0x3FFFFFFF
- #define BF_ANADIG_PLL_AUDIO_NUM_A(v) \
- (((v) << 0) & BM_ANADIG_PLL_AUDIO_NUM_A)
-
- #define BP_ANADIG_PLL_AUDIO_DENOM_RSVD0 30
- #define BM_ANADIG_PLL_AUDIO_DENOM_RSVD0 0xC0000000
- #define BF_ANADIG_PLL_AUDIO_DENOM_RSVD0(v) \
- (((v) << 30) & BM_ANADIG_PLL_AUDIO_DENOM_RSVD0)
- #define BP_ANADIG_PLL_AUDIO_DENOM_B 0
- #define BM_ANADIG_PLL_AUDIO_DENOM_B 0x3FFFFFFF
- #define BF_ANADIG_PLL_AUDIO_DENOM_B(v) \
- (((v) << 0) & BM_ANADIG_PLL_AUDIO_DENOM_B)
-
- #define BM_ANADIG_PLL_VIDEO_LOCK 0x80000000
- #define BP_ANADIG_PLL_VIDEO_RSVD0 22
- #define BM_ANADIG_PLL_VIDEO_RSVD0 0x7FC00000
- #define BF_ANADIG_PLL_VIDEO_RSVD0(v) \
- (((v) << 22) & BM_ANADIG_PLL_VIDEO_RSVD0)
- #define BM_ANADIG_PLL_VIDEO_SSC_EN 0x00200000
- #define BP_ANADIG_PLL_VIDEO_POST_DIV_SELECT 19
- #define BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT 0x00180000
- #define BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(v) \
- (((v) << 19) & BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT)
- #define BM_ANADIG_PLL_VIDEO_PFD_OFFSET_EN 0x00040000
- #define BM_ANADIG_PLL_VIDEO_DITHER_ENABLE 0x00020000
- #define BM_ANADIG_PLL_VIDEO_BYPASS 0x00010000
- #define BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC 14
- #define BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC 0x0000C000
- #define BF_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC(v) \
- (((v) << 14) & BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
- #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__OSC_24M 0x0
- #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_1 0x1
- #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_2 0x2
- #define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__XOR 0x3
- #define BM_ANADIG_PLL_VIDEO_ENABLE 0x00002000
- #define BM_ANADIG_PLL_VIDEO_POWERDOWN 0x00001000
- #define BM_ANADIG_PLL_VIDEO_HOLD_RING_OFF 0x00000800
- #define BM_ANADIG_PLL_VIDEO_DOUBLE_CP 0x00000400
- #define BM_ANADIG_PLL_VIDEO_HALF_CP 0x00000200
- #define BM_ANADIG_PLL_VIDEO_DOUBLE_LF 0x00000100
- #define BM_ANADIG_PLL_VIDEO_HALF_LF 0x00000080
- #define BP_ANADIG_PLL_VIDEO_DIV_SELECT 0
- #define BM_ANADIG_PLL_VIDEO_DIV_SELECT 0x0000007F
- #define BF_ANADIG_PLL_VIDEO_DIV_SELECT(v) \
- (((v) << 0) & BM_ANADIG_PLL_VIDEO_DIV_SELECT)
-
- #define BP_ANADIG_PLL_VIDEO_NUM_RSVD0 30
- #define BM_ANADIG_PLL_VIDEO_NUM_RSVD0 0xC0000000
- #define BF_ANADIG_PLL_VIDEO_NUM_RSVD0(v) \
- (((v) << 30) & BM_ANADIG_PLL_VIDEO_NUM_RSVD0)
- #define BP_ANADIG_PLL_VIDEO_NUM_A 0
- #define BM_ANADIG_PLL_VIDEO_NUM_A 0x3FFFFFFF
- #define BF_ANADIG_PLL_VIDEO_NUM_A(v) \
- (((v) << 0) & BM_ANADIG_PLL_VIDEO_NUM_A)
-
- #define BP_ANADIG_PLL_VIDEO_DENOM_RSVD0 30
- #define BM_ANADIG_PLL_VIDEO_DENOM_RSVD0 0xC0000000
- #define BF_ANADIG_PLL_VIDEO_DENOM_RSVD0(v) \
- (((v) << 30) & BM_ANADIG_PLL_VIDEO_DENOM_RSVD0)
- #define BP_ANADIG_PLL_VIDEO_DENOM_B 0
- #define BM_ANADIG_PLL_VIDEO_DENOM_B 0x3FFFFFFF
- #define BF_ANADIG_PLL_VIDEO_DENOM_B(v) \
- (((v) << 0) & BM_ANADIG_PLL_VIDEO_DENOM_B)
-
- #define BM_ANADIG_PLL_ENET_LOCK 0x80000000
- #define BP_ANADIG_PLL_ENET_RSVD1 21
- #define BM_ANADIG_PLL_ENET_RSVD1 0x7FE00000
- #define BF_ANADIG_PLL_ENET_RSVD1(v) \
- (((v) << 21) & BM_ANADIG_PLL_ENET_RSVD1)
- #define BM_ANADIG_PLL_ENET_REF_25M_ENABLE 0x00200000
- #define BM_ANADIG_PLL_ENET_ENABLE_SATA 0x00100000
- #define BM_ANADIG_PLL_ENET_ENABLE_PCIE 0x00080000
- #define BM_ANADIG_PLL_ENET_PFD_OFFSET_EN 0x00040000
- #define BM_ANADIG_PLL_ENET_DITHER_ENABLE 0x00020000
- #define BM_ANADIG_PLL_ENET_BYPASS 0x00010000
- #define BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC 14
- #define BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC 0x0000C000
- #define BF_ANADIG_PLL_ENET_BYPASS_CLK_SRC(v) \
- (((v) << 14) & BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
- #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__OSC_24M 0x0
- #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_1 0x1
- #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_2 0x2
- #define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__XOR 0x3
- #define BM_ANADIG_PLL_ENET_ENABLE 0x00002000
- #define BM_ANADIG_PLL_ENET_POWERDOWN 0x00001000
- #define BM_ANADIG_PLL_ENET_HOLD_RING_OFF 0x00000800
- #define BM_ANADIG_PLL_ENET_DOUBLE_CP 0x00000400
- #define BM_ANADIG_PLL_ENET_HALF_CP 0x00000200
- #define BM_ANADIG_PLL_ENET_DOUBLE_LF 0x00000100
- #define BM_ANADIG_PLL_ENET_HALF_LF 0x00000080
- #define BP_ANADIG_PLL_ENET_RSVD0 2
- #define BM_ANADIG_PLL_ENET_RSVD0 0x0000007C
- #define BF_ANADIG_PLL_ENET_RSVD0(v) \
- (((v) << 2) & BM_ANADIG_PLL_ENET_RSVD0)
- #define BP_ANADIG_PLL_ENET_DIV_SELECT 0
- #define BM_ANADIG_PLL_ENET_DIV_SELECT 0x00000003
- #define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \
- (((v) << 0) & BM_ANADIG_PLL_ENET_DIV_SELECT)
-
- #define BM_ANADIG_PFD_480_PFD3_CLKGATE 0x80000000
- #define BM_ANADIG_PFD_480_PFD3_STABLE 0x40000000
- #define BP_ANADIG_PFD_480_PFD3_FRAC 24
- #define BM_ANADIG_PFD_480_PFD3_FRAC 0x3F000000
- #define BF_ANADIG_PFD_480_PFD3_FRAC(v) \
- (((v) << 24) & BM_ANADIG_PFD_480_PFD3_FRAC)
- #define BM_ANADIG_PFD_480_PFD2_CLKGATE 0x00800000
- #define BM_ANADIG_PFD_480_PFD2_STABLE 0x00400000
- #define BP_ANADIG_PFD_480_PFD2_FRAC 16
- #define BM_ANADIG_PFD_480_PFD2_FRAC 0x003F0000
- #define BF_ANADIG_PFD_480_PFD2_FRAC(v) \
- (((v) << 16) & BM_ANADIG_PFD_480_PFD2_FRAC)
- #define BM_ANADIG_PFD_480_PFD1_CLKGATE 0x00008000
- #define BM_ANADIG_PFD_480_PFD1_STABLE 0x00004000
- #define BP_ANADIG_PFD_480_PFD1_FRAC 8
- #define BM_ANADIG_PFD_480_PFD1_FRAC 0x00003F00
- #define BF_ANADIG_PFD_480_PFD1_FRAC(v) \
- (((v) << 8) & BM_ANADIG_PFD_480_PFD1_FRAC)
- #define BM_ANADIG_PFD_480_PFD0_CLKGATE 0x00000080
- #define BM_ANADIG_PFD_480_PFD0_STABLE 0x00000040
- #define BP_ANADIG_PFD_480_PFD0_FRAC 0
- #define BM_ANADIG_PFD_480_PFD0_FRAC 0x0000003F
- #define BF_ANADIG_PFD_480_PFD0_FRAC(v) \
- (((v) << 0) & BM_ANADIG_PFD_480_PFD0_FRAC)
-
- #define BM_ANADIG_PFD_528_PFD3_CLKGATE 0x80000000
- #define BM_ANADIG_PFD_528_PFD3_STABLE 0x40000000
- #define BP_ANADIG_PFD_528_PFD3_FRAC 24
- #define BM_ANADIG_PFD_528_PFD3_FRAC 0x3F000000
- #define BF_ANADIG_PFD_528_PFD3_FRAC(v) \
- (((v) << 24) & BM_ANADIG_PFD_528_PFD3_FRAC)
- #define BM_ANADIG_PFD_528_PFD2_CLKGATE 0x00800000
- #define BM_ANADIG_PFD_528_PFD2_STABLE 0x00400000
- #define BP_ANADIG_PFD_528_PFD2_FRAC 16
- #define BM_ANADIG_PFD_528_PFD2_FRAC 0x003F0000
- #define BF_ANADIG_PFD_528_PFD2_FRAC(v) \
- (((v) << 16) & BM_ANADIG_PFD_528_PFD2_FRAC)
- #define BM_ANADIG_PFD_528_PFD1_CLKGATE 0x00008000
- #define BM_ANADIG_PFD_528_PFD1_STABLE 0x00004000
- #define BP_ANADIG_PFD_528_PFD1_FRAC 8
- #define BM_ANADIG_PFD_528_PFD1_FRAC 0x00003F00
- #define BF_ANADIG_PFD_528_PFD1_FRAC(v) \
- (((v) << 8) & BM_ANADIG_PFD_528_PFD1_FRAC)
- #define BM_ANADIG_PFD_528_PFD0_CLKGATE 0x00000080
- #define BM_ANADIG_PFD_528_PFD0_STABLE 0x00000040
- #define BP_ANADIG_PFD_528_PFD0_FRAC 0
- #define BM_ANADIG_PFD_528_PFD0_FRAC 0x0000003F
- #define BF_ANADIG_PFD_528_PFD0_FRAC(v) \
- (((v) << 0) & BM_ANADIG_PFD_528_PFD0_FRAC)
++#define BM_ANADIG_USB_PLL_480_CTRL_LOCK (1 << 31)
++#define BM_ANADIG_USB_PLL_480_CTRL_BYPASS (1 << 16)
++#define BP_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC 14
++#define BM_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC (0x3 << BP_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC)
++#define BF_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC) & \
++ BM_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC)
++#define BV_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_USB_PLL_480_CTRL_BYPASS_CLK_SRC__XOR 0x3
++#define BM_ANADIG_USB_PLL_480_CTRL_ENABLE (1 << 13)
++#define BM_ANADIG_USB_PLL_480_CTRL_POWER (1 << 12)
++#define BM_ANADIG_USB_PLL_480_CTRL_HOLD_RING_OFF (1 << 11)
++#define BM_ANADIG_USB_PLL_480_CTRL_DOUBLE_CP (1 << 10)
++#define BM_ANADIG_USB_PLL_480_CTRL_HALF_CP (1 << 9)
++#define BM_ANADIG_USB_PLL_480_CTRL_DOUBLE_LF (1 << 8)
++#define BM_ANADIG_USB_PLL_480_CTRL_HALF_LF (1 << 7)
++#define BM_ANADIG_USB_PLL_480_CTRL_EN_USB_CLKS (1 << 6)
++#define BP_ANADIG_USB_PLL_480_CTRL_CONTROL0 2
++#define BM_ANADIG_USB_PLL_480_CTRL_CONTROL0 (0x7 << BP_ANADIG_USB_PLL_480_CTRL_CONTROL0)
++#define BF_ANADIG_USB_PLL_480_CTRL_CONTROL0(v) \
++ (((v) << BP_ANADIG_USB_PLL_480_CTRL_CONTROL0) & \
++ BM_ANADIG_USB_PLL_480_CTRL_CONTROL0)
++#define BP_ANADIG_USB_PLL_480_CTRL_DIV_SELECT 0
++#define BM_ANADIG_USB_PLL_480_CTRL_DIV_SELECT (0x3 << BP_ANADIG_USB_PLL_480_CTRL_DIV_SELECT)
++#define BF_ANADIG_USB_PLL_480_CTRL_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_USB_PLL_480_CTRL_DIV_SELECT) & \
++ BM_ANADIG_USB_PLL_480_CTRL_DIV_SELECT)
++
++#define BM_ANADIG_PLL_528_LOCK (1 << 31)
++#define BM_ANADIG_PLL_528_PLL_SEL (1 << 19)
++#define BM_ANADIG_PLL_528_LVDS_24MHZ_SEL (1 << 18)
++#define BM_ANADIG_PLL_528_LVDS_SEL (1 << 17)
++#define BM_ANADIG_PLL_528_BYPASS (1 << 16)
++#define BP_ANADIG_PLL_528_BYPASS_CLK_SRC 14
++#define BM_ANADIG_PLL_528_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_528_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_528_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_528_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_528_BYPASS_CLK_SRC)
++#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_PLL_528_BYPASS_CLK_SRC__XOR 0x3
++#define BM_ANADIG_PLL_528_ENABLE (1 << 13)
++#define BM_ANADIG_PLL_528_POWERDOWN (1 << 12)
++#define BM_ANADIG_PLL_528_HOLD_RING_OFF (1 << 11)
++#define BM_ANADIG_PLL_528_DOUBLE_CP (1 << 10)
++#define BM_ANADIG_PLL_528_HALF_CP (1 << 9)
++#define BM_ANADIG_PLL_528_DOUBLE_LF (1 << 8)
++#define BM_ANADIG_PLL_528_HALF_LF (1 << 7)
++#define BP_ANADIG_PLL_528_DIV_SELECT 0
++#define BM_ANADIG_PLL_528_DIV_SELECT (0x7F << BP_ANADIG_PLL_528_DIV_SELECT)
++#define BF_ANADIG_PLL_528_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_528_DIV_SELECT) & \
++ BM_ANADIG_PLL_528_DIV_SELECT)
++
++#define BP_ANADIG_PLL_528_SS_STOP 16
++#define BM_ANADIG_PLL_528_SS_STOP (0xFFFF << BP_ANADIG_PLL_528_SS_STOP)
++#define BF_ANADIG_PLL_528_SS_STOP(v) \
++ (((v) << BP_ANADIG_PLL_528_SS_STOP) & \
++ BM_ANADIG_PLL_528_SS_STOP)
++#define BM_ANADIG_PLL_528_SS_ENABLE (1 << 15)
++#define BP_ANADIG_PLL_528_SS_STEP 0
++#define BM_ANADIG_PLL_528_SS_STEP (0x7FFF << BP_ANADIG_PLL_528_SS_STEP)
++#define BF_ANADIG_PLL_528_SS_STEP(v) \
++ (((v) << BP_ANADIG_PLL_528_SS_STEP) & \
++ BM_ANADIG_PLL_528_SS_STEP)
++
++#define BP_ANADIG_PLL_528_NUM_A 0
++#define BM_ANADIG_PLL_528_NUM_A (0x3FFFFFFF << BP_ANADIG_PLL_528_NUM_A)
++#define BF_ANADIG_PLL_528_NUM_A(v) \
++ (((v) << BP_ANADIG_PLL_528_NUM_A) & \
++ BM_ANADIG_PLL_528_NUM_A)
++
++#define BP_ANADIG_PLL_528_DENOM_B 0
++#define BM_ANADIG_PLL_528_DENOM_B (0x3FFFFFFF << BP_ANADIG_PLL_528_DENOM_B)
++#define BF_ANADIG_PLL_528_DENOM_B(v) \
++ (((v) << BP_ANADIG_PLL_528_DENOM_B) & \
++ BM_ANADIG_PLL_528_DENOM_B)
++
++#define BM_ANADIG_PLL_AUDIO_LOCK (1 << 31)
++#define BM_ANADIG_PLL_AUDIO_SSC_EN (1 << 21)
++#define BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT 19
++#define BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT (0x3 << BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT)
++#define BF_ANADIG_PLL_AUDIO_TEST_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_TEST_DIV_SELECT) & \
++ BM_ANADIG_PLL_AUDIO_TEST_DIV_SELECT)
++#define BM_ANADIG_PLL_AUDIO_PFD_OFFSET_EN (1 << 18)
++#define BM_ANADIG_PLL_AUDIO_DITHER_ENABLE (1 << 17)
++#define BM_ANADIG_PLL_AUDIO_BYPASS (1 << 16)
++#define BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC 14
++#define BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC)
++#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_PLL_AUDIO_BYPASS_CLK_SRC__XOR 0x3
++#define BM_ANADIG_PLL_AUDIO_ENABLE (1 << 13)
++#define BM_ANADIG_PLL_AUDIO_POWERDOWN (1 << 12)
++#define BM_ANADIG_PLL_AUDIO_HOLD_RING_OFF (1 << 11)
++#define BM_ANADIG_PLL_AUDIO_DOUBLE_CP (1 << 10)
++#define BM_ANADIG_PLL_AUDIO_HALF_CP (1 << 9)
++#define BM_ANADIG_PLL_AUDIO_DOUBLE_LF (1 << 8)
++#define BM_ANADIG_PLL_AUDIO_HALF_LF (1 << 7)
++#define BP_ANADIG_PLL_AUDIO_DIV_SELECT 0
++#define BM_ANADIG_PLL_AUDIO_DIV_SELECT (0x7F << BP_ANADIG_PLL_AUDIO_DIV_SELECT)
++#define BF_ANADIG_PLL_AUDIO_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_DIV_SELECT) & \
++ BM_ANADIG_PLL_AUDIO_DIV_SELECT)
++
++#define BP_ANADIG_PLL_AUDIO_NUM_A 0
++#define BM_ANADIG_PLL_AUDIO_NUM_A (0x3FFFFFFF << BP_ANADIG_PLL_AUDIO_NUM_A)
++#define BF_ANADIG_PLL_AUDIO_NUM_A(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_NUM_A) & \
++ BM_ANADIG_PLL_AUDIO_NUM_A)
++
++#define BP_ANADIG_PLL_AUDIO_DENOM_B 0
++#define BM_ANADIG_PLL_AUDIO_DENOM_B (0x3FFFFFFF << BP_ANADIG_PLL_AUDIO_DENOM_B)
++#define BF_ANADIG_PLL_AUDIO_DENOM_B(v) \
++ (((v) << BP_ANADIG_PLL_AUDIO_DENOM_B) & \
++ BM_ANADIG_PLL_AUDIO_DENOM_B)
++
++#define BM_ANADIG_PLL_VIDEO_LOCK (1 << 31)
++#define BM_ANADIG_PLL_VIDEO_SSC_EN (1 << 21)
++#define BP_ANADIG_PLL_VIDEO_POST_DIV_SELECT 19
++#define BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT (0x3 << BP_ANADIG_PLL_VIDEO_POST_DIV_SELECT)
++#define BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_POST_DIV_SELECT) & \
++ BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT)
++#define BM_ANADIG_PLL_VIDEO_PFD_OFFSET_EN (1 << 18)
++#define BM_ANADIG_PLL_VIDEO_DITHER_ENABLE (1 << 17)
++#define BM_ANADIG_PLL_VIDEO_BYPASS (1 << 16)
++#define BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC 14
++#define BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC)
++#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_PLL_VIDEO_BYPASS_CLK_SRC__XOR 0x3
++#define BM_ANADIG_PLL_VIDEO_ENABLE (1 << 13)
++#define BM_ANADIG_PLL_VIDEO_POWERDOWN (1 << 12)
++#define BM_ANADIG_PLL_VIDEO_HOLD_RING_OFF (1 << 11)
++#define BM_ANADIG_PLL_VIDEO_DOUBLE_CP (1 << 10)
++#define BM_ANADIG_PLL_VIDEO_HALF_CP (1 << 9)
++#define BM_ANADIG_PLL_VIDEO_DOUBLE_LF (1 << 8)
++#define BM_ANADIG_PLL_VIDEO_HALF_LF (1 << 7)
++#define BP_ANADIG_PLL_VIDEO_DIV_SELECT 0
++#define BM_ANADIG_PLL_VIDEO_DIV_SELECT (0x7F << BP_ANADIG_PLL_VIDEO_DIV_SELECT)
++#define BF_ANADIG_PLL_VIDEO_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_DIV_SELECT) & \
++ BM_ANADIG_PLL_VIDEO_DIV_SELECT)
++
++#define BP_ANADIG_PLL_VIDEO_NUM_A 0
++#define BM_ANADIG_PLL_VIDEO_NUM_A (0x3FFFFFFF << BP_ANADIG_PLL_VIDEO_NUM_A)
++#define BF_ANADIG_PLL_VIDEO_NUM_A(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_NUM_A) & \
++ BM_ANADIG_PLL_VIDEO_NUM_A)
++
++#define BP_ANADIG_PLL_VIDEO_DENOM_B 0
++#define BM_ANADIG_PLL_VIDEO_DENOM_B (0x3FFFFFFF << BP_ANADIG_PLL_VIDEO_DENOM_B)
++#define BF_ANADIG_PLL_VIDEO_DENOM_B(v) \
++ (((v) << BP_ANADIG_PLL_VIDEO_DENOM_B) & \
++ BM_ANADIG_PLL_VIDEO_DENOM_B)
++
++#define BM_ANADIG_PLL_ENET_LOCK (1 << 31)
++#define BM_ANADIG_PLL_ENET_REF_25M_ENABLE (1 << 21)
++#define BM_ANADIG_PLL_ENET_ENABLE_SATA (1 << 20)
++#define BM_ANADIG_PLL_ENET_ENABLE_PCIE (1 << 19)
++#define BM_ANADIG_PLL_ENET_PFD_OFFSET_EN (1 << 18)
++#define BM_ANADIG_PLL_ENET_DITHER_ENABLE (1 << 17)
++#define BM_ANADIG_PLL_ENET_BYPASS (1 << 16)
++#define BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC 14
++#define BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC (0x3 << BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
++#define BF_ANADIG_PLL_ENET_BYPASS_CLK_SRC(v) \
++ (((v) << BP_ANADIG_PLL_ENET_BYPASS_CLK_SRC) & \
++ BM_ANADIG_PLL_ENET_BYPASS_CLK_SRC)
++#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__OSC_24M 0x0
++#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_1 0x1
++#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__ANACLK_2 0x2
++#define BV_ANADIG_PLL_ENET_BYPASS_CLK_SRC__XOR 0x3
++#define BM_ANADIG_PLL_ENET_ENABLE (1 << 13)
++#define BM_ANADIG_PLL_ENET_POWERDOWN (1 << 12)
++#define BM_ANADIG_PLL_ENET_HOLD_RING_OFF (1 << 11)
++#define BM_ANADIG_PLL_ENET_DOUBLE_CP (1 << 10)
++#define BM_ANADIG_PLL_ENET_HALF_CP (1 << 9)
++#define BM_ANADIG_PLL_ENET_DOUBLE_LF (1 << 8)
++#define BM_ANADIG_PLL_ENET_HALF_LF (1 << 7)
++#define BP_ANADIG_PLL_ENET_DIV_SELECT 0
++#define BM_ANADIG_PLL_ENET_DIV_SELECT (0x3 << BP_ANADIG_PLL_ENET_DIV_SELECT)
++#define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \
++ (((v) << BP_ANADIG_PLL_ENET_DIV_SELECT) & \
++ BM_ANADIG_PLL_ENET_DIV_SELECT)
++
++#define BM_ANADIG_PFD_480_PFD3_CLKGATE (1 << 31)
++#define BM_ANADIG_PFD_480_PFD3_STABLE (1 << 30)
++#define BP_ANADIG_PFD_480_PFD3_FRAC 24
++#define BM_ANADIG_PFD_480_PFD3_FRAC (0x3F << BP_ANADIG_PFD_480_PFD3_FRAC)
++#define BF_ANADIG_PFD_480_PFD3_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_480_PFD3_FRAC) & \
++ BM_ANADIG_PFD_480_PFD3_FRAC)
++#define BM_ANADIG_PFD_480_PFD2_CLKGATE (1 << 23)
++#define BM_ANADIG_PFD_480_PFD2_STABLE (1 << 22)
++#define BP_ANADIG_PFD_480_PFD2_FRAC 16
++#define BM_ANADIG_PFD_480_PFD2_FRAC (0x3F << BP_ANADIG_PFD_480_PFD2_FRAC)
++#define BF_ANADIG_PFD_480_PFD2_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_480_PFD2_FRAC) & \
++ BM_ANADIG_PFD_480_PFD2_FRAC)
++#define BM_ANADIG_PFD_480_PFD1_CLKGATE (1 << 15)
++#define BM_ANADIG_PFD_480_PFD1_STABLE (1 << 14)
++#define BP_ANADIG_PFD_480_PFD1_FRAC 8
++#define BM_ANADIG_PFD_480_PFD1_FRAC (0x3F << BP_ANADIG_PFD_480_PFD1_FRAC)
++#define BF_ANADIG_PFD_480_PFD1_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_480_PFD1_FRAC) & \
++ BM_ANADIG_PFD_480_PFD1_FRAC)
++#define BM_ANADIG_PFD_480_PFD0_CLKGATE (1 << 7)
++#define BM_ANADIG_PFD_480_PFD0_STABLE (1 << 6)
++#define BP_ANADIG_PFD_480_PFD0_FRAC 0
++#define BM_ANADIG_PFD_480_PFD0_FRAC (0x3F << BP_ANADIG_PFD_480_PFD0_FRAC)
++#define BF_ANADIG_PFD_480_PFD0_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_480_PFD0_FRAC) & \
++ BM_ANADIG_PFD_480_PFD0_FRAC)
++
++#define BM_ANADIG_PFD_528_PFD3_CLKGATE (1 << 31)
++#define BM_ANADIG_PFD_528_PFD3_STABLE (1 << 30)
++#define BP_ANADIG_PFD_528_PFD3_FRAC 24
++#define BM_ANADIG_PFD_528_PFD3_FRAC (0x3F << BP_ANADIG_PFD_528_PFD3_FRAC)
++#define BF_ANADIG_PFD_528_PFD3_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_528_PFD3_FRAC) & \
++ BM_ANADIG_PFD_528_PFD3_FRAC)
++#define BM_ANADIG_PFD_528_PFD2_CLKGATE (1 << 23)
++#define BM_ANADIG_PFD_528_PFD2_STABLE (1 << 22)
++#define BP_ANADIG_PFD_528_PFD2_FRAC 16
++#define BM_ANADIG_PFD_528_PFD2_FRAC (0x3F << BP_ANADIG_PFD_528_PFD2_FRAC)
++#define BF_ANADIG_PFD_528_PFD2_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_528_PFD2_FRAC) & \
++ BM_ANADIG_PFD_528_PFD2_FRAC)
++#define BM_ANADIG_PFD_528_PFD1_CLKGATE (1 << 15)
++#define BM_ANADIG_PFD_528_PFD1_STABLE (1 << 14)
++#define BP_ANADIG_PFD_528_PFD1_FRAC 8
++#define BM_ANADIG_PFD_528_PFD1_FRAC (0x3F << BP_ANADIG_PFD_528_PFD1_FRAC)
++#define BF_ANADIG_PFD_528_PFD1_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_528_PFD1_FRAC) & \
++ BM_ANADIG_PFD_528_PFD1_FRAC)
++#define BM_ANADIG_PFD_528_PFD0_CLKGATE (1 << 7)
++#define BM_ANADIG_PFD_528_PFD0_STABLE (1 << 6)
++#define BP_ANADIG_PFD_528_PFD0_FRAC 0
++#define BM_ANADIG_PFD_528_PFD0_FRAC (0x3F << BP_ANADIG_PFD_528_PFD0_FRAC)
++#define BF_ANADIG_PFD_528_PFD0_FRAC(v) \
++ (((v) << BP_ANADIG_PFD_528_PFD0_FRAC) & \
++ BM_ANADIG_PFD_528_PFD0_FRAC)
#endif /*__ARCH_ARM_MACH_MX6_CCM_REGS_H__ */
#ifndef __ASM_ARCH_MX6_IMX_REGS_H__
#define __ASM_ARCH_MX6_IMX_REGS_H__
+ #include <asm/imx-common/regs-common.h>
+
#define ARCH_MXC
- #define CONFIG_SYS_CACHELINE_SIZE 32
++#define CONFIG_SYS_CACHELINE_SIZE 64
+
- #define ROMCP_ARB_BASE_ADDR 0x00000000
- #define ROMCP_ARB_END_ADDR 0x000FFFFF
+ #define ROMCP_ARB_BASE_ADDR 0x00000000
+ #define ROMCP_ARB_END_ADDR 0x000FFFFF
#ifdef CONFIG_MX6SL
- #define GPU_2D_ARB_BASE_ADDR 0x02200000
- #define GPU_2D_ARB_END_ADDR 0x02203FFF
- #define OPENVG_ARB_BASE_ADDR 0x02204000
- #define OPENVG_ARB_END_ADDR 0x02207FFF
- #elif CONFIG_MX6SX
- #define CAAM_ARB_BASE_ADDR 0x00100000
- #define CAAM_ARB_END_ADDR 0x00107FFF
- #define GPU_ARB_BASE_ADDR 0x01800000
- #define GPU_ARB_END_ADDR 0x01803FFF
- #define APBH_DMA_ARB_BASE_ADDR 0x01804000
- #define APBH_DMA_ARB_END_ADDR 0x0180BFFF
- #define M4_BOOTROM_BASE_ADDR 0x007F8000
+ #define GPU_2D_ARB_BASE_ADDR 0x02200000
+ #define GPU_2D_ARB_END_ADDR 0x02203FFF
+ #define OPENVG_ARB_BASE_ADDR 0x02204000
+ #define OPENVG_ARB_END_ADDR 0x02207FFF
++#elif defined(CONFIG_MX6SX)
++#define CAAM_ARB_BASE_ADDR 0x00100000
++#define CAAM_ARB_END_ADDR 0x00107FFF
++#define GPU_ARB_BASE_ADDR 0x01800000
++#define GPU_ARB_END_ADDR 0x01803FFF
++#define APBH_DMA_ARB_BASE_ADDR 0x01804000
++#define APBH_DMA_ARB_END_ADDR 0x0180BFFF
++#define M4_BOOTROM_BASE_ADDR 0x007F8000
+
+#define MXS_APBH_BASE APBH_DMA_ARB_BASE_ADDR
+#define MXS_GPMI_BASE (APBH_DMA_ARB_BASE_ADDR + 0x02000)
+#define MXS_BCH_BASE (APBH_DMA_ARB_BASE_ADDR + 0x04000)
+
#else
- #define CAAM_ARB_BASE_ADDR 0x00100000
- #define CAAM_ARB_END_ADDR 0x00103FFF
- #define APBH_DMA_ARB_BASE_ADDR 0x00110000
- #define APBH_DMA_ARB_END_ADDR 0x00117FFF
- #define HDMI_ARB_BASE_ADDR 0x00120000
- #define HDMI_ARB_END_ADDR 0x00128FFF
- #define GPU_3D_ARB_BASE_ADDR 0x00130000
- #define GPU_3D_ARB_END_ADDR 0x00133FFF
- #define GPU_2D_ARB_BASE_ADDR 0x00134000
- #define GPU_2D_ARB_END_ADDR 0x00137FFF
- #define DTCP_ARB_BASE_ADDR 0x00138000
- #define DTCP_ARB_END_ADDR 0x0013BFFF
+ #define CAAM_ARB_BASE_ADDR 0x00100000
+ #define CAAM_ARB_END_ADDR 0x00103FFF
+ #define APBH_DMA_ARB_BASE_ADDR 0x00110000
+ #define APBH_DMA_ARB_END_ADDR 0x00117FFF
+ #define HDMI_ARB_BASE_ADDR 0x00120000
+ #define HDMI_ARB_END_ADDR 0x00128FFF
+ #define GPU_3D_ARB_BASE_ADDR 0x00130000
+ #define GPU_3D_ARB_END_ADDR 0x00133FFF
+ #define GPU_2D_ARB_BASE_ADDR 0x00134000
+ #define GPU_2D_ARB_END_ADDR 0x00137FFF
+ #define DTCP_ARB_BASE_ADDR 0x00138000
+ #define DTCP_ARB_END_ADDR 0x0013BFFF
#endif /* CONFIG_MX6SL */
#define MXS_APBH_BASE APBH_DMA_ARB_BASE_ADDR
#define MXS_BCH_BASE (APBH_DMA_ARB_BASE_ADDR + 0x04000)
/* GPV - PL301 configuration ports */
-#ifdef CONFIG_MX6SL
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
- #define GPV2_BASE_ADDR 0x00D00000
+ #define GPV2_BASE_ADDR 0x00D00000
#else
#define GPV2_BASE_ADDR 0x00200000
#endif
- #define PCIE_ARB_BASE_ADDR 0x08000000
- #define PCIE_ARB_END_ADDR 0x08FFFFFF
+#ifdef CONFIG_MX6SX
+#define GPV3_BASE_ADDR 0x00E00000
+#define GPV4_BASE_ADDR 0x00F00000
+#define GPV5_BASE_ADDR 0x01000000
+#define GPV6_BASE_ADDR 0x01100000
++#define PCIE_ARB_BASE_ADDR 0x08000000
++#define PCIE_ARB_END_ADDR 0x08FFFFFF
+
+#else
#define GPV3_BASE_ADDR 0x00300000
#define GPV4_BASE_ADDR 0x00800000
- #define PCIE_ARB_BASE_ADDR 0x01000000
- #define PCIE_ARB_END_ADDR 0x01FFFFFF
++#define PCIE_ARB_BASE_ADDR 0x01000000
++#define PCIE_ARB_END_ADDR 0x01FFFFFF
+#endif
+
#define IRAM_BASE_ADDR 0x00900000
- #define SCU_BASE_ADDR 0x00A00000
- #define IC_INTERFACES_BASE_ADDR 0x00A00100
- #define GLOBAL_TIMER_BASE_ADDR 0x00A00200
- #define PRIVATE_TIMERS_WD_BASE_ADDR 0x00A00600
- #define IC_DISTRIBUTOR_BASE_ADDR 0x00A01000
+ #define SCU_BASE_ADDR 0x00A00000
+ #define IC_INTERFACES_BASE_ADDR 0x00A00100
+ #define GLOBAL_TIMER_BASE_ADDR 0x00A00200
+ #define PRIVATE_TIMERS_WD_BASE_ADDR 0x00A00600
+ #define IC_DISTRIBUTOR_BASE_ADDR 0x00A01000
+#define L2_PL310_BASE 0x00A02000
- #define GPV0_BASE_ADDR 0x00B00000
- #define GPV1_BASE_ADDR 0x00C00000
+ #define GPV0_BASE_ADDR 0x00B00000
+ #define GPV1_BASE_ADDR 0x00C00000
-#define PCIE_ARB_BASE_ADDR 0x01000000
-#define PCIE_ARB_END_ADDR 0x01FFFFFF
- #define AIPS1_ARB_BASE_ADDR 0x02000000
- #define AIPS1_ARB_END_ADDR 0x020FFFFF
- #define AIPS2_ARB_BASE_ADDR 0x02100000
- #define AIPS2_ARB_END_ADDR 0x021FFFFF
+ #define AIPS1_ARB_BASE_ADDR 0x02000000
+ #define AIPS1_ARB_END_ADDR 0x020FFFFF
+ #define AIPS2_ARB_BASE_ADDR 0x02100000
+ #define AIPS2_ARB_END_ADDR 0x021FFFFF
+#ifdef CONFIG_MX6SX
+#define AIPS3_BASE_ADDR 0x02200000
+#define AIPS3_END_ADDR 0x022FFFFF
- #define WEIM_ARB_BASE_ADDR 0x50000000
- #define WEIM_ARB_END_ADDR 0x57FFFFFF
- #define QSPI0_AMBA_BASE 0x60000000
- #define QSPI0_AMBA_END 0x6FFFFFFF
- #define QSPI1_AMBA_BASE 0x70000000
- #define QSPI1_AMBA_END 0x7FFFFFFF
++#define WEIM_ARB_BASE_ADDR 0x50000000
++#define WEIM_ARB_END_ADDR 0x57FFFFFF
++#define QSPI0_AMBA_BASE 0x60000000
++#define QSPI0_AMBA_END 0x6FFFFFFF
++#define QSPI1_AMBA_BASE 0x70000000
++#define QSPI1_AMBA_END 0x7FFFFFFF
+#else
- #define SATA_ARB_BASE_ADDR 0x02200000
- #define SATA_ARB_END_ADDR 0x02203FFF
- #define OPENVG_ARB_BASE_ADDR 0x02204000
- #define OPENVG_ARB_END_ADDR 0x02207FFF
- #define HSI_ARB_BASE_ADDR 0x02208000
- #define HSI_ARB_END_ADDR 0x0220BFFF
- #define IPU1_ARB_BASE_ADDR 0x02400000
- #define IPU1_ARB_END_ADDR 0x027FFFFF
- #define IPU2_ARB_BASE_ADDR 0x02800000
- #define IPU2_ARB_END_ADDR 0x02BFFFFF
- #define WEIM_ARB_BASE_ADDR 0x08000000
- #define WEIM_ARB_END_ADDR 0x0FFFFFFF
+ #define SATA_ARB_BASE_ADDR 0x02200000
+ #define SATA_ARB_END_ADDR 0x02203FFF
+ #define OPENVG_ARB_BASE_ADDR 0x02204000
+ #define OPENVG_ARB_END_ADDR 0x02207FFF
+ #define HSI_ARB_BASE_ADDR 0x02208000
+ #define HSI_ARB_END_ADDR 0x0220BFFF
+ #define IPU1_ARB_BASE_ADDR 0x02400000
+ #define IPU1_ARB_END_ADDR 0x027FFFFF
+ #define IPU2_ARB_BASE_ADDR 0x02800000
+ #define IPU2_ARB_END_ADDR 0x02BFFFFF
+ #define WEIM_ARB_BASE_ADDR 0x08000000
+ #define WEIM_ARB_END_ADDR 0x0FFFFFFF
+#endif
-#ifdef CONFIG_MX6SL
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
- #define MMDC0_ARB_BASE_ADDR 0x80000000
- #define MMDC0_ARB_END_ADDR 0xFFFFFFFF
- #define MMDC1_ARB_BASE_ADDR 0xC0000000
- #define MMDC1_ARB_END_ADDR 0xFFFFFFFF
+ #define MMDC0_ARB_BASE_ADDR 0x80000000
+ #define MMDC0_ARB_END_ADDR 0xFFFFFFFF
+ #define MMDC1_ARB_BASE_ADDR 0xC0000000
+ #define MMDC1_ARB_END_ADDR 0xFFFFFFFF
#else
- #define MMDC0_ARB_BASE_ADDR 0x10000000
- #define MMDC0_ARB_END_ADDR 0x7FFFFFFF
- #define MMDC1_ARB_BASE_ADDR 0x80000000
- #define MMDC1_ARB_END_ADDR 0xFFFFFFFF
+ #define MMDC0_ARB_BASE_ADDR 0x10000000
+ #define MMDC0_ARB_END_ADDR 0x7FFFFFFF
+ #define MMDC1_ARB_BASE_ADDR 0x80000000
+ #define MMDC1_ARB_END_ADDR 0xFFFFFFFF
#endif
+#ifndef CONFIG_MX6SX
#define IPU_SOC_BASE_ADDR IPU1_ARB_BASE_ADDR
#define IPU_SOC_OFFSET 0x00200000
+#endif
/* Defines for Blocks connected via AIPS (SkyBlue) */
- #define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR
- #define ATZ2_BASE_ADDR AIPS2_ARB_BASE_ADDR
- #define AIPS1_BASE_ADDR AIPS1_ON_BASE_ADDR
- #define AIPS2_BASE_ADDR AIPS2_ON_BASE_ADDR
-
- #define SPDIF_BASE_ADDR (ATZ1_BASE_ADDR + 0x04000)
- #define ECSPI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x08000)
- #define ECSPI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x0C000)
- #define ECSPI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x10000)
- #define ECSPI4_BASE_ADDR (ATZ1_BASE_ADDR + 0x14000)
+ #define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR
+ #define ATZ2_BASE_ADDR AIPS2_ARB_BASE_ADDR
+ #define AIPS1_BASE_ADDR AIPS1_ON_BASE_ADDR
+ #define AIPS2_BASE_ADDR AIPS2_ON_BASE_ADDR
+
+ #define SPDIF_BASE_ADDR (ATZ1_BASE_ADDR + 0x04000)
+ #define ECSPI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x08000)
+ #define ECSPI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x0C000)
+ #define ECSPI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x10000)
+ #define ECSPI4_BASE_ADDR (ATZ1_BASE_ADDR + 0x14000)
#ifdef CONFIG_MX6SL
- #define UART5_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000)
- #define UART1_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000)
- #define UART2_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000)
- #define SSI1_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000)
- #define SSI2_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000)
- #define SSI3_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000)
- #define UART3_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000)
- #define UART4_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x38000)
+ #define UART5_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000)
+ #define UART1_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000)
+ #define UART2_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000)
+ #define SSI1_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000)
+ #define SSI2_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000)
+ #define SSI3_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000)
+ #define UART3_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000)
+ #define UART4_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x38000)
#else
- #define ECSPI5_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000)
+#ifndef CONFIG_MX6SX
- #define UART1_BASE (ATZ1_BASE_ADDR + 0x20000)
- #define ESAI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000)
- #define SSI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000)
- #define SSI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000)
- #define SSI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000)
- #define ASRC_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000)
+ #define ECSPI5_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000)
+#endif
+ #define UART1_BASE (ATZ1_BASE_ADDR + 0x20000)
+ #define ESAI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000)
+ #define SSI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000)
+ #define SSI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000)
+ #define SSI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000)
+ #define ASRC_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000)
#endif
- #define SPBA_BASE_ADDR (ATZ1_BASE_ADDR + 0x3C000)
- #define VPU_BASE_ADDR (ATZ1_BASE_ADDR + 0x40000)
+#ifndef CONFIG_MX6SX
- #define AIPS1_ON_BASE_ADDR (ATZ1_BASE_ADDR + 0x7C000)
-
- #define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000)
- #define PWM1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x0000)
- #define PWM2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4000)
- #define PWM3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x8000)
- #define PWM4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0xC000)
- #define CAN1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x10000)
- #define CAN2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x14000)
- #define GPT1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x18000)
- #define GPIO1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x1C000)
- #define GPIO2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x20000)
- #define GPIO3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x24000)
- #define GPIO4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x28000)
- #define GPIO5_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x2C000)
- #define GPIO6_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x30000)
- #define GPIO7_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x34000)
- #define KPP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x38000)
- #define WDOG1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x3C000)
- #define WDOG2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x40000)
- #define ANATOP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x48000)
- #define USB_PHY0_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x49000)
- #define USB_PHY1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4a000)
- #define CCM_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x44000)
- #define SNVS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4C000)
- #define EPIT1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x50000)
- #define EPIT2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x54000)
- #define SRC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x58000)
- #define GPC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x5C000)
- #define IOMUXC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x60000)
+ #define SPBA_BASE_ADDR (ATZ1_BASE_ADDR + 0x3C000)
+ #define VPU_BASE_ADDR (ATZ1_BASE_ADDR + 0x40000)
+#endif
+ #define AIPS1_ON_BASE_ADDR (ATZ1_BASE_ADDR + 0x7C000)
+
+ #define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000)
+ #define PWM1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x0000)
+ #define PWM2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4000)
+ #define PWM3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x8000)
+ #define PWM4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0xC000)
+ #define CAN1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x10000)
+ #define CAN2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x14000)
+ #define GPT1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x18000)
+ #define GPIO1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x1C000)
+ #define GPIO2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x20000)
+ #define GPIO3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x24000)
+ #define GPIO4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x28000)
+ #define GPIO5_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x2C000)
+ #define GPIO6_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x30000)
+ #define GPIO7_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x34000)
+ #define KPP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x38000)
+ #define WDOG1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x3C000)
+ #define WDOG2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x40000)
+ #define CCM_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x44000)
+ #define ANATOP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x48000)
+ #define USB_PHY0_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x49000)
+ #define USB_PHY1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4a000)
+ #define SNVS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4C000)
+ #define EPIT1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x50000)
+ #define EPIT2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x54000)
+ #define SRC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x58000)
+ #define GPC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x5C000)
+ #define IOMUXC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x60000)
#ifdef CONFIG_MX6SL
- #define CSI_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000)
- #define SIPIX_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
+ #define CSI_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000)
+ #define SIPIX_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
#define SDMA_PORT_HOST_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000)
- #elif CONFIG_MX6SX
++#elif defined(CONFIG_MX6SX)
+#define CANFD1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
+#define SDMA_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000)
+#define CANFD2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x70000)
+#define SEMAPHORE1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x74000)
+#define SEMAPHORE2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x78000)
+#define RDC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x7C000)
#else
- #define DCIC1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000)
- #define DCIC2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
+ #define DCIC1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000)
+ #define DCIC2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
#define DMA_REQ_PORT_HOST_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000)
#endif
- #define AIPS2_ON_BASE_ADDR (ATZ2_BASE_ADDR + 0x7C000)
- #define AIPS2_OFF_BASE_ADDR (ATZ2_BASE_ADDR + 0x80000)
- #define CAAM_BASE_ADDR (ATZ2_BASE_ADDR)
+ #define AIPS2_ON_BASE_ADDR (ATZ2_BASE_ADDR + 0x7C000)
+ #define AIPS2_OFF_BASE_ADDR (ATZ2_BASE_ADDR + 0x80000)
+ #define CAAM_BASE_ADDR (ATZ2_BASE_ADDR)
#define ARM_BASE_ADDR (ATZ2_BASE_ADDR + 0x40000)
- #define USB_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
- #define USB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
-#ifdef CONFIG_MX6SL
-#define USBO2H_PL301_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
-#define USBO2H_USB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
-#else
-#define USBOH3_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
-#define USBOH3_USB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
-#endif
++#define USB_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
++#define USB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
- #define ENET_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x8000)
+ #define ENET_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x8000)
#ifdef CONFIG_MX6SL
- #define MSHC_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0xC000)
+ #define MSHC_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0xC000)
#else
- #define MLB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0xC000)
+ #define MLB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0xC000)
#endif
- #define USDHC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x10000)
- #define USDHC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x14000)
- #define USDHC3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x18000)
- #define USDHC4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x1C000)
- #define I2C1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x20000)
- #define I2C2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x24000)
- #define I2C3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x28000)
- #define ROMCP_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x2C000)
- #define MMDC_P0_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x30000)
+ #define USDHC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x10000)
+ #define USDHC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x14000)
+ #define USDHC3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x18000)
+ #define USDHC4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x1C000)
+ #define I2C1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x20000)
+ #define I2C2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x24000)
+ #define I2C3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x28000)
+ #define ROMCP_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x2C000)
+ #define MMDC_P0_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x30000)
#ifdef CONFIG_MX6SL
- #define RNGB_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
- #elif CONFIG_MX6SX
- #define ENET2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
+ #define RNGB_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
++#elif defined(CONFIG_MX6SX)
++#define ENET2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
#else
- #define MMDC_P1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
+ #define MMDC_P1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
#endif
- #define WEIM_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x38000)
- #define OCOTP_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x3C000)
- #define CSU_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x40000)
+ #define WEIM_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x38000)
+ #define OCOTP_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x3C000)
+ #define CSU_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x40000)
#define IP2APB_PERFMON1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x44000)
#define IP2APB_PERFMON2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x48000)
+#ifdef CONFIG_MX6SX
+#define DEBUG_MONITOR_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4C000)
+#else
#define IP2APB_PERFMON3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4C000)
- #define IP2APB_TZASC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x50000)
+#endif
- #define SAI1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000)
+ #define IP2APB_TZASC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x50000)
+#ifdef CONFIG_MX6SX
- #define IP2APB_TZASC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000)
++#define SAI1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000)
+#else
- #define AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000)
- #define AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000)
+ #define IP2APB_TZASC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000)
+#endif
- #define SAI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000)
- #define QSPI0_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000)
- #define QSPI1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000)
+ #define AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000)
+#ifdef CONFIG_MX6SX
- #define MIPI_CSI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000)
- #define MIPI_DSI_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000)
- #define VDOA_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000)
++#define SAI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000)
++#define QSPI0_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000)
++#define QSPI1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000)
+#else
- #define UART2_BASE (AIPS2_OFF_BASE_ADDR + 0x68000)
- #define UART3_BASE (AIPS2_OFF_BASE_ADDR + 0x6C000)
- #define UART4_BASE (AIPS2_OFF_BASE_ADDR + 0x70000)
- #define UART5_BASE (AIPS2_OFF_BASE_ADDR + 0x74000)
+ #define MIPI_CSI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000)
+ #define MIPI_DSI_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000)
+ #define VDOA_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000)
+#endif
+ #define UART2_BASE (AIPS2_OFF_BASE_ADDR + 0x68000)
+ #define UART3_BASE (AIPS2_OFF_BASE_ADDR + 0x6C000)
+ #define UART4_BASE (AIPS2_OFF_BASE_ADDR + 0x70000)
+ #define UART5_BASE (AIPS2_OFF_BASE_ADDR + 0x74000)
#define IP2APB_USBPHY1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x78000)
#define IP2APB_USBPHY2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x7C000)
- #define GIS_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x04000)
- #define DCIC1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x0C000)
- #define DCIC2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x10000)
- #define CSI1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x14000)
- #define PXP_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x18000)
- #define CSI2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x1C000)
- #define LCDIF1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x20000)
- #define LCDIF2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x24000)
- #define VADC_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x28000)
- #define VDEC_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x2C000)
- #define SPBA_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x3C000)
- #define AIPS3_CONFIG_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x7C000)
- #define ADC1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x80000)
- #define ADC2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x84000)
- #define WDOG3_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x88000)
- #define ECSPI5_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x8C000)
- #define HS_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x90000)
- #define MU_MCU_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x94000)
- #define CANFD_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x98000)
- #define MU_DSP_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x9C000)
- #define UART6_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xA0000)
- #define PWM5_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xA4000)
- #define PWM6_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xA8000)
- #define PWM7_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xAC000)
- #define PWM8_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xB0000)
+#ifdef CONFIG_MX6SX
- #define CHIP_REV_1_0 0x10
- #define CHIP_REV_1_2 0x12
- #define CHIP_REV_1_5 0x15
++#define GIS_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x04000)
++#define DCIC1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x0C000)
++#define DCIC2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x10000)
++#define CSI1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x14000)
++#define PXP_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x18000)
++#define CSI2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x1C000)
++#define LCDIF1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x20000)
++#define LCDIF2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x24000)
++#define VADC_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x28000)
++#define VDEC_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x2C000)
++#define SPBA_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x3C000)
++#define AIPS3_CONFIG_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x7C000)
++#define ADC1_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x80000)
++#define ADC2_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x84000)
++#define WDOG3_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x88000)
++#define ECSPI5_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x8C000)
++#define HS_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x90000)
++#define MU_MCU_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x94000)
++#define CANFD_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x98000)
++#define MU_DSP_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0x9C000)
++#define UART6_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xA0000)
++#define PWM5_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xA4000)
++#define PWM6_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xA8000)
++#define PWM7_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xAC000)
++#define PWM8_BASE_ADDR (AIPS3_ARB_BASE_ADDR + 0xB0000)
+#endif
+
- #define IRAM_SIZE 0x00040000
+ #define CHIP_REV_1_0 0x10
++#define CHIP_REV_1_2 0x12
++#define CHIP_REV_1_5 0x15
+#ifndef CONFIG_MX6SX
- #define IRAM_SIZE 0x00020000
+ #define IRAM_SIZE 0x00040000
+#else
++#define IRAM_SIZE 0x00020000
+#endif
+ #define IMX_IIM_BASE OCOTP_BASE_ADDR
#define FEC_QUIRK_ENET_MAC
#if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__))
#include <asm/types.h>
- extern void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
-
- #define SRC_SCR_CORE_1_RESET_OFFSET 14
- #define SRC_SCR_CORE_1_RESET_MASK (1<<SRC_SCR_CORE_1_RESET_OFFSET)
- #define SRC_SCR_CORE_2_RESET_OFFSET 15
- #define SRC_SCR_CORE_2_RESET_MASK (1<<SRC_SCR_CORE_2_RESET_OFFSET)
- #define SRC_SCR_CORE_3_RESET_OFFSET 16
- #define SRC_SCR_CORE_3_RESET_MASK (1<<SRC_SCR_CORE_3_RESET_OFFSET)
- #define SRC_SCR_CORE_1_ENABLE_OFFSET 22
- #define SRC_SCR_CORE_1_ENABLE_MASK (1<<SRC_SCR_CORE_1_ENABLE_OFFSET)
- #define SRC_SCR_CORE_2_ENABLE_OFFSET 23
- #define SRC_SCR_CORE_2_ENABLE_MASK (1<<SRC_SCR_CORE_2_ENABLE_OFFSET)
- #define SRC_SCR_CORE_3_ENABLE_OFFSET 24
- #define SRC_SCR_CORE_3_ENABLE_MASK (1<<SRC_SCR_CORE_3_ENABLE_OFFSET)
++#define SRC_SCR_CORE_1_RESET_OFFSET 14
++#define SRC_SCR_CORE_1_RESET_MASK (1 << SRC_SCR_CORE_1_RESET_OFFSET)
++#define SRC_SCR_CORE_2_RESET_OFFSET 15
++#define SRC_SCR_CORE_2_RESET_MASK (1 << SRC_SCR_CORE_2_RESET_OFFSET)
++#define SRC_SCR_CORE_3_RESET_OFFSET 16
++#define SRC_SCR_CORE_3_RESET_MASK (1 << SRC_SCR_CORE_3_RESET_OFFSET)
++#define SRC_SCR_CORE_1_ENABLE_OFFSET 22
++#define SRC_SCR_CORE_1_ENABLE_MASK (1 << SRC_SCR_CORE_1_ENABLE_OFFSET)
++#define SRC_SCR_CORE_2_ENABLE_OFFSET 23
++#define SRC_SCR_CORE_2_ENABLE_MASK (1 << SRC_SCR_CORE_2_ENABLE_OFFSET)
++#define SRC_SCR_CORE_3_ENABLE_OFFSET 24
++#define SRC_SCR_CORE_3_ENABLE_MASK (1 << SRC_SCR_CORE_3_ENABLE_OFFSET)
+
+/* WEIM registers */
+struct weim {
+ u32 cs0gcr1;
+ u32 cs0gcr2;
+ u32 cs0rcr1;
+ u32 cs0rcr2;
+ u32 cs0wcr1;
+ u32 cs0wcr2;
+
+ u32 cs1gcr1;
+ u32 cs1gcr2;
+ u32 cs1rcr1;
+ u32 cs1rcr2;
+ u32 cs1wcr1;
+ u32 cs1wcr2;
+
+ u32 cs2gcr1;
+ u32 cs2gcr2;
+ u32 cs2rcr1;
+ u32 cs2rcr2;
+ u32 cs2wcr1;
+ u32 cs2wcr2;
+
+ u32 cs3gcr1;
+ u32 cs3gcr2;
+ u32 cs3rcr1;
+ u32 cs3rcr2;
+ u32 cs3wcr1;
+ u32 cs3wcr2;
+
+ u32 unused[12];
+
+ u32 wcr;
+ u32 wiar;
+ u32 ear;
+};
+
/* System Reset Controller (SRC) */
struct src {
u32 scr;
u32 reserved1[2];
u32 sisr;
u32 simr;
- u32 sbmr2;
- u32 gpr1;
- u32 gpr2;
- u32 gpr3;
- u32 gpr4;
- u32 gpr5;
- u32 gpr6;
- u32 gpr7;
- u32 gpr8;
- u32 gpr9;
- u32 gpr10;
+ u32 sbmr2;
+ u32 gpr1;
+ u32 gpr2;
+ u32 gpr3;
+ u32 gpr4;
+ u32 gpr5;
+ u32 gpr6;
+ u32 gpr7;
+ u32 gpr8;
+ u32 gpr9;
+ u32 gpr10;
};
+/* GPR1 bitfields */
+#define IOMUXC_GPR1_ENET_CLK_SEL_OFFSET 21
+#define IOMUXC_GPR1_ENET_CLK_SEL_MASK (1 << IOMUXC_GPR1_ENET_CLK_SEL_OFFSET)
+#define IOMUXC_GPR1_USB_OTG_ID_OFFSET 13
+#define IOMUXC_GPR1_USB_OTG_ID_SEL_MASK (1 << IOMUXC_GPR1_USB_OTG_ID_OFFSET)
+
/* GPR3 bitfields */
#define IOMUXC_GPR3_GPU_DBG_OFFSET 29
#define IOMUXC_GPR3_GPU_DBG_MASK (3<<IOMUXC_GPR3_GPU_DBG_OFFSET)
struct iomuxc {
- u8 reserved[0x4000];
+#ifdef CONFIG_MX6SX
++ u32 reserved[0x1000];
+#endif
u32 gpr[14];
- u32 omux[5];
- /* mux and pad registers */
+};
+
+struct gpc {
+ u32 cntr;
+ u32 pgr;
+ u32 imr1;
+ u32 imr2;
+ u32 imr3;
+ u32 imr4;
+ u32 isr1;
+ u32 isr2;
+ u32 isr3;
+ u32 isr4;
};
#define IOMUXC_GPR2_COUNTER_RESET_VAL_OFFSET 20
#define MXC_CSPICTRL_RXOVF (1 << 6)
#define MXC_CSPIPERIOD_32KHZ (1 << 15)
#define MAX_SPI_BYTES 32
+#define SPI_MAX_NUM 4
/* Bit position inside CTRL register to be associated with SS */
#define MXC_CSPICTRL_CHAN 18
/* Bit position inside CON register to be associated with SS */
-#define MXC_CSPICON_POL 4
-#define MXC_CSPICON_PHA 0
-#define MXC_CSPICON_SSPOL 12
-#ifdef CONFIG_MX6SL
+#define MXC_CSPICON_PHA 0 /* SCLK phase control */
+#define MXC_CSPICON_POL 4 /* SCLK polarity */
+#define MXC_CSPICON_SSPOL 12 /* SS polarity */
+#define MXC_CSPICON_CTL 20 /* inactive state of SCLK */
+#if defined(CONFIG_MX6SL) || defined(CONFIG_MX6DL)
#define MXC_SPI_BASE_ADDRESSES \
ECSPI1_BASE_ADDR, \
ECSPI2_BASE_ADDR, \
#endif
struct ocotp_regs {
- u32 ctrl;
- u32 ctrl_set;
- u32 ctrl_clr;
- u32 ctrl_tog;
- u32 timing;
- u32 rsvd0[3];
- u32 data;
- u32 rsvd1[3];
- u32 read_ctrl;
- u32 rsvd2[3];
- u32 read_fuse_data;
- u32 rsvd3[3];
- u32 sw_sticky;
- u32 rsvd4[3];
- u32 scs;
- u32 scs_set;
- u32 scs_clr;
- u32 scs_tog;
- u32 crc_addr;
- u32 rsvd5[3];
- u32 crc_value;
- u32 rsvd6[3];
- u32 version;
- u32 rsvd7[0xdb];
+ mxs_reg_32(ctrl);
+ reg_32(timing);
+ reg_32(data);
+ reg_32(read_ctrl);
+ reg_32(fuse_data);
+ reg_32(sticky);
+ mxs_reg_32(scs);
+ reg_32(crc_addr);
+ reg_32(crc_value);
+ reg_32(version);
+ reg_32(rsvd[0x36]);
struct fuse_bank {
- u32 fuse_regs[0x20];
+ reg_32(fuse_regs[8]);
} bank[16];
};
struct fuse_bank0_regs {
- u32 lock;
- u32 rsvd0[3];
- u32 uid_low;
- u32 rsvd1[3];
- u32 uid_high;
- u32 rsvd2[3];
- u32 rsvd3[4];
- u32 rsvd4[4];
- u32 rsvd5[4];
- u32 cfg5;
- u32 rsvd6[3];
- u32 rsvd7[4];
+ reg_32(misc_conf_lock);
- reg_32(cfg0);
- reg_32(cfg1);
++ union {
++ reg_32(cfg0);
++ reg_32(uid_low);
++ };
++ union {
++ reg_32(cfg1);
++ reg_32(uid_high);
++ };
+ reg_32(cfg2);
+ reg_32(cfg3);
+ reg_32(cfg4);
+ reg_32(cfg5);
+ reg_32(cfg6);
};
+#ifdef CONFIG_MX6SX
+struct fuse_bank4_regs {
+ u32 sjc_resp_low;
+ u32 rsvd0[3];
+ u32 sjc_resp_high;
+ u32 rsvd1[3];
+ u32 mac_addr_low;
+ u32 rsvd2[3];
+ u32 mac_addr_high;
+ u32 rsvd3[3];
+ u32 mac_addr2;
+ u32 rsvd4[7];
+ u32 gp1;
+ u32 rsvd5[7];
+};
+#else
struct fuse_bank4_regs {
- u32 sjc_resp_low;
- u32 rsvd0[3];
- u32 sjc_resp_high;
- u32 rsvd1[3];
- u32 mac_addr_low;
- u32 rsvd2[3];
- u32 mac_addr_high;
- u32 rsvd3[0xb];
- u32 gp1;
- u32 rsvd4[3];
- u32 gp2;
- u32 rsvd5[3];
+ reg_32(sjc_resp_low);
+ reg_32(sjc_resp_high);
+ reg_32(mac_addr_low);
+ reg_32(mac_addr_high);
+ reg_32(rsvd[2]);
+ reg_32(gp1);
+ reg_32(gp2);
+ };
+
+ struct fuse_bank5_regs {
+ reg_32(rsvd[5]);
+ reg_32(pad_settings);
+ reg_32(field_return);
};
+#endif
struct aipstz_regs {
u32 mprot0;
u32 opacr4;
};
-struct iomuxc_base_regs {
- u32 gpr[14]; /* 0x000 */
- u32 obsrv[5]; /* 0x038 */
- u32 swmux_ctl[197]; /* 0x04c */
- u32 swpad_ctl[250]; /* 0x360 */
- u32 swgrp[26]; /* 0x748 */
- u32 daisy[104]; /* 0x7b0..94c */
+struct anatop_regs {
- u32 pll_sys; /* 0x000 */
- u32 pll_sys_set; /* 0x004 */
- u32 pll_sys_clr; /* 0x008 */
- u32 pll_sys_tog; /* 0x00c */
- u32 usb1_pll_480_ctrl; /* 0x010 */
- u32 usb1_pll_480_ctrl_set; /* 0x014 */
- u32 usb1_pll_480_ctrl_clr; /* 0x018 */
- u32 usb1_pll_480_ctrl_tog; /* 0x01c */
- u32 usb2_pll_480_ctrl; /* 0x020 */
- u32 usb2_pll_480_ctrl_set; /* 0x024 */
- u32 usb2_pll_480_ctrl_clr; /* 0x028 */
- u32 usb2_pll_480_ctrl_tog; /* 0x02c */
- u32 pll_528; /* 0x030 */
- u32 pll_528_set; /* 0x034 */
- u32 pll_528_clr; /* 0x038 */
- u32 pll_528_tog; /* 0x03c */
- u32 pll_528_ss; /* 0x040 */
- u32 rsvd0[3];
- u32 pll_528_num; /* 0x050 */
- u32 rsvd1[3];
- u32 pll_528_denom; /* 0x060 */
- u32 rsvd2[3];
- u32 pll_audio; /* 0x070 */
- u32 pll_audio_set; /* 0x074 */
- u32 pll_audio_clr; /* 0x078 */
- u32 pll_audio_tog; /* 0x07c */
- u32 pll_audio_num; /* 0x080 */
- u32 rsvd3[3];
- u32 pll_audio_denom; /* 0x090 */
- u32 rsvd4[3];
- u32 pll_video; /* 0x0a0 */
- u32 pll_video_set; /* 0x0a4 */
- u32 pll_video_clr; /* 0x0a8 */
- u32 pll_video_tog; /* 0x0ac */
- u32 pll_video_num; /* 0x0b0 */
- u32 rsvd5[3];
- u32 pll_video_denom; /* 0x0c0 */
- u32 rsvd6[3];
- u32 pll_mlb; /* 0x0d0 */
- u32 pll_mlb_set; /* 0x0d4 */
- u32 pll_mlb_clr; /* 0x0d8 */
- u32 pll_mlb_tog; /* 0x0dc */
- u32 pll_enet; /* 0x0e0 */
- u32 pll_enet_set; /* 0x0e4 */
- u32 pll_enet_clr; /* 0x0e8 */
- u32 pll_enet_tog; /* 0x0ec */
- u32 pfd_480; /* 0x0f0 */
- u32 pfd_480_set; /* 0x0f4 */
- u32 pfd_480_clr; /* 0x0f8 */
- u32 pfd_480_tog; /* 0x0fc */
- u32 pfd_528; /* 0x100 */
- u32 pfd_528_set; /* 0x104 */
- u32 pfd_528_clr; /* 0x108 */
- u32 pfd_528_tog; /* 0x10c */
- u32 reg_1p1; /* 0x110 */
- u32 reg_1p1_set; /* 0x114 */
- u32 reg_1p1_clr; /* 0x118 */
- u32 reg_1p1_tog; /* 0x11c */
- u32 reg_3p0; /* 0x120 */
- u32 reg_3p0_set; /* 0x124 */
- u32 reg_3p0_clr; /* 0x128 */
- u32 reg_3p0_tog; /* 0x12c */
- u32 reg_2p5; /* 0x130 */
- u32 reg_2p5_set; /* 0x134 */
- u32 reg_2p5_clr; /* 0x138 */
- u32 reg_2p5_tog; /* 0x13c */
- u32 reg_core; /* 0x140 */
- u32 reg_core_set; /* 0x144 */
- u32 reg_core_clr; /* 0x148 */
- u32 reg_core_tog; /* 0x14c */
- u32 ana_misc0; /* 0x150 */
- u32 ana_misc0_set; /* 0x154 */
- u32 ana_misc0_clr; /* 0x158 */
- u32 ana_misc0_tog; /* 0x15c */
- u32 ana_misc1; /* 0x160 */
- u32 ana_misc1_set; /* 0x164 */
- u32 ana_misc1_clr; /* 0x168 */
- u32 ana_misc1_tog; /* 0x16c */
- u32 ana_misc2; /* 0x170 */
- u32 ana_misc2_set; /* 0x174 */
- u32 ana_misc2_clr; /* 0x178 */
- u32 ana_misc2_tog; /* 0x17c */
- u32 tempsense0; /* 0x180 */
- u32 tempsense0_set; /* 0x184 */
- u32 tempsense0_clr; /* 0x188 */
- u32 tempsense0_tog; /* 0x18c */
- u32 tempsense1; /* 0x190 */
- u32 tempsense1_set; /* 0x194 */
- u32 tempsense1_clr; /* 0x198 */
- u32 tempsense1_tog; /* 0x19c */
- u32 usb1_vbus_detect; /* 0x1a0 */
- u32 usb1_vbus_detect_set; /* 0x1a4 */
- u32 usb1_vbus_detect_clr; /* 0x1a8 */
- u32 usb1_vbus_detect_tog; /* 0x1ac */
- u32 usb1_chrg_detect; /* 0x1b0 */
- u32 usb1_chrg_detect_set; /* 0x1b4 */
- u32 usb1_chrg_detect_clr; /* 0x1b8 */
- u32 usb1_chrg_detect_tog; /* 0x1bc */
- u32 usb1_vbus_det_stat; /* 0x1c0 */
- u32 usb1_vbus_det_stat_set; /* 0x1c4 */
- u32 usb1_vbus_det_stat_clr; /* 0x1c8 */
- u32 usb1_vbus_det_stat_tog; /* 0x1cc */
- u32 usb1_chrg_det_stat; /* 0x1d0 */
- u32 usb1_chrg_det_stat_set; /* 0x1d4 */
- u32 usb1_chrg_det_stat_clr; /* 0x1d8 */
- u32 usb1_chrg_det_stat_tog; /* 0x1dc */
- u32 usb1_loopback; /* 0x1e0 */
- u32 usb1_loopback_set; /* 0x1e4 */
- u32 usb1_loopback_clr; /* 0x1e8 */
- u32 usb1_loopback_tog; /* 0x1ec */
- u32 usb1_misc; /* 0x1f0 */
- u32 usb1_misc_set; /* 0x1f4 */
- u32 usb1_misc_clr; /* 0x1f8 */
- u32 usb1_misc_tog; /* 0x1fc */
- u32 usb2_vbus_detect; /* 0x200 */
- u32 usb2_vbus_detect_set; /* 0x204 */
- u32 usb2_vbus_detect_clr; /* 0x208 */
- u32 usb2_vbus_detect_tog; /* 0x20c */
- u32 usb2_chrg_detect; /* 0x210 */
- u32 usb2_chrg_detect_set; /* 0x214 */
- u32 usb2_chrg_detect_clr; /* 0x218 */
- u32 usb2_chrg_detect_tog; /* 0x21c */
- u32 usb2_vbus_det_stat; /* 0x220 */
- u32 usb2_vbus_det_stat_set; /* 0x224 */
- u32 usb2_vbus_det_stat_clr; /* 0x228 */
- u32 usb2_vbus_det_stat_tog; /* 0x22c */
- u32 usb2_chrg_det_stat; /* 0x230 */
- u32 usb2_chrg_det_stat_set; /* 0x234 */
- u32 usb2_chrg_det_stat_clr; /* 0x238 */
- u32 usb2_chrg_det_stat_tog; /* 0x23c */
- u32 usb2_loopback; /* 0x240 */
- u32 usb2_loopback_set; /* 0x244 */
- u32 usb2_loopback_clr; /* 0x248 */
- u32 usb2_loopback_tog; /* 0x24c */
- u32 usb2_misc; /* 0x250 */
- u32 usb2_misc_set; /* 0x254 */
- u32 usb2_misc_clr; /* 0x258 */
- u32 usb2_misc_tog; /* 0x25c */
- u32 digprog; /* 0x260 */
- u32 reserved1[7];
- u32 digprog_sololite; /* 0x280 */
++ mxs_reg_32(pll_arm); /* 0x000 */
++ mxs_reg_32(usb1_pll_480_ctrl); /* 0x010 */
++ mxs_reg_32(usb2_pll_480_ctrl); /* 0x020 */
++ mxs_reg_32(pll_528); /* 0x030 */
++ reg_32(pll_528_ss); /* 0x040 */
++ reg_32(pll_528_num); /* 0x050 */
++ reg_32(pll_528_denom); /* 0x060 */
++ mxs_reg_32(pll_audio); /* 0x070 */
++ reg_32(pll_audio_num); /* 0x080 */
++ reg_32(pll_audio_denom); /* 0x090 */
++ mxs_reg_32(pll_video); /* 0x0a0 */
++ reg_32(pll_video_num); /* 0x0b0 */
++ reg_32(pll_video_denom); /* 0x0c0 */
++ mxs_reg_32(pll_mlb); /* 0x0d0 */
++ mxs_reg_32(pll_enet); /* 0x0e0 */
++ mxs_reg_32(pfd_480); /* 0x0f0 */
++ mxs_reg_32(pfd_528); /* 0x100 */
++ mxs_reg_32(reg_1p1); /* 0x110 */
++ mxs_reg_32(reg_3p0); /* 0x120 */
++ mxs_reg_32(reg_2p5); /* 0x130 */
++ mxs_reg_32(reg_core); /* 0x140 */
++ mxs_reg_32(ana_misc0); /* 0x150 */
++ mxs_reg_32(ana_misc1); /* 0x160 */
++ mxs_reg_32(ana_misc2); /* 0x170 */
++ mxs_reg_32(tempsense0); /* 0x180 */
++ mxs_reg_32(tempsense1); /* 0x190 */
++ mxs_reg_32(usb1_vbus_detect); /* 0x1a0 */
++ mxs_reg_32(usb1_chrg_detect); /* 0x1b0 */
++ mxs_reg_32(usb1_vbus_det_stat); /* 0x1c0 */
++ mxs_reg_32(usb1_chrg_det_stat); /* 0x1d0 */
++ mxs_reg_32(usb1_loopback); /* 0x1e0 */
++ mxs_reg_32(usb1_misc); /* 0x1f0 */
++ mxs_reg_32(usb2_vbus_detect); /* 0x200 */
++ mxs_reg_32(usb2_chrg_detect); /* 0x210 */
++ mxs_reg_32(usb2_vbus_det_stat); /* 0x220 */
++ mxs_reg_32(usb2_chrg_det_stat); /* 0x230 */
++ mxs_reg_32(usb2_loopback); /* 0x240 */
++ mxs_reg_32(usb2_misc); /* 0x250 */
++ reg_32(digprog); /* 0x260 */
++ reg_32(rsrvd); /* 0x270 */
++ reg_32(digprog_sololite); /* 0x280 */
};
- #define ANATOP_PFD_FRAC_SHIFT(n) ((n)*8)
- #define ANATOP_PFD_FRAC_MASK(n) (0x3f<<ANATOP_PFD_FRAC_SHIFT(n))
- #define ANATOP_PFD_STABLE_SHIFT(n) (6+((n)*8))
- #define ANATOP_PFD_STABLE_MASK(n) (1<<ANATOP_PFD_STABLE_SHIFT(n))
- #define ANATOP_PFD_CLKGATE_SHIFT(n) (7+((n)*8))
- #define ANATOP_PFD_CLKGATE_MASK(n) (1<<ANATOP_PFD_CLKGATE_SHIFT(n))
++#define ANATOP_PFD_FRAC_SHIFT(n) ((n) * 8)
++#define ANATOP_PFD_FRAC_MASK(n) (0x3f << ANATOP_PFD_FRAC_SHIFT(n))
++#define ANATOP_PFD_STABLE_SHIFT(n) (6 + ((n) * 8))
++#define ANATOP_PFD_STABLE_MASK(n) (1 << ANATOP_PFD_STABLE_SHIFT(n))
++#define ANATOP_PFD_CLKGATE_SHIFT(n) (7 + ((n) * 8))
++#define ANATOP_PFD_CLKGATE_MASK(n) (1 << ANATOP_PFD_CLKGATE_SHIFT(n))
+
struct wdog_regs {
u16 wcr; /* Control */
u16 wsr; /* Service */
u16 wmcr; /* Miscellaneous Control */
};
- #define PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4)
++#define PWMCR_PRESCALER(x) ((((x) - 1) & 0xFFF) << 4)
+#define PWMCR_DOZEEN (1 << 24)
+#define PWMCR_WAITEN (1 << 23)
+#define PWMCR_DBGEN (1 << 22)
+#define PWMCR_CLKSRC_IPG_HIGH (2 << 16)
+#define PWMCR_CLKSRC_IPG (1 << 16)
+#define PWMCR_EN (1 << 0)
+
+struct pwm_regs {
+ u32 cr;
+ u32 sr;
+ u32 ir;
+ u32 sar;
+ u32 pr;
+ u32 cnr;
+};
#endif /* __ASSEMBLER__*/
-
#endif /* __ASM_ARCH_MX6_IMX_REGS_H__ */
#define _SYS_PROTO_H_
#include <asm/imx-common/regs-common.h>
+#include "../arch-imx/cpu.h"
-#define MXC_CPU_MX51 0x51
-#define MXC_CPU_MX53 0x53
-#define MXC_CPU_MX6SL 0x60
-#define MXC_CPU_MX6DL 0x61
-#define MXC_CPU_MX6SOLO 0x62
-#define MXC_CPU_MX6Q 0x63
+#define soc_rev() (get_cpu_rev() & 0xFF)
+#define is_soc_rev(rev) (soc_rev() - rev)
-#define is_soc_rev(rev) ((get_cpu_rev() & 0xFF) - rev)
+u32 get_nr_cpus(void);
u32 get_cpu_rev(void);
+
+/* returns MXC_CPU_ value */
+#define cpu_type(rev) (((rev) >> 12)&0xff)
+
+/* both macros return/take MXC_CPU_ constants */
+#define get_cpu_type() (cpu_type(get_cpu_rev()))
+#define is_cpu_type(cpu) (get_cpu_type() == cpu)
+
const char *get_imx_type(u32 imxtype);
unsigned imx_ddr_size(void);
+void set_chipselect_size(int const);
+
+ struct mxs_register_32;
+
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
+
/*
* Initializes on-chip ethernet controllers.
* to override, implement board_eth_init()
int mxs_wait_mask_clr(struct mxs_register_32 *reg,
uint32_t mask,
unsigned int timeout);
+
+ int read_cpu_temperature(void);
+ int check_cpu_temperature(int boot);
#endif
#ifndef __SYS_PROTO_H__
#define __SYS_PROTO_H__
-struct mxs_register_32;
+#include <asm/imx-common/regs-common.h>
int mxs_reset_block(struct mxs_register_32 *reg);
int mxs_wait_mask_set(struct mxs_register_32 *reg,
int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int));
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
+
#ifdef CONFIG_SPL_BUILD
#if defined(CONFIG_MX23)
#include <asm/arch/iomux-mx28.h>
#endif
-void mxs_common_spl_init(const iomux_cfg_t *iomux_setup,
- const unsigned int iomux_size);
+void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
+ const iomux_cfg_t *iomux_setup,
+ const unsigned int iomux_size);
#endif
struct mxs_pair {
{ 0x02, 0x1f, "SSP SPI #1, master, NOR" },
{ 0x03, 0x1f, "SSP SPI #2, master, NOR" },
{ 0x04, 0x1f, "NAND" },
+ { 0x06, 0x1f, "JTAG" },
{ 0x08, 0x1f, "SSP SPI #3, master, EEPROM" },
{ 0x09, 0x1f, "SSP SD/MMC #0" },
{ 0x0a, 0x1f, "SSP SD/MMC #1" },
{ 0x13, 0x1f, "SSP SPI #3, master, 1V8 NOR" },
{ 0x04, 0x1f, "NAND, 3V3" },
{ 0x14, 0x1f, "NAND, 1V8" },
+ { 0x06, 0x1f, "JTAG" },
{ 0x08, 0x1f, "SSP SPI #3, master, 3V3 EEPROM" },
{ 0x18, 0x1f, "SSP SPI #3, master, 1V8 EEPROM" },
{ 0x09, 0x1f, "SSP SD/MMC #0, 3V3" },
#define _EMIF_H_
#include <asm/types.h>
#include <common.h>
+#include <asm/io.h>
/* Base address */
#define EMIF1_BASE 0x4c000000
#define EMIF2_BASE 0x4d000000
+#define EMIF_4D 0x4
+#define EMIF_4D5 0x5
+
/* Registers shifts, masks and values */
/* EMIF_MOD_ID_REV */
(0xFF << EMIF_SYS_ADDR_SHIFT))
#define EMIF_EXT_PHY_CTRL_TIMING_REG 0x5
-#define EMIF_EXT_PHY_CTRL_CONST_REG 0x14
/* Reg mapping structure */
struct emif_reg_struct {
- u32 emif_mod_id_rev;
- u32 emif_status;
- u32 emif_sdram_config;
- u32 emif_lpddr2_nvm_config;
- u32 emif_sdram_ref_ctrl;
- u32 emif_sdram_ref_ctrl_shdw;
- u32 emif_sdram_tim_1;
- u32 emif_sdram_tim_1_shdw;
- u32 emif_sdram_tim_2;
- u32 emif_sdram_tim_2_shdw;
- u32 emif_sdram_tim_3;
- u32 emif_sdram_tim_3_shdw;
- u32 emif_lpddr2_nvm_tim;
- u32 emif_lpddr2_nvm_tim_shdw;
- u32 emif_pwr_mgmt_ctrl;
- u32 emif_pwr_mgmt_ctrl_shdw;
- u32 emif_lpddr2_mode_reg_data;
- u32 padding1[1];
- u32 emif_lpddr2_mode_reg_data_es2;
- u32 padding11[1];
- u32 emif_lpddr2_mode_reg_cfg;
- u32 emif_l3_config;
- u32 emif_l3_cfg_val_1;
- u32 emif_l3_cfg_val_2;
- u32 emif_iodft_tlgc;
- u32 padding2[7];
- u32 emif_perf_cnt_1;
- u32 emif_perf_cnt_2;
- u32 emif_perf_cnt_cfg;
- u32 emif_perf_cnt_sel;
- u32 emif_perf_cnt_tim;
- u32 padding3;
- u32 emif_read_idlectrl;
- u32 emif_read_idlectrl_shdw;
- u32 padding4;
- u32 emif_irqstatus_raw_sys;
- u32 emif_irqstatus_raw_ll;
- u32 emif_irqstatus_sys;
- u32 emif_irqstatus_ll;
- u32 emif_irqenable_set_sys;
- u32 emif_irqenable_set_ll;
- u32 emif_irqenable_clr_sys;
- u32 emif_irqenable_clr_ll;
- u32 padding5;
- u32 emif_zq_config;
- u32 emif_temp_alert_config;
- u32 emif_l3_err_log;
- u32 emif_rd_wr_lvl_rmp_win;
- u32 emif_rd_wr_lvl_rmp_ctl;
- u32 emif_rd_wr_lvl_ctl;
- u32 padding6[1];
- u32 emif_ddr_phy_ctrl_1;
- u32 emif_ddr_phy_ctrl_1_shdw;
- u32 emif_ddr_phy_ctrl_2;
- u32 padding7[4];
- u32 emif_prio_class_serv_map;
- u32 emif_connect_id_serv_1_map;
- u32 emif_connect_id_serv_2_map;
- u32 padding8[5];
- u32 emif_rd_wr_exec_thresh;
- u32 emif_cos_config;
- u32 padding9[6];
- u32 emif_ddr_phy_status[21];
- u32 padding10[27];
- u32 emif_ddr_ext_phy_ctrl_1;
- u32 emif_ddr_ext_phy_ctrl_1_shdw;
- u32 emif_ddr_ext_phy_ctrl_2;
- u32 emif_ddr_ext_phy_ctrl_2_shdw;
- u32 emif_ddr_ext_phy_ctrl_3;
- u32 emif_ddr_ext_phy_ctrl_3_shdw;
- u32 emif_ddr_ext_phy_ctrl_4;
- u32 emif_ddr_ext_phy_ctrl_4_shdw;
- u32 emif_ddr_ext_phy_ctrl_5;
- u32 emif_ddr_ext_phy_ctrl_5_shdw;
- u32 emif_ddr_ext_phy_ctrl_6;
- u32 emif_ddr_ext_phy_ctrl_6_shdw;
- u32 emif_ddr_ext_phy_ctrl_7;
- u32 emif_ddr_ext_phy_ctrl_7_shdw;
- u32 emif_ddr_ext_phy_ctrl_8;
- u32 emif_ddr_ext_phy_ctrl_8_shdw;
- u32 emif_ddr_ext_phy_ctrl_9;
- u32 emif_ddr_ext_phy_ctrl_9_shdw;
- u32 emif_ddr_ext_phy_ctrl_10;
- u32 emif_ddr_ext_phy_ctrl_10_shdw;
- u32 emif_ddr_ext_phy_ctrl_11;
- u32 emif_ddr_ext_phy_ctrl_11_shdw;
- u32 emif_ddr_ext_phy_ctrl_12;
- u32 emif_ddr_ext_phy_ctrl_12_shdw;
- u32 emif_ddr_ext_phy_ctrl_13;
- u32 emif_ddr_ext_phy_ctrl_13_shdw;
- u32 emif_ddr_ext_phy_ctrl_14;
- u32 emif_ddr_ext_phy_ctrl_14_shdw;
- u32 emif_ddr_ext_phy_ctrl_15;
- u32 emif_ddr_ext_phy_ctrl_15_shdw;
- u32 emif_ddr_ext_phy_ctrl_16;
- u32 emif_ddr_ext_phy_ctrl_16_shdw;
- u32 emif_ddr_ext_phy_ctrl_17;
- u32 emif_ddr_ext_phy_ctrl_17_shdw;
- u32 emif_ddr_ext_phy_ctrl_18;
- u32 emif_ddr_ext_phy_ctrl_18_shdw;
- u32 emif_ddr_ext_phy_ctrl_19;
- u32 emif_ddr_ext_phy_ctrl_19_shdw;
- u32 emif_ddr_ext_phy_ctrl_20;
- u32 emif_ddr_ext_phy_ctrl_20_shdw;
- u32 emif_ddr_ext_phy_ctrl_21;
- u32 emif_ddr_ext_phy_ctrl_21_shdw;
- u32 emif_ddr_ext_phy_ctrl_22;
- u32 emif_ddr_ext_phy_ctrl_22_shdw;
- u32 emif_ddr_ext_phy_ctrl_23;
- u32 emif_ddr_ext_phy_ctrl_23_shdw;
- u32 emif_ddr_ext_phy_ctrl_24;
- u32 emif_ddr_ext_phy_ctrl_24_shdw;
- u32 padding[22];
- u32 emif_ddr_fifo_misaligned_clear_1;
- u32 emif_ddr_fifo_misaligned_clear_2;
+ u32 emif_mod_id_rev; /* 0x000 */
+ u32 emif_status; /* 0x004 */
+ u32 emif_sdram_config; /* 0x008 */
+ u32 emif_lpddr2_nvm_config; /* 0x00c */
+ u32 emif_sdram_ref_ctrl; /* 0x010 */
+ u32 emif_sdram_ref_ctrl_shdw; /* 0x014 */
+ u32 emif_sdram_tim_1; /* 0x018 */
+ u32 emif_sdram_tim_1_shdw; /* 0x01c */
+ u32 emif_sdram_tim_2; /* 0x020 */
+ u32 emif_sdram_tim_2_shdw; /* 0x024 */
+ u32 emif_sdram_tim_3; /* 0x028 */
+ u32 emif_sdram_tim_3_shdw; /* 0x02c */
+ u32 emif_lpddr2_nvm_tim; /* 0x030 */
+ u32 emif_lpddr2_nvm_tim_shdw; /* 0x034 */
+ u32 emif_pwr_mgmt_ctrl; /* 0x038 */
+ u32 emif_pwr_mgmt_ctrl_shdw; /* 0x03c */
+ u32 emif_lpddr2_mode_reg_data; /* 0x040 */
+ u32 padding1[1]; /* 0x044 */
+ u32 emif_lpddr2_mode_reg_data_es2; /* 0x048 */
+ u32 padding11[1]; /* 0x04c */
+ u32 emif_lpddr2_mode_reg_cfg; /* 0x050 */
+ u32 emif_l3_config; /* 0x054 */
+ u32 emif_l3_cfg_val_1; /* 0x058 */
+ u32 emif_l3_cfg_val_2; /* 0x05c */
+ u32 emif_iodft_tlgc; /* 0x060 */
+ u32 padding2[7]; /* 0x064 */
+ u32 emif_perf_cnt_1; /* 0x080 */
+ u32 emif_perf_cnt_2; /* 0x084 */
+ u32 emif_perf_cnt_cfg; /* 0x088 */
+ u32 emif_perf_cnt_sel; /* 0x08c */
+ u32 emif_perf_cnt_tim; /* 0x090 */
+ u32 padding3; /* 0x094 */
+ u32 emif_read_idlectrl; /* 0x098 */
+ u32 emif_read_idlectrl_shdw; /* 0x09c */
+ u32 padding4; /* 0x0a0 */
+ u32 emif_irqstatus_raw_sys; /* 0x0a4 */
+ u32 emif_irqstatus_raw_ll; /* 0x0a8 */
+ u32 emif_irqstatus_sys; /* 0x0ac */
+ u32 emif_irqstatus_ll; /* 0x0b0 */
+ u32 emif_irqenable_set_sys; /* 0x0b4 */
+ u32 emif_irqenable_set_ll; /* 0x0b8 */
+ u32 emif_irqenable_clr_sys; /* 0x0bc */
+ u32 emif_irqenable_clr_ll; /* 0x0c0 */
+ u32 padding5; /* 0x0c4 */
+ u32 emif_zq_config; /* 0x0c8 */
+ u32 emif_temp_alert_config; /* 0x0cc */
+ u32 emif_l3_err_log; /* 0x0d0 */
+ u32 emif_rd_wr_lvl_rmp_win; /* 0x0d4 */
+ u32 emif_rd_wr_lvl_rmp_ctl; /* 0x0d8 */
+ u32 emif_rd_wr_lvl_ctl; /* 0x0dc */
+ u32 padding6[1]; /* 0x0e0 */
+ u32 emif_ddr_phy_ctrl_1; /* 0x0e4 */
+ u32 emif_ddr_phy_ctrl_1_shdw; /* 0x0e8 */
+ u32 emif_ddr_phy_ctrl_2; /* 0x0ec */
- u32 padding7[12]; /* 0x0f0 */
++ u32 padding7[4]; /* 0x0f0 */
++ u32 emif_prio_class_serv_map; /* 0x100 */
++ u32 emif_connect_id_serv_1_map; /* 0x104 */
++ u32 emif_connect_id_serv_2_map; /* 0x108 */
++ u32 padding8[5]; /* 0x10c */
+ u32 emif_rd_wr_exec_thresh; /* 0x120 */
- u32 padding8[55]; /* 0x124 */
++ u32 padding9[6]; /* 0x124 */
++ u32 emif_ddr_phy_status[21]; /* 0x13c */
++ u32 padding10[27]; /* 0x1fc */
+ u32 emif_ddr_ext_phy_ctrl_1; /* 0x200 */
+ u32 emif_ddr_ext_phy_ctrl_1_shdw; /* 0x204 */
+ u32 emif_ddr_ext_phy_ctrl_2; /* 0x248 */
+ u32 emif_ddr_ext_phy_ctrl_2_shdw; /* 0x24c */
+ u32 emif_ddr_ext_phy_ctrl_3; /* 0x200 */
+ u32 emif_ddr_ext_phy_ctrl_3_shdw; /* 0x204 */
+ u32 emif_ddr_ext_phy_ctrl_4; /* 0x208 */
+ u32 emif_ddr_ext_phy_ctrl_4_shdw; /* 0x20c */
+ u32 emif_ddr_ext_phy_ctrl_5; /* 0x210 */
+ u32 emif_ddr_ext_phy_ctrl_5_shdw; /* 0x214 */
+ u32 emif_ddr_ext_phy_ctrl_6; /* 0x218 */
+ u32 emif_ddr_ext_phy_ctrl_6_shdw; /* 0x21c */
+ u32 emif_ddr_ext_phy_ctrl_7; /* 0x220 */
+ u32 emif_ddr_ext_phy_ctrl_7_shdw; /* 0x224 */
+ u32 emif_ddr_ext_phy_ctrl_8; /* 0x228 */
+ u32 emif_ddr_ext_phy_ctrl_8_shdw; /* 0x22c */
+ u32 emif_ddr_ext_phy_ctrl_9; /* 0x230 */
+ u32 emif_ddr_ext_phy_ctrl_9_shdw; /* 0x234 */
+ u32 emif_ddr_ext_phy_ctrl_10; /* 0x238 */
+ u32 emif_ddr_ext_phy_ctrl_10_shdw; /* 0x23c */
+ u32 emif_ddr_ext_phy_ctrl_11; /* 0x240 */
+ u32 emif_ddr_ext_phy_ctrl_11_shdw; /* 0x244 */
+ u32 emif_ddr_ext_phy_ctrl_12; /* 0x248 */
+ u32 emif_ddr_ext_phy_ctrl_12_shdw; /* 0x24c */
+ u32 emif_ddr_ext_phy_ctrl_13; /* 0x250 */
+ u32 emif_ddr_ext_phy_ctrl_13_shdw; /* 0x254 */
+ u32 emif_ddr_ext_phy_ctrl_14; /* 0x258 */
+ u32 emif_ddr_ext_phy_ctrl_14_shdw; /* 0x25c */
+ u32 emif_ddr_ext_phy_ctrl_15; /* 0x260 */
+ u32 emif_ddr_ext_phy_ctrl_15_shdw; /* 0x264 */
+ u32 emif_ddr_ext_phy_ctrl_16; /* 0x268 */
+ u32 emif_ddr_ext_phy_ctrl_16_shdw; /* 0x26c */
+ u32 emif_ddr_ext_phy_ctrl_17; /* 0x270 */
+ u32 emif_ddr_ext_phy_ctrl_17_shdw; /* 0x274 */
+ u32 emif_ddr_ext_phy_ctrl_18; /* 0x278 */
+ u32 emif_ddr_ext_phy_ctrl_18_shdw; /* 0x27c */
+ u32 emif_ddr_ext_phy_ctrl_19; /* 0x280 */
+ u32 emif_ddr_ext_phy_ctrl_19_shdw; /* 0x284 */
+ u32 emif_ddr_ext_phy_ctrl_20; /* 0x288 */
+ u32 emif_ddr_ext_phy_ctrl_20_shdw; /* 0x28c */
+ u32 emif_ddr_ext_phy_ctrl_21; /* 0x290 */
+ u32 emif_ddr_ext_phy_ctrl_21_shdw; /* 0x294 */
+ u32 emif_ddr_ext_phy_ctrl_22; /* 0x298 */
+ u32 emif_ddr_ext_phy_ctrl_22_shdw; /* 0x29c */
+ u32 emif_ddr_ext_phy_ctrl_23; /* 0x2a0 */
+ u32 emif_ddr_ext_phy_ctrl_23_shdw; /* 0x2a4 */
+ u32 emif_ddr_ext_phy_ctrl_24; /* 0x2a8 */
+ u32 emif_ddr_ext_phy_ctrl_24_shdw; /* 0x2ac */
++ u32 padding[22]; /* 0x2b0 */
++ u32 emif_ddr_fifo_misaligned_clear_1; /* 0x308 */
++ u32 emif_ddr_fifo_misaligned_clear_2; /* 0x30c */
};
struct dmm_lisa_map_regs {
((REG_CS_TIM << EMIF_REG_CS_TIM_SHIFT) & EMIF_REG_CS_TIM_MASK)|\
((REG_SR_TIM << EMIF_REG_SR_TIM_SHIFT) & EMIF_REG_SR_TIM_MASK)|\
((REG_PD_TIM << EMIF_REG_PD_TIM_SHIFT) & EMIF_REG_PD_TIM_MASK)|\
- ((REG_PD_TIM << EMIF_REG_PD_TIM_SHIFT) & EMIF_REG_PD_TIM_MASK)|\
((LP_MODE_DISABLE << EMIF_REG_LP_MODE_SHIFT)\
& EMIF_REG_LP_MODE_MASK) |\
((DPD_DISABLE << EMIF_REG_DPD_EN_SHIFT)\
& EMIF_REG_CS_TIM_SHDW_MASK) |\
((REG_SR_TIM << EMIF_REG_SR_TIM_SHDW_SHIFT)\
& EMIF_REG_SR_TIM_SHDW_MASK) |\
- ((REG_PD_TIM << EMIF_REG_PD_TIM_SHDW_SHIFT)\
- & EMIF_REG_PD_TIM_SHDW_MASK) |\
((REG_PD_TIM << EMIF_REG_PD_TIM_SHDW_SHIFT)\
& EMIF_REG_PD_TIM_SHDW_MASK))
u32 emif_rd_wr_lvl_rmp_ctl;
u32 emif_rd_wr_lvl_ctl;
u32 emif_rd_wr_exec_thresh;
+ u32 emif_prio_class_serv_map;
+ u32 emif_connect_id_serv_1_map;
+ u32 emif_connect_id_serv_2_map;
+ u32 emif_cos_config;
};
struct lpddr2_mr_regs {
s8 mr16;
};
+struct read_write_regs {
+ u32 read_reg;
+ u32 write_reg;
+};
+
+static inline u32 get_emif_rev(u32 base)
+{
+ struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+ return (readl(&emif->emif_mod_id_rev) & EMIF_REG_MAJOR_REVISION_MASK)
+ >> EMIF_REG_MAJOR_REVISION_SHIFT;
+}
+
+/*
+ * Get SDRAM type connected to EMIF.
+ * Assuming similar SDRAM parts are connected to both EMIF's
+ * which is typically the case. So it is sufficient to get
+ * SDRAM type from EMIF1.
+ */
+static inline u32 emif_sdram_type(void)
+{
+ struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+
+ return (readl(&emif->emif_sdram_config) &
+ EMIF_REG_SDRAM_TYPE_MASK) >> EMIF_REG_SDRAM_TYPE_SHIFT;
+}
+
/* assert macros */
#if defined(DEBUG)
- #define emif_assert(c) ({ if (!(c)) for (;;); })
+ #define emif_assert(c) ({ if (!(c)) hang(); })
#else
- #define emif_assert(c) ({ if (0) hang(); })
+ #define emif_assert(c) (c)
#endif
#ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
void config_data_eye_leveling_samples(u32 emif_base);
u32 emif_sdram_type(void);
+const struct read_write_regs *get_bug_regs(u32 *iterations);
#endif
#if defined(CONFIG_FSL_ESDHC)
u32 sdhc_clk;
#endif
+
+#if defined(CONFIG_U_QE)
+ u32 qe_clk;
+ u32 brg_clk;
+ uint mp_alloc_base;
+ uint mp_alloc_top;
+#endif /* CONFIG_U_QE */
+
+ #ifdef CONFIG_VIDEO_IPUV3
+ unsigned int ipu_hw_rev;
+ #endif
++
#ifdef CONFIG_AT91FAMILY
/* "static data" needed by at91's clock.c */
unsigned long cpu_clk_rate_hz;
unsigned long tbl;
unsigned long lastinc;
unsigned long long timer_reset_value;
-#ifdef CONFIG_IXP425
- unsigned long timestamp;
-#endif
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
unsigned long tlb_addr;
unsigned long tlb_size;
#include <asm-generic/global_data.h>
-#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
+#ifdef __clang__
+
+#define DECLARE_GLOBAL_DATA_PTR
+#define gd get_gd()
+
+static inline gd_t *get_gd(void)
+{
+ gd_t *gd_ptr;
+
+#ifdef CONFIG_ARM64
+ /*
+ * Make will already error that reserving x18 is not supported at the
+ * time of writing, clang: error: unknown argument: '-ffixed-x18'
+ */
+ __asm__ volatile("mov %0, x18\n" : "=r" (gd_ptr));
+#else
+ __asm__ volatile("mov %0, r9\n" : "=r" (gd_ptr));
+#endif
+
+ return gd_ptr;
+}
+
+#else
+
+#ifdef CONFIG_ARM64
+#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("x18")
+#else
+#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")
+#endif
+#endif
#endif /* __ASM_GBL_DATA_H */
unsigned int pending_num;
struct list_head active;
struct list_head done;
+ unsigned long timeout;
};
struct mxs_dma_desc *mxs_dma_desc_alloc(void);
void mxs_dma_desc_free(struct mxs_dma_desc *);
int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
+ int mxs_dma_set_timeout(int channel, unsigned long timeout);
+ unsigned long mxs_dma_get_timeout(int channel);
int mxs_dma_go(int chan);
void mxs_dma_init(void);
int mxs_dma_init_channel(int chan);
int mxs_dma_release(int chan);
+void mxs_dma_circ_start(int chan, struct mxs_dma_desc *pdesc);
+
#endif /* __DMA_H__ */
* SPDX-License-Identifier: GPL-2.0+
*/
- #ifndef __MACH_IOMUX_V3_H__
- #define __MACH_IOMUX_V3_H__
+ #ifndef __ASM_ARCH_IOMUX_V3_H__
+ #define __ASM_ARCH_IOMUX_V3_H__
#include <common.h>
*
* IOMUX/PAD Bit field definitions
*
- * MUX_CTRL_OFS: 0..11 (12)
- * PAD_CTRL_OFS: 12..23 (12)
- * SEL_INPUT_OFS: 24..35 (12)
- * MUX_MODE + SION: 36..40 (5)
- * PAD_CTRL + NO_PAD_CTRL: 41..58 (18)
- * SEL_INP: 59..62 (4)
- * reserved: 63 (1)
+ * MUX_CTRL_OFS: 0..11 (12)
+ * PAD_CTRL_OFS: 12..23 (12)
+ * SEL_INPUT_OFS: 24..35 (12)
+ * MUX_MODE + SION: 36..40 (5)
+ * PAD_CTRL + PAD_CTRL_VALID: 41..58 (18)
+ * SEL_INP: 59..62 (4)
+ * reserved: 63 (1)
*/
typedef u64 iomux_v3_cfg_t;
#define MUX_MODE_SHIFT 36
#define MUX_MODE_MASK ((iomux_v3_cfg_t)0x1f << MUX_MODE_SHIFT)
#define MUX_PAD_CTRL_SHIFT 41
- #define MUX_PAD_CTRL_MASK ((iomux_v3_cfg_t)0x3ffff << MUX_PAD_CTRL_SHIFT)
+ #define MUX_PAD_CTRL_MASK ((iomux_v3_cfg_t)0x1ffff << MUX_PAD_CTRL_SHIFT)
#define MUX_SEL_INPUT_SHIFT 59
#define MUX_SEL_INPUT_MASK ((iomux_v3_cfg_t)0xf << MUX_SEL_INPUT_SHIFT)
- #define MUX_PAD_CTRL(x) ((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)
+#define MUX_MODE_SION ((iomux_v3_cfg_t)IOMUX_CONFIG_SION << \
+ MUX_MODE_SHIFT)
+ #define __MUX_PAD_CTRL(x) ((x) | __PAD_CTRL_VALID)
+ #define MUX_PAD_CTRL(x) (((iomux_v3_cfg_t)__MUX_PAD_CTRL(x) << \
+ MUX_PAD_CTRL_SHIFT))
#define IOMUX_PAD(pad_ctrl_ofs, mux_ctrl_ofs, mux_mode, sel_input_ofs, \
sel_input, pad_ctrl) \
#define NO_MUX_I 0
#define NO_PAD_I 0
- #define NO_PAD_CTRL (1 << 17)
+ #define NO_MUX_I 0
+ #define NO_PAD_I 0
+
+ #define NO_PAD_CTRL 0
+ #define __PAD_CTRL_VALID (1 << 17)
+ #define PAD_CTRL_VALID ((iomux_v3_cfg_t)__PAD_CTRL_VALID << MUX_PAD_CTRL_SHIFT)
#ifdef CONFIG_MX6
- #define PAD_CTL_HYS (1 << 16)
+ #define PAD_CTL_HYS __MUX_PAD_CTRL(1 << 16)
- #define PAD_CTL_PUS_100K_DOWN (0 << 14 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_47K_UP (1 << 14 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_100K_UP (2 << 14 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_22K_UP (3 << 14 | PAD_CTL_PUE)
- #define PAD_CTL_PUE (1 << 13 | PAD_CTL_PKE)
- #define PAD_CTL_PKE (1 << 12)
+ #define PAD_CTL_PUS_100K_DOWN __MUX_PAD_CTRL(0 << 14 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_47K_UP __MUX_PAD_CTRL(1 << 14 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_100K_UP __MUX_PAD_CTRL(2 << 14 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_22K_UP __MUX_PAD_CTRL(3 << 14 | PAD_CTL_PUE)
+ #define PAD_CTL_PUE __MUX_PAD_CTRL(1 << 13 | PAD_CTL_PKE)
+ #define PAD_CTL_PKE __MUX_PAD_CTRL(1 << 12)
- #define PAD_CTL_ODE (1 << 11)
+ #define PAD_CTL_ODE __MUX_PAD_CTRL(1 << 11)
- #define PAD_CTL_SPEED_LOW (1 << 6)
- #define PAD_CTL_SPEED_MED (2 << 6)
- #define PAD_CTL_SPEED_HIGH (3 << 6)
+ #define PAD_CTL_SPEED_LOW __MUX_PAD_CTRL(1 << 6)
+ #define PAD_CTL_SPEED_MED __MUX_PAD_CTRL(2 << 6)
+ #define PAD_CTL_SPEED_HIGH __MUX_PAD_CTRL(3 << 6)
- #define PAD_CTL_DSE_DISABLE (0 << 3)
- #define PAD_CTL_DSE_240ohm (1 << 3)
- #define PAD_CTL_DSE_120ohm (2 << 3)
- #define PAD_CTL_DSE_80ohm (3 << 3)
- #define PAD_CTL_DSE_60ohm (4 << 3)
- #define PAD_CTL_DSE_48ohm (5 << 3)
- #define PAD_CTL_DSE_40ohm (6 << 3)
- #define PAD_CTL_DSE_34ohm (7 << 3)
+ #define PAD_CTL_DSE_DISABLE __MUX_PAD_CTRL(0 << 3)
+ #define PAD_CTL_DSE_240ohm __MUX_PAD_CTRL(1 << 3)
+ #define PAD_CTL_DSE_120ohm __MUX_PAD_CTRL(2 << 3)
+ #define PAD_CTL_DSE_80ohm __MUX_PAD_CTRL(3 << 3)
+ #define PAD_CTL_DSE_60ohm __MUX_PAD_CTRL(4 << 3)
+ #define PAD_CTL_DSE_48ohm __MUX_PAD_CTRL(5 << 3)
+ #define PAD_CTL_DSE_40ohm __MUX_PAD_CTRL(6 << 3)
+ #define PAD_CTL_DSE_34ohm __MUX_PAD_CTRL(7 << 3)
- #define PAD_CTL_LVE (1 << 1)
- #define PAD_CTL_LVE_BIT (1 << 22)
+#if defined CONFIG_MX6SL
++#define PAD_CTL_LVE __MUX_PAD_CTRL(1 << 1)
++#define PAD_CTL_LVE_BIT __MUX_PAD_CTRL(1 << 22)
+#endif
+
#elif defined(CONFIG_VF610)
#define PAD_MUX_MODE_SHIFT 20
- #define PAD_CTL_INPUT_DIFFERENTIAL (1 << 16)
++#define PAD_CTL_INPUT_DIFFERENTIAL __MUX_PAD_CTRL(1 << 16)
+
- #define PAD_CTL_SPEED_MED (1 << 12)
- #define PAD_CTL_SPEED_HIGH (3 << 12)
+ #define PAD_CTL_SPEED_MED __MUX_PAD_CTRL(1 << 12)
+ #define PAD_CTL_SPEED_HIGH __MUX_PAD_CTRL(3 << 12)
- #define PAD_CTL_SRE (1 << 11)
++#define PAD_CTL_SRE __MUX_PAD_CTRL(1 << 11)
+
- #define PAD_CTL_DSE_150ohm (1 << 6)
- #define PAD_CTL_DSE_50ohm (3 << 6)
- #define PAD_CTL_DSE_25ohm (6 << 6)
- #define PAD_CTL_DSE_20ohm (7 << 6)
++#define PAD_CTL_DSE_150ohm __MUX_PAD_CTRL(1 << 6)
+ #define PAD_CTL_DSE_50ohm __MUX_PAD_CTRL(3 << 6)
+ #define PAD_CTL_DSE_25ohm __MUX_PAD_CTRL(6 << 6)
+ #define PAD_CTL_DSE_20ohm __MUX_PAD_CTRL(7 << 6)
- #define PAD_CTL_PUS_47K_UP (1 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_100K_UP (2 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_22K_UP (3 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_PKE (1 << 3)
- #define PAD_CTL_PUE (1 << 2 | PAD_CTL_PKE)
+ #define PAD_CTL_PUS_47K_UP __MUX_PAD_CTRL(1 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_100K_UP __MUX_PAD_CTRL(2 << 4 | PAD_CTL_PUE)
++#define PAD_CTL_PUS_22K_UP __MUX_PAD_CTRL(3 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_PKE __MUX_PAD_CTRL(1 << 3)
+ #define PAD_CTL_PUE __MUX_PAD_CTRL(1 << 2 | PAD_CTL_PKE)
- #define PAD_CTL_OBE_IBE_ENABLE (3 << 0)
- #define PAD_CTL_OBE_ENABLE (1 << 1)
- #define PAD_CTL_IBE_ENABLE (1 << 0)
+ #define PAD_CTL_OBE_IBE_ENABLE __MUX_PAD_CTRL(3 << 0)
++#define PAD_CTL_OBE_ENABLE __MUX_PAD_CTRL(1 << 1)
++#define PAD_CTL_IBE_ENABLE __MUX_PAD_CTRL(1 << 0)
#else
- #define PAD_CTL_DVS (1 << 13)
- #define PAD_CTL_INPUT_DDR (1 << 9)
- #define PAD_CTL_HYS (1 << 8)
+ #define PAD_CTL_DVS __MUX_PAD_CTRL(1 << 13)
+ #define PAD_CTL_INPUT_DDR __MUX_PAD_CTRL(1 << 9)
+ #define PAD_CTL_HYS __MUX_PAD_CTRL(1 << 8)
- #define PAD_CTL_PKE (1 << 7)
- #define PAD_CTL_PUE (1 << 6 | PAD_CTL_PKE)
- #define PAD_CTL_PUS_100K_DOWN (0 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_47K_UP (1 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_100K_UP (2 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_PUS_22K_UP (3 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_PKE __MUX_PAD_CTRL(1 << 7)
+ #define PAD_CTL_PUE __MUX_PAD_CTRL(1 << 6 | PAD_CTL_PKE)
+ #define PAD_CTL_PUS_100K_DOWN __MUX_PAD_CTRL(0 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_47K_UP __MUX_PAD_CTRL(1 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_100K_UP __MUX_PAD_CTRL(2 << 4 | PAD_CTL_PUE)
+ #define PAD_CTL_PUS_22K_UP __MUX_PAD_CTRL(3 << 4 | PAD_CTL_PUE)
- #define PAD_CTL_ODE (1 << 3)
+ #define PAD_CTL_ODE __MUX_PAD_CTRL(1 << 3)
- #define PAD_CTL_DSE_LOW (0 << 1)
- #define PAD_CTL_DSE_MED (1 << 1)
- #define PAD_CTL_DSE_HIGH (2 << 1)
- #define PAD_CTL_DSE_MAX (3 << 1)
+ #define PAD_CTL_DSE_LOW __MUX_PAD_CTRL(0 << 1)
+ #define PAD_CTL_DSE_MED __MUX_PAD_CTRL(1 << 1)
+ #define PAD_CTL_DSE_HIGH __MUX_PAD_CTRL(2 << 1)
+ #define PAD_CTL_DSE_MAX __MUX_PAD_CTRL(3 << 1)
#endif
- #define PAD_CTL_SRE_SLOW (0 << 0)
- #define PAD_CTL_SRE_FAST (1 << 0)
+ #define PAD_CTL_SRE_SLOW __MUX_PAD_CTRL(0 << 0)
+ #define PAD_CTL_SRE_FAST __MUX_PAD_CTRL(1 << 0)
#define IOMUX_CONFIG_SION 0x10
#define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
#define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
--void imx_iomux_v3_setup_pad(iomux_v3_cfg_t pad);
++void imx_iomux_v3_setup_pad(const iomux_v3_cfg_t const pad);
void imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list,
unsigned count);
+/*
+* Set bits for general purpose registers
+*/
+void imx_iomux_set_gpr_register(int group, int start_bit,
+ int num_bits, int value);
+
+/* macros for declaring and using pinmux array */
+#if defined(CONFIG_MX6QDL)
+#define IOMUX_PADS(x) (MX6Q_##x), (MX6DL_##x)
+#define SETUP_IOMUX_PAD(def) \
+if (is_cpu_type(MXC_CPU_MX6Q)) { \
+ imx_iomux_v3_setup_pad(MX6Q_##def); \
+} else { \
+ imx_iomux_v3_setup_pad(MX6DL_##def); \
+}
+#define SETUP_IOMUX_PADS(x) \
+ imx_iomux_v3_setup_multiple_pads(x, ARRAY_SIZE(x)/2)
+#elif defined(CONFIG_MX6Q) || defined(CONFIG_MX6D)
+#define IOMUX_PADS(x) MX6Q_##x
+#define SETUP_IOMUX_PAD(def) \
+ imx_iomux_v3_setup_pad(MX6Q_##def);
+#define SETUP_IOMUX_PADS(x) \
+ imx_iomux_v3_setup_multiple_pads(x, ARRAY_SIZE(x))
+#else
+#define IOMUX_PADS(x) MX6DL_##x
+#define SETUP_IOMUX_PAD(def) \
+ imx_iomux_v3_setup_pad(MX6DL_##def);
+#define SETUP_IOMUX_PADS(x) \
+ imx_iomux_v3_setup_multiple_pads(x, ARRAY_SIZE(x))
+#endif
- #endif /* __MACH_IOMUX_V3_H__*/
+ #endif /* __ASM_ARCH_IOMUX_V3_H__*/
#ifndef __ASM_ARM_SYSTEM_H
#define __ASM_ARM_SYSTEM_H
+#ifdef CONFIG_ARM64
+
+/*
+ * SCTLR_EL1/SCTLR_EL2/SCTLR_EL3 bits definitions
+ */
+#define CR_M (1 << 0) /* MMU enable */
+#define CR_A (1 << 1) /* Alignment abort enable */
+#define CR_C (1 << 2) /* Dcache enable */
+#define CR_SA (1 << 3) /* Stack Alignment Check Enable */
+#define CR_I (1 << 12) /* Icache enable */
+#define CR_WXN (1 << 19) /* Write Permision Imply XN */
+#define CR_EE (1 << 25) /* Exception (Big) Endian */
+
+#define PGTABLE_SIZE (0x10000)
+
+#ifndef __ASSEMBLY__
+
+#define isb() \
+ ({asm volatile( \
+ "isb" : : : "memory"); \
+ })
+
+#define wfi() \
+ ({asm volatile( \
+ "wfi" : : : "memory"); \
+ })
+
+static inline unsigned int current_el(void)
+{
+ unsigned int el;
+ asm volatile("mrs %0, CurrentEL" : "=r" (el) : : "cc");
+ return el >> 2;
+}
+
+static inline unsigned int get_sctlr(void)
+{
+ unsigned int el, val;
+
+ el = current_el();
+ if (el == 1)
+ asm volatile("mrs %0, sctlr_el1" : "=r" (val) : : "cc");
+ else if (el == 2)
+ asm volatile("mrs %0, sctlr_el2" : "=r" (val) : : "cc");
+ else
+ asm volatile("mrs %0, sctlr_el3" : "=r" (val) : : "cc");
+
+ return val;
+}
+
+static inline void set_sctlr(unsigned int val)
+{
+ unsigned int el;
+
+ el = current_el();
+ if (el == 1)
+ asm volatile("msr sctlr_el1, %0" : : "r" (val) : "cc");
+ else if (el == 2)
+ asm volatile("msr sctlr_el2, %0" : : "r" (val) : "cc");
+ else
+ asm volatile("msr sctlr_el3, %0" : : "r" (val) : "cc");
+
+ asm volatile("isb");
+}
+
+void __asm_flush_dcache_all(void);
+void __asm_invalidate_dcache_all(void);
+void __asm_flush_dcache_range(u64 start, u64 end);
+void __asm_invalidate_tlb_all(void);
+void __asm_invalidate_icache_all(void);
+
+void armv8_switch_to_el2(void);
+void armv8_switch_to_el1(void);
+void gic_init(void);
+void gic_send_sgi(unsigned long sgino);
+void wait_for_wakeup(void);
+void smp_kick_all_cpus(void);
+
+void flush_l3_cache(void);
+
+#endif /* __ASSEMBLY__ */
+
+#else /* CONFIG_ARM64 */
+
#ifdef __KERNEL__
#define CPU_ARCH_UNKNOWN 0
#define CR_AFE (1 << 29) /* Access flag enable */
#define CR_TE (1 << 30) /* Thumb exception enable */
+#define PGTABLE_SIZE (4096 * 4)
+
/*
* This is used to ensure the compiler did actually allocate the register we
* asked it for some inline assembly sequences. Apparently we can't trust
static inline unsigned int get_cr(void)
{
unsigned int val;
- asm("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc");
+ asm volatile("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc");
return val;
}
DCACHE_OFF = 0x12,
DCACHE_WRITETHROUGH = 0x1a,
DCACHE_WRITEBACK = 0x1e,
+ DCACHE_WRITEALLOC = 0x16,
};
/* Size of an MMU section */
* \param size size of memory region to change
* \param option dcache option to select
*/
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
enum dcache_option option);
/**
*/
void mmu_page_table_flush(unsigned long start, unsigned long stop);
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+void noncached_init(void);
+phys_addr_t noncached_alloc(size_t size, size_t align);
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
+
#endif /* __ASSEMBLY__ */
#define arch_align_stack(x) (x)
#endif /* __KERNEL__ */
+#endif /* CONFIG_ARM64 */
+
#endif
--- /dev/null
- || defined(CONFIG_MX51) || defined(CONFIG_MX53)
+/*
+ * Adapted from Linux v2.6.36 kernel: arch/powerpc/kernel/asm-offsets.c
+ *
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/kbuild.h>
+
+#if defined(CONFIG_MB86R0x)
+#include <asm/arch/mb86r0x.h>
+#endif
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) \
++ || defined(CONFIG_MX51) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+#include <asm/arch/imx-regs.h>
+#endif
++#if defined(CONFIG_MX6)
++#include <asm/arch/crm_regs.h>
++#endif
+
+int main(void)
+{
+ /*
+ * TODO : Check if each entry in this file is really necessary.
+ * - struct mb86r0x_ddr2
+ * - struct mb86r0x_memc
+ * - struct esdramc_regs
+ * - struct max_regs
+ * - struct aips_regs
+ * - struct aipi_regs
+ * - struct clkctl
+ * - struct dpll
+ * are used only for generating asm-offsets.h.
+ * It means their offset addresses are referenced only from assembly
+ * code. Is it better to define the macros directly in headers?
+ */
+
+#if defined(CONFIG_MB86R0x)
+ /* ddr2 controller */
+ DEFINE(DDR2_DRIC, offsetof(struct mb86r0x_ddr2c, dric));
+ DEFINE(DDR2_DRIC1, offsetof(struct mb86r0x_ddr2c, dric1));
+ DEFINE(DDR2_DRIC2, offsetof(struct mb86r0x_ddr2c, dric2));
+ DEFINE(DDR2_DRCA, offsetof(struct mb86r0x_ddr2c, drca));
+ DEFINE(DDR2_DRCM, offsetof(struct mb86r0x_ddr2c, drcm));
+ DEFINE(DDR2_DRCST1, offsetof(struct mb86r0x_ddr2c, drcst1));
+ DEFINE(DDR2_DRCST2, offsetof(struct mb86r0x_ddr2c, drcst2));
+ DEFINE(DDR2_DRCR, offsetof(struct mb86r0x_ddr2c, drcr));
+ DEFINE(DDR2_DRCF, offsetof(struct mb86r0x_ddr2c, drcf));
+ DEFINE(DDR2_DRASR, offsetof(struct mb86r0x_ddr2c, drasr));
+ DEFINE(DDR2_DRIMS, offsetof(struct mb86r0x_ddr2c, drims));
+ DEFINE(DDR2_DROS, offsetof(struct mb86r0x_ddr2c, dros));
+ DEFINE(DDR2_DRIBSODT1, offsetof(struct mb86r0x_ddr2c, dribsodt1));
+ DEFINE(DDR2_DROABA, offsetof(struct mb86r0x_ddr2c, droaba));
+ DEFINE(DDR2_DROBS, offsetof(struct mb86r0x_ddr2c, drobs));
+
+ /* clock reset generator */
+ DEFINE(CRG_CRPR, offsetof(struct mb86r0x_crg, crpr));
+ DEFINE(CRG_CRHA, offsetof(struct mb86r0x_crg, crha));
+ DEFINE(CRG_CRPA, offsetof(struct mb86r0x_crg, crpa));
+ DEFINE(CRG_CRPB, offsetof(struct mb86r0x_crg, crpb));
+ DEFINE(CRG_CRHB, offsetof(struct mb86r0x_crg, crhb));
+ DEFINE(CRG_CRAM, offsetof(struct mb86r0x_crg, cram));
+
+ /* chip control module */
+ DEFINE(CCNT_CDCRC, offsetof(struct mb86r0x_ccnt, cdcrc));
+
+ /* external bus interface */
+ DEFINE(MEMC_MCFMODE0, offsetof(struct mb86r0x_memc, mcfmode[0]));
+ DEFINE(MEMC_MCFMODE2, offsetof(struct mb86r0x_memc, mcfmode[2]));
+ DEFINE(MEMC_MCFMODE4, offsetof(struct mb86r0x_memc, mcfmode[4]));
+ DEFINE(MEMC_MCFTIM0, offsetof(struct mb86r0x_memc, mcftim[0]));
+ DEFINE(MEMC_MCFTIM2, offsetof(struct mb86r0x_memc, mcftim[2]));
+ DEFINE(MEMC_MCFTIM4, offsetof(struct mb86r0x_memc, mcftim[4]));
+ DEFINE(MEMC_MCFAREA0, offsetof(struct mb86r0x_memc, mcfarea[0]));
+ DEFINE(MEMC_MCFAREA2, offsetof(struct mb86r0x_memc, mcfarea[2]));
+ DEFINE(MEMC_MCFAREA4, offsetof(struct mb86r0x_memc, mcfarea[4]));
+#endif
+
+#if defined(CONFIG_MX25)
+ /* Clock Control Module */
+ DEFINE(CCM_CCTL, offsetof(struct ccm_regs, cctl));
+ DEFINE(CCM_CGCR0, offsetof(struct ccm_regs, cgr0));
+ DEFINE(CCM_CGCR1, offsetof(struct ccm_regs, cgr1));
+ DEFINE(CCM_CGCR2, offsetof(struct ccm_regs, cgr2));
+ DEFINE(CCM_PCDR2, offsetof(struct ccm_regs, pcdr[2]));
+ DEFINE(CCM_MCR, offsetof(struct ccm_regs, mcr));
+
+ /* Enhanced SDRAM Controller */
+ DEFINE(ESDRAMC_ESDCTL0, offsetof(struct esdramc_regs, ctl0));
+ DEFINE(ESDRAMC_ESDCFG0, offsetof(struct esdramc_regs, cfg0));
+ DEFINE(ESDRAMC_ESDMISC, offsetof(struct esdramc_regs, misc));
+
+ /* Multi-Layer AHB Crossbar Switch */
+ DEFINE(MAX_MPR0, offsetof(struct max_regs, mpr0));
+ DEFINE(MAX_SGPCR0, offsetof(struct max_regs, sgpcr0));
+ DEFINE(MAX_MPR1, offsetof(struct max_regs, mpr1));
+ DEFINE(MAX_SGPCR1, offsetof(struct max_regs, sgpcr1));
+ DEFINE(MAX_MPR2, offsetof(struct max_regs, mpr2));
+ DEFINE(MAX_SGPCR2, offsetof(struct max_regs, sgpcr2));
+ DEFINE(MAX_MPR3, offsetof(struct max_regs, mpr3));
+ DEFINE(MAX_SGPCR3, offsetof(struct max_regs, sgpcr3));
+ DEFINE(MAX_MPR4, offsetof(struct max_regs, mpr4));
+ DEFINE(MAX_SGPCR4, offsetof(struct max_regs, sgpcr4));
+ DEFINE(MAX_MGPCR0, offsetof(struct max_regs, mgpcr0));
+ DEFINE(MAX_MGPCR1, offsetof(struct max_regs, mgpcr1));
+ DEFINE(MAX_MGPCR2, offsetof(struct max_regs, mgpcr2));
+ DEFINE(MAX_MGPCR3, offsetof(struct max_regs, mgpcr3));
+ DEFINE(MAX_MGPCR4, offsetof(struct max_regs, mgpcr4));
+
+ /* AHB <-> IP-Bus Interface */
+ DEFINE(AIPS_MPR_0_7, offsetof(struct aips_regs, mpr_0_7));
+ DEFINE(AIPS_MPR_8_15, offsetof(struct aips_regs, mpr_8_15));
+#endif
+
+#if defined(CONFIG_MX27)
+ DEFINE(AIPI1_PSR0, IMX_AIPI1_BASE + offsetof(struct aipi_regs, psr0));
+ DEFINE(AIPI1_PSR1, IMX_AIPI1_BASE + offsetof(struct aipi_regs, psr1));
+ DEFINE(AIPI2_PSR0, IMX_AIPI2_BASE + offsetof(struct aipi_regs, psr0));
+ DEFINE(AIPI2_PSR1, IMX_AIPI2_BASE + offsetof(struct aipi_regs, psr1));
+
+ DEFINE(CSCR, IMX_PLL_BASE + offsetof(struct pll_regs, cscr));
+ DEFINE(MPCTL0, IMX_PLL_BASE + offsetof(struct pll_regs, mpctl0));
+ DEFINE(SPCTL0, IMX_PLL_BASE + offsetof(struct pll_regs, spctl0));
+ DEFINE(PCDR0, IMX_PLL_BASE + offsetof(struct pll_regs, pcdr0));
+ DEFINE(PCDR1, IMX_PLL_BASE + offsetof(struct pll_regs, pcdr1));
+ DEFINE(PCCR0, IMX_PLL_BASE + offsetof(struct pll_regs, pccr0));
+ DEFINE(PCCR1, IMX_PLL_BASE + offsetof(struct pll_regs, pccr1));
+
+ DEFINE(ESDCTL0_ROF, offsetof(struct esdramc_regs, esdctl0));
+ DEFINE(ESDCFG0_ROF, offsetof(struct esdramc_regs, esdcfg0));
+ DEFINE(ESDCTL1_ROF, offsetof(struct esdramc_regs, esdctl1));
+ DEFINE(ESDCFG1_ROF, offsetof(struct esdramc_regs, esdcfg1));
+ DEFINE(ESDMISC_ROF, offsetof(struct esdramc_regs, esdmisc));
+
+ DEFINE(GPCR, IMX_SYSTEM_CTL_BASE +
+ offsetof(struct system_control_regs, gpcr));
+ DEFINE(FMCR, IMX_SYSTEM_CTL_BASE +
+ offsetof(struct system_control_regs, fmcr));
+#endif
+
+#if defined(CONFIG_MX35)
+ /* Round up to make sure size gives nice stack alignment */
+ DEFINE(CLKCTL_CCMR, offsetof(struct ccm_regs, ccmr));
+ DEFINE(CLKCTL_PDR0, offsetof(struct ccm_regs, pdr0));
+ DEFINE(CLKCTL_PDR1, offsetof(struct ccm_regs, pdr1));
+ DEFINE(CLKCTL_PDR2, offsetof(struct ccm_regs, pdr2));
+ DEFINE(CLKCTL_PDR3, offsetof(struct ccm_regs, pdr3));
+ DEFINE(CLKCTL_PDR4, offsetof(struct ccm_regs, pdr4));
+ DEFINE(CLKCTL_RCSR, offsetof(struct ccm_regs, rcsr));
+ DEFINE(CLKCTL_MPCTL, offsetof(struct ccm_regs, mpctl));
+ DEFINE(CLKCTL_PPCTL, offsetof(struct ccm_regs, ppctl));
+ DEFINE(CLKCTL_ACMR, offsetof(struct ccm_regs, acmr));
+ DEFINE(CLKCTL_COSR, offsetof(struct ccm_regs, cosr));
+ DEFINE(CLKCTL_CGR0, offsetof(struct ccm_regs, cgr0));
+ DEFINE(CLKCTL_CGR1, offsetof(struct ccm_regs, cgr1));
+ DEFINE(CLKCTL_CGR2, offsetof(struct ccm_regs, cgr2));
+ DEFINE(CLKCTL_CGR3, offsetof(struct ccm_regs, cgr3));
+
+ /* Multi-Layer AHB Crossbar Switch */
+ DEFINE(MAX_MPR0, offsetof(struct max_regs, mpr0));
+ DEFINE(MAX_SGPCR0, offsetof(struct max_regs, sgpcr0));
+ DEFINE(MAX_MPR1, offsetof(struct max_regs, mpr1));
+ DEFINE(MAX_SGPCR1, offsetof(struct max_regs, sgpcr1));
+ DEFINE(MAX_MPR2, offsetof(struct max_regs, mpr2));
+ DEFINE(MAX_SGPCR2, offsetof(struct max_regs, sgpcr2));
+ DEFINE(MAX_MPR3, offsetof(struct max_regs, mpr3));
+ DEFINE(MAX_SGPCR3, offsetof(struct max_regs, sgpcr3));
+ DEFINE(MAX_MPR4, offsetof(struct max_regs, mpr4));
+ DEFINE(MAX_SGPCR4, offsetof(struct max_regs, sgpcr4));
+ DEFINE(MAX_MGPCR0, offsetof(struct max_regs, mgpcr0));
+ DEFINE(MAX_MGPCR1, offsetof(struct max_regs, mgpcr1));
+ DEFINE(MAX_MGPCR2, offsetof(struct max_regs, mgpcr2));
+ DEFINE(MAX_MGPCR3, offsetof(struct max_regs, mgpcr3));
+ DEFINE(MAX_MGPCR4, offsetof(struct max_regs, mgpcr4));
+ DEFINE(MAX_MGPCR5, offsetof(struct max_regs, mgpcr5));
+
+ /* AHB <-> IP-Bus Interface */
+ DEFINE(AIPS_MPR_0_7, offsetof(struct aips_regs, mpr_0_7));
+ DEFINE(AIPS_MPR_8_15, offsetof(struct aips_regs, mpr_8_15));
+ DEFINE(AIPS_PACR_0_7, offsetof(struct aips_regs, pacr_0_7));
+ DEFINE(AIPS_PACR_8_15, offsetof(struct aips_regs, pacr_8_15));
+ DEFINE(AIPS_PACR_16_23, offsetof(struct aips_regs, pacr_16_23));
+ DEFINE(AIPS_PACR_24_31, offsetof(struct aips_regs, pacr_24_31));
+ DEFINE(AIPS_OPACR_0_7, offsetof(struct aips_regs, opacr_0_7));
+ DEFINE(AIPS_OPACR_8_15, offsetof(struct aips_regs, opacr_8_15));
+ DEFINE(AIPS_OPACR_16_23, offsetof(struct aips_regs, opacr_16_23));
+ DEFINE(AIPS_OPACR_24_31, offsetof(struct aips_regs, opacr_24_31));
+ DEFINE(AIPS_OPACR_32_39, offsetof(struct aips_regs, opacr_32_39));
+#endif
+
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
+ /* Round up to make sure size gives nice stack alignment */
+ DEFINE(CLKCTL_CCMR, offsetof(struct clkctl, ccr));
+ DEFINE(CLKCTL_CCDR, offsetof(struct clkctl, ccdr));
+ DEFINE(CLKCTL_CSR, offsetof(struct clkctl, csr));
+ DEFINE(CLKCTL_CCSR, offsetof(struct clkctl, ccsr));
+ DEFINE(CLKCTL_CACRR, offsetof(struct clkctl, cacrr));
+ DEFINE(CLKCTL_CBCDR, offsetof(struct clkctl, cbcdr));
+ DEFINE(CLKCTL_CBCMR, offsetof(struct clkctl, cbcmr));
+ DEFINE(CLKCTL_CSCMR1, offsetof(struct clkctl, cscmr1));
+ DEFINE(CLKCTL_CSCMR2, offsetof(struct clkctl, cscmr2));
+ DEFINE(CLKCTL_CSCDR1, offsetof(struct clkctl, cscdr1));
+ DEFINE(CLKCTL_CS1CDR, offsetof(struct clkctl, cs1cdr));
+ DEFINE(CLKCTL_CS2CDR, offsetof(struct clkctl, cs2cdr));
+ DEFINE(CLKCTL_CDCDR, offsetof(struct clkctl, cdcdr));
+ DEFINE(CLKCTL_CHSCCDR, offsetof(struct clkctl, chsccdr));
+ DEFINE(CLKCTL_CSCDR2, offsetof(struct clkctl, cscdr2));
+ DEFINE(CLKCTL_CSCDR3, offsetof(struct clkctl, cscdr3));
+ DEFINE(CLKCTL_CSCDR4, offsetof(struct clkctl, cscdr4));
+ DEFINE(CLKCTL_CWDR, offsetof(struct clkctl, cwdr));
+ DEFINE(CLKCTL_CDHIPR, offsetof(struct clkctl, cdhipr));
+ DEFINE(CLKCTL_CDCR, offsetof(struct clkctl, cdcr));
+ DEFINE(CLKCTL_CTOR, offsetof(struct clkctl, ctor));
+ DEFINE(CLKCTL_CLPCR, offsetof(struct clkctl, clpcr));
+ DEFINE(CLKCTL_CISR, offsetof(struct clkctl, cisr));
+ DEFINE(CLKCTL_CIMR, offsetof(struct clkctl, cimr));
+ DEFINE(CLKCTL_CCOSR, offsetof(struct clkctl, ccosr));
+ DEFINE(CLKCTL_CGPR, offsetof(struct clkctl, cgpr));
+ DEFINE(CLKCTL_CCGR0, offsetof(struct clkctl, ccgr0));
+ DEFINE(CLKCTL_CCGR1, offsetof(struct clkctl, ccgr1));
+ DEFINE(CLKCTL_CCGR2, offsetof(struct clkctl, ccgr2));
+ DEFINE(CLKCTL_CCGR3, offsetof(struct clkctl, ccgr3));
+ DEFINE(CLKCTL_CCGR4, offsetof(struct clkctl, ccgr4));
+ DEFINE(CLKCTL_CCGR5, offsetof(struct clkctl, ccgr5));
+ DEFINE(CLKCTL_CCGR6, offsetof(struct clkctl, ccgr6));
+ DEFINE(CLKCTL_CMEOR, offsetof(struct clkctl, cmeor));
+#if defined(CONFIG_MX53)
+ DEFINE(CLKCTL_CCGR7, offsetof(struct clkctl, ccgr7));
+#endif
+
+ /* DPLL */
+ DEFINE(PLL_DP_CTL, offsetof(struct dpll, dp_ctl));
+ DEFINE(PLL_DP_CONFIG, offsetof(struct dpll, dp_config));
+ DEFINE(PLL_DP_OP, offsetof(struct dpll, dp_op));
+ DEFINE(PLL_DP_MFD, offsetof(struct dpll, dp_mfd));
+ DEFINE(PLL_DP_MFN, offsetof(struct dpll, dp_mfn));
+ DEFINE(PLL_DP_HFS_OP, offsetof(struct dpll, dp_hfs_op));
+ DEFINE(PLL_DP_HFS_MFD, offsetof(struct dpll, dp_hfs_mfd));
+ DEFINE(PLL_DP_HFS_MFN, offsetof(struct dpll, dp_hfs_mfn));
+#endif
++#if defined(CONFIG_MX6)
++ DEFINE(CCM_CCR, offsetof(struct mxc_ccm_reg, ccr));
++ DEFINE(CCM_CCDR, offsetof(struct mxc_ccm_reg, ccdr));
++ DEFINE(CCM_CSR, offsetof(struct mxc_ccm_reg, csr));
++ DEFINE(CCM_CCSR, offsetof(struct mxc_ccm_reg, ccsr));
++ DEFINE(CCM_CACRR, offsetof(struct mxc_ccm_reg, cacrr));
++ DEFINE(CCM_CBCDR, offsetof(struct mxc_ccm_reg, cbcdr));
++ DEFINE(CCM_CBCMR, offsetof(struct mxc_ccm_reg, cbcmr));
++ DEFINE(CCM_CSCMR1, offsetof(struct mxc_ccm_reg, cscmr1));
++ DEFINE(CCM_CSCMR2, offsetof(struct mxc_ccm_reg, cscmr2));
++ DEFINE(CCM_CSCDR1, offsetof(struct mxc_ccm_reg, cscdr1));
++ DEFINE(CCM_CS1CDR, offsetof(struct mxc_ccm_reg, cs1cdr));
++ DEFINE(CCM_CS2CDR, offsetof(struct mxc_ccm_reg, cs2cdr));
++ DEFINE(CCM_CDCDR, offsetof(struct mxc_ccm_reg, cdcdr));
++ DEFINE(CCM_CHSCCDR, offsetof(struct mxc_ccm_reg, chsccdr));
++ DEFINE(CCM_CSCDR2, offsetof(struct mxc_ccm_reg, cscdr2));
++ DEFINE(CCM_CSCDR3, offsetof(struct mxc_ccm_reg, cscdr3));
++ DEFINE(CCM_CSCDR4, offsetof(struct mxc_ccm_reg, cscdr4));
++ DEFINE(CCM_CDHIPR, offsetof(struct mxc_ccm_reg, cdhipr));
++ DEFINE(CCM_CDCR, offsetof(struct mxc_ccm_reg, cdcr));
++ DEFINE(CCM_CTOR, offsetof(struct mxc_ccm_reg, ctor));
++ DEFINE(CCM_CLPCR, offsetof(struct mxc_ccm_reg, clpcr));
++ DEFINE(CCM_CISR, offsetof(struct mxc_ccm_reg, cisr));
++ DEFINE(CCM_CIMR, offsetof(struct mxc_ccm_reg, cimr));
++ DEFINE(CCM_CCOSR, offsetof(struct mxc_ccm_reg, ccosr));
++ DEFINE(CCM_CGPR, offsetof(struct mxc_ccm_reg, cgpr));
++ DEFINE(CCM_CCGR0, offsetof(struct mxc_ccm_reg, CCGR0));
++ DEFINE(CCM_CCGR1, offsetof(struct mxc_ccm_reg, CCGR1));
++ DEFINE(CCM_CCGR2, offsetof(struct mxc_ccm_reg, CCGR2));
++ DEFINE(CCM_CCGR3, offsetof(struct mxc_ccm_reg, CCGR3));
++ DEFINE(CCM_CCGR4, offsetof(struct mxc_ccm_reg, CCGR4));
++ DEFINE(CCM_CCGR5, offsetof(struct mxc_ccm_reg, CCGR5));
++ DEFINE(CCM_CCGR6, offsetof(struct mxc_ccm_reg, CCGR6));
++ DEFINE(CCM_CCGR7, offsetof(struct mxc_ccm_reg, CCGR7));
++ DEFINE(CCM_CMEOR, offsetof(struct mxc_ccm_reg, cmeor));
+
++ DEFINE(ANATOP_PLL_ENET, offsetof(struct anatop_regs, pll_enet));
++#endif
+ return 0;
+}
#include <nand.h>
#include <onenand_uboot.h>
#include <mmc.h>
+#include <scsi.h>
+#include <status_led.h>
#include <libfdt.h>
#include <fdtdec.h>
#include <post.h>
************************************************************************
* May be supplied by boards if desired
*/
-inline void __coloured_LED_init(void) {}
-void coloured_LED_init(void)
- __attribute__((weak, alias("__coloured_LED_init")));
-inline void __red_led_on(void) {}
-void red_led_on(void) __attribute__((weak, alias("__red_led_on")));
-inline void __red_led_off(void) {}
-void red_led_off(void) __attribute__((weak, alias("__red_led_off")));
-inline void __green_led_on(void) {}
-void green_led_on(void) __attribute__((weak, alias("__green_led_on")));
-inline void __green_led_off(void) {}
-void green_led_off(void) __attribute__((weak, alias("__green_led_off")));
-inline void __yellow_led_on(void) {}
-void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on")));
-inline void __yellow_led_off(void) {}
-void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off")));
-inline void __blue_led_on(void) {}
-void blue_led_on(void) __attribute__((weak, alias("__blue_led_on")));
-inline void __blue_led_off(void) {}
-void blue_led_off(void) __attribute__((weak, alias("__blue_led_off")));
+__weak void coloured_LED_init(void) {}
+__weak void red_led_on(void) {}
+__weak void red_led_off(void) {}
+__weak void green_led_on(void) {}
+__weak void green_led_off(void) {}
+__weak void yellow_led_on(void) {}
+__weak void yellow_led_off(void) {}
+__weak void blue_led_on(void) {}
+__weak void blue_led_off(void) {}
/*
************************************************************************
{
printf("\n\n%s\n\n", version_string);
debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
- _TEXT_BASE,
- _bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE);
+ (ulong)&_start,
+ (ulong)&__bss_start, (ulong)&__bss_end);
#ifdef CONFIG_MODEM_SUPPORT
debug("Modem Support enabled\n");
#endif
*/
typedef int (init_fnc_t) (void);
-int print_cpuinfo(void);
-
-void __dram_init_banksize(void)
+__weak void dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
gd->bd->bi_dram[0].size = gd->ram_size;
}
-void dram_init_banksize(void)
- __attribute__((weak, alias("__dram_init_banksize")));
-int __arch_cpu_init(void)
+__weak int arch_cpu_init(void)
{
return 0;
}
-int arch_cpu_init(void)
- __attribute__((weak, alias("__arch_cpu_init")));
-int __power_init_board(void)
+__weak int power_init_board(void)
{
return 0;
}
-int power_init_board(void)
- __attribute__((weak, alias("__power_init_board")));
/* Record the board_init_f() bootstage (after arch_cpu_init()) */
static int mark_bootstage(void)
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
-#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
-#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
memset((void *)gd, 0, sizeof(gd_t));
- gd->mon_len = _bss_end_ofs;
+ gd->mon_len = (ulong)&__bss_end - (ulong)_start;
#ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */
- gd->fdt_blob = _binary_dt_dtb_start;
+ gd->fdt_blob = __dtb_dt_begin;
#elif defined CONFIG_OF_SEPARATE
/* FDT is at end of image */
- gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
+ gd->fdt_blob = &_end;
#endif
/* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
#endif
- addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
+ addr = CONFIG_SYS_SDRAM_BASE + get_effective_memsize();
#ifdef CONFIG_LOGBUFFER
#ifndef CONFIG_ALT_LB_ADDR
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
/* reserve TLB table */
- gd->arch.tlb_size = 4096 * 4;
+ gd->arch.tlb_size = PGTABLE_SIZE;
addr -= gd->arch.tlb_size;
/* round down to next 64 kB limit */
}
#endif
+#ifndef CONFIG_ARM64
/* setup stackpointer for exeptions */
gd->irq_sp = addr_sp;
#ifdef CONFIG_USE_IRQ
/* 8-byte alignment for ABI compliance */
addr_sp &= ~0x07;
+#else /* CONFIG_ARM64 */
+ /* 16-byte alignment for ABI compliance */
+ addr_sp &= ~0x0f;
+#endif /* CONFIG_ARM64 */
#else
addr_sp += 128; /* leave 32 words for abort-stack */
gd->irq_sp = addr_sp;
post_run(NULL, POST_ROM | post_bootmode_get(0));
#endif
- gd->bd->bi_baudrate = gd->baudrate;
/* Ram ist board specific, so move it to board code ... */
dram_init_banksize();
display_dram_config(); /* and display it */
gd->relocaddr = addr;
gd->start_addr_sp = addr_sp;
- gd->reloc_off = addr - _TEXT_BASE;
-
+ gd->reloc_off = addr - (ulong)&_start;
debug("relocation Offset is: %08lx\n", gd->reloc_off);
if (new_fdt) {
memcpy(new_fdt, gd->fdt_blob, fdt_size);
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
- monitor_flash_len = _end_ofs;
+ monitor_flash_len = (ulong)&__rel_dyn_end - (ulong)_start;
/* Enable caches */
enable_caches();
debug("monitor flash len: %08lX\n", monitor_flash_len);
board_init(); /* Setup chipselects */
/*
- * TODO: printing of the clock inforamtion of the board is now
+ * TODO: printing of the clock information of the board is now
* implemented as part of bdinfo command. Currently only support for
* davinci SOC's is added. Remove this check once all the board
* implement this.
mmc_initialize(gd->bd);
#endif
+#ifdef CONFIG_CMD_SCSI
+ puts("SCSI: ");
+ scsi_init();
+#endif
+
#ifdef CONFIG_HAS_DATAFLASH
AT91F_DataflashInit();
dataflash_print_info();
DECLARE_GLOBAL_DATA_PTR;
-void __arm_init_before_mmu(void)
+__weak void arm_init_before_mmu(void)
{
}
-void arm_init_before_mmu(void)
- __attribute__((weak, alias("__arm_init_before_mmu")));
__weak void arm_init_domains(void)
{
}
- static void cp_delay (void)
- {
- volatile int i;
-
- /* copro seems to need some delay between reading and writing */
- for (i = 0; i < 100; i++)
- nop();
- asm volatile("" : : : "memory");
- }
-
void set_section_dcache(int section, enum dcache_option option)
{
u32 *page_table = (u32 *)gd->arch.tlb_addr;
page_table[section] = value;
}
-void __mmu_page_table_flush(unsigned long start, unsigned long stop)
+__weak void mmu_page_table_flush(unsigned long start, unsigned long stop)
{
debug("%s: Warning: not implemented\n", __func__);
}
-void mmu_page_table_flush(unsigned long start, unsigned long stop)
- __attribute__((weak, alias("__mmu_page_table_flush")));
-
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
enum dcache_option option)
{
u32 *page_table = (u32 *)gd->arch.tlb_addr;
- u32 upto, end;
+ unsigned long upto, end;
end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
start = start >> MMU_SECTION_SHIFT;
- debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
+ debug("%s: start=%pa, size=%zu, option=%d\n", __func__, &start, size,
option);
for (upto = start; upto < end; upto++)
set_section_dcache(upto, option);
debug("%s: bank: %d\n", __func__, bank);
for (i = bd->bi_dram[bank].start >> 20;
- i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
+ i < (bd->bi_dram[bank].start >> 20) + (bd->bi_dram[bank].size >> 20);
i++) {
#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
set_section_dcache(i, DCACHE_WRITETHROUGH);
+#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC)
+ set_section_dcache(i, DCACHE_WRITEALLOC);
#else
set_section_dcache(i, DCACHE_WRITEBACK);
#endif
dram_bank_mmu_setup(i);
}
- /* Copy the page table address to cp15 */
- asm volatile("mcr p15, 0, %0, c2, c0, 0"
- : : "r" (gd->arch.tlb_addr) : "memory");
- /* Set the access control to all-supervisor */
- asm volatile("mcr p15, 0, %0, c3, c0, 0"
- : : "r" (~0));
+ asm volatile(
+ /* Copy the page table address to cp15 */
+ "mcr p15, 0, %0, c2, c0, 0\n"
+ /* Set the access control to all-supervisor */
+ "mcr p15, 0, %1, c3, c0, 0\n"
+ :
+ : "r"(gd->arch.tlb_addr), "r"(~0)
+ : "memory"
+ );
arm_init_domains();
/* and enable the mmu */
reg = get_cr(); /* get control reg. */
- cp_delay();
set_cr(reg | CR_M);
}
if ((cache_bit == CR_C) && !mmu_enabled())
mmu_setup();
reg = get_cr(); /* get control reg. */
- cp_delay();
set_cr(reg | cache_bit);
}
uint32_t reg;
reg = get_cr();
- cp_delay();
if (cache_bit == CR_C) {
/* if cache isn;t enabled no need to disable */
cache_bit |= CR_M;
}
reg = get_cr();
- cp_delay();
if (cache_bit == (CR_C | CR_M))
flush_dcache_all();
set_cr(reg & ~cache_bit);
/* for now: just dummy functions to satisfy the linker */
#include <common.h>
+#include <malloc.h>
-void __flush_cache(unsigned long start, unsigned long size)
+__weak void flush_cache(unsigned long start, unsigned long size)
{
-#if defined(CONFIG_ARM1136)
- void arm1136_cache_flush(void);
+#if defined(CONFIG_CPU_ARM1136)
- arm1136_cache_flush();
+#if !defined(CONFIG_SYS_ICACHE_OFF)
+ asm("mcr p15, 0, r1, c7, c5, 0"); /* invalidate I cache */
#endif
- #ifdef CONFIG_CPU_ARM926EJS
- /* test and clean, page 2-23 of arm926ejs manual */
- asm("0: mrc p15, 0, r15, c7, c10, 3\n\t" "bne 0b\n" : : : "memory");
- /* disable write buffer as well (page 2-22) */
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
- #endif /* CONFIG_CPU_ARM926EJS */
+
+#if !defined(CONFIG_SYS_DCACHE_OFF)
+ asm("mcr p15, 0, r1, c7, c14, 0"); /* Clean+invalidate D cache */
+#endif
+
+#endif /* CONFIG_CPU_ARM1136 */
+
+ #ifdef CONFIG_ARM926EJS
+ asm(
+ /* test and clean, page 2-23 of arm926ejs manual */
+ "0: mrc p15, 0, r15, c7, c10, 3\n\t" "bne 0b\n"
+ /* flush write buffer as well (page 2-22) */
+ "mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory"
+ );
+ #endif
return;
}
-void flush_cache(unsigned long start, unsigned long size)
- __attribute__((weak, alias("__flush_cache")));
/*
* Default implementation:
* do a range flush for the entire range
*/
-void __flush_dcache_all(void)
+__weak void flush_dcache_all(void)
{
flush_cache(0, ~0);
}
-void flush_dcache_all(void)
- __attribute__((weak, alias("__flush_dcache_all")));
-
/*
* Default implementation of enable_caches()
* Real implementation should be in platform code
*/
-void __enable_caches(void)
+__weak void enable_caches(void)
{
puts("WARNING: Caches not enabled\n");
}
-void enable_caches(void)
- __attribute__((weak, alias("__enable_caches")));
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+/*
+ * Reserve one MMU section worth of address space below the malloc() area that
+ * will be mapped uncached.
+ */
+static unsigned long noncached_start;
+static unsigned long noncached_end;
+static unsigned long noncached_next;
+
+void noncached_init(void)
+{
+ phys_addr_t start, end;
+ size_t size;
+
+ end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
+ size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
+ start = end - size;
+
+ debug("mapping memory %pa-%pa non-cached\n", &start, &end);
+
+ noncached_start = start;
+ noncached_end = end;
+ noncached_next = start;
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+ mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
+#endif
+}
+
+phys_addr_t noncached_alloc(size_t size, size_t align)
+{
+ phys_addr_t next = ALIGN(noncached_next, align);
+
+ if (next >= noncached_end || (noncached_end - next) < size)
+ return 0;
+
+ debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
+ noncached_next = next + size;
+
+ return next;
+}
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
*/
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
- ldr sp, =(CONFIG_SPL_STACK)
+ ldr sp, =CONFIG_SPL_STACK
#else
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
+ ldr sp, =CONFIG_SYS_INIT_SP_ADDR
#endif
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- sub sp, #GD_SIZE /* allocate one GD above SP */
+ mov r2, sp
+ sub sp, sp, #GD_SIZE /* allocate one GD above SP */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- mov r8, sp /* GD is above SP */
+ mov r9, sp /* GD is above SP */
+ mov r1, sp
mov r0, #0
+clr_gd:
+ cmp r1, r2 /* while not at end of GD */
+ strlo r0, [r1] /* clear 32-bit GD word */
+ addlo r1, r1, #4 /* move to next */
+ blo clr_gd
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+ sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN
+ str sp, [r9, #GD_MALLOC_BASE]
+#endif
+ /* mov r0, #0 not needed due to above code */
bl board_init_f
#if ! defined(CONFIG_SPL_BUILD)
* 'here' but relocated.
*/
- ldr sp, [r8, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
+ ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- ldr r8, [r8, #GD_BD] /* r8 = gd->bd */
- sub r8, r8, #GD_SIZE /* new GD is below bd */
+ ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
+ sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, here
- ldr r0, [r8, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
+ ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
- ldr r0, [r8, #GD_RELOCADDR] /* r0 = gd->relocaddr */
+ ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
here:
+/*
+ * now relocate vectors
+ */
+
+ bl relocate_vectors
/* Set up final (full) environment */
bl red_led_on
/* call board_init_r(gd_t *id, ulong dest_addr) */
- mov r0, r8 /* gd_t */
- ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */
+ mov r0, r9 /* gd_t */
+ ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
/* call board_init_r */
ldr pc, =board_init_r /* this is auto-relocated! */
* (C) Copyright 2004
* Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
-#include <asm/ptrace.h>
+#include <asm/proc-armv/ptrace.h>
+#include <asm/u-boot-arm.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_USE_IRQ
int interrupt_init (void)
{
+ unsigned long cpsr;
+
/*
* setup up stacks if necessary
*/
IRQ_STACK_START_IN = gd->irq_sp + 8;
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
+
+ __asm__ __volatile__("mrs %0, cpsr\n"
+ : "=r" (cpsr)
+ :
+ : "memory");
+
+ __asm__ __volatile__("msr cpsr_c, %0\n"
+ "mov sp, %1\n"
+ :
+ : "r" (IRQ_MODE | I_BIT | F_BIT | (cpsr & ~FIQ_MODE)),
+ "r" (IRQ_STACK_START)
+ : "memory");
+
+ __asm__ __volatile__("msr cpsr_c, %0\n"
+ "mov sp, %1\n"
+ :
+ : "r" (FIQ_MODE | I_BIT | F_BIT | (cpsr & ~IRQ_MODE)),
+ "r" (FIQ_STACK_START)
+ : "memory");
+
+ __asm__ __volatile__("msr cpsr_c, %0"
+ :
+ : "r" (cpsr)
+ : "memory");
+
return arch_interrupt_init();
}
"UK12_26", "UK13_26", "UK14_26", "UK15_26",
"USER_32", "FIQ_32", "IRQ_32", "SVC_32",
"UK4_32", "UK5_32", "UK6_32", "ABT_32",
- "UK8_32", "UK9_32", "UK10_32", "UND_32",
+ "UK8_32", "UK9_32", "HYP_32", "UND_32",
"UK12_32", "UK13_32", "UK14_32", "SYS_32",
};
- flags = condition_codes (regs);
-
- printf ("pc : [<%08lx>] lr : [<%08lx>]\n"
- "sp : %08lx ip : %08lx fp : %08lx\n",
- instruction_pointer (regs),
- regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+ flags = condition_codes(regs);
+
+ if (gd->flags & GD_FLG_RELOC)
+ printf ("pc : [<%08lx>] (pre-reloc: [<%08lx>]) lr : [<%08lx>]\n"
+ "sp : %08lx ip : %08lx fp : %08lx\n",
+ instruction_pointer(regs),
+ instruction_pointer(regs) - gd->reloc_off,
+ regs->ARM_lr, regs->ARM_sp,
+ regs->ARM_ip, regs->ARM_fp);
+ else
+ printf ("pc : [<%08lx>] lr : [<%08lx>]\n"
+ "sp : %08lx ip : %08lx fp : %08lx\n",
+ instruction_pointer(regs), regs->ARM_lr, regs->ARM_sp,
+ regs->ARM_ip, regs->ARM_fp);
printf ("r10: %08lx r9 : %08lx r8 : %08lx\n",
regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
thumb_mode (regs) ? " (T)" : "");
}
+ /* fixup PC to point to instruction leading to exception */
+ static inline void fixup_pc(struct pt_regs *regs, int offset)
+ {
+ uint32_t pc = instruction_pointer(regs) + offset;
+ regs->ARM_pc = pc | (regs->ARM_pc & PCMASK);
+ }
+
void do_undefined_instruction (struct pt_regs *pt_regs)
{
printf ("undefined instruction\n");
+ fixup_pc(pt_regs, -4);
show_regs (pt_regs);
bad_mode ();
}
void do_software_interrupt (struct pt_regs *pt_regs)
{
printf ("software interrupt\n");
+ fixup_pc(pt_regs, -4);
show_regs (pt_regs);
bad_mode ();
}
void do_prefetch_abort (struct pt_regs *pt_regs)
{
printf ("prefetch abort\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
void do_data_abort (struct pt_regs *pt_regs)
{
- unsigned long fsr;
-
- /* Read Fault Status Register */
- asm volatile ("mrc p15, 0, %0, c5, c0, 0" : "=r"(fsr));
-
- printf ("data abort\n\n");
- if (fsr & 1)
- printf ("MAYBE you should read doc/README.arm-unaligned-accesses\n\n");
+ printf ("data abort\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
void do_not_used (struct pt_regs *pt_regs)
{
printf ("not used\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
void do_fiq (struct pt_regs *pt_regs)
{
printf ("fast interrupt request\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
void do_irq (struct pt_regs *pt_regs)
{
printf ("interrupt request\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
#include <common.h>
+__weak void reset_misc(void)
+{
+}
+
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
puts ("resetting ...\n");
udelay (50000); /* wait 50 ms */
disable_interrupts();
+
+ reset_misc();
reset_cpu(0);
-
- /*NOTREACHED*/
- return 0;
+ hang();
}
--- /dev/null
+/*
+ * vectors - Generic ARM exception table code
+ *
+ * Copyright (c) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (c) 2000 Wolfgang Denk <wd@denx.de>
+ * Copyright (c) 2001 Alex Züpke <azu@sysgo.de>
+ * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
+ * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
+ * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
+ * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Symbol _start is referenced elsewhere, so make it global
+ *
+ *************************************************************************
+ */
+
+.globl _start
+
+/*
+ *************************************************************************
+ *
+ * Vectors have their own section so linker script can map them easily
+ *
+ *************************************************************************
+ */
+
+ .section ".vectors", "ax"
+
+/*
+ *************************************************************************
+ *
+ * Exception vectors as described in ARM reference manuals
+ *
+ * Uses indirect branch to allow reaching handlers anywhere in memory.
+ *
+ *************************************************************************
+ */
+
+_start:
+
+#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
+ .word CONFIG_SYS_DV_NOR_BOOT_CFG
+#endif
+
+ b reset
+ ldr pc, _undefined_instruction
+ ldr pc, _software_interrupt
+ ldr pc, _prefetch_abort
+ ldr pc, _data_abort
+ ldr pc, _not_used
+ ldr pc, _irq
+ ldr pc, _fiq
+
+/*
+ *************************************************************************
+ *
+ * Indirect vectors table
+ *
+ * Symbols referenced here must be defined somewhere else
+ *
+ *************************************************************************
+ */
+
+ .globl _undefined_instruction
+ .globl _software_interrupt
+ .globl _prefetch_abort
+ .globl _data_abort
+ .globl _not_used
+ .globl _irq
+ .globl _fiq
+
+_undefined_instruction: .word undefined_instruction
+_software_interrupt: .word software_interrupt
+_prefetch_abort: .word prefetch_abort
+_data_abort: .word data_abort
+_not_used: .word not_used
+_irq: .word irq
+_fiq: .word fiq
+
+ .balignl 16,0xdeadbeef
+
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+
+/* SPL interrupt handling: just hang */
+
+#ifdef CONFIG_SPL_BUILD
+
+ .align 5
+undefined_instruction:
+software_interrupt:
+prefetch_abort:
+data_abort:
+not_used:
+irq:
+fiq:
+
+1:
+ bl 1b /* hang and never return */
+
+#else /* !CONFIG_SPL_BUILD */
+
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
++#ifndef IRAM_BASE_ADDR
+ .word 0x0badc0de
++#else
++ .word IRAM_BASE_ADDR + 0x20
++#endif
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+ .word 0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+ .word 0x0badc0de
+
+#endif /* CONFIG_USE_IRQ */
+
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE 72
+
+#define S_OLD_R0 68
+#define S_PSR 64
+#define S_PC 60
+#define S_LR 56
+#define S_SP 52
+
+#define S_IP 48
+#define S_FP 44
+#define S_R10 40
+#define S_R9 36
+#define S_R8 32
+#define S_R7 28
+#define S_R6 24
+#define S_R5 20
+#define S_R4 16
+#define S_R3 12
+#define S_R2 8
+#define S_R1 4
+#define S_R0 0
+
+#define MODE_SVC 0x13
+#define I_BIT 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+ .macro bad_save_user_regs
+ @ carve out a frame on current user stack
+ sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
+ ldr r2, IRQ_STACK_START_IN
+ @ get values for "aborted" pc and cpsr (into parm regs)
+ ldmia r2, {r2 - r3}
+ add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
+ add r5, sp, #S_SP
+ mov r1, lr
+ stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
+ mov r0, sp @ save current stack into r0 (param register)
+ .endm
+
+ .macro irq_save_user_regs
+ sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ Calling r0-r12
+ @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
+ add r8, sp, #S_PC
+ stmdb r8, {sp, lr}^ @ Calling SP, LR
+ str lr, [r8, #0] @ Save calling PC
+ mrs r6, spsr
+ str r6, [r8, #4] @ Save CPSR
+ str r0, [r8, #8] @ Save OLD_R0
+ mov r0, sp
+ .endm
+
+ .macro irq_restore_user_regs
+ ldmia sp, {r0 - lr}^ @ Calling r0 - lr
+ mov r0, r0
+ ldr lr, [sp, #S_PC] @ Get PC
+ add sp, sp, #S_FRAME_SIZE
+ subs pc, lr, #4 @ return & move spsr_svc into cpsr
+ .endm
+
+ .macro get_bad_stack
+ ldr r13, IRQ_STACK_START_IN @ setup our mode stack
+
+ str lr, [r13] @ save caller lr in position 0 of saved stack
+ mrs lr, spsr @ get the spsr
+ str lr, [r13, #4] @ save spsr in position 1 of saved stack
+ mov r13, #MODE_SVC @ prepare SVC-Mode
+ @ msr spsr_c, r13
+ msr spsr, r13 @ switch modes, make sure moves will execute
+ mov lr, pc @ capture return pc
+ movs pc, lr @ jump to next instruction & switch modes.
+ .endm
+
+ .macro get_irq_stack @ setup IRQ stack
+ ldr sp, IRQ_STACK_START
+ .endm
+
+ .macro get_fiq_stack @ setup FIQ stack
+ ldr sp, FIQ_STACK_START
+ .endm
+
+/*
+ * exception handlers
+ */
+
+ .align 5
+undefined_instruction:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_undefined_instruction
+
+ .align 5
+software_interrupt:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_software_interrupt
+
+ .align 5
+prefetch_abort:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_prefetch_abort
+
+ .align 5
+data_abort:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_data_abort
+
+ .align 5
+not_used:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+ .align 5
+irq:
+ get_irq_stack
+ irq_save_user_regs
+ bl do_irq
+ irq_restore_user_regs
+
+ .align 5
+fiq:
+ get_fiq_stack
+ /* someone ought to write a more effiction fiq_save_user_regs */
+ irq_save_user_regs
+ bl do_fiq
+ irq_restore_user_regs
+
+#else
+
+ .align 5
+irq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_irq
+
+ .align 5
+fiq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_fiq
+
+#endif /* CONFIG_USE_IRQ */
+
+#endif /* CONFIG_SPL_BUILD */
* Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
* Copyright (C) 2013, Boundary Devices <info@boundarydevices.com>
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/gpio.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm/imx-common/mxc_i2c.h>
+#include <asm/imx-common/sata.h>
+#include <asm/imx-common/spi.h>
#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/video.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <micrel.h>
#include <miiphy.h>
#include <netdev.h>
-#include <linux/fb.h>
-#include <ipu_pixfmt.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/mxc_hdmi.h>
#include <i2c.h>
+#include <input.h>
+#include <netdev.h>
+#include <usb/ehci-fsl.h>
DECLARE_GLOBAL_DATA_PTR;
+#define GP_USB_OTG_PWR IMX_GPIO_NR(3, 22)
#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
return 0;
}
-iomux_v3_cfg_t const uart1_pads[] = {
- MX6_PAD_SD3_DAT6__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_SD3_DAT7__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+static iomux_v3_cfg_t const uart1_pads[] = {
+ MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
-iomux_v3_cfg_t const uart2_pads[] = {
- MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+static iomux_v3_cfg_t const uart2_pads[] = {
+ MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
/* I2C1, SGTL5000 */
-struct i2c_pads_info i2c_pad_info0 = {
+static struct i2c_pads_info i2c_pad_info0 = {
.scl = {
.i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
- .gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC,
+ .gpio_mode = MX6_PAD_EIM_D21__GPIO3_IO21 | PC,
.gp = IMX_GPIO_NR(3, 21)
},
.sda = {
.i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
- .gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC,
+ .gpio_mode = MX6_PAD_EIM_D28__GPIO3_IO28 | PC,
.gp = IMX_GPIO_NR(3, 28)
}
};
/* I2C2 Camera, MIPI */
-struct i2c_pads_info i2c_pad_info1 = {
+static struct i2c_pads_info i2c_pad_info1 = {
.scl = {
.i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
- .gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC,
+ .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12 | PC,
.gp = IMX_GPIO_NR(4, 12)
},
.sda = {
.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
- .gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
+ .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | PC,
.gp = IMX_GPIO_NR(4, 13)
}
};
/* I2C3, J15 - RGB connector */
-struct i2c_pads_info i2c_pad_info2 = {
+static struct i2c_pads_info i2c_pad_info2 = {
.scl = {
.i2c_mode = MX6_PAD_GPIO_5__I2C3_SCL | PC,
- .gpio_mode = MX6_PAD_GPIO_5__GPIO_1_5 | PC,
+ .gpio_mode = MX6_PAD_GPIO_5__GPIO1_IO05 | PC,
.gp = IMX_GPIO_NR(1, 5)
},
.sda = {
.i2c_mode = MX6_PAD_GPIO_16__I2C3_SDA | PC,
- .gpio_mode = MX6_PAD_GPIO_16__GPIO_7_11 | PC,
+ .gpio_mode = MX6_PAD_GPIO_16__GPIO7_IO11 | PC,
.gp = IMX_GPIO_NR(7, 11)
}
};
-iomux_v3_cfg_t const usdhc3_pads[] = {
- MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT5__GPIO_7_0, /* CD */
+static iomux_v3_cfg_t const usdhc2_pads[] = {
+ MX6_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const usdhc3_pads[] = {
+ MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT5__GPIO7_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
++ MX6_PAD_SD3_DAT5__GPIO7_IO00, /* CD */
};
-iomux_v3_cfg_t const usdhc4_pads[] = {
- MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D6__GPIO_2_6, /* CD */
+static iomux_v3_cfg_t const usdhc4_pads[] = {
+ MX6_PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D6__GPIO2_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
++ MX6_PAD_NANDF_D6__GPIO2_IO06, /* CD */
};
-iomux_v3_cfg_t const enet_pads1[] = {
+static iomux_v3_cfg_t const enet_pads1[] = {
MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
/* pin 35 - 1 (PHY_AD2) on reset */
- MX6_PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_RGMII_RXC__GPIO_6_30,
++ MX6_PAD_RGMII_RXC__GPIO6_IO30,
/* pin 32 - 1 - (MODE0) all */
- MX6_PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_RGMII_RD0__GPIO_6_25,
++ MX6_PAD_RGMII_RD0__GPIO6_IO25,
/* pin 31 - 1 - (MODE1) all */
- MX6_PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_RGMII_RD1__GPIO_6_27,
++ MX6_PAD_RGMII_RD1__GPIO6_IO27,
/* pin 28 - 1 - (MODE2) all */
- MX6_PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_RGMII_RD2__GPIO_6_28,
++ MX6_PAD_RGMII_RD2__GPIO6_IO28,
/* pin 27 - 1 - (MODE3) all */
- MX6_PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_RGMII_RD3__GPIO_6_29,
++ MX6_PAD_RGMII_RD3__GPIO6_IO29,
/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
- MX6_PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_RGMII_RX_CTL__GPIO_6_24,
++ MX6_PAD_RGMII_RX_CTL__GPIO6_IO24,
/* pin 42 PHY nRST */
- MX6_PAD_EIM_D23__GPIO3_IO23 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_EIM_D23__GPIO_3_23,
- MX6_PAD_ENET_RXD0__GPIO_1_27,
++ MX6_PAD_EIM_D23__GPIO3_IO23,
++ MX6_PAD_ENET_RXD0__GPIO1_IO27,
};
-iomux_v3_cfg_t const enet_pads2[] = {
- MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+static iomux_v3_cfg_t const enet_pads2[] = {
+ MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
+static iomux_v3_cfg_t const misc_pads[] = {
+ MX6_PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(WEAK_PULLUP),
+ MX6_PAD_KEY_COL4__USB_OTG_OC | MUX_PAD_CTRL(WEAK_PULLUP),
+ MX6_PAD_EIM_D30__USB_H1_OC | MUX_PAD_CTRL(WEAK_PULLUP),
+ /* OTG Power enable */
+ MX6_PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(OUTPUT_40OHM),
+};
+
/* wl1271 pads on nitrogen6x */
-iomux_v3_cfg_t const wl12xx_pads[] = {
- (MX6_PAD_NANDF_CS1__GPIO_6_14 & ~MUX_PAD_CTRL_MASK)
+static iomux_v3_cfg_t const wl12xx_pads[] = {
+ (MX6_PAD_NANDF_CS1__GPIO6_IO14 & ~MUX_PAD_CTRL_MASK)
| MUX_PAD_CTRL(WEAK_PULLDOWN),
- (MX6_PAD_NANDF_CS2__GPIO_6_15 & ~MUX_PAD_CTRL_MASK)
+ (MX6_PAD_NANDF_CS2__GPIO6_IO15 & ~MUX_PAD_CTRL_MASK)
| MUX_PAD_CTRL(OUTPUT_40OHM),
- (MX6_PAD_NANDF_CS3__GPIO_6_16 & ~MUX_PAD_CTRL_MASK)
+ (MX6_PAD_NANDF_CS3__GPIO6_IO16 & ~MUX_PAD_CTRL_MASK)
| MUX_PAD_CTRL(OUTPUT_40OHM),
};
#define WL12XX_WL_IRQ_GP IMX_GPIO_NR(6, 14)
/* Button assignments for J14 */
static iomux_v3_cfg_t const button_pads[] = {
/* Menu */
- MX6_PAD_NANDF_D1__GPIO_2_1 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ MX6_PAD_NANDF_D1__GPIO2_IO01 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
/* Back */
- MX6_PAD_NANDF_D2__GPIO_2_2 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ MX6_PAD_NANDF_D2__GPIO2_IO02 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
/* Labelled Search (mapped to Power under Android) */
- MX6_PAD_NANDF_D3__GPIO_2_3 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ MX6_PAD_NANDF_D3__GPIO2_IO03 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
/* Home */
- MX6_PAD_NANDF_D4__GPIO_2_4 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ MX6_PAD_NANDF_D4__GPIO2_IO04 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
/* Volume Down */
- MX6_PAD_GPIO_19__GPIO_4_5 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ MX6_PAD_GPIO_19__GPIO4_IO05 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
/* Volume Up */
- MX6_PAD_GPIO_18__GPIO_7_13 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ MX6_PAD_GPIO_18__GPIO7_IO13 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
};
static void setup_iomux_enet(void)
gpio_set_value(IMX_GPIO_NR(1, 27), 1); /* Nitrogen6X PHY reset */
imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
+ udelay(100); /* Wait 100 us before using mii interface */
}
-iomux_v3_cfg_t const usb_pads[] = {
- MX6_PAD_GPIO_17__GPIO_7_12,
+static iomux_v3_cfg_t const usb_pads[] = {
- MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_GPIO_17__GPIO7_IO12,
};
static void setup_iomux_uart(void)
return 0;
}
+
+int board_ehci_power(int port, int on)
+{
+ if (port)
+ return 0;
+ gpio_set_value(GP_USB_OTG_PWR, on);
+ return 0;
+}
+
#endif
#ifdef CONFIG_FSL_ESDHC
-struct fsl_esdhc_cfg usdhc_cfg[2] = {
+static struct fsl_esdhc_cfg usdhc_cfg[2] = {
{USDHC3_BASE_ADDR},
{USDHC4_BASE_ADDR},
};
int board_mmc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
- int ret;
+ int gp_cd = (cfg->esdhc_base == USDHC3_BASE_ADDR) ? IMX_GPIO_NR(7, 0) :
+ IMX_GPIO_NR(2, 6);
- if (cfg->esdhc_base == USDHC3_BASE_ADDR) {
- gpio_direction_input(IMX_GPIO_NR(7, 0));
- ret = !gpio_get_value(IMX_GPIO_NR(7, 0));
- } else {
- gpio_direction_input(IMX_GPIO_NR(2, 6));
- ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
- }
-
- return ret;
+ gpio_direction_input(gp_cd);
+ return !gpio_get_value(gp_cd);
}
int board_mmc_init(bd_t *bis)
{
- s32 status = 0;
+ int ret;
u32 index = 0;
usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
printf("Warning: you configured more USDHC controllers"
"(%d) then supported by the board (%d)\n",
index + 1, CONFIG_SYS_FSL_USDHC_NUM);
- return status;
+ return -EINVAL;
}
- status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ ret = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ if (ret)
+ return ret;
}
- return status;
+ return 0;
}
#endif
#ifdef CONFIG_MXC_SPI
-iomux_v3_cfg_t const ecspi1_pads[] = {
+int board_spi_cs_gpio(unsigned bus, unsigned cs)
+{
+ return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(3, 19)) : -1;
+}
+
+static iomux_v3_cfg_t const ecspi1_pads[] = {
/* SS1 */
- MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_EIM_D19__GPIO_3_19 | MUX_PAD_CTRL(SPI_PAD_CTRL),
++ MX6_PAD_EIM_D19__GPIO3_IO19,
MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
};
-void setup_spi(void)
+static void setup_spi(void)
{
imx_iomux_v3_setup_multiple_pads(ecspi1_pads,
ARRAY_SIZE(ecspi1_pads));
free(bus);
}
#endif
+
+#ifdef CONFIG_CI_UDC
+ /* For otg ethernet*/
+ usb_eth_initialize(bis);
+#endif
return 0;
}
ARRAY_SIZE(button_pads));
}
-#ifdef CONFIG_CMD_SATA
-
-int setup_sata(void)
-{
- struct iomuxc_base_regs *const iomuxc_regs
- = (struct iomuxc_base_regs *) IOMUXC_BASE_ADDR;
- int ret = enable_sata_clock();
- if (ret)
- return ret;
-
- clrsetbits_le32(&iomuxc_regs->gpr[13],
- IOMUXC_GPR13_SATA_MASK,
- IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
- |IOMUXC_GPR13_SATA_PHY_7_SATA2M
- |IOMUXC_GPR13_SATA_SPEED_3G
- |(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
- |IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
- |IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
- |IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
- |IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
- |IOMUXC_GPR13_SATA_PHY_1_SLOW);
-
- return 0;
-}
-#endif
-
#if defined(CONFIG_VIDEO_IPUV3)
static iomux_v3_cfg_t const backlight_pads[] = {
/* Backlight on RGB connector: J15 */
- MX6_PAD_SD1_DAT3__GPIO1_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_SD1_DAT3__GPIO_1_21,
++ MX6_PAD_SD1_DAT3__GPIO1_IO21,
#define RGB_BACKLIGHT_GP IMX_GPIO_NR(1, 21)
/* Backlight on LVDS connector: J6 */
- MX6_PAD_SD1_CMD__GPIO1_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_SD1_CMD__GPIO_1_18,
++ MX6_PAD_SD1_CMD__GPIO1_IO18,
#define LVDS_BACKLIGHT_GP IMX_GPIO_NR(1, 18)
};
static iomux_v3_cfg_t const rgb_pads[] = {
MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15,
- MX6_PAD_DI0_PIN2__IPU1_DI0_PIN2,
- MX6_PAD_DI0_PIN3__IPU1_DI0_PIN3,
- MX6_PAD_DI0_PIN4__GPIO_4_20,
- MX6_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
- MX6_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
- MX6_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
- MX6_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
- MX6_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
- MX6_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
- MX6_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
- MX6_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
- MX6_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
- MX6_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
- MX6_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
- MX6_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
- MX6_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
- MX6_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
- MX6_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
- MX6_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
- MX6_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
- MX6_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
- MX6_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
- MX6_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
- MX6_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
- MX6_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
- MX6_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
- MX6_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+ MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02,
+ MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03,
+ MX6_PAD_DI0_PIN4__GPIO4_IO20,
+ MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00,
+ MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01,
+ MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02,
+ MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03,
+ MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04,
+ MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05,
+ MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06,
+ MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07,
+ MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08,
+ MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09,
+ MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10,
+ MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11,
+ MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12,
+ MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13,
+ MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14,
+ MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15,
+ MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16,
+ MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17,
+ MX6_PAD_DISP0_DAT18__IPU1_DISP0_DATA18,
+ MX6_PAD_DISP0_DAT19__IPU1_DISP0_DATA19,
+ MX6_PAD_DISP0_DAT20__IPU1_DISP0_DATA20,
+ MX6_PAD_DISP0_DAT21__IPU1_DISP0_DATA21,
+ MX6_PAD_DISP0_DAT22__IPU1_DISP0_DATA22,
+ MX6_PAD_DISP0_DAT23__IPU1_DISP0_DATA23,
};
-struct display_info_t {
- int bus;
- int addr;
- int pixfmt;
- int (*detect)(struct display_info_t const *dev);
- void (*enable)(struct display_info_t const *dev);
- struct fb_videomode mode;
-};
-
-
-static int detect_hdmi(struct display_info_t const *dev)
-{
- struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
- return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD;
-}
-
-static void enable_hdmi(struct display_info_t const *dev)
+static void do_enable_hdmi(struct display_info_t const *dev)
{
- struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
- u8 reg;
- printf("%s: setup HDMI monitor\n", __func__);
- reg = readb(&hdmi->phy_conf0);
- reg |= HDMI_PHY_CONF0_PDZ_MASK;
- writeb(reg, &hdmi->phy_conf0);
-
- udelay(3000);
- reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
- writeb(reg, &hdmi->phy_conf0);
- udelay(3000);
- reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
- writeb(reg, &hdmi->phy_conf0);
- writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
+ imx_enable_hdmi_phy();
}
static int detect_i2c(struct display_info_t const *dev)
gpio_direction_output(LVDS_BACKLIGHT_GP, 1);
}
+static void enable_lvds_jeida(struct display_info_t const *dev)
+{
+ struct iomuxc *iomux = (struct iomuxc *)
+ IOMUXC_BASE_ADDR;
+ u32 reg = readl(&iomux->gpr[2]);
+ reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT
+ |IOMUXC_GPR2_BIT_MAPPING_CH0_JEIDA;
+ writel(reg, &iomux->gpr[2]);
+ gpio_direction_output(LVDS_BACKLIGHT_GP, 1);
+}
+
static void enable_rgb(struct display_info_t const *dev)
{
imx_iomux_v3_setup_multiple_pads(
gpio_direction_output(RGB_BACKLIGHT_GP, 1);
}
-static struct display_info_t const displays[] = {{
- .bus = -1,
- .addr = 0,
+struct display_info_t const displays[] = {{
+ .bus = 1,
+ .addr = 0x50,
.pixfmt = IPU_PIX_FMT_RGB24,
- .detect = detect_hdmi,
- .enable = enable_hdmi,
+ .detect = detect_i2c,
+ .enable = do_enable_hdmi,
.mode = {
.name = "HDMI",
.refresh = 60,
.vsync_len = 10,
.sync = FB_SYNC_EXT,
.vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = NULL,
+ .enable = enable_lvds_jeida,
+ .mode = {
+ .name = "LDB-WXGA",
+ .refresh = 60,
+ .xres = 1280,
+ .yres = 800,
+ .pixclock = 14065,
+ .left_margin = 40,
+ .right_margin = 40,
+ .upper_margin = 3,
+ .lower_margin = 80,
+ .hsync_len = 10,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = NULL,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "LDB-WXGA-S",
+ .refresh = 60,
+ .xres = 1280,
+ .yres = 800,
+ .pixclock = 14065,
+ .left_margin = 40,
+ .right_margin = 40,
+ .upper_margin = 3,
+ .lower_margin = 80,
+ .hsync_len = 10,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
} }, {
.bus = 2,
.addr = 0x4,
.vsync_len = 10,
.sync = FB_SYNC_EXT,
.vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_LVDS666,
+ .detect = NULL,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "LG-9.7",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385, /* ~65MHz */
+ .left_margin = 480,
+ .right_margin = 260,
+ .upper_margin = 16,
+ .lower_margin = 6,
+ .hsync_len = 250,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
} }, {
.bus = 2,
.addr = 0x38,
.vsync_len = 10,
.sync = FB_SYNC_EXT,
.vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 2,
+ .addr = 0x10,
+ .pixfmt = IPU_PIX_FMT_RGB666,
+ .detect = detect_i2c,
+ .enable = enable_rgb,
+ .mode = {
+ .name = "fusion7",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 33898,
+ .left_margin = 96,
+ .right_margin = 24,
+ .upper_margin = 3,
+ .lower_margin = 10,
+ .hsync_len = 72,
+ .vsync_len = 7,
+ .sync = 0x40000002,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB666,
+ .detect = NULL,
+ .enable = enable_rgb,
+ .mode = {
+ .name = "svga",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 2,
+ .addr = 0x41,
+ .pixfmt = IPU_PIX_FMT_LVDS666,
+ .detect = detect_i2c,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "amp1024x600",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 600,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_LVDS666,
+ .detect = 0,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "wvga-lvds",
+ .refresh = 57,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
} }, {
.bus = 2,
.addr = 0x48,
.vsync_len = 10,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = NULL,
+ .enable = enable_rgb,
+ .mode = {
+ .name = "qvga",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = 37037,
+ .left_margin = 38,
+ .right_margin = 37,
+ .upper_margin = 16,
+ .lower_margin = 15,
+ .hsync_len = 30,
+ .vsync_len = 3,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
} } };
+size_t display_count = ARRAY_SIZE(displays);
-int board_video_skip(void)
+int board_cfb_skip(void)
{
- int i;
- int ret;
- char const *panel = getenv("panel");
- if (!panel) {
- for (i = 0; i < ARRAY_SIZE(displays); i++) {
- struct display_info_t const *dev = displays+i;
- if (dev->detect(dev)) {
- panel = dev->mode.name;
- printf("auto-detected panel %s\n", panel);
- break;
- }
- }
- if (!panel) {
- panel = displays[0].mode.name;
- printf("No panel detected: default to %s\n", panel);
- }
- } else {
- for (i = 0; i < ARRAY_SIZE(displays); i++) {
- if (!strcmp(panel, displays[i].mode.name))
- break;
- }
- }
- if (i < ARRAY_SIZE(displays)) {
- ret = ipuv3_fb_init(&displays[i].mode, 0,
- displays[i].pixfmt);
- if (!ret) {
- displays[i].enable(displays+i);
- printf("Display: %s (%ux%u)\n",
- displays[i].mode.name,
- displays[i].mode.xres,
- displays[i].mode.yres);
- } else
- printf("LCD %s cannot be configured: %d\n",
- displays[i].mode.name, ret);
- } else {
- printf("unsupported panel %s\n", panel);
- ret = -EINVAL;
- }
- return (0 != ret);
+ return NULL != getenv("novideo");
}
static void setup_display(void)
{
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
- struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
- struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
-
int reg;
+ enable_ipu_clock();
+ imx_setup_hdmi();
/* Turn on LDB0,IPU,IPU DI0 clocks */
reg = __raw_readl(&mxc_ccm->CCGR3);
- reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET
- |MXC_CCM_CCGR3_LDB_DI0_MASK;
+ reg |= MXC_CCM_CCGR3_LDB_DI0_MASK;
writel(reg, &mxc_ccm->CCGR3);
- /* Turn on HDMI PHY clock */
- reg = __raw_readl(&mxc_ccm->CCGR2);
- reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
- |MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
- writel(reg, &mxc_ccm->CCGR2);
-
- /* clear HDMI PHY reset */
- writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
-
- /* set PFD1_FRAC to 0x13 == 455 MHz (480*18)/0x13 */
- writel(ANATOP_PFD_480_PFD1_FRAC_MASK, &anatop->pfd_480_clr);
- writel(0x13<<ANATOP_PFD_480_PFD1_FRAC_SHIFT, &anatop->pfd_480_set);
-
/* set LDB0, LDB1 clk select to 011/011 */
reg = readl(&mxc_ccm->cs2cdr);
reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
writel(reg, &mxc_ccm->cscmr2);
reg = readl(&mxc_ccm->chsccdr);
- reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK
- |MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK
- |MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
reg |= (CHSCCDR_CLK_SEL_LDB_DI0
- <<MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)
- |(CHSCCDR_PODF_DIVIDE_BY_3
- <<MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
- |(CHSCCDR_IPU_PRE_CLK_540M_PFD
- <<MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+ <<MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
writel(reg, &mxc_ccm->chsccdr);
reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
writel(reg, &iomux->gpr[2]);
reg = readl(&iomux->gpr[3]);
- reg = (reg & ~IOMUXC_GPR3_LVDS0_MUX_CTL_MASK)
+ reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK
+ |IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
| (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
<<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
writel(reg, &iomux->gpr[3]);
}
#endif
+static iomux_v3_cfg_t const init_pads[] = {
+ /* SGTL5000 sys_mclk */
+ NEW_PAD_CTRL(MX6_PAD_GPIO_0__CCM_CLKO1, OUTPUT_40OHM),
+
+ /* J5 - Camera MCLK */
+ NEW_PAD_CTRL(MX6_PAD_GPIO_3__CCM_CLKO2, OUTPUT_40OHM),
+
+ /* wl1271 pads on nitrogen6x */
+ /* WL12XX_WL_IRQ_GP */
+ NEW_PAD_CTRL(MX6_PAD_NANDF_CS1__GPIO6_IO14, WEAK_PULLDOWN),
+ /* WL12XX_WL_ENABLE_GP */
+ NEW_PAD_CTRL(MX6_PAD_NANDF_CS2__GPIO6_IO15, OUTPUT_40OHM),
+ /* WL12XX_BT_ENABLE_GP */
+ NEW_PAD_CTRL(MX6_PAD_NANDF_CS3__GPIO6_IO16, OUTPUT_40OHM),
+ /* USB otg power */
+ NEW_PAD_CTRL(MX6_PAD_EIM_D22__GPIO3_IO22, OUTPUT_40OHM),
+ NEW_PAD_CTRL(MX6_PAD_NANDF_D5__GPIO2_IO05, OUTPUT_40OHM),
+ NEW_PAD_CTRL(MX6_PAD_NANDF_WP_B__GPIO6_IO09, OUTPUT_40OHM),
+ NEW_PAD_CTRL(MX6_PAD_GPIO_8__GPIO1_IO08, OUTPUT_40OHM),
+ NEW_PAD_CTRL(MX6_PAD_GPIO_6__GPIO1_IO06, OUTPUT_40OHM),
+};
+
+#define WL12XX_WL_IRQ_GP IMX_GPIO_NR(6, 14)
+
+static unsigned gpios_out_low[] = {
+ /* Disable wl1271 */
+ IMX_GPIO_NR(6, 15), /* disable wireless */
+ IMX_GPIO_NR(6, 16), /* disable bluetooth */
+ IMX_GPIO_NR(3, 22), /* disable USB otg power */
+ IMX_GPIO_NR(2, 5), /* ov5640 mipi camera reset */
+ IMX_GPIO_NR(1, 8), /* ov5642 reset */
+};
+
+static unsigned gpios_out_high[] = {
+ IMX_GPIO_NR(1, 6), /* ov5642 powerdown */
+ IMX_GPIO_NR(6, 9), /* ov5640 mipi camera power down */
+};
+
+static void set_gpios(unsigned *p, int cnt, int val)
+{
+ int i;
+
+ for (i = 0; i < cnt; i++)
+ gpio_direction_output(*p++, val);
+}
+
int board_early_init_f(void)
{
setup_iomux_uart();
- /* Disable wl1271 For Nitrogen6w */
+ set_gpios(gpios_out_high, ARRAY_SIZE(gpios_out_high), 1);
+ set_gpios(gpios_out_low, ARRAY_SIZE(gpios_out_low), 0);
gpio_direction_input(WL12XX_WL_IRQ_GP);
- gpio_direction_output(WL12XX_WL_ENABLE_GP, 0);
- gpio_direction_output(WL12XX_BT_ENABLE_GP, 0);
imx_iomux_v3_setup_multiple_pads(wl12xx_pads, ARRAY_SIZE(wl12xx_pads));
+ imx_iomux_v3_setup_multiple_pads(init_pads, ARRAY_SIZE(init_pads));
setup_buttons();
#if defined(CONFIG_VIDEO_IPUV3)
int board_init(void)
{
+ struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+ clrsetbits_le32(&iomuxc_regs->gpr[1],
+ IOMUXC_GPR1_OTG_ID_MASK,
+ IOMUXC_GPR1_OTG_ID_GPIO1);
+
+ imx_iomux_v3_setup_multiple_pads(misc_pads, ARRAY_SIZE(misc_pads));
+
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
#ifdef CONFIG_MXC_SPI
setup_spi();
#endif
+ imx_iomux_v3_setup_multiple_pads(
+ usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
* Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
* Leo Sartre, <lsartre@adeneo-embedded.com>
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
}
iomux_v3_cfg_t const uart2_pads[] = {
- MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
iomux_v3_cfg_t const usdhc2_pads[] = {
- MX6_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_GPIO_4__GPIO_1_4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_GPIO_4__GPIO1_IO04 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
iomux_v3_cfg_t const usdhc4_pads[] = {
- MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D6__GPIO_2_6, /* CD */
+ MX6_PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D6__GPIO2_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
++ MX6_PAD_NANDF_D6__GPIO2_IO06, /* CD */
};
static void setup_iomux_uart(void)
(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
};
-void board_init_ll(void)
+void board_init_ll(const uint32_t arg, const uint32_t *resptr)
{
- mxs_common_spl_init(iomux_setup, ARRAY_SIZE(iomux_setup));
+ mxs_common_spl_init(arg, resptr, iomux_setup, ARRAY_SIZE(iomux_setup));
}
+
+ static uint32_t dram_vals[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
+ 0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
+ 0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+ 0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
+ 0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
+ 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
+ 0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
+ 0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
+ 0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+ 0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
+ 0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
+ 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
+ 0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+ 0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
+ };
+
+ void mx28_ddr2_setup(void)
+ {
+ int i;
+
+ serial_puts("\n");
+ for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+ writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+ }
#include <common.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
-#include <asm/arch/mx6q_pins.h>
+#include <asm/arch/mx6-pins.h>
#include <asm/arch/clock.h>
#include <asm/errno.h>
#include <asm/gpio.h>
#include <fsl_esdhc.h>
#include <miiphy.h>
#include <netdev.h>
+#include <usb.h>
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
- gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+#if defined(CONFIG_MX6DL) && !defined(CONFIG_MX6DL_LPDDR2) && \
+ defined(CONFIG_DDR_32BIT)
+ gd->ram_size = ((phys_size_t)CONFIG_DDR_MB * 1024 * 1024) / 2;
+#else
+ gd->ram_size = (phys_size_t)CONFIG_DDR_MB * 1024 * 1024;
+#endif
return 0;
}
iomux_v3_cfg_t const uart4_pads[] = {
- MX6_PAD_KEY_COL0__UART4_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_KEY_ROW0__UART4_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
iomux_v3_cfg_t const usdhc3_pads[] = {
- MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_CS0__GPIO_6_11, /* CD */
+ MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_CS0__GPIO6_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
++ MX6_PAD_NANDF_CS0__GPIO6_IO11, /* CD */
};
iomux_v3_cfg_t const usdhc4_pads[] = {
- MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_KEY_COL1__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_COL2__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
int board_mmc_init(bd_t *bis)
{
- s32 status = 0;
+ int ret;
u32 index = 0;
usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
printf("Warning: you configured more USDHC controllers"
"(%d) then supported by the board (%d)\n",
index + 1, CONFIG_SYS_FSL_USDHC_NUM);
- return status;
+ return -EINVAL;
}
- status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ ret = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ if (ret)
+ return ret;
}
- return status;
+ return 0;
}
#endif
int board_eth_init(bd_t *bis)
{
struct eth_device *dev;
- int ret;
+ int ret = cpu_eth_init(bis);
- ret = cpu_eth_init(bis);
- if (ret) {
- printf("FEC MXC: %s:failed\n", __func__);
+ if (ret)
return ret;
- }
dev = eth_get_dev_by_name("FEC");
if (!dev) {
return 0;
}
- MX6_PAD_EIM_D22__USB_OTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
+#ifdef CONFIG_USB_EHCI_MX6
+#define USB_OTHERREGS_OFFSET 0x800
+#define UCTRL_PWR_POL (1 << 9)
+
+static iomux_v3_cfg_t const usb_otg_pads[] = {
++ MX6_PAD_EIM_D22__USB_OTG_PWR,
++ MX6_PAD_GPIO_1__USB_OTG_ID,
+};
+
+static void setup_usb(void)
+{
+ imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
+ ARRAY_SIZE(usb_otg_pads));
+
+ /*
+ * set daisy chain for otg_pin_id on 6q.
+ * for 6dl, this bit is reserved
+ */
+ imx_iomux_set_gpr_register(1, 13, 1, 1);
+}
+
+int board_ehci_hcd_init(int port)
+{
+ u32 *usbnc_usb_ctrl;
+
+ if (port > 0)
+ return -EINVAL;
+
+ usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
+ port * 4);
+
+ setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
+
+ return 0;
+}
+#endif
+
int board_early_init_f(void)
{
setup_iomux_uart();
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+#ifdef CONFIG_USB_EHCI_MX6
+ setup_usb();
+#endif
+
return 0;
}
int checkboard(void)
{
+#ifdef CONFIG_MX6DL
+ puts("Board: MX6DL-Armadillo2\n");
+#else
puts("Board: MX6Q-Armadillo2\n");
+#endif
return 0;
}
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/iomux.h>
-#include <asm/arch/mx6q_pins.h>
+#include <asm/arch/mx6-pins.h>
#include <asm/errno.h>
#include <asm/gpio.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm/imx-common/mxc_i2c.h>
#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/spi.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/arch/sys_proto.h>
#include <i2c.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <asm/imx-common/video.h>
+#include <asm/arch/crm_regs.h>
+#include <pca953x.h>
+#include <power/pmic.h>
+#include "../common/pfuze.h"
DECLARE_GLOBAL_DATA_PTR;
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
+#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \
+ PAD_CTL_SRE_FAST)
+#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1)
+
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+#define WEIM_NOR_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
+ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define I2C_PMIC 1
+
int dram_init(void)
{
gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
return 0;
}
-iomux_v3_cfg_t const uart4_pads[] = {
- MX6_PAD_KEY_COL0__UART4_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_KEY_ROW0__UART4_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+static iomux_v3_cfg_t const uart4_pads[] = {
+ MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
-iomux_v3_cfg_t const enet_pads[] = {
+static iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_KEY_COL1__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_COL2__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
/* I2C2 PMIC, iPod, Tuner, Codec, Touch, HDMI EDID, MIPI CSI2 card */
-struct i2c_pads_info i2c_pad_info1 = {
+static struct i2c_pads_info i2c_pad_info1 = {
.scl = {
.i2c_mode = MX6_PAD_EIM_EB2__I2C2_SCL | PC,
- .gpio_mode = MX6_PAD_EIM_EB2__GPIO_2_30 | PC,
+ .gpio_mode = MX6_PAD_EIM_EB2__GPIO2_IO30 | PC,
.gp = IMX_GPIO_NR(2, 30)
},
.sda = {
.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
- .gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
+ .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | PC,
.gp = IMX_GPIO_NR(4, 13)
}
};
+#ifndef CONFIG_SYS_FLASH_CFI
/*
* I2C3 MLB, Port Expanders (A, B, C), Video ADC, Light Sensor,
* Compass Sensor, Accelerometer, Res Touch
*/
-struct i2c_pads_info i2c_pad_info2 = {
+static struct i2c_pads_info i2c_pad_info2 = {
.scl = {
.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
- .gpio_mode = MX6_PAD_GPIO_3__GPIO_1_3 | PC,
+ .gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03 | PC,
.gp = IMX_GPIO_NR(1, 3)
},
.sda = {
.i2c_mode = MX6_PAD_EIM_D18__I2C3_SDA | PC,
- .gpio_mode = MX6_PAD_EIM_D18__GPIO_3_18 | PC,
+ .gpio_mode = MX6_PAD_EIM_D18__GPIO3_IO18 | PC,
.gp = IMX_GPIO_NR(3, 18)
}
};
- MX6_PAD_EIM_A24__GPIO5_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
+#endif
+
+static iomux_v3_cfg_t const i2c3_pads[] = {
++ MX6_PAD_EIM_A24__GPIO5_IO04,
+};
-iomux_v3_cfg_t const i2c3_pads[] = {
- MX6_PAD_EIM_A24__GPIO_5_4,
+static iomux_v3_cfg_t const port_exp[] = {
- MX6_PAD_SD2_DAT0__GPIO1_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_SD2_DAT0__GPIO1_IO15,
};
-iomux_v3_cfg_t const port_exp[] = {
- MX6_PAD_SD2_DAT0__GPIO_1_15,
+/*Define for building port exp gpio, pin starts from 0*/
+#define PORTEXP_IO_NR(chip, pin) \
+ ((chip << 5) + pin)
+
+/*Get the chip addr from a ioexp gpio*/
+#define PORTEXP_IO_TO_CHIP(gpio_nr) \
+ (gpio_nr >> 5)
+
+/*Get the pin number from a ioexp gpio*/
+#define PORTEXP_IO_TO_PIN(gpio_nr) \
+ (gpio_nr & 0x1f)
+
+static int port_exp_direction_output(unsigned gpio, int value)
+{
+ int ret;
+
+ i2c_set_bus_num(2);
+ ret = i2c_probe(PORTEXP_IO_TO_CHIP(gpio));
+ if (ret)
+ return ret;
+
+ ret = pca953x_set_dir(PORTEXP_IO_TO_CHIP(gpio),
+ (1 << PORTEXP_IO_TO_PIN(gpio)),
+ (PCA953X_DIR_OUT << PORTEXP_IO_TO_PIN(gpio)));
+
+ if (ret)
+ return ret;
+
+ ret = pca953x_set_val(PORTEXP_IO_TO_CHIP(gpio),
+ (1 << PORTEXP_IO_TO_PIN(gpio)),
+ (value << PORTEXP_IO_TO_PIN(gpio)));
+
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static iomux_v3_cfg_t const eimnor_pads[] = {
+ MX6_PAD_EIM_D16__EIM_DATA16 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D17__EIM_DATA17 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D18__EIM_DATA18 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D19__EIM_DATA19 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D20__EIM_DATA20 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D21__EIM_DATA21 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D22__EIM_DATA22 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D23__EIM_DATA23 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D24__EIM_DATA24 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D25__EIM_DATA25 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D26__EIM_DATA26 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D27__EIM_DATA27 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D28__EIM_DATA28 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D29__EIM_DATA29 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D30__EIM_DATA30 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_D31__EIM_DATA31 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA0__EIM_AD00 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA1__EIM_AD01 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA2__EIM_AD02 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA3__EIM_AD03 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA4__EIM_AD04 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA5__EIM_AD05 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA6__EIM_AD06 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA7__EIM_AD07 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA8__EIM_AD08 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA9__EIM_AD09 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA10__EIM_AD10 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA11__EIM_AD11 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL) ,
+ MX6_PAD_EIM_DA12__EIM_AD12 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA13__EIM_AD13 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA14__EIM_AD14 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_DA15__EIM_AD15 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A16__EIM_ADDR16 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A17__EIM_ADDR17 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A18__EIM_ADDR18 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A19__EIM_ADDR19 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A20__EIM_ADDR20 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A21__EIM_ADDR21 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A22__EIM_ADDR22 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
+ MX6_PAD_EIM_A23__EIM_ADDR23 | MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL),
- MX6_PAD_EIM_OE__EIM_OE_B | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_EIM_RW__EIM_RW | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_EIM_CS0__EIM_CS0_B | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_EIM_OE__EIM_OE_B,
++ MX6_PAD_EIM_RW__EIM_RW,
++ MX6_PAD_EIM_CS0__EIM_CS0_B,
};
+static void eimnor_cs_setup(void)
+{
+ struct weim *weim_regs = (struct weim *)WEIM_BASE_ADDR;
+
+ writel(0x00020181, &weim_regs->cs0gcr1);
+ writel(0x00000001, &weim_regs->cs0gcr2);
+ writel(0x0a020000, &weim_regs->cs0rcr1);
+ writel(0x0000c000, &weim_regs->cs0rcr2);
+ writel(0x0804a240, &weim_regs->cs0wcr1);
+ writel(0x00000120, &weim_regs->wcr);
+
+ set_chipselect_size(CS0_128);
+}
+
+static void setup_iomux_eimnor(void)
+{
+ imx_iomux_v3_setup_multiple_pads(eimnor_pads, ARRAY_SIZE(eimnor_pads));
+
+ gpio_direction_output(IMX_GPIO_NR(5, 4), 0);
+
+ eimnor_cs_setup();
+}
+
static void setup_iomux_enet(void)
{
imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
}
-iomux_v3_cfg_t const usdhc3_pads[] = {
- MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_GPIO_18__USDHC3_VSELECT | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_CS2__GPIO_6_15,
+static iomux_v3_cfg_t const usdhc3_pads[] = {
+ MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_GPIO_18__SD3_VSELECT | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_CS2__GPIO6_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_NANDF_CS2__GPIO6_IO15,
};
static void setup_iomux_uart(void)
}
#ifdef CONFIG_FSL_ESDHC
-struct fsl_esdhc_cfg usdhc_cfg[1] = {
+static struct fsl_esdhc_cfg usdhc_cfg[1] = {
{USDHC3_BASE_ADDR},
};
}
#endif
+#ifdef CONFIG_NAND_MXS
+static iomux_v3_cfg_t gpmi_pads[] = {
+ MX6_PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_WP_B__NAND_WP_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(GPMI_PAD_CTRL0),
+ MX6_PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
+ MX6_PAD_SD4_DAT0__NAND_DQS | MUX_PAD_CTRL(GPMI_PAD_CTRL1),
+};
+
+static void setup_gpmi_nand(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ /* config gpmi nand iomux */
+ imx_iomux_v3_setup_multiple_pads(gpmi_pads, ARRAY_SIZE(gpmi_pads));
+
+ /* gate ENFC_CLK_ROOT clock first,before clk source switch */
+ clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
+ clrbits_le32(&mxc_ccm->CCGR4,
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
+
+ /* config gpmi and bch clock to 100 MHz */
+ clrsetbits_le32(&mxc_ccm->cs2cdr,
+ MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
+ MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
+ MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+ MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
+
+ /* enable ENFC_CLK_ROOT clock */
+ setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
+
+ /* enable gpmi and bch clock gating */
+ setbits_le32(&mxc_ccm->CCGR4,
+ MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+
+ /* enable apbh clock gating */
+ setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
+}
+#endif
+
int mx6_rgmii_rework(struct phy_device *phydev)
{
unsigned short val;
int board_eth_init(bd_t *bis)
{
- int ret;
-
setup_iomux_enet();
- ret = cpu_eth_init(bis);
- if (ret)
- printf("FEC MXC: %s:failed\n", __func__);
-
- return 0;
+ return cpu_eth_init(bis);
}
#define BOARD_REV_B 0x200
return (get_cpu_rev() & ~(0xF << 8)) | rev;
}
+#if defined(CONFIG_VIDEO_IPUV3)
+static void do_enable_hdmi(struct display_info_t const *dev)
+{
+ imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {{
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = detect_hdmi,
+ .enable = do_enable_hdmi,
+ .mode = {
+ .name = "HDMI",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED,
+} } };
+size_t display_count = ARRAY_SIZE(displays);
+
+static void setup_display(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ int reg;
+
+ enable_ipu_clock();
+ imx_setup_hdmi();
+
+ reg = readl(&mxc_ccm->chsccdr);
+ reg |= (CHSCCDR_CLK_SEL_LDB_DI0
+ << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+ writel(reg, &mxc_ccm->chsccdr);
+}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
+/*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+int overwrite_console(void)
+{
+ return 1;
+}
+
int board_early_init_f(void)
{
setup_iomux_uart();
+#ifdef CONFIG_VIDEO_IPUV3
+ setup_display();
+#endif
+
+#ifdef CONFIG_NAND_MXS
+ setup_gpmi_nand();
+#endif
return 0;
}
/* I2C 3 Steer */
gpio_direction_output(IMX_GPIO_NR(5, 4), 1);
imx_iomux_v3_setup_multiple_pads(i2c3_pads, ARRAY_SIZE(i2c3_pads));
+#ifndef CONFIG_SYS_FLASH_CFI
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
-
+#endif
gpio_direction_output(IMX_GPIO_NR(1, 15), 1);
imx_iomux_v3_setup_multiple_pads(port_exp, ARRAY_SIZE(port_exp));
+ setup_iomux_eimnor();
+ return 0;
+}
+
+#ifdef CONFIG_MXC_SPI
+int board_spi_cs_gpio(unsigned bus, unsigned cs)
+{
+ return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
+}
+#endif
+
+int power_init_board(void)
+{
+ struct pmic *p;
+
+ p = pfuze_common_init(I2C_PMIC);
+ if (!p)
+ return -ENODEV;
+
return 0;
}
return 0;
}
- MX6_PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
+
+#ifdef CONFIG_USB_EHCI_MX6
+#define USB_HOST1_PWR PORTEXP_IO_NR(0x32, 7)
+#define USB_OTG_PWR PORTEXP_IO_NR(0x34, 1)
+
+iomux_v3_cfg_t const usb_otg_pads[] = {
++ MX6_PAD_ENET_RX_ER__USB_OTG_ID,
+};
+
+int board_ehci_hcd_init(int port)
+{
+ switch (port) {
+ case 0:
+ imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
+ ARRAY_SIZE(usb_otg_pads));
+
+ /*
+ * Set daisy chain for otg_pin_id on 6q.
+ * For 6dl, this bit is reserved.
+ */
+ imx_iomux_set_gpr_register(1, 13, 1, 0);
+ break;
+ case 1:
+ break;
+ default:
+ printf("MXC USB port %d not yet supported\n", port);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int board_ehci_power(int port, int on)
+{
+ switch (port) {
+ case 0:
+ if (on)
+ port_exp_direction_output(USB_OTG_PWR, 1);
+ else
+ port_exp_direction_output(USB_OTG_PWR, 0);
+ break;
+ case 1:
+ if (on)
+ port_exp_direction_output(USB_HOST1_PWR, 1);
+ else
+ port_exp_direction_output(USB_HOST1_PWR, 0);
+ break;
+ default:
+ printf("MXC USB port %d not yet supported\n", port);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
--- /dev/null
- struct iomuxc_base_regs *const iomuxc_regs
- = (struct iomuxc_base_regs *) IOMUXC_BASE_ADDR;
+ /*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+ #include <common.h>
+ #include <asm/io.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/iomux.h>
+ #include <asm/arch/mx6q_pins.h>
+ #include <asm/errno.h>
+ #include <asm/gpio.h>
+ #include <asm/imx-common/iomux-v3.h>
+ #include <asm/imx-common/mxc_i2c.h>
+ #include <asm/imx-common/boot_mode.h>
+ #include <mmc.h>
+ #include <fsl_esdhc.h>
+ #include <malloc.h>
+ #include <micrel.h>
+ #include <miiphy.h>
+ #include <netdev.h>
+ #include <linux/fb.h>
+ #include <ipu_pixfmt.h>
+ #include <asm/arch/crm_regs.h>
+ #include <asm/arch/mxc_hdmi.h>
+ #include <i2c.h>
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
+ PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+
+ #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
+ PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
+ PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+
+ #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+ #define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+ #define BUTTON_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+ #define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
+ PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+
+ int dram_init(void)
+ {
+ gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+ return 0;
+ }
+
+ iomux_v3_cfg_t const uart1_pads[] = {
+ MX6_PAD_SD3_DAT6__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_SD3_DAT7__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ };
+
+ iomux_v3_cfg_t const uart2_pads[] = {
+ MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ };
+
+ #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+ /* I2C1, SGTL5000 */
+ struct i2c_pads_info i2c_pad_info0 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
+ .gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC,
+ .gp = IMX_GPIO_NR(3, 21)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
+ .gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC,
+ .gp = IMX_GPIO_NR(3, 28)
+ }
+ };
+
+ /* I2C2 Camera, MIPI */
+ struct i2c_pads_info i2c_pad_info1 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
+ .gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC,
+ .gp = IMX_GPIO_NR(4, 12)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
+ .gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
+ .gp = IMX_GPIO_NR(4, 13)
+ }
+ };
+
+ /* I2C3, J15 - RGB connector */
+ struct i2c_pads_info i2c_pad_info2 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_GPIO_5__I2C3_SCL | PC,
+ .gpio_mode = MX6_PAD_GPIO_5__GPIO_1_5 | PC,
+ .gp = IMX_GPIO_NR(1, 5)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_GPIO_16__I2C3_SDA | PC,
+ .gpio_mode = MX6_PAD_GPIO_16__GPIO_7_11 | PC,
+ .gp = IMX_GPIO_NR(7, 11)
+ }
+ };
+
+ iomux_v3_cfg_t const usdhc3_pads[] = {
+ MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT5__GPIO_7_0, /* CD */
+ };
+
+ iomux_v3_cfg_t const usdhc4_pads[] = {
+ MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_NANDF_D6__GPIO_2_6, /* CD */
+ };
+
+ iomux_v3_cfg_t const enet_pads1[] = {
+ MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ /* pin 35 - 1 (PHY_AD2) on reset */
+ MX6_PAD_RGMII_RXC__GPIO_6_30,
+ /* pin 32 - 1 - (MODE0) all */
+ MX6_PAD_RGMII_RD0__GPIO_6_25,
+ /* pin 31 - 1 - (MODE1) all */
+ MX6_PAD_RGMII_RD1__GPIO_6_27,
+ /* pin 28 - 1 - (MODE2) all */
+ MX6_PAD_RGMII_RD2__GPIO_6_28,
+ /* pin 27 - 1 - (MODE3) all */
+ MX6_PAD_RGMII_RD3__GPIO_6_29,
+ /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
+ MX6_PAD_RGMII_RX_CTL__GPIO_6_24,
+ /* pin 42 PHY nRST */
+ MX6_PAD_EIM_D23__GPIO_3_23,
+ };
+
+ iomux_v3_cfg_t const enet_pads2[] = {
+ MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ };
+
+ /* Button assignments for J14 */
+ static iomux_v3_cfg_t const button_pads[] = {
+ /* Menu */
+ MX6_PAD_NANDF_D1__GPIO_2_1 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ /* Back */
+ MX6_PAD_NANDF_D2__GPIO_2_2 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ /* Labelled Search (mapped to Power under Android) */
+ MX6_PAD_NANDF_D3__GPIO_2_3 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ /* Home */
+ MX6_PAD_NANDF_D4__GPIO_2_4 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ /* Volume Down */
+ MX6_PAD_GPIO_19__GPIO_4_5 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ /* Volume Up */
+ MX6_PAD_GPIO_18__GPIO_7_13 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+ };
+
+ static void setup_iomux_enet(void)
+ {
+ gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+ gpio_direction_output(IMX_GPIO_NR(6, 30), 1);
+ gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
+ gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
+ gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
+ gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
+ imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1));
+ gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
+
+ /* Need delay 10ms according to KSZ9021 spec */
+ udelay(1000 * 10);
+ gpio_set_value(IMX_GPIO_NR(3, 23), 1);
+
+ imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
+ }
+
+ iomux_v3_cfg_t const usb_pads[] = {
+ MX6_PAD_GPIO_17__GPIO_7_12,
+ };
+
+ static void setup_iomux_uart(void)
+ {
+ imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+ imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+ }
+
+ #ifdef CONFIG_USB_EHCI_MX6
+ int board_ehci_hcd_init(int port)
+ {
+ imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads));
+
+ /* Reset USB hub */
+ gpio_direction_output(IMX_GPIO_NR(7, 12), 0);
+ mdelay(2);
+ gpio_set_value(IMX_GPIO_NR(7, 12), 1);
+
+ return 0;
+ }
+ #endif
+
+ #ifdef CONFIG_FSL_ESDHC
+ struct fsl_esdhc_cfg usdhc_cfg[2] = {
+ {USDHC3_BASE_ADDR},
+ {USDHC4_BASE_ADDR},
+ };
+
+ int board_mmc_getcd(struct mmc *mmc)
+ {
+ struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+ int ret;
+
+ if (cfg->esdhc_base == USDHC3_BASE_ADDR) {
+ gpio_direction_input(IMX_GPIO_NR(7, 0));
+ ret = !gpio_get_value(IMX_GPIO_NR(7, 0));
+ } else {
+ gpio_direction_input(IMX_GPIO_NR(2, 6));
+ ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
+ }
+
+ return ret;
+ }
+
+ int board_mmc_init(bd_t *bis)
+ {
+ s32 status = 0;
+ u32 index = 0;
+
+ usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+ usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+
+ usdhc_cfg[0].max_bus_width = 4;
+ usdhc_cfg[1].max_bus_width = 4;
+
+ for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
+ switch (index) {
+ case 0:
+ imx_iomux_v3_setup_multiple_pads(
+ usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+ break;
+ case 1:
+ imx_iomux_v3_setup_multiple_pads(
+ usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+ break;
+ default:
+ printf("Warning: you configured more USDHC controllers"
+ "(%d) then supported by the board (%d)\n",
+ index + 1, CONFIG_SYS_FSL_USDHC_NUM);
+ return status;
+ }
+
+ status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ }
+
+ return status;
+ }
+ #endif
+
+ #ifdef CONFIG_MXC_SPI
+ iomux_v3_cfg_t const ecspi1_pads[] = {
+ /* SS1 */
+ MX6_PAD_EIM_D19__GPIO_3_19 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ };
+
+ void setup_spi(void)
+ {
+ imx_iomux_v3_setup_multiple_pads(ecspi1_pads,
+ ARRAY_SIZE(ecspi1_pads));
+ }
+ #endif
+
+ int board_phy_config(struct phy_device *phydev)
+ {
+ /* min rx data delay */
+ ksz9021_phy_extended_write(phydev,
+ MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0);
+ /* min tx data delay */
+ ksz9021_phy_extended_write(phydev,
+ MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0);
+ /* max rx/tx clock delay, min rx/tx control */
+ ksz9021_phy_extended_write(phydev,
+ MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0);
+ if (phydev->drv->config)
+ phydev->drv->config(phydev);
+
+ return 0;
+ }
+
+ int board_eth_init(bd_t *bis)
+ {
+ uint32_t base = IMX_FEC_BASE;
+ struct mii_dev *bus = NULL;
+ struct phy_device *phydev = NULL;
+ int ret;
+
+ setup_iomux_enet();
+
+ #ifdef CONFIG_FEC_MXC
+ bus = fec_get_miibus(base, -1);
+ if (!bus)
+ return 0;
+ /* scan phy 4,5,6,7 */
+ phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
+ if (!phydev) {
+ free(bus);
+ return 0;
+ }
+ printf("using phy at %d\n", phydev->addr);
+ ret = fec_probe(bis, -1, base, bus, phydev);
+ if (ret) {
+ printf("FEC MXC: %s:failed\n", __func__);
+ free(phydev);
+ free(bus);
+ }
+ #endif
+ return 0;
+ }
+
+ static void setup_buttons(void)
+ {
+ imx_iomux_v3_setup_multiple_pads(button_pads,
+ ARRAY_SIZE(button_pads));
+ }
+
+ #ifdef CONFIG_CMD_SATA
+
+ int setup_sata(void)
+ {
++ struct iomuxc *const iomuxc_regs = (void *)IOMUXC_BASE_ADDR;
+ int ret = enable_sata_clock();
++
+ if (ret)
+ return ret;
+
+ clrsetbits_le32(&iomuxc_regs->gpr[13],
+ IOMUXC_GPR13_SATA_MASK,
+ IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
+ |IOMUXC_GPR13_SATA_PHY_7_SATA2M
+ |IOMUXC_GPR13_SATA_SPEED_3G
+ |(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
+ |IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
+ |IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
+ |IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
+ |IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
+ |IOMUXC_GPR13_SATA_PHY_1_SLOW);
+
+ return 0;
+ }
+ #endif
+
+ #if defined(CONFIG_VIDEO_IPUV3)
+
+ static iomux_v3_cfg_t const backlight_pads[] = {
+ /* Backlight on RGB connector: J15 */
+ MX6_PAD_SD1_DAT3__GPIO_1_21,
+ #define RGB_BACKLIGHT_GP IMX_GPIO_NR(1, 21)
+
+ /* Backlight on LVDS connector: J6 */
+ MX6_PAD_SD1_CMD__GPIO_1_18,
+ #define LVDS_BACKLIGHT_GP IMX_GPIO_NR(1, 18)
+ };
+
+ static iomux_v3_cfg_t const rgb_pads[] = {
+ MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15,
+ MX6_PAD_DI0_PIN2__IPU1_DI0_PIN2,
+ MX6_PAD_DI0_PIN3__IPU1_DI0_PIN3,
+ MX6_PAD_DI0_PIN4__GPIO_4_20,
+ MX6_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
+ MX6_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
+ MX6_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
+ MX6_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
+ MX6_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
+ MX6_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
+ MX6_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
+ MX6_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
+ MX6_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
+ MX6_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
+ MX6_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
+ MX6_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
+ MX6_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
+ MX6_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
+ MX6_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
+ MX6_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
+ MX6_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
+ MX6_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
+ MX6_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
+ MX6_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
+ MX6_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
+ MX6_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
+ MX6_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
+ MX6_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
+ };
+
+ struct display_info_t {
+ int bus;
+ int addr;
+ int pixfmt;
+ int (*detect)(struct display_info_t const *dev);
+ void (*enable)(struct display_info_t const *dev);
+ struct fb_videomode mode;
+ };
+
+
+ static int detect_hdmi(struct display_info_t const *dev)
+ {
+ struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+ return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD;
+ }
+
+ static void enable_hdmi(struct display_info_t const *dev)
+ {
+ struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+ u8 reg;
+ printf("%s: setup HDMI monitor\n", __func__);
+ reg = readb(&hdmi->phy_conf0);
+ reg |= HDMI_PHY_CONF0_PDZ_MASK;
+ writeb(reg, &hdmi->phy_conf0);
+
+ udelay(3000);
+ reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
+ writeb(reg, &hdmi->phy_conf0);
+ udelay(3000);
+ reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
+ writeb(reg, &hdmi->phy_conf0);
+ writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
+ }
+
+ static int detect_i2c(struct display_info_t const *dev)
+ {
+ return ((0 == i2c_set_bus_num(dev->bus))
+ &&
+ (0 == i2c_probe(dev->addr)));
+ }
+
+ static void enable_lvds(struct display_info_t const *dev)
+ {
+ struct iomuxc *iomux = (struct iomuxc *)
+ IOMUXC_BASE_ADDR;
+ u32 reg = readl(&iomux->gpr[2]);
+ reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT;
+ writel(reg, &iomux->gpr[2]);
+ gpio_direction_output(LVDS_BACKLIGHT_GP, 1);
+ }
+
+ static void enable_rgb(struct display_info_t const *dev)
+ {
+ imx_iomux_v3_setup_multiple_pads(
+ rgb_pads,
+ ARRAY_SIZE(rgb_pads));
+ gpio_direction_output(RGB_BACKLIGHT_GP, 1);
+ }
+
+ static struct display_info_t const displays[] = {{
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = detect_hdmi,
+ .enable = enable_hdmi,
+ .mode = {
+ .name = "HDMI",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+ } }, {
+ .bus = 2,
+ .addr = 0x4,
+ .pixfmt = IPU_PIX_FMT_LVDS666,
+ .detect = detect_i2c,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "Hannstar-XGA",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+ } }, {
+ .bus = 2,
+ .addr = 0x38,
+ .pixfmt = IPU_PIX_FMT_LVDS666,
+ .detect = detect_i2c,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "wsvga-lvds",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 600,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+ } }, {
+ .bus = 2,
+ .addr = 0x48,
+ .pixfmt = IPU_PIX_FMT_RGB666,
+ .detect = detect_i2c,
+ .enable = enable_rgb,
+ .mode = {
+ .name = "wvga-rgb",
+ .refresh = 57,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 37037,
+ .left_margin = 40,
+ .right_margin = 60,
+ .upper_margin = 10,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+ } } };
+
+ int board_video_skip(void)
+ {
+ int i;
+ int ret;
+ char const *panel = getenv("panel");
+ if (!panel) {
+ for (i = 0; i < ARRAY_SIZE(displays); i++) {
+ struct display_info_t const *dev = displays+i;
+ if (dev->detect(dev)) {
+ panel = dev->mode.name;
+ printf("auto-detected panel %s\n", panel);
+ break;
+ }
+ }
+ if (!panel) {
+ panel = displays[0].mode.name;
+ printf("No panel detected: default to %s\n", panel);
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(displays); i++) {
+ if (!strcmp(panel, displays[i].mode.name))
+ break;
+ }
+ }
+ if (i < ARRAY_SIZE(displays)) {
+ ret = ipuv3_fb_init(&displays[i].mode, 0,
+ displays[i].pixfmt);
+ if (!ret) {
+ displays[i].enable(displays+i);
+ printf("Display: %s (%ux%u)\n",
+ displays[i].mode.name,
+ displays[i].mode.xres,
+ displays[i].mode.yres);
+ } else
+ printf("LCD %s cannot be configured: %d\n",
+ displays[i].mode.name, ret);
+ } else {
+ printf("unsupported panel %s\n", panel);
+ ret = -EINVAL;
+ }
+ return (0 != ret);
+ }
+
+ static void setup_display(void)
+ {
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
+ struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+ struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+
+ int reg;
+
+ /* Turn on LDB0,IPU,IPU DI0 clocks */
+ reg = __raw_readl(&mxc_ccm->CCGR3);
+ reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET
+ |MXC_CCM_CCGR3_LDB_DI0_MASK;
+ writel(reg, &mxc_ccm->CCGR3);
+
+ /* Turn on HDMI PHY clock */
+ reg = __raw_readl(&mxc_ccm->CCGR2);
+ reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
+ |MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
+ writel(reg, &mxc_ccm->CCGR2);
+
+ /* clear HDMI PHY reset */
+ writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
+
+ /* set PFD1_FRAC to 0x13 == 455 MHz (480*18)/0x13 */
+ writel(ANATOP_PFD_480_PFD1_FRAC_MASK, &anatop->pfd_480_clr);
+ writel(0x13<<ANATOP_PFD_480_PFD1_FRAC_SHIFT, &anatop->pfd_480_set);
+
+ /* set LDB0, LDB1 clk select to 011/011 */
+ reg = readl(&mxc_ccm->cs2cdr);
+ reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
+ |MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
+ reg |= (3<<MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
+ |(3<<MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
+ writel(reg, &mxc_ccm->cs2cdr);
+
+ reg = readl(&mxc_ccm->cscmr2);
+ reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+ writel(reg, &mxc_ccm->cscmr2);
+
+ reg = readl(&mxc_ccm->chsccdr);
+ reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK
+ |MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK
+ |MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+ reg |= (CHSCCDR_CLK_SEL_LDB_DI0
+ <<MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)
+ |(CHSCCDR_PODF_DIVIDE_BY_3
+ <<MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
+ |(CHSCCDR_IPU_PRE_CLK_540M_PFD
+ <<MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+ writel(reg, &mxc_ccm->chsccdr);
+
+ reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
+ |IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
+ |IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
+ |IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
+ |IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
+ |IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
+ |IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
+ |IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED
+ |IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
+ writel(reg, &iomux->gpr[2]);
+
+ reg = readl(&iomux->gpr[3]);
+ reg = (reg & ~IOMUXC_GPR3_LVDS0_MUX_CTL_MASK)
+ | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
+ <<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
+ writel(reg, &iomux->gpr[3]);
+
+ /* backlights off until needed */
+ imx_iomux_v3_setup_multiple_pads(backlight_pads,
+ ARRAY_SIZE(backlight_pads));
+ gpio_direction_input(LVDS_BACKLIGHT_GP);
+ gpio_direction_input(RGB_BACKLIGHT_GP);
+ }
+ #endif
+
+ int board_early_init_f(void)
+ {
+ setup_iomux_uart();
+ setup_buttons();
+
+ #if defined(CONFIG_VIDEO_IPUV3)
+ setup_display();
+ #endif
+ return 0;
+ }
+
+ /*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+ int overwrite_console(void)
+ {
+ return 1;
+ }
+
+ int board_init(void)
+ {
+ /* address of boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+ #ifdef CONFIG_MXC_SPI
+ setup_spi();
+ #endif
+ setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+ setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+ setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+ #ifdef CONFIG_CMD_SATA
+ setup_sata();
+ #endif
+
+ return 0;
+ }
+
+ int checkboard(void)
+ {
+ puts("Board: MX6Q-Sabre Lite\n");
+
+ return 0;
+ }
+
+ struct button_key {
+ char const *name;
+ unsigned gpnum;
+ char ident;
+ };
+
+ static struct button_key const buttons[] = {
+ {"back", IMX_GPIO_NR(2, 2), 'B'},
+ {"home", IMX_GPIO_NR(2, 4), 'H'},
+ {"menu", IMX_GPIO_NR(2, 1), 'M'},
+ {"search", IMX_GPIO_NR(2, 3), 'S'},
+ {"volup", IMX_GPIO_NR(7, 13), 'V'},
+ {"voldown", IMX_GPIO_NR(4, 5), 'v'},
+ };
+
+ /*
+ * generate a null-terminated string containing the buttons pressed
+ * returns number of keys pressed
+ */
+ static int read_keys(char *buf)
+ {
+ int i, numpressed = 0;
+ for (i = 0; i < ARRAY_SIZE(buttons); i++) {
+ if (!gpio_get_value(buttons[i].gpnum))
+ buf[numpressed++] = buttons[i].ident;
+ }
+ buf[numpressed] = '\0';
+ return numpressed;
+ }
+
+ static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+ {
+ char envvalue[ARRAY_SIZE(buttons)+1];
+ int numpressed = read_keys(envvalue);
+ setenv("keybd", envvalue);
+ return numpressed == 0;
+ }
+
+ U_BOOT_CMD(
+ kbd, 1, 1, do_kbd,
+ "Tests for keypresses, sets 'keybd' environment variable",
+ "Returns 0 (true) to shell if key is pressed."
+ );
+
+ #ifdef CONFIG_PREBOOT
+ static char const kbd_magic_prefix[] = "key_magic";
+ static char const kbd_command_prefix[] = "key_cmd";
+
+ static void preboot_keys(void)
+ {
+ int numpressed;
+ char keypress[ARRAY_SIZE(buttons)+1];
+ numpressed = read_keys(keypress);
+ if (numpressed) {
+ char *kbd_magic_keys = getenv("magic_keys");
+ char *suffix;
+ /*
+ * loop over all magic keys
+ */
+ for (suffix = kbd_magic_keys; *suffix; ++suffix) {
+ char *keys;
+ char magic[sizeof(kbd_magic_prefix) + 1];
+ sprintf(magic, "%s%c", kbd_magic_prefix, *suffix);
+ keys = getenv(magic);
+ if (keys) {
+ if (!strcmp(keys, keypress))
+ break;
+ }
+ }
+ if (*suffix) {
+ char cmd_name[sizeof(kbd_command_prefix) + 1];
+ char *cmd;
+ sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix);
+ cmd = getenv(cmd_name);
+ if (cmd) {
+ setenv("preboot", cmd);
+ return;
+ }
+ }
+ }
+ }
+ #endif
+
+ #ifdef CONFIG_CMD_BMODE
+ static const struct boot_mode board_boot_modes[] = {
+ /* 4 bit bus width */
+ {"mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
+ {"mmc1", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
+ {NULL, 0},
+ };
+ #endif
+
+ int misc_init_r(void)
+ {
+ #ifdef CONFIG_PREBOOT
+ preboot_keys();
+ #endif
+
+ #ifdef CONFIG_CMD_BMODE
+ add_board_boot_modes(board_boot_modes);
+ #endif
+ return 0;
+ }
#include <asm/arch/mx6-pins.h>
#include <asm/errno.h>
#include <asm/gpio.h>
+#include <asm/imx-common/mxc_i2c.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/video.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <miiphy.h>
#include <netdev.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/pfuze100_pmic.h>
+#include "../common/pfuze.h"
+#include <asm/arch/mx6-ddr.h>
+#include <usb.h>
DECLARE_GLOBAL_DATA_PTR;
#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
+ PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+
+#define I2C_PMIC 1
+
+#define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+#define DISP0_PWR_EN IMX_GPIO_NR(1, 21)
+
int dram_init(void)
{
- gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
-
+ gd->ram_size = imx_ddr_size();
return 0;
}
-iomux_v3_cfg_t const uart1_pads[] = {
- MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+static iomux_v3_cfg_t const uart1_pads[] = {
+ MX6_PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
-iomux_v3_cfg_t const enet_pads[] = {
+static iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
/* AR8031 PHY Reset */
- MX6_PAD_ENET_CRS_DV__GPIO1_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_ENET_CRS_DV__GPIO_1_25,
++ MX6_PAD_ENET_CRS_DV__GPIO1_IO25,
};
static void setup_iomux_enet(void)
gpio_set_value(IMX_GPIO_NR(1, 25), 1);
}
-iomux_v3_cfg_t const usdhc2_pads[] = {
- MX6_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D4__USDHC2_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D5__USDHC2_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D6__USDHC2_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D7__USDHC2_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D2__GPIO_2_2, /* CD */
+static iomux_v3_cfg_t const usdhc2_pads[] = {
+ MX6_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_NANDF_D4__SD2_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_NANDF_D5__SD2_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_NANDF_D6__SD2_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_NANDF_D7__SD2_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D2__GPIO2_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
++ MX6_PAD_NANDF_D2__GPIO2_IO02, /* CD */
+};
+
+static iomux_v3_cfg_t const usdhc3_pads[] = {
+ MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D0__GPIO2_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
++ MX6_PAD_NANDF_D0__GPIO2_IO00, /* CD */
+};
+
+static iomux_v3_cfg_t const usdhc4_pads[] = {
+ MX6_PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
-iomux_v3_cfg_t const usdhc3_pads[] = {
- MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_NANDF_D0__GPIO_2_0, /* CD */
+static iomux_v3_cfg_t const ecspi1_pads[] = {
+ MX6_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
- MX6_PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_KEY_ROW1__GPIO4_IO09,
};
-iomux_v3_cfg_t const usdhc4_pads[] = {
- MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+static iomux_v3_cfg_t const rgb_pads[] = {
- MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DI0_PIN4__IPU1_DI0_PIN04 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_SD1_DAT3__GPIO1_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
++ MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15,
++ MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02,
++ MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03,
++ MX6_PAD_DI0_PIN4__IPU1_DI0_PIN04,
++ MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00,
++ MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01,
++ MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02,
++ MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03,
++ MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04,
++ MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05,
++ MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06,
++ MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07,
++ MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08,
++ MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09,
++ MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10,
++ MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11,
++ MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12,
++ MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13,
++ MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14,
++ MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15,
++ MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16,
++ MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17,
++ MX6_PAD_DISP0_DAT18__IPU1_DISP0_DATA18,
++ MX6_PAD_DISP0_DAT19__IPU1_DISP0_DATA19,
++ MX6_PAD_DISP0_DAT20__IPU1_DISP0_DATA20,
++ MX6_PAD_DISP0_DAT21__IPU1_DISP0_DATA21,
++ MX6_PAD_DISP0_DAT22__IPU1_DISP0_DATA22,
++ MX6_PAD_DISP0_DAT23__IPU1_DISP0_DATA23,
++ MX6_PAD_SD1_DAT3__GPIO1_IO21,
+};
+
+static void enable_rgb(struct display_info_t const *dev)
+{
+ imx_iomux_v3_setup_multiple_pads(rgb_pads, ARRAY_SIZE(rgb_pads));
+ gpio_direction_output(DISP0_PWR_EN, 1);
+}
+
+static struct i2c_pads_info i2c_pad_info1 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | I2C_PAD,
+ .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12 | I2C_PAD,
+ .gp = IMX_GPIO_NR(4, 12)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | I2C_PAD,
+ .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | I2C_PAD,
+ .gp = IMX_GPIO_NR(4, 13)
+ }
+};
+
+static void setup_spi(void)
+{
+ imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+}
+
+iomux_v3_cfg_t const pcie_pads[] = {
- MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL), /* POWER */
- MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL), /* RESET */
++ MX6_PAD_EIM_D19__GPIO3_IO19, /* POWER */
++ MX6_PAD_GPIO_17__GPIO7_IO12, /* RESET */
+};
+
+static void setup_pcie(void)
+{
+ imx_iomux_v3_setup_multiple_pads(pcie_pads, ARRAY_SIZE(pcie_pads));
+}
+
+iomux_v3_cfg_t const di0_pads[] = {
+ MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, /* DISP0_CLK */
+ MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02, /* DISP0_HSYNC */
+ MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03, /* DISP0_VSYNC */
};
static void setup_iomux_uart(void)
int board_mmc_init(bd_t *bis)
{
- s32 status = 0;
+#ifndef CONFIG_SPL_BUILD
+ int ret;
int i;
/*
printf("Warning: you configured more USDHC controllers"
"(%d) then supported by the board (%d)\n",
i + 1, CONFIG_SYS_FSL_USDHC_NUM);
- return status;
+ return -EINVAL;
}
- status |= fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
+ ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+#else
+ struct src *psrc = (struct src *)SRC_BASE_ADDR;
+ unsigned reg = readl(&psrc->sbmr1) >> 11;
+ /*
+ * Upon reading BOOT_CFG register the following map is done:
+ * Bit 11 and 12 of BOOT_CFG register can determine the current
+ * mmc port
+ * 0x1 SD1
+ * 0x2 SD2
+ * 0x3 SD4
+ */
+
+ switch (reg & 0x3) {
+ case 0x1:
+ imx_iomux_v3_setup_multiple_pads(
+ usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+ usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
+ usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+ gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+ break;
+ case 0x2:
+ imx_iomux_v3_setup_multiple_pads(
+ usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+ usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR;
+ usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+ gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+ break;
+ case 0x3:
+ imx_iomux_v3_setup_multiple_pads(
+ usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+ usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
+ usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+ gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+ break;
}
- return status;
+ return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+#endif
}
#endif
return 0;
}
-int board_eth_init(bd_t *bis)
+#if defined(CONFIG_VIDEO_IPUV3)
+static void disable_lvds(struct display_info_t const *dev)
{
- int ret;
+ struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+ int reg = readl(&iomux->gpr[2]);
+
+ reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
+ IOMUXC_GPR2_LVDS_CH1_MODE_MASK);
+
+ writel(reg, &iomux->gpr[2]);
+}
+
+static void do_enable_hdmi(struct display_info_t const *dev)
+{
+ disable_lvds(dev);
+ imx_enable_hdmi_phy();
+}
+
+static void enable_lvds(struct display_info_t const *dev)
+{
+ struct iomuxc *iomux = (struct iomuxc *)
+ IOMUXC_BASE_ADDR;
+ u32 reg = readl(&iomux->gpr[2]);
+ reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT |
+ IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT;
+ writel(reg, &iomux->gpr[2]);
+}
+struct display_info_t const displays[] = {{
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB666,
+ .detect = NULL,
+ .enable = enable_lvds,
+ .mode = {
+ .name = "Hannstar-XGA",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = detect_hdmi,
+ .enable = do_enable_hdmi,
+ .mode = {
+ .name = "HDMI",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 0,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = NULL,
+ .enable = enable_rgb,
+ .mode = {
+ .name = "SEIKO-WVGA",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 29850,
+ .left_margin = 89,
+ .right_margin = 164,
+ .upper_margin = 23,
+ .lower_margin = 10,
+ .hsync_len = 10,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+} } };
+size_t display_count = ARRAY_SIZE(displays);
+
+static void setup_display(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+ int reg;
+
+ /* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */
+ imx_iomux_v3_setup_multiple_pads(di0_pads, ARRAY_SIZE(di0_pads));
+
+ enable_ipu_clock();
+ imx_setup_hdmi();
+
+ /* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */
+ reg = readl(&mxc_ccm->CCGR3);
+ reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK;
+ writel(reg, &mxc_ccm->CCGR3);
+
+ /* set LDB0, LDB1 clk select to 011/011 */
+ reg = readl(&mxc_ccm->cs2cdr);
+ reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
+ | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
+ reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
+ | (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
+ writel(reg, &mxc_ccm->cs2cdr);
+
+ reg = readl(&mxc_ccm->cscmr2);
+ reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
+ writel(reg, &mxc_ccm->cscmr2);
+
+ reg = readl(&mxc_ccm->chsccdr);
+ reg |= (CHSCCDR_CLK_SEL_LDB_DI0
+ << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+ reg |= (CHSCCDR_CLK_SEL_LDB_DI0
+ << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
+ writel(reg, &mxc_ccm->chsccdr);
+
+ reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
+ | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW
+ | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
+ | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
+ | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
+ | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
+ | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
+ | IOMUXC_GPR2_LVDS_CH0_MODE_DISABLED
+ | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0;
+ writel(reg, &iomux->gpr[2]);
+
+ reg = readl(&iomux->gpr[3]);
+ reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK
+ | IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
+ | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
+ << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
+ writel(reg, &iomux->gpr[3]);
+}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
+/*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+int overwrite_console(void)
+{
+ return 1;
+}
+
+int board_eth_init(bd_t *bis)
+{
setup_iomux_enet();
+ setup_pcie();
+
+ return cpu_eth_init(bis);
+}
+
+#ifdef CONFIG_USB_EHCI_MX6
+#define USB_OTHERREGS_OFFSET 0x800
+#define UCTRL_PWR_POL (1 << 9)
- ret = cpu_eth_init(bis);
- if (ret)
- printf("FEC MXC: %s:failed\n", __func__);
+static iomux_v3_cfg_t const usb_otg_pads[] = {
- MX6_PAD_EIM_D22__USB_OTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_EIM_D22__USB_OTG_PWR,
++ MX6_PAD_ENET_RX_ER__USB_OTG_ID,
+};
+
+static iomux_v3_cfg_t const usb_hc1_pads[] = {
- MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
++ MX6_PAD_ENET_TXD1__GPIO1_IO29,
+};
+
+static void setup_usb(void)
+{
+ imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
+ ARRAY_SIZE(usb_otg_pads));
+
+ /*
+ * set daisy chain for otg_pin_id on 6q.
+ * for 6dl, this bit is reserved
+ */
+ imx_iomux_set_gpr_register(1, 13, 1, 0);
+
+ imx_iomux_v3_setup_multiple_pads(usb_hc1_pads,
+ ARRAY_SIZE(usb_hc1_pads));
+}
+
+int board_ehci_hcd_init(int port)
+{
+ u32 *usbnc_usb_ctrl;
+
+ if (port > 1)
+ return -EINVAL;
+
+ usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
+ port * 4);
+
+ setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
+
+ return 0;
+}
+
+int board_ehci_power(int port, int on)
+{
+ switch (port) {
+ case 0:
+ break;
+ case 1:
+ if (on)
+ gpio_direction_output(IMX_GPIO_NR(1, 29), 1);
+ else
+ gpio_direction_output(IMX_GPIO_NR(1, 29), 0);
+ break;
+ default:
+ printf("MXC USB port %d not yet supported\n", port);
+ return -EINVAL;
+ }
return 0;
}
+#endif
int board_early_init_f(void)
{
setup_iomux_uart();
+#if defined(CONFIG_VIDEO_IPUV3)
+ setup_display();
+#endif
return 0;
}
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+#ifdef CONFIG_MXC_SPI
+ setup_spi();
+#endif
+ setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+
+#ifdef CONFIG_USB_EHCI_MX6
+ setup_usb();
+#endif
+
return 0;
}
+int power_init_board(void)
+{
+ struct pmic *p;
+ unsigned int reg;
+
+ p = pfuze_common_init(I2C_PMIC);
+ if (!p)
+ return -ENODEV;
+
+ /* Increase VGEN3 from 2.5 to 2.8V */
+ pmic_reg_read(p, PFUZE100_VGEN3VOL, ®);
+ reg &= ~LDO_VOL_MASK;
+ reg |= LDOB_2_80V;
+ pmic_reg_write(p, PFUZE100_VGEN3VOL, reg);
+
+ /* Increase VGEN5 from 2.8 to 3V */
+ pmic_reg_read(p, PFUZE100_VGEN5VOL, ®);
+ reg &= ~LDO_VOL_MASK;
+ reg |= LDOB_3_00V;
+ pmic_reg_write(p, PFUZE100_VGEN5VOL, reg);
+
+ return 0;
+}
+
+#ifdef CONFIG_MXC_SPI
+int board_spi_cs_gpio(unsigned bus, unsigned cs)
+{
+ return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
+}
+#endif
+
#ifdef CONFIG_CMD_BMODE
static const struct boot_mode board_boot_modes[] = {
/* 4 bit bus width */
#ifdef CONFIG_CMD_BMODE
add_board_boot_modes(board_boot_modes);
#endif
-
return 0;
}
puts("Board: MX6-SabreSD\n");
return 0;
}
+
+#ifdef CONFIG_SPL_BUILD
+#include <spl.h>
+#include <libfdt.h>
+
+const struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = {
+ .dram_sdclk_0 = 0x00020030,
+ .dram_sdclk_1 = 0x00020030,
+ .dram_cas = 0x00020030,
+ .dram_ras = 0x00020030,
+ .dram_reset = 0x00020030,
+ .dram_sdcke0 = 0x00003000,
+ .dram_sdcke1 = 0x00003000,
+ .dram_sdba2 = 0x00000000,
+ .dram_sdodt0 = 0x00003030,
+ .dram_sdodt1 = 0x00003030,
+ .dram_sdqs0 = 0x00000030,
+ .dram_sdqs1 = 0x00000030,
+ .dram_sdqs2 = 0x00000030,
+ .dram_sdqs3 = 0x00000030,
+ .dram_sdqs4 = 0x00000030,
+ .dram_sdqs5 = 0x00000030,
+ .dram_sdqs6 = 0x00000030,
+ .dram_sdqs7 = 0x00000030,
+ .dram_dqm0 = 0x00020030,
+ .dram_dqm1 = 0x00020030,
+ .dram_dqm2 = 0x00020030,
+ .dram_dqm3 = 0x00020030,
+ .dram_dqm4 = 0x00020030,
+ .dram_dqm5 = 0x00020030,
+ .dram_dqm6 = 0x00020030,
+ .dram_dqm7 = 0x00020030,
+};
+
+const struct mx6dq_iomux_grp_regs mx6_grp_ioregs = {
+ .grp_ddr_type = 0x000C0000,
+ .grp_ddrmode_ctl = 0x00020000,
+ .grp_ddrpke = 0x00000000,
+ .grp_addds = 0x00000030,
+ .grp_ctlds = 0x00000030,
+ .grp_ddrmode = 0x00020000,
+ .grp_b0ds = 0x00000030,
+ .grp_b1ds = 0x00000030,
+ .grp_b2ds = 0x00000030,
+ .grp_b3ds = 0x00000030,
+ .grp_b4ds = 0x00000030,
+ .grp_b5ds = 0x00000030,
+ .grp_b6ds = 0x00000030,
+ .grp_b7ds = 0x00000030,
+};
+
+const struct mx6_mmdc_calibration mx6_mmcd_calib = {
+ .p0_mpwldectrl0 = 0x001F001F,
+ .p0_mpwldectrl1 = 0x001F001F,
+ .p1_mpwldectrl0 = 0x00440044,
+ .p1_mpwldectrl1 = 0x00440044,
+ .p0_mpdgctrl0 = 0x434B0350,
+ .p0_mpdgctrl1 = 0x034C0359,
+ .p1_mpdgctrl0 = 0x434B0350,
+ .p1_mpdgctrl1 = 0x03650348,
+ .p0_mprddlctl = 0x4436383B,
+ .p1_mprddlctl = 0x39393341,
+ .p0_mpwrdlctl = 0x35373933,
+ .p1_mpwrdlctl = 0x48254A36,
+};
+
+static struct mx6_ddr3_cfg mem_ddr = {
+ .mem_speed = 1600,
+ .density = 4,
+ .width = 64,
+ .banks = 8,
+ .rowaddr = 14,
+ .coladdr = 10,
+ .pagesz = 2,
+ .trcd = 1375,
+ .trcmin = 4875,
+ .trasmin = 3500,
+};
+
+static void ccgr_init(void)
+{
+ struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ writel(0x00C03F3F, &ccm->CCGR0);
+ writel(0x0030FC03, &ccm->CCGR1);
+ writel(0x0FFFC000, &ccm->CCGR2);
+ writel(0x3FF00000, &ccm->CCGR3);
+ writel(0x00FFF300, &ccm->CCGR4);
+ writel(0x0F0000C3, &ccm->CCGR5);
+ writel(0x000003FF, &ccm->CCGR6);
+}
+
+static void gpr_init(void)
+{
+ struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+ /* enable AXI cache for VDOA/VPU/IPU */
+ writel(0xF00000CF, &iomux->gpr[4]);
+ /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+ writel(0x007F007F, &iomux->gpr[6]);
+ writel(0x007F007F, &iomux->gpr[7]);
+}
+
+/*
+ * This section requires the differentiation between iMX6 Sabre boards, but
+ * for now, it will configure only for the mx6q variant.
+ */
+static void spl_dram_init(void)
+{
+ struct mx6_ddr_sysinfo sysinfo = {
+ /* width of data bus:0=16,1=32,2=64 */
+ .dsize = mem_ddr.width/32,
+ /* config for full 4GB range so that get_mem_size() works */
+ .cs_density = 32, /* 32Gb per CS */
+ /* single chip select */
+ .ncs = 1,
+ .cs1_mirror = 0,
+ .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */
+#ifdef RTT_NOM_120OHM
+ .rtt_nom = 2 /*DDR3_RTT_120_OHM*/, /* RTT_Nom = RZQ/2 */
+#else
+ .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */
+#endif
+ .walat = 1, /* Write additional latency */
+ .ralat = 5, /* Read additional latency */
+ .mif3_mode = 3, /* Command prediction working mode */
+ .bi_on = 1, /* Bank interleaving enabled */
+ .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
+ .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
+ };
+
+ mx6dq_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
+ mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr);
+}
+
+void board_init_f(ulong dummy)
+{
+ /* setup AIPS and disable watchdog */
+ arch_cpu_init();
+
+ ccgr_init();
+ gpr_init();
+
+ /* iomux and setup of i2c */
+ board_early_init_f();
+
+ /* setup GP timer */
+ timer_init();
+
+ /* UART clocks enabled and gd valid - init serial console */
+ preloader_console_init();
+
+ /* DDR initialization */
+ spl_dram_init();
+
+ /* Clear the BSS. */
+ memset(__bss_start, 0, __bss_end - __bss_start);
+
+ /* load/boot image from boot device */
+ board_init_r(NULL, 0);
+}
+
+void reset_cpu(ulong addr)
+{
+}
+#endif
--- /dev/null
-# (C) Copyright 2012 Lothar Waßmann <LW@KARO-electronics.de>
+ #
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# 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.
++# (C) Copyright 2012-2015 Lothar Waßmann <LW@KARO-electronics.de>
+ #
-include $(TOPDIR)/config.mk
-
-ifneq ($(OBJTREE),$(SRCTREE))
-$(shell mkdir -p $(obj)board/$(VENDOR)/common)
-endif
-
-LIB = $(obj)lib$(VENDOR).o
-
++# SPDX-License-Identifier: GPL-2.0+
+ #
+
- COBJS-$(CONFIG_OF_BOARD_SETUP) += fdt.o
- COBJS-$(CONFIG_SPLASH_SCREEN) += splashimage.o
+ ifeq ($(CONFIG_SPL_BUILD),)
-COBJS-$(CONFIG_CMD_NAND) += nand.o
-COBJS-$(CONFIG_ENV_IS_IN_MMC) += mmc.o
-COBJS-y += env.o
-COBJS := $(COBJS-y)
-SOBJS :=
-
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-SOBJS := $(addprefix $(obj),$(SOBJS))
-
-$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(call cmd_link_o_target, $(OBJS) $(SOBJS))
-
-all: $(LIB)
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
++ obj-$(CONFIG_OF_LIBFDT) += fdt.o
++ obj-$(CONFIG_SPLASH_SCREEN) += splashimage.o
+ endif
++obj-$(CONFIG_CMD_NAND) += nand.o
++obj-$(CONFIG_ENV_IS_IN_MMC) += mmc.o
++obj-y += env.o
--- /dev/null
+ /*
+ * (C) Copyright 2012 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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.
+ *
+ */
+ struct fb_videomode;
+
+ #ifdef CONFIG_SYS_LVDS_IF
+ #define is_lvds() 1
+ #else
+ #define is_lvds() 0
+ #endif
+
+ void env_cleanup(void);
+
+ #ifdef CONFIG_OF_LIBFDT
+ void karo_fdt_remove_node(void *blob, const char *node);
+ void karo_fdt_move_fdt(void);
+ void karo_fdt_fixup_touchpanel(void *blob, const char *panels[],
+ size_t num_panels);
+ void karo_fdt_fixup_usb_otg(void *blob, const char *node, const char *phy,
+ const char *phy_supply);
+ void karo_fdt_fixup_flexcan(void *blob, int xcvr_present);
+ void karo_fdt_del_prop(void *blob, const char *compat, u32 offs,
+ const char *prop);
+ void karo_fdt_enable_node(void *blob, const char *node, int enable);
+ int karo_fdt_get_fb_mode(void *blob, const char *name,
+ struct fb_videomode *fb_mode);
+ int karo_fdt_update_fb_mode(void *blob, const char *name);
+ int karo_fdt_create_fb_mode(void *blob, const char *name,
+ struct fb_videomode *mode);
+ int karo_fdt_get_backlight_polarity(const void *blob);
+ #else
+ static inline void karo_fdt_remove_node(void *blob, const char *node)
+ {
+ }
+ static inline void karo_fdt_move_fdt(void)
+ {
+ }
+ static inline void karo_fdt_fixup_touchpanel(void *blob, const char *panels[],
+ size_t num_panels)
+ {
+ }
+ static inline void karo_fdt_fixup_usb_otg(void *blob, const char *node,
+ const char *phy,
+ const char *phy_supply)
+ {
+ }
+ static inline void karo_fdt_fixup_flexcan(void *blob, int xcvr_present)
+ {
+ }
+ static inline void karo_fdt_del_prop(void *blob, const char *compat,
+ u32 offs, const char *prop)
+ {
+ }
+ static inline void karo_fdt_enable_node(void *blob, const char *node,
+ int enable)
+ {
+ }
+ static inline int karo_fdt_get_fb_mode(void *blob, const char *name,
+ struct fb_videomode *fb_mode)
+ {
+ return 0;
+ }
+ static inline int karo_fdt_update_fb_mode(void *blob, const char *name)
+ {
+ return 0;
+ }
+ static inline int karo_fdt_create_fb_mode(void *blob,
+ const char *name,
+ struct fb_videomode *mode)
+ {
+ return 0;
+ }
+ static inline int karo_fdt_get_backlight_polarity(const void *blob)
+ {
+ return getenv_yesno("backlight_polarity");
+ }
+ #endif
+
+ #if defined(CONFIG_SYS_LVDS_IF) && defined(CONFIG_OF_LIBFDT)
+ int karo_fdt_get_lcd_bus_width(const void *blob, int default_width);
+ int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping);
+ u8 karo_fdt_get_lvds_channels(const void *blob);
+ #else
+ static inline int karo_fdt_get_lcd_bus_width(const void *blob, int default_width)
+ {
+ return default_width;
+ }
+ static inline int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping)
+ {
+ return default_mapping;
+ }
+ static inline u8 karo_fdt_get_lvds_channels(const void *blob)
+ {
+ return 0;
+ }
+ #endif
+
+ static inline const char *karo_get_vmode(const char *video_mode)
+ {
+ const char *vmode = NULL;
+
+ if (video_mode == NULL || strlen(video_mode) == 0)
+ return NULL;
+
+ vmode = strchr(video_mode, ':');
+ return vmode ? vmode + 1 : video_mode;
+ }
+
+ #ifdef CONFIG_SPLASH_SCREEN
+ int karo_load_splashimage(int mode);
+ #else
+ static inline int karo_load_splashimage(int mode)
+ {
+ return 0;
+ }
+ #endif
+
+ #ifdef CONFIG_CMD_NAND
+ int karo_load_nand_part(const char *part, void *addr, size_t len);
+ #else
+ static inline int karo_load_nand_part(const char *part, void *addr, size_t len)
+ {
+ return -EOPNOTSUPP;
+ }
+ #endif
+
+ #ifdef CONFIG_ENV_IS_IN_MMC
+ int karo_load_mmc_part(const char *part, void *addr, size_t len);
+ #else
+ static inline int karo_load_mmc_part(const char *part, void *addr, size_t len)
+ {
+ return -EOPNOTSUPP;
+ }
+ #endif
+
+ static inline int karo_load_part(const char *part, void *addr, size_t len)
+ {
+ int ret;
+
+ ret = karo_load_nand_part(part, addr, len);
+ if (ret == -EOPNOTSUPP)
+ return karo_load_mmc_part(part, addr, len);
+ return ret;
+ }
++
++#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d))
--- /dev/null
- int len_read;
-
- printf("Reading file %s from mmc partition %d\n", part, 0);
- len_read = fs_read(part, (ulong)addr, 0, len);
+ /*
+ * (C) Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <errno.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <mmc.h>
+ #include <mxcfb.h>
+ #include <fs.h>
+ #include <fat.h>
+ #include <malloc.h>
+ #include <linux/list.h>
+ #include <linux/fb.h>
+ #include <jffs2/load_kernel.h>
+
+ #include "karo.h"
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define MAX_SEARCH_PARTITIONS 16
+
+ static int find_partitions(const char *ifname, int devno, int fstype,
+ block_dev_desc_t **dev_desc, disk_partition_t *info)
+ {
+ int ret = -1;
+ char *dup_str = NULL;
+ int p;
+ int part;
+ block_dev_desc_t *dd;
+
+ dd = get_dev(ifname, devno);
+ if (!dd || dd->type == DEV_TYPE_UNKNOWN) {
+ printf("** Bad device %s %d **\n", ifname, devno);
+ return -1;
+ }
+ init_part(dd);
+
+ /*
+ * No partition table on device,
+ * or user requested partition 0 (entire device).
+ */
+ if (dd->part_type == PART_TYPE_UNKNOWN) {
+ printf("** No partition table on device %s %d **\n",
+ ifname, devno);
+ goto cleanup;
+ }
+
+ part = 0;
+ for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
+ ret = get_partition_info(dd, p, info);
+ if (ret)
+ continue;
+
+ if (fat_register_device(dd, p) == 0) {
+ part = p;
+ dd->log2blksz = LOG2(dd->blksz);
+ break;
+ }
+ }
+ if (!part) {
+ printf("** No valid partition on device %s %d **\n",
+ ifname, devno);
+ ret = -1;
+ goto cleanup;
+ }
+
+ ret = part;
+ *dev_desc = dd;
+
+ cleanup:
+ free(dup_str);
+ return ret;
+ }
+
+ static int karo_mmc_find_part(struct mmc *mmc, const char *part, int devno,
+ disk_partition_t *part_info)
+ {
+ int ret;
+ block_dev_desc_t *mmc_dev;
+
+ #if defined(CONFIG_SYS_DTB_OFFSET) && defined(CONFIG_SYS_MMC_ENV_PART)
+ if (strcmp(part, "dtb") == 0) {
+ const int partnum = CONFIG_SYS_MMC_ENV_PART;
+
+ part_info->blksz = mmc->read_bl_len;
+ part_info->start = CONFIG_SYS_DTB_OFFSET / part_info->blksz;
+ part_info->size = CONFIG_SYS_DTB_PART_SIZE / part_info->blksz;
+ printf("Using virtual partition %s(%d) ["LBAF".."LBAF"]\n",
+ part, partnum, part_info->start,
+ part_info->start + part_info->size - 1);
+ return partnum;
+ }
+ #endif
+ ret = find_partitions("mmc", devno, FS_TYPE_FAT, &mmc_dev, part_info);
+ if (ret < 0) {
+ printf("No (e)MMC partition found: %d\n", ret);
+ return ret;
+ }
+ return 0;
+ }
+
+ int karo_load_mmc_part(const char *part, void *addr, size_t len)
+ {
+ int ret;
+ struct mmc *mmc;
+ disk_partition_t part_info;
+ int devno = CONFIG_SYS_MMC_ENV_DEV;
+ lbaint_t blk_cnt;
+ int partnum;
+
+ mmc = find_mmc_device(devno);
+ if (!mmc) {
+ printf("Failed to find mmc%u\n", devno);
+ return -ENODEV;
+ }
+
+ if (mmc_init(mmc)) {
+ printf("Failed to init MMC device %d\n", devno);
+ return -EIO;
+ }
+
+ blk_cnt = DIV_ROUND_UP(len, mmc->read_bl_len);
+
+ partnum = karo_mmc_find_part(mmc, part, devno, &part_info);
+ if (partnum > 0) {
+ if (part_info.start + blk_cnt < part_info.start) {
+ printf("%s: given length 0x%08x exceeds size of partition\n",
+ __func__, len);
+ return -EINVAL;
+ }
+ if (part_info.start + blk_cnt > mmc->block_dev.lba)
+ blk_cnt = mmc->block_dev.lba - part_info.start;
+
+ mmc_switch_part(devno, partnum);
+
+ memset(addr, 0xee, len);
+
+ debug("Reading 0x"LBAF" blks from MMC partition %d offset 0x"LBAF" to %p\n",
+ blk_cnt, partnum, part_info.start, addr);
+ ret = mmc->block_dev.block_read(devno, part_info.start, blk_cnt, addr);
+ if (ret == 0) {
+ printf("Failed to read MMC partition %s\n", part);
+ ret = -EIO;
+ goto out;
+ }
+ debug("Read %u (%u) byte from partition '%s' @ offset 0x"LBAF"\n",
+ ret * mmc->read_bl_len, len, part, part_info.start);
+ } else if (partnum == 0) {
- printf("Read only %u of %u bytes\n", len_read, len);
++ loff_t len_read;
++
++ debug("Reading file %s from mmc partition %d\n", part,
++ partnum);
++ ret = fs_read(part, (ulong)addr, 0, len, &len_read);
++ if (ret < 0) {
++ printf("Failed to read %u byte from mmc partition %d\n",
++ len, partnum);
++ goto out;
++ }
+ if (len_read < len) {
++ printf("Read only %llu of %u bytes\n", (u64)len_read, len);
+ }
+ } else {
+ ret = partnum;
+ goto out;
+ }
+ ret = 0;
+ out:
+ if (partnum > 0)
+ mmc_switch_part(devno, 0);
+ return ret < 0 ? ret : 0;
+ }
--- /dev/null
- debug("Found partition '%s': offset=%08x size=%08x\n",
- part, part_info->offset, part_info->size);
+ /*
+ * (C) Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <errno.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <nand.h>
+ #include <mxcfb.h>
+ #include <linux/list.h>
+ #include <linux/fb.h>
+ #include <jffs2/load_kernel.h>
+ #include <malloc.h>
+
+ #include "karo.h"
+
+ #ifdef CONFIG_MAX_DTB_SIZE
+ #define MAX_DTB_SIZE CONFIG_MAX_DTB_SIZE
+ #else
+ #define MAX_DTB_SIZE SZ_64K
+ #endif
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int karo_load_nand_part(const char *part, void *addr, size_t len)
+ {
+ int ret;
+ struct mtd_device *dev;
+ struct part_info *part_info;
+ u8 part_num;
+
+ debug("Initializing mtd_parts\n");
+ ret = mtdparts_init();
+ if (ret)
+ return ret;
+
+ debug("Trying to find NAND partition '%s'\n", part);
+ ret = find_dev_and_part(part, &dev, &part_num, &part_info);
+ if (ret) {
+ printf("Failed to find flash partition '%s': %d\n",
+ part, ret);
+
+ return ret;
+ }
- debug("Read %u byte from partition '%s' @ offset %08x\n",
- len, part, part_info->offset);
++ debug("Found partition '%s': offset=%08llx size=%08llx\n",
++ part, (u64)part_info->offset, (u64)part_info->size);
+
+ if (part_info->size < len)
+ len = part_info->size;
+
+ debug("Reading NAND partition '%s' to %p\n", part, addr);
+ ret = nand_read_skip_bad(&nand_info[0], part_info->offset, &len,
+ NULL, part_info->size, addr);
+ if (ret) {
+ printf("Failed to load partition '%s' to %p\n", part, addr);
+ return ret;
+ }
+
++ debug("Read %u byte from partition '%s' @ offset %08llx\n",
++ len, part, (u64)part_info->offset);
+ return 0;
+ }
+
+ #if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_MTDPARTS)
+ static int erase_flash(loff_t offs, size_t len)
+ {
+ nand_erase_options_t nand_erase_options;
+
+ memset(&nand_erase_options, 0, sizeof(nand_erase_options));
+ nand_erase_options.length = len;
+ nand_erase_options.offset = offs;
+
+ return nand_erase_opts(&nand_info[0], &nand_erase_options);
+ }
+
+ int do_fbdump(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int ret;
+ size_t fbsize = calc_fbsize();
+ const char *part = "logo";
+ struct mtd_device *dev;
+ struct part_info *part_info;
+ u8 part_num;
+ u_char *addr = (u_char *)gd->fb_base;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ if (argc == 2)
+ part = argv[1];
+
+ if (!addr) {
+ printf("fb address unknown\n");
+ return CMD_RET_FAILURE;
+ }
+
+ debug("Initializing mtd_parts\n");
+ ret = mtdparts_init();
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ debug("Trying to find NAND partition '%s'\n", part);
+ ret = find_dev_and_part(part, &dev, &part_num,
+ &part_info);
+ if (ret) {
+ printf("Failed to find flash partition '%s': %d\n",
+ part, ret);
+ return CMD_RET_FAILURE;
+ }
+ debug("Found partition '%s': offset=%08x size=%08x\n",
+ part, part_info->offset, part_info->size);
+ if (part_info->size < fbsize) {
+ printf("Error: partition '%s' smaller than frame buffer size: %u\n",
+ part, fbsize);
+ return CMD_RET_FAILURE;
+ }
+ debug("Writing framebuffer %p to NAND partition '%s'\n",
+ addr, part);
+
+ ret = erase_flash(part_info->offset, fbsize);
+ if (ret) {
+ printf("Failed to erase partition '%s'\n", part);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = nand_write_skip_bad(&nand_info[0], part_info->offset,
+ &fbsize, NULL, part_info->size,
+ addr, WITH_DROP_FFS);
+ if (ret) {
+ printf("Failed to write partition '%s'\n", part);
+ return CMD_RET_FAILURE;
+ }
+
+ debug("Wrote %u byte from %p to partition '%s' @ offset %08x\n",
+ fbsize, addr, part, part_info->offset);
+
+ return CMD_RET_SUCCESS;
+ }
+
+ U_BOOT_CMD(fbdump, 2, 0, do_fbdump, "dump framebuffer contents to flash",
+ "[partition name]\n"
+ " default partition name: 'logo'\n");
+ #endif
--- /dev/null
--- /dev/null
++if TARGET_TX28_40X1
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-40x1"
++
++endif
++
++if TARGET_TX28_40X1_NOENV
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-40x1_noenv"
++
++endif
++
++if TARGET_TX28_40X2
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-40x2"
++
++endif
++
++if TARGET_TX28_40X2_NOENV
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-40x2_noenv"
++
++endif
++
++if TARGET_TX28_40X3
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-40x3"
++
++endif
++
++if TARGET_TX28_40X3_NOENV
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-40x3_noenv"
++
++endif
++
++if TARGET_TX28_41X0
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-41x0"
++
++endif
++
++if TARGET_TX28_41X0_NOENV
++
++config SYS_BOARD
++ default "tx28"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mxs"
++
++config SYS_CONFIG_NAME
++ default "tx28-41x0_noenv"
++
++endif
--- /dev/null
-# (C) Copyright 2009 DENX Software Engineering
-# Author: John Rigby <jcrigby@gmail.com>
+ #
-# See file CREDITS for list of people who contributed to this
-# project.
++# (C) Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-# MA 02111-1307 USA
-#
-
-include $(TOPDIR)/config.mk
++# SPDX-License-Identifier: GPL-2.0+
+ #
-LIB = $(obj)lib$(BOARD).o
-
-COBJS := tx28.o
-ifeq ($(CONFIG_SPL_BUILD),y)
- COBJS += spl_boot.o
-else
-ifeq ($(CONFIG_CMD_ROMUPDATE),y)
- COBJS += flash.o
-endif
+
-
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-SOBJS := $(addprefix $(obj),$(SOBJS))
-
-$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(call cmd_link_o_target, $(OBJS) $(SOBJS))
-
-$(obj)u-boot.db: u-boot.db.in
- sed "s:@@BUILD_DIR@@:${BUILD_DIR:-.}/:" $< > $@
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
++obj-y += tx28.o
++obj-$(CONFIG_SPL_BUILD) += spl_boot.o
++ifneq ($(CONFIG_SPL_BUILD),y)
++ obj-$(CONFIG_CMD_ROMUPDATE) += flash.o
+ endif
--- /dev/null
-#include <asm/sizes.h>
+ /*
+ * Copyright (C) 2011-2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <malloc.h>
+ #include <nand.h>
+ #include <errno.h>
+
+ #include <linux/err.h>
+ #include <jffs2/load_kernel.h>
+
+ #include <asm/io.h>
++#include <linux/sizes.h>
+ #include <asm/arch/regs-base.h>
+ #include <asm/imx-common/regs-gpmi.h>
+ #include <asm/imx-common/regs-bch.h>
+
+ struct mx28_nand_timing {
+ u8 data_setup;
+ u8 data_hold;
+ u8 address_setup;
+ u8 dsample_time;
+ u8 nand_timing_state;
+ u8 tREA;
+ u8 tRLOH;
+ u8 tRHOH;
+ };
+
+ struct mx28_fcb {
+ u32 checksum;
+ u32 fingerprint;
+ u32 version;
+ struct mx28_nand_timing timing;
+ u32 page_data_size;
+ u32 total_page_size;
+ u32 sectors_per_block;
+ u32 number_of_nands; /* not used by ROM code */
+ u32 total_internal_die; /* not used by ROM code */
+ u32 cell_type; /* not used by ROM code */
+ u32 ecc_blockn_type;
+ u32 ecc_block0_size;
+ u32 ecc_blockn_size;
+ u32 ecc_block0_type;
+ u32 metadata_size;
+ u32 ecc_blocks_per_page;
+ u32 rsrvd[6]; /* not used by ROM code */
+ u32 bch_mode;
+ u32 boot_patch;
+ u32 patch_sectors;
+ u32 fw1_start_page;
+ u32 fw2_start_page;
+ u32 fw1_sectors;
+ u32 fw2_sectors;
+ u32 dbbt_search_area;
+ u32 bb_mark_byte;
+ u32 bb_mark_startbit;
+ u32 bb_mark_phys_offset;
+ };
+
+ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
+
+ static nand_info_t *mtd = &nand_info[0];
+
+ extern void *_start;
+
+ #define BIT(v,n) (((v) >> (n)) & 0x1)
+
+ static u8 calculate_parity_13_8(u8 d)
+ {
+ u8 p = 0;
+
+ p |= (BIT(d, 6) ^ BIT(d, 5) ^ BIT(d, 3) ^ BIT(d, 2)) << 0;
+ p |= (BIT(d, 7) ^ BIT(d, 5) ^ BIT(d, 4) ^ BIT(d, 2) ^ BIT(d, 1)) << 1;
+ p |= (BIT(d, 7) ^ BIT(d, 6) ^ BIT(d, 5) ^ BIT(d, 1) ^ BIT(d, 0)) << 2;
+ p |= (BIT(d, 7) ^ BIT(d, 4) ^ BIT(d, 3) ^ BIT(d, 0)) << 3;
+ p |= (BIT(d, 6) ^ BIT(d, 4) ^ BIT(d, 3) ^ BIT(d, 2) ^ BIT(d, 1) ^ BIT(d, 0)) << 4;
+ return p;
+ }
+
+ static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
+ {
+ int i;
+ u8 *src = _src;
+ u8 *ecc = _ecc;
+
+ for (i = 0; i < size; i++)
+ ecc[i] = calculate_parity_13_8(src[i]);
+ }
+
+ static u32 calc_chksum(void *buf, size_t size)
+ {
+ u32 chksum = 0;
+ u8 *bp = buf;
+ size_t i;
+
+ for (i = 0; i < size; i++) {
+ chksum += bp[i];
+ }
+ return ~chksum;
+ }
+
+ /*
+ Physical organisation of data in NAND flash:
+ metadata
+ payload chunk 0 (may be empty)
+ ecc for metadata + payload chunk 0
+ payload chunk 1
+ ecc for payload chunk 1
+ ...
+ payload chunk n
+ ecc for payload chunk n
+ */
+
+ static int calc_bb_offset(nand_info_t *mtd, struct mx28_fcb *fcb)
+ {
+ int bb_mark_offset;
+ int chunk_data_size = fcb->ecc_blockn_size * 8;
+ int chunk_ecc_size = (fcb->ecc_blockn_type << 1) * 13;
+ int chunk_total_size = chunk_data_size + chunk_ecc_size;
+ int bb_mark_chunk, bb_mark_chunk_offs;
+
+ bb_mark_offset = (mtd->writesize - fcb->metadata_size) * 8;
+ if (fcb->ecc_block0_size == 0)
+ bb_mark_offset -= (fcb->ecc_block0_type << 1) * 13;
+
+ bb_mark_chunk = bb_mark_offset / chunk_total_size;
+ bb_mark_chunk_offs = bb_mark_offset - (bb_mark_chunk * chunk_total_size);
+ if (bb_mark_chunk_offs > chunk_data_size) {
+ printf("Unsupported ECC layout; BB mark resides in ECC data: %u\n",
+ bb_mark_chunk_offs);
+ return -EINVAL;
+ }
+ bb_mark_offset -= bb_mark_chunk * chunk_ecc_size;
+ return bb_mark_offset;
+ }
+
+ /*
+ * return number of blocks to skip for a contiguous partition
+ * of given # blocks
+ */
+ static int find_contig_space(int block, int num_blocks, int max_blocks)
+ {
+ int skip = 0;
+ int found = 0;
+ int last = block + max_blocks;
+
+ debug("Searching %u contiguous blocks from %d..%d\n",
+ num_blocks, block, block + max_blocks - 1);
+ for (; block < last; block++) {
+ if (nand_block_isbad(mtd, block * mtd->erasesize)) {
+ skip += found + 1;
+ found = 0;
+ debug("Skipping %u blocks to %u\n",
+ skip, block + 1);
+ } else {
+ found++;
+ if (found >= num_blocks) {
+ debug("Found %u good blocks from %d..%d\n",
+ found, block - found + 1, block);
+ return skip;
+ }
+ }
+ }
+ return -ENOSPC;
+ }
+
+ #define pr_fcb_val(p, n) debug("%s=%08x(%d)\n", #n, (p)->n, (p)->n)
+
+ static struct mx28_fcb *create_fcb(void *buf, int fw1_start_block,
+ int fw2_start_block, int fw_num_blocks)
+ {
+ struct gpmi_regs *gpmi_base = (void *)GPMI_BASE_ADDRESS;
+ struct bch_regs *bch_base = (void *)BCH_BASE_ADDRESS;
+ u32 fl0, fl1;
+ u32 t0;
+ int metadata_size;
+ int bb_mark_bit_offs;
+ struct mx28_fcb *fcb;
+ int fcb_offs;
+
+ if (gpmi_base == NULL || bch_base == NULL) {
+ return ERR_PTR(-ENOMEM);
+ }
+
+ fl0 = readl(&bch_base->hw_bch_flash0layout0);
+ fl1 = readl(&bch_base->hw_bch_flash0layout1);
+ t0 = readl(&gpmi_base->hw_gpmi_timing0);
+
+ metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+
+ fcb = buf + ALIGN(metadata_size, 4);
+ fcb_offs = (void *)fcb - buf;
+
+ memset(buf, 0xff, fcb_offs);
+ memset(fcb, 0x00, sizeof(*fcb));
+ memset(fcb + 1, 0xff, mtd->erasesize - fcb_offs - sizeof(*fcb));
+
+ strncpy((char *)&fcb->fingerprint, "FCB ", 4);
+ fcb->version = cpu_to_be32(1);
+
+ /* ROM code assumes GPMI clock of 25 MHz */
+ fcb->timing.data_setup = BF_VAL(t0, GPMI_TIMING0_DATA_SETUP) * 40;
+ fcb->timing.data_hold = BF_VAL(t0, GPMI_TIMING0_DATA_HOLD) * 40;
+ fcb->timing.address_setup = BF_VAL(t0, GPMI_TIMING0_ADDRESS_SETUP) * 40;
+
+ fcb->page_data_size = mtd->writesize;
+ fcb->total_page_size = mtd->writesize + mtd->oobsize;
+ fcb->sectors_per_block = mtd->erasesize / mtd->writesize;
+
+ fcb->ecc_block0_type = BF_VAL(fl0, BCH_FLASHLAYOUT0_ECC0);
+ fcb->ecc_block0_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_DATA0_SIZE);
+ fcb->ecc_blockn_type = BF_VAL(fl1, BCH_FLASHLAYOUT1_ECCN);
+ fcb->ecc_blockn_size = BF_VAL(fl1, BCH_FLASHLAYOUT1_DATAN_SIZE);
+
+ pr_fcb_val(fcb, ecc_block0_type);
+ pr_fcb_val(fcb, ecc_blockn_type);
+ pr_fcb_val(fcb, ecc_block0_size);
+ pr_fcb_val(fcb, ecc_blockn_size);
+
+ fcb->metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+ fcb->ecc_blocks_per_page = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
+ fcb->bch_mode = readl(&bch_base->hw_bch_mode);
+
+ fcb->fw1_start_page = fw1_start_block * fcb->sectors_per_block;
+ fcb->fw1_sectors = fw_num_blocks * fcb->sectors_per_block;
+ pr_fcb_val(fcb, fw1_start_page);
+ pr_fcb_val(fcb, fw1_sectors);
+
+ if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) {
+ fcb->fw2_start_page = fw2_start_block * fcb->sectors_per_block;
+ fcb->fw2_sectors = fcb->fw1_sectors;
+ pr_fcb_val(fcb, fw2_start_page);
+ pr_fcb_val(fcb, fw2_sectors);
+ }
+
+ fcb->dbbt_search_area = 1;
+
+ bb_mark_bit_offs = calc_bb_offset(mtd, fcb);
+ if (bb_mark_bit_offs < 0)
+ return ERR_PTR(bb_mark_bit_offs);
+ fcb->bb_mark_byte = bb_mark_bit_offs / 8;
+ fcb->bb_mark_startbit = bb_mark_bit_offs % 8;
+ fcb->bb_mark_phys_offset = mtd->writesize;
+
+ pr_fcb_val(fcb, bb_mark_byte);
+ pr_fcb_val(fcb, bb_mark_startbit);
+ pr_fcb_val(fcb, bb_mark_phys_offset);
+
+ fcb->checksum = calc_chksum(&fcb->fingerprint, 512 - 4);
+ return fcb;
+ }
+
+ static int find_fcb(void *ref, int page)
+ {
+ int ret = 0;
+ struct nand_chip *chip = mtd->priv;
+ void *buf = malloc(mtd->erasesize);
+
+ if (buf == NULL) {
+ return -ENOMEM;
+ }
+ chip->select_chip(mtd, 0);
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+ ret = chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
+ if (ret) {
+ printf("Failed to read FCB from page %u: %d\n", page, ret);
+ goto out;
+ }
+ if (memcmp(buf, ref, mtd->writesize) == 0) {
+ debug("Found FCB in page %u (%08x)\n",
+ page, page * mtd->writesize);
+ ret = 1;
+ }
+ out:
+ chip->select_chip(mtd, -1);
+ free(buf);
+ return ret;
+ }
+
+ static int write_fcb(void *buf, int block)
+ {
+ int ret;
+ struct nand_chip *chip = mtd->priv;
+ int page = block * mtd->erasesize / mtd->writesize;
+
+ ret = find_fcb(buf, page);
+ if (ret > 0) {
+ printf("FCB at block %d is up to date\n", block);
+ return 0;
+ }
+
+ ret = nand_erase(mtd, block * mtd->erasesize, mtd->erasesize);
+ if (ret) {
+ printf("Failed to erase FCB block %u\n", block);
+ return ret;
+ }
+
+ printf("Writing FCB to block %d @ %08llx\n", block,
+ (u64)block * mtd->erasesize);
+ chip->select_chip(mtd, 0);
+ ret = chip->write_page(mtd, chip, buf, 1, page, 0, 1);
+ if (ret) {
+ printf("Failed to write FCB to block %u: %d\n", block, ret);
+ }
+ chip->select_chip(mtd, -1);
+ return ret;
+ }
+
+ #define chk_overlap(a,b) \
+ ((a##_start_block <= b##_end_block && \
+ a##_end_block >= b##_start_block) || \
+ (b##_start_block <= a##_end_block && \
+ b##_end_block >= a##_start_block))
+
+ #define fail_if_overlap(a,b,m1,m2) do { \
+ if (chk_overlap(a, b)) { \
+ printf("%s blocks %lu..%lu overlap %s in blocks %lu..%lu!\n", \
+ m1, a##_start_block, a##_end_block, \
+ m2, b##_start_block, b##_end_block); \
+ return -EINVAL; \
+ } \
+ } while (0)
+
+ static int tx28_prog_uboot(void *addr, int start_block, int skip,
+ size_t size, size_t max_len)
+ {
+ int ret;
+ nand_erase_options_t erase_opts = { 0, };
+ size_t actual;
+ size_t prg_length = max_len - skip * mtd->erasesize;
+ int prg_start = (start_block + skip) * mtd->erasesize;
+
+ erase_opts.offset = start_block * mtd->erasesize;
+ erase_opts.length = max_len;
+ erase_opts.quiet = 1;
+
+ printf("Erasing flash @ %08llx..%08llx\n", erase_opts.offset,
+ erase_opts.offset + erase_opts.length - 1);
+ ret = nand_erase_opts(mtd, &erase_opts);
+ if (ret) {
+ printf("Failed to erase flash: %d\n", ret);
+ return ret;
+ }
+
+ printf("Programming flash @ %08llx..%08llx from %p\n",
+ (u64)start_block * mtd->erasesize,
+ (u64)start_block * mtd->erasesize + size - 1, addr);
+ actual = size;
+ ret = nand_write_skip_bad(mtd, prg_start, &actual, NULL,
+ prg_length, addr, WITH_DROP_FFS);
+ if (ret) {
+ printf("Failed to program flash: %d\n", ret);
+ return ret;
+ }
+ if (actual < size) {
+ printf("Could only write %u of %u bytes\n", actual, size);
+ return -EIO;
+ }
+ return 0;
+ }
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #ifndef CONFIG_ENV_OFFSET_REDUND
+ #define TOTAL_ENV_SIZE CONFIG_ENV_RANGE
+ #else
+ #define TOTAL_ENV_SIZE (CONFIG_ENV_RANGE * 2)
+ #endif
+ #endif
+
+ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int ret;
+ const unsigned long fcb_start_block = 0, fcb_end_block = 0;
+ int erase_size = mtd->erasesize;
+ int page_size = mtd->writesize;
+ void *buf;
+ char *load_addr;
+ char *file_size;
+ size_t size = 0;
+ void *addr = NULL;
+ struct mx28_fcb *fcb;
+ unsigned long mtd_num_blocks = mtd->size / mtd->erasesize;
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ unsigned long env_start_block = CONFIG_ENV_OFFSET / mtd->erasesize;
+ unsigned long env_end_block = env_start_block +
+ DIV_ROUND_UP(TOTAL_ENV_SIZE, mtd->erasesize) - 1;
+ #endif
+ int optind;
+ int fw2_set = 0;
+ unsigned long fw1_start_block = 0, fw1_end_block;
+ unsigned long fw2_start_block = 0, fw2_end_block;
+ unsigned long fw_num_blocks;
+ int fw1_skip, fw2_skip;
+ unsigned long extra_blocks = 0;
+ size_t max_len1, max_len2;
+ struct mtd_device *dev;
+ struct part_info *part_info;
+ struct part_info *redund_part_info;
+ const char *uboot_part = "u-boot";
+ const char *redund_part = NULL;
+ u8 part_num;
+ u8 redund_part_num;
+
+ ret = mtdparts_init();
+ if (ret)
+ return ret;
+
+ for (optind = 1; optind < argc; optind++) {
+ char *endp;
+
+ if (strcmp(argv[optind], "-f") == 0) {
+ if (optind >= argc - 1) {
+ printf("Option %s requires an argument\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+ optind++;
+ fw1_start_block = simple_strtoul(argv[optind], &endp, 0);
+ if (*endp != '\0') {
+ uboot_part = argv[optind];
+ continue;
+ }
+ uboot_part = NULL;
+ if (fw1_start_block >= mtd_num_blocks) {
+ printf("Block number %lu is out of range: 0..%lu\n",
+ fw1_start_block, mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ } else if (strcmp(argv[optind], "-r") == 0) {
+ fw2_set = 1;
+ if (optind < argc - 1 && argv[optind + 1][0] != '-') {
+ optind++;
+ fw2_start_block = simple_strtoul(argv[optind],
+ &endp, 0);
+ if (*endp != '\0') {
+ redund_part = argv[optind];
+ continue;
+ }
+ if (fw2_start_block >= mtd_num_blocks) {
+ printf("Block number %lu is out of range: 0..%lu\n",
+ fw2_start_block,
+ mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ }
+ } else if (strcmp(argv[optind], "-e") == 0) {
+ if (optind >= argc - 1) {
+ printf("Option %s requires an argument\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+ optind++;
+ extra_blocks = simple_strtoul(argv[optind], NULL, 0);
+ if (extra_blocks >= mtd_num_blocks) {
+ printf("Extra block count %lu is out of range: 0..%lu\n",
+ extra_blocks,
+ mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ } else if (argv[optind][0] == '-') {
+ printf("Unrecognized option %s\n", argv[optind]);
+ return -EINVAL;
+ } else {
+ break;
+ }
+ }
+
+ load_addr = getenv("fileaddr");
+ file_size = getenv("filesize");
+
+ if (argc - optind < 1 && load_addr == NULL) {
+ printf("Load address not specified\n");
+ return -EINVAL;
+ }
+ if (argc - optind < 2 && file_size == NULL) {
+ printf("WARNING: Image size not specified; overwriting whole uboot partition\n");
+ }
+ if (argc > optind) {
+ load_addr = NULL;
+ addr = (void *)simple_strtoul(argv[optind], NULL, 16);
+ optind++;
+ }
+ if (argc > optind) {
+ file_size = NULL;
+ size = simple_strtoul(argv[optind], NULL, 16);
+ optind++;
+ }
+ if (load_addr != NULL) {
+ addr = (void *)simple_strtoul(load_addr, NULL, 16);
+ printf("Using default load address %p\n", addr);
+ }
+ if (file_size != NULL) {
+ size = simple_strtoul(file_size, NULL, 16);
+ printf("Using default file size %08x\n", size);
+ }
+ if (size > 0) {
+ fw_num_blocks = DIV_ROUND_UP(size, mtd->erasesize);
+ } else {
+ fw_num_blocks = part_info->size / mtd->erasesize -
+ extra_blocks;
+ size = fw_num_blocks * mtd->erasesize;
+ }
+
+ if (uboot_part) {
+ ret = find_dev_and_part(uboot_part, &dev, &part_num,
+ &part_info);
+ if (ret) {
+ printf("Failed to find '%s' partition: %d\n",
+ uboot_part, ret);
+ return ret;
+ }
+ fw1_start_block = part_info->offset / mtd->erasesize;
+ max_len1 = part_info->size;
+ } else {
+ max_len1 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ }
+
+ if (redund_part) {
+ ret = find_dev_and_part(redund_part, &dev, &redund_part_num,
+ &redund_part_info);
+ if (ret) {
+ printf("Failed to find '%s' partition: %d\n",
+ redund_part, ret);
+ return ret;
+ }
+ fw2_start_block = redund_part_info->offset / mtd->erasesize;
+ max_len2 = redund_part_info->size;
+ } else if (fw2_set) {
+ max_len2 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ } else {
+ max_len2 = 0;
+ }
+
+ fw1_skip = find_contig_space(fw1_start_block, fw_num_blocks,
+ max_len1 / mtd->erasesize);
+ if (fw1_skip < 0) {
+ printf("Could not find %lu contiguous good blocks for fw image\n",
+ fw_num_blocks);
+ if (uboot_part) {
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ if (part_info->offset <= CONFIG_ENV_OFFSET + TOTAL_ENV_SIZE) {
+ printf("Use a different partition\n");
+ } else {
+ printf("Increase the size of the '%s' partition\n",
+ uboot_part);
+ }
+ #else
+ printf("Increase the size of the '%s' partition\n",
+ uboot_part);
+ #endif
+ } else {
+ printf("Increase the number of spare blocks to use with the '-e' option\n");
+ }
+ return -ENOSPC;
+ }
+ fw1_end_block = fw1_start_block + fw1_skip + fw_num_blocks - 1;
+
+ if (fw2_set && fw2_start_block == 0)
+ fw2_start_block = fw1_end_block + 1;
+ if (fw2_start_block > 0) {
+ fw2_skip = find_contig_space(fw2_start_block, fw_num_blocks,
+ max_len2 / mtd->erasesize);
+ if (fw2_skip < 0) {
+ printf("Could not find %lu contiguous good blocks for redundant fw image\n",
+ fw_num_blocks);
+ if (redund_part) {
+ printf("Increase the size of the '%s' partition or use a different partition\n",
+ redund_part);
+ } else {
+ printf("Increase the number of spare blocks to use with the '-e' option\n");
+ }
+ return -ENOSPC;
+ }
+ } else {
+ fw2_skip = 0;
+ }
+ fw2_end_block = fw2_start_block + fw2_skip + fw_num_blocks - 1;
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ fail_if_overlap(fcb, env, "FCB", "Environment");
+ fail_if_overlap(fw1, env, "FW1", "Environment");
+ #endif
+ fail_if_overlap(fcb, fw1, "FCB", "FW1");
+ if (fw2_set) {
+ fail_if_overlap(fcb, fw2, "FCB", "FW2");
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ fail_if_overlap(fw2, env, "FW2", "Environment");
+ #endif
+ fail_if_overlap(fw1, fw2, "FW1", "FW2");
+ }
+
+ buf = malloc(erase_size);
+ if (buf == NULL) {
+ printf("Failed to allocate buffer\n");
+ return -ENOMEM;
+ }
+
+ fcb = create_fcb(buf, fw1_start_block + fw1_skip,
+ fw2_start_block + fw2_skip, fw_num_blocks);
+ if (IS_ERR(fcb)) {
+ printf("Failed to initialize FCB: %ld\n", PTR_ERR(fcb));
+ free(buf);
+ return PTR_ERR(fcb);
+ }
+ encode_hamming_13_8(fcb, (void *)fcb + 512, 512);
+
+ ret = write_fcb(buf, fcb_start_block);
+ free(buf);
+ if (ret) {
+ printf("Failed to write FCB to block %lu\n", fcb_start_block);
+ return ret;
+ }
+
+ if (size & (page_size - 1)) {
+ memset(addr + size, 0xff, size & (page_size - 1));
+ size = ALIGN(size, page_size);
+ }
+
+ printf("Programming U-Boot image from %p to block %lu @ %08llx\n",
+ addr, fw1_start_block + fw1_skip,
+ (u64)(fw1_start_block + fw1_skip) * mtd->erasesize);
+ ret = tx28_prog_uboot(addr, fw1_start_block, fw1_skip, size,
+ max_len1);
+
+ if (fw2_start_block == 0) {
+ return ret;
+ }
+
+ printf("Programming redundant U-Boot image to block %lu @ %08llx\n",
+ fw2_start_block + fw2_skip,
+ (u64)(fw2_start_block + fw2_skip) * mtd->erasesize);
+ ret = tx28_prog_uboot(addr, fw2_start_block, fw2_skip, fw_num_blocks,
+ max_len2);
+ return ret;
+ }
+
+ U_BOOT_CMD(romupdate, 11, 0, do_update,
+ "Creates an FCB data structure and writes an U-Boot image to flash",
+ "[-f {<part>|block#}] [-r [{<part>|block#}]] [-e #] [<address>] [<length>]\n"
+ "\t-f <part>\twrite bootloader image to partition <part>\n"
+ "\t-f #\twrite bootloader image at block # (decimal)\n"
+ "\t-r\twrite redundant bootloader image at next free block after first image\n"
+ "\t-r <part>\twrite redundant bootloader image to partition <part>\n"
+ "\t-r #\twrite redundant bootloader image at block # (decimal)\n"
+ "\t-e #\tspecify number of redundant blocks per boot loader image\n"
+ "\t\tonly valid if -f or -r specify a flash address rather than a partition name\n"
+ "\t<address>\tRAM address of bootloader image (default: ${fileaddr}\n"
+ "\t<length>\tlength of bootloader image in RAM (default: ${filesize}"
+ );
--- /dev/null
- { TX28_USBH_VBUSEN_GPIO, GPIOF_OUTPUT_INIT_LOW, "USBH VBUSEN", },
- { TX28_USBH_OC_GPIO, GPIOF_INPUT, "USBH OC", },
- { TX28_USBOTG_VBUSEN_GPIO, GPIOF_OUTPUT_INIT_LOW, "USBOTG VBUSEN", },
- { TX28_USBOTG_OC_GPIO, GPIOF_INPUT, "USBOTG OC", },
- { TX28_USBOTG_ID_GPIO, GPIOF_INPUT, "USBOTG ID", },
+ /*
+ * Copyright (C) 2011-2013 Lothar Waßmann <LW@KARO-electronics.de>
+ * based on: board/freescale/mx28_evk.c (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <errno.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <lcd.h>
+ #include <netdev.h>
+ #include <mmc.h>
+ #include <mxcfb.h>
+ #include <linux/list.h>
+ #include <linux/fb.h>
+ #include <asm/io.h>
+ #include <asm/gpio.h>
+ #include <asm/arch/iomux-mx28.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/sys_proto.h>
+
+ #include "../common/karo.h"
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define MXS_GPIO_NR(p, o) (((p) << 5) | (o))
+
+ #define TX28_LCD_PWR_GPIO MX28_PAD_LCD_ENABLE__GPIO_1_31
+ #define TX28_LCD_RST_GPIO MX28_PAD_LCD_RESET__GPIO_3_30
+ #define TX28_LCD_BACKLIGHT_GPIO MX28_PAD_PWM0__GPIO_3_16
+
+ #define TX28_USBH_VBUSEN_GPIO MX28_PAD_SPDIF__GPIO_3_27
+ #define TX28_USBH_OC_GPIO MX28_PAD_JTAG_RTCK__GPIO_4_20
+ #define TX28_USBOTG_VBUSEN_GPIO MX28_PAD_GPMI_CE2N__GPIO_0_18
+ #define TX28_USBOTG_OC_GPIO MX28_PAD_GPMI_CE3N__GPIO_0_19
+ #define TX28_USBOTG_ID_GPIO MX28_PAD_PWM2__GPIO_3_18
+
+ #define TX28_LED_GPIO MX28_PAD_ENET0_RXD3__GPIO_4_10
+
+ #define STK5_CAN_XCVR_GPIO MX28_PAD_LCD_D00__GPIO_1_0
+
+ static const struct gpio tx28_gpios[] = {
- .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
++ { TX28_USBH_VBUSEN_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "USBH VBUSEN", },
++ { TX28_USBH_OC_GPIO, GPIOFLAG_INPUT, "USBH OC", },
++ { TX28_USBOTG_VBUSEN_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "USBOTG VBUSEN", },
++ { TX28_USBOTG_OC_GPIO, GPIOFLAG_INPUT, "USBOTG OC", },
++ { TX28_USBOTG_ID_GPIO, GPIOFLAG_INPUT, "USBOTG ID", },
+ };
+
+ static const iomux_cfg_t tx28_pads[] = {
+ /* UART pads */
+ #if CONFIG_CONS_INDEX == 0
+ MX28_PAD_AUART0_RX__DUART_CTS,
+ MX28_PAD_AUART0_TX__DUART_RTS,
+ MX28_PAD_AUART0_CTS__DUART_RX,
+ MX28_PAD_AUART0_RTS__DUART_TX,
+ #elif CONFIG_CONS_INDEX == 1
+ MX28_PAD_AUART1_RX__AUART1_RX,
+ MX28_PAD_AUART1_TX__AUART1_TX,
+ MX28_PAD_AUART1_CTS__AUART1_CTS,
+ MX28_PAD_AUART1_RTS__AUART1_RTS,
+ #elif CONFIG_CONS_INDEX == 2
+ MX28_PAD_AUART3_RX__AUART3_RX,
+ MX28_PAD_AUART3_TX__AUART3_TX,
+ MX28_PAD_AUART3_CTS__AUART3_CTS,
+ MX28_PAD_AUART3_RTS__AUART3_RTS,
+ #endif
+ /* I2C bus for internal DS1339, PCA9554 and on DIMM pins 40/41 */
+ MX28_PAD_I2C0_SCL__I2C0_SCL,
+ MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+ /* USBH VBUSEN, OC */
+ MX28_PAD_SPDIF__GPIO_3_27,
+ MX28_PAD_JTAG_RTCK__GPIO_4_20,
+
+ /* USBOTG VBUSEN, OC, ID */
+ MX28_PAD_GPMI_CE2N__GPIO_0_18,
+ MX28_PAD_GPMI_CE3N__GPIO_0_19,
+ MX28_PAD_PWM2__GPIO_3_18,
+ };
+
+ /*
+ * Functions
+ */
+
+ /* provide at least _some_ sort of randomness */
+ #define MAX_LOOPS 100
+
+ static u32 random;
+
+ static inline void random_init(void)
+ {
+ struct mxs_digctl_regs *digctl_regs = (void *)MXS_DIGCTL_BASE;
+ u32 seed = 0;
+ int i;
+
+ for (i = 0; i < MAX_LOOPS; i++) {
+ u32 hclk = readl(&digctl_regs->hw_digctl_hclkcount);
+ u32 entropy = readl(&digctl_regs->hw_digctl_entropy);
+ u32 usec = readl(&digctl_regs->hw_digctl_microseconds);
+
+ seed = get_timer(hclk ^ entropy ^ usec ^ random ^ seed);
+ srand(seed);
+ random = rand();
+ }
+ }
+
+ #define RTC_PERSISTENT0_CLK32_MASK (RTC_PERSISTENT0_CLOCKSOURCE | \
+ RTC_PERSISTENT0_XTAL32KHZ_PWRUP)
+ static u32 boot_cause __attribute__((section("data")));
+
+ int board_early_init_f(void)
+ {
+ struct mxs_rtc_regs *rtc_regs = (void *)MXS_RTC_BASE;
+ u32 rtc_stat;
+ int timeout = 5000;
+
+ random_init();
+
+ /* IO0 clock at 480MHz */
+ mxs_set_ioclk(MXC_IOCLK0, 480000);
+ /* IO1 clock at 480MHz */
+ mxs_set_ioclk(MXC_IOCLK1, 480000);
+
+ /* SSP0 clock at 96MHz */
+ mxs_set_sspclk(MXC_SSPCLK0, 96000, 0);
+ /* SSP2 clock at 96MHz */
+ mxs_set_sspclk(MXC_SSPCLK2, 96000, 0);
+
+ gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios));
+ mxs_iomux_setup_multiple_pads(tx28_pads, ARRAY_SIZE(tx28_pads));
+
+ while ((rtc_stat = readl(&rtc_regs->hw_rtc_stat)) &
+ RTC_STAT_STALE_REGS_PERSISTENT0) {
+ if (timeout-- < 0)
+ return 1;
+ udelay(1);
+ }
+ boot_cause = readl(&rtc_regs->hw_rtc_persistent0);
+ if ((boot_cause & RTC_PERSISTENT0_CLK32_MASK) !=
+ RTC_PERSISTENT0_CLK32_MASK) {
+ if (boot_cause & RTC_PERSISTENT0_CLOCKSOURCE)
+ goto rtc_err;
+ writel(RTC_PERSISTENT0_CLK32_MASK,
+ &rtc_regs->hw_rtc_persistent0_set);
+ }
+ return 0;
+
+ rtc_err:
+ serial_puts("Inconsistent value in RTC_PERSISTENT0 register; power-on-reset required\n");
+ return 1;
+ }
+
+ int board_init(void)
+ {
+ if (ctrlc()) {
+ printf("CTRL-C detected; safeboot enabled\n");
+ return 1;
+ }
+
+ /* Address of boot parameters */
+ #ifdef CONFIG_OF_LIBFDT
+ gd->bd->bi_arch_number = -1;
+ #endif
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000;
+ return 0;
+ }
+
+ int dram_init(void)
+ {
+ return mxs_dram_init();
+ }
+
+ #ifdef CONFIG_CMD_MMC
+ static int tx28_mmc_wp(int dev_no)
+ {
+ return 0;
+ }
+
+ int board_mmc_init(bd_t *bis)
+ {
+ return mxsmmc_initialize(bis, 0, tx28_mmc_wp, NULL);
+ }
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_FEC_MXC
+ #ifdef CONFIG_GET_FEC_MAC_ADDR_FROM_IIM
+
+ #ifdef CONFIG_FEC_MXC_MULTI
+ #define FEC_MAX_IDX 1
+ #else
+ #define FEC_MAX_IDX 0
+ #endif
+ #ifndef ETH_ALEN
+ #define ETH_ALEN 6
+ #endif
+
+ static int fec_get_mac_addr(int index)
+ {
+ int timeout = 1000;
+ struct mxs_ocotp_regs *ocotp_regs =
+ (struct mxs_ocotp_regs *)MXS_OCOTP_BASE;
+ u32 *cust = &ocotp_regs->hw_ocotp_cust0;
+ u8 mac[ETH_ALEN];
+ char env_name[] = "eth.addr";
+ u32 val = 0;
+ int i;
+
+ if (index < 0 || index > FEC_MAX_IDX)
+ return -EINVAL;
+
+ /* set this bit to open the OTP banks for reading */
+ writel(OCOTP_CTRL_RD_BANK_OPEN,
+ &ocotp_regs->hw_ocotp_ctrl_set);
+
+ /* wait until OTP contents are readable */
+ while (OCOTP_CTRL_BUSY & readl(&ocotp_regs->hw_ocotp_ctrl)) {
+ if (timeout-- < 0)
+ return -ETIMEDOUT;
+ udelay(100);
+ }
+
+ for (i = 0; i < sizeof(mac); i++) {
+ int shift = 24 - i % 4 * 8;
+
+ if (i % 4 == 0)
+ val = readl(&cust[index * 8 + i]);
+ mac[i] = val >> shift;
+ }
+ if (!is_valid_ether_addr(mac)) {
+ if (index == 0)
+ printf("No valid MAC address programmed\n");
+ return 0;
+ }
+
+ if (index == 0) {
+ printf("MAC addr from fuse: %pM\n", mac);
+ snprintf(env_name, sizeof(env_name), "ethaddr");
+ } else {
+ snprintf(env_name, sizeof(env_name), "eth%daddr", index);
+ }
+ eth_setenv_enetaddr(env_name, mac);
+ return 0;
+ }
+ #endif /* CONFIG_GET_FEC_MAC_ADDR_FROM_IIM */
+
+ static const iomux_cfg_t tx28_fec_pads[] = {
+ MX28_PAD_ENET0_RX_EN__ENET0_RX_EN,
+ MX28_PAD_ENET0_RXD0__ENET0_RXD0,
+ MX28_PAD_ENET0_RXD1__ENET0_RXD1,
+ };
+
+ int board_eth_init(bd_t *bis)
+ {
+ int ret;
+
+ /* Reset the external phy */
+ gpio_direction_output(MX28_PAD_ENET0_RX_CLK__GPIO_4_13, 0);
+
+ /* Power on the external phy */
+ gpio_direction_output(MX28_PAD_PWM4__GPIO_3_29, 1);
+
+ /* Pull strap pins to high */
+ gpio_direction_output(MX28_PAD_ENET0_RX_EN__GPIO_4_2, 1);
+ gpio_direction_output(MX28_PAD_ENET0_RXD0__GPIO_4_3, 1);
+ gpio_direction_output(MX28_PAD_ENET0_RXD1__GPIO_4_4, 1);
+ gpio_direction_input(MX28_PAD_ENET0_TX_CLK__GPIO_4_5);
+
+ udelay(25000);
+ gpio_set_value(MX28_PAD_ENET0_RX_CLK__GPIO_4_13, 1);
+ udelay(100);
+
+ mxs_iomux_setup_multiple_pads(tx28_fec_pads, ARRAY_SIZE(tx28_fec_pads));
+
+ ret = cpu_eth_init(bis);
+ if (ret) {
+ printf("cpu_eth_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ #ifdef CONFIG_FEC_MXC_MULTI
+ if (getenv("ethaddr")) {
+ ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
+ if (ret) {
+ printf("FEC MXS: Unable to init FEC0\n");
+ return ret;
+ }
+ }
+
+ if (getenv("eth1addr")) {
+ ret = fecmxc_initialize_multi(bis, 1, 1, MXS_ENET1_BASE);
+ if (ret) {
+ printf("FEC MXS: Unable to init FEC1\n");
+ return ret;
+ }
+ }
+ #else
+ if (getenv("ethaddr")) {
+ ret = fecmxc_initialize(bis);
+ if (ret) {
+ printf("FEC MXS: Unable to init FEC\n");
+ return ret;
+ }
+ }
+ #endif
+ return 0;
+ }
+ #endif /* CONFIG_FEC_MXC */
+
+ enum {
+ LED_STATE_INIT = -1,
+ LED_STATE_OFF,
+ LED_STATE_ON,
+ };
+
+ void show_activity(int arg)
+ {
+ static int led_state = LED_STATE_INIT;
+ static ulong last;
+
+ if (led_state == LED_STATE_INIT) {
+ last = get_timer(0);
+ gpio_set_value(TX28_LED_GPIO, 1);
+ led_state = LED_STATE_ON;
+ } else {
+ if (get_timer(last) > CONFIG_SYS_HZ) {
+ last = get_timer(0);
+ if (led_state == LED_STATE_ON) {
+ gpio_set_value(TX28_LED_GPIO, 0);
+ } else {
+ gpio_set_value(TX28_LED_GPIO, 1);
+ }
+ led_state = 1 - led_state;
+ }
+ }
+ }
+
+ static const iomux_cfg_t stk5_pads[] = {
+ /* SW controlled LED on STK5 baseboard */
+ MX28_PAD_ENET0_RXD3__GPIO_4_10,
+ };
+
+ static const struct gpio stk5_gpios[] = {
+ };
+
+ #ifdef CONFIG_LCD
+ static ushort tx28_cmap[256];
+ vidinfo_t panel_info = {
+ /* set to max. size supported by SoC */
+ .vl_col = 1600,
+ .vl_row = 1200,
+
- { TX28_LCD_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
- { TX28_LCD_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
- { TX28_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
++ .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
+ .cmap = tx28_cmap,
+ };
+
+ static struct fb_videomode tx28_fb_modes[] = {
+ {
+ /* Standard VGA timing */
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* Emerging ETV570 640 x 480 display. Syncs low active,
+ * DE high active, 115.2 mm x 86.4 mm display area
+ * VGA compatible timing
+ */
+ .name = "ETV570",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 114,
+ .hsync_len = 30,
+ .right_margin = 16,
+ .upper_margin = 32,
+ .vsync_len = 3,
+ .lower_margin = 10,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* Emerging ET0350G0DH6 320 x 240 display.
+ * 70.08 mm x 52.56 mm display area.
+ */
+ .name = "ET0350",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6500),
+ .left_margin = 68 - 34,
+ .hsync_len = 34,
+ .right_margin = 20,
+ .upper_margin = 18 - 3,
+ .vsync_len = 3,
+ .lower_margin = 4,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* Emerging ET0430G0DH6 480 x 272 display.
+ * 95.04 mm x 53.856 mm display area.
+ */
+ .name = "ET0430",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 272,
+ .pixclock = KHZ2PICOS(9000),
+ .left_margin = 2,
+ .hsync_len = 41,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .vsync_len = 10,
+ .lower_margin = 2,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* Emerging ET0500G0DH6 800 x 480 display.
+ * 109.6 mm x 66.4 mm display area.
+ */
+ .name = "ET0500",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* Emerging ETQ570G0DH6 320 x 240 display.
+ * 115.2 mm x 86.4 mm display area.
+ */
+ .name = "ETQ570",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6400),
+ .left_margin = 38,
+ .hsync_len = 30,
+ .right_margin = 30,
+ .upper_margin = 16, /* 15 according to datasheet */
+ .vsync_len = 3, /* TVP -> 1>x>5 */
+ .lower_margin = 4, /* 4.5 according to datasheet */
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* Emerging ET0700G0DH6 800 x 480 display.
+ * 152.4 mm x 91.44 mm display area.
+ */
+ .name = "ET0700",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ {
+ /* unnamed entry for assigning parameters parsed from 'video_mode' string */
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ };
+
+ static int lcd_enabled = 1;
+ static int lcd_bl_polarity;
+
+ static int lcd_backlight_polarity(void)
+ {
+ return lcd_bl_polarity;
+ }
+
+ void lcd_enable(void)
+ {
+ /* HACK ALERT:
+ * global variable from common/lcd.c
+ * Set to 0 here to prevent messages from going to LCD
+ * rather than serial console
+ */
+ lcd_is_enabled = 0;
+
+ karo_load_splashimage(1);
+ if (lcd_enabled) {
+ debug("Switching LCD on\n");
+ gpio_set_value(TX28_LCD_PWR_GPIO, 1);
+ udelay(100);
+ gpio_set_value(TX28_LCD_RST_GPIO, 1);
+ udelay(300000);
+ gpio_set_value(TX28_LCD_BACKLIGHT_GPIO,
+ lcd_backlight_polarity());
+ }
+ }
+
+ void lcd_disable(void)
+ {
+ }
+
+ void lcd_panel_disable(void)
+ {
+ if (lcd_enabled) {
+ debug("Switching LCD off\n");
+ gpio_set_value(TX28_LCD_BACKLIGHT_GPIO,
+ !lcd_backlight_polarity());
+ gpio_set_value(TX28_LCD_RST_GPIO, 0);
+ gpio_set_value(TX28_LCD_PWR_GPIO, 0);
+ }
+ }
+
+ static const iomux_cfg_t stk5_lcd_pads[] = {
+ /* LCD RESET */
+ MX28_PAD_LCD_RESET__GPIO_3_30 | MXS_PAD_CTRL,
+ /* LCD POWER_ENABLE */
+ MX28_PAD_LCD_ENABLE__GPIO_1_31 | MXS_PAD_CTRL,
+ /* LCD Backlight (PWM) */
+ MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+
+ /* Display */
+ MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_RD_E__LCD_VSYNC | MXS_PAD_CTRL,
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MXS_PAD_CTRL,
+ MX28_PAD_LCD_RS__LCD_DOTCLK | MXS_PAD_CTRL,
+ MX28_PAD_LCD_CS__LCD_CS | MXS_PAD_CTRL,
+ };
+
+ static const struct gpio stk5_lcd_gpios[] = {
- panel_info.vl_bpix = LCD_COLOR24;
++ { TX28_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
++ { TX28_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
++ { TX28_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ };
+
+ extern void video_hw_init(void *lcdbase);
+
+ void lcd_ctrl_init(void *lcdbase)
+ {
+ int color_depth = 24;
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ const char *vm;
+ unsigned long val;
+ int refresh = 60;
+ struct fb_videomode *p = tx28_fb_modes;
+ struct fb_videomode fb_mode;
+ int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
+
+ if (!lcd_enabled) {
+ debug("LCD disabled\n");
+ return;
+ }
+
+ if (had_ctrlc()) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ setenv("splashimage", NULL);
+ return;
+ }
+
+ karo_fdt_move_fdt();
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
+
+ if (video_mode == NULL) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ return;
+ }
+ vm = video_mode;
+ if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
+ p = &fb_mode;
+ debug("Using video mode from FDT\n");
+ vm += strlen(vm);
+ if (fb_mode.xres > panel_info.vl_col ||
+ fb_mode.yres > panel_info.vl_row) {
+ printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+ fb_mode.xres, fb_mode.yres,
+ panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ }
+ if (p->name != NULL)
+ debug("Trying compiled-in video modes\n");
+ while (p->name != NULL) {
+ if (strcmp(p->name, vm) == 0) {
+ debug("Using video mode: '%s'\n", p->name);
+ vm += strlen(vm);
+ break;
+ }
+ p++;
+ }
+ if (*vm != '\0')
+ debug("Trying to decode video_mode: '%s'\n", vm);
+ while (*vm != '\0') {
+ if (*vm >= '0' && *vm <= '9') {
+ char *end;
+
+ val = simple_strtoul(vm, &end, 0);
+ if (end > vm) {
+ if (!xres_set) {
+ if (val > panel_info.vl_col)
+ val = panel_info.vl_col;
+ p->xres = val;
+ panel_info.vl_col = val;
+ xres_set = 1;
+ } else if (!yres_set) {
+ if (val > panel_info.vl_row)
+ val = panel_info.vl_row;
+ p->yres = val;
+ panel_info.vl_row = val;
+ yres_set = 1;
+ } else if (!bpp_set) {
+ switch (val) {
+ case 8:
+ case 16:
+ case 18:
+ case 24:
+ color_depth = val;
+ break;
+
+ default:
+ printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
+ end - vm, vm, color_depth);
+ }
+ bpp_set = 1;
+ } else if (!refresh_set) {
+ refresh = val;
+ refresh_set = 1;
+ }
+ }
+ vm = end;
+ }
+ switch (*vm) {
+ case '@':
+ bpp_set = 1;
+ /* fallthru */
+ case '-':
+ yres_set = 1;
+ /* fallthru */
+ case 'x':
+ xres_set = 1;
+ /* fallthru */
+ case 'M':
+ case 'R':
+ vm++;
+ break;
+
+ default:
+ if (*vm != '\0')
+ vm++;
+ }
+ }
+ if (p->xres == 0 || p->yres == 0) {
+ printf("Invalid video mode: %s\n", getenv("video_mode"));
+ lcd_enabled = 0;
+ printf("Supported video modes are:");
+ for (p = &tx28_fb_modes[0]; p->name != NULL; p++) {
+ printf(" %s", p->name);
+ }
+ printf("\n");
+ return;
+ }
+ if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
+ printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
+ p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ panel_info.vl_col = p->xres;
+ panel_info.vl_row = p->yres;
+
+ switch (color_depth) {
+ case 8:
+ panel_info.vl_bpix = LCD_COLOR8;
+ break;
+ case 16:
+ panel_info.vl_bpix = LCD_COLOR16;
+ break;
+ default:
- gpio_request_one(STK5_CAN_XCVR_GPIO, GPIOF_OUTPUT_INIT_HIGH,
++ panel_info.vl_bpix = LCD_COLOR32;
+ }
+
+ p->pixclock = KHZ2PICOS(refresh *
+ (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
+ (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) /
+ 1000);
+ debug("Pixel clock set to %lu.%03lu MHz\n",
+ PICOS2KHZ(p->pixclock) / 1000, PICOS2KHZ(p->pixclock) % 1000);
+
+ if (p != &fb_mode) {
+ int ret;
+
+ debug("Creating new display-timing node from '%s'\n",
+ video_mode);
+ ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
+ if (ret)
+ printf("Failed to create new display-timing node from '%s': %d\n",
+ video_mode, ret);
+ }
+
+ gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
+ mxs_iomux_setup_multiple_pads(stk5_lcd_pads,
+ ARRAY_SIZE(stk5_lcd_pads));
+
+ debug("video format: %ux%u-%u@%u\n", p->xres, p->yres,
+ color_depth, refresh);
+
+ if (karo_load_splashimage(0) == 0) {
+ char vmode[128];
+
+ /* setup env variable for mxsfb display driver */
+ snprintf(vmode, sizeof(vmode),
+ "x:%d,y:%d,le:%d,ri:%d,up:%d,lo:%d,hs:%d,vs:%d,sync:%d,pclk:%d,depth:%d",
+ p->xres, p->yres, p->left_margin, p->right_margin,
+ p->upper_margin, p->lower_margin, p->hsync_len,
+ p->vsync_len, p->sync, p->pixclock, color_depth);
+ setenv("videomode", vmode);
+
+ debug("Initializing LCD controller\n");
+ video_hw_init(lcdbase);
+ setenv("videomode", NULL);
+ } else {
+ debug("Skipping initialization of LCD controller\n");
+ }
+ }
+ #else
+ #define lcd_enabled 0
+ #endif /* CONFIG_LCD */
+
+ static void stk5_board_init(void)
+ {
+ gpio_request_array(stk5_gpios, ARRAY_SIZE(stk5_gpios));
+ mxs_iomux_setup_multiple_pads(stk5_pads, ARRAY_SIZE(stk5_pads));
+ }
+
+ static void stk5v3_board_init(void)
+ {
+ stk5_board_init();
+ }
+
+ static void stk5v5_board_init(void)
+ {
+ stk5_board_init();
+
+ /* init flexcan transceiver enable GPIO */
- mxs_iomux_setup_pad(STK5_CAN_XCVR_GPIO);
++ gpio_request_one(STK5_CAN_XCVR_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH,
+ "Flexcan Transceiver");
-void ft_board_setup(void *blob, bd_t *bd)
++ SETUP_IOMUX_PAD(STK5_CAN_XCVR_GPIO);
+ }
+
+ int tx28_fec1_enabled(void)
+ {
+ const char *status;
+ int off;
+
+ if (!gd->fdt_blob)
+ return 0;
+
+ off = fdt_path_offset(gd->fdt_blob, "ethernet1");
+ if (off < 0)
+ return 0;
+
+ status = fdt_getprop(gd->fdt_blob, off, "status", NULL);
+ return status && (strcmp(status, "okay") == 0);
+ }
+
+ static void tx28_init_mac(void)
+ {
+ int ret;
+
+ ret = fec_get_mac_addr(0);
+ if (ret < 0) {
+ printf("Failed to read FEC0 MAC address from OCOTP\n");
+ return;
+ }
+ #ifdef CONFIG_FEC_MXC_MULTI
+ if (tx28_fec1_enabled()) {
+ ret = fec_get_mac_addr(1);
+ if (ret < 0) {
+ printf("Failed to read FEC1 MAC address from OCOTP\n");
+ return;
+ }
+ }
+ #endif
+ }
+
+ int board_late_init(void)
+ {
+ int ret = 0;
+ const char *baseboard;
+
+ env_cleanup();
+
+ if (had_ctrlc())
+ setenv_ulong("safeboot", 1);
+ else
+ karo_fdt_move_fdt();
+
+ baseboard = getenv("baseboard");
+ if (!baseboard)
+ goto exit;
+
+ printf("Baseboard: %s\n", baseboard);
+
+ if (strncmp(baseboard, "stk5", 4) == 0) {
+ if ((strlen(baseboard) == 4) ||
+ strcmp(baseboard, "stk5-v3") == 0) {
+ stk5v3_board_init();
+ } else if (strcmp(baseboard, "stk5-v5") == 0) {
+ const char *otg_mode = getenv("otg_mode");
+
+ if (otg_mode && strcmp(otg_mode, "host") == 0) {
+ printf("otg_mode='%s' is incompatible with baseboard %s; setting to 'none'\n",
+ otg_mode, baseboard);
+ setenv("otg_mode", "none");
+ }
+ stk5v5_board_init();
+ } else {
+ printf("WARNING: Unsupported STK5 board rev.: %s\n",
+ baseboard + 4);
+ }
+ } else {
+ printf("WARNING: Unsupported baseboard: '%s'\n",
+ baseboard);
+ ret = -EINVAL;
+ }
+
+ exit:
+ tx28_init_mac();
+ clear_ctrlc();
+ return ret;
+ }
+
+ #define BOOT_CAUSE_MASK (RTC_PERSISTENT0_EXTERNAL_RESET | \
+ RTC_PERSISTENT0_ALARM_WAKE | \
+ RTC_PERSISTENT0_THERMAL_RESET)
+
+ static void thermal_init(void)
+ {
+ struct mxs_power_regs *power_regs = (void *)MXS_POWER_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs = (void *)MXS_CLKCTRL_BASE;
+
+ writel(POWER_THERMAL_LOW_POWER | POWER_THERMAL_OFFSET_ADJ_ENABLE |
+ POWER_THERMAL_OFFSET_ADJ_OFFSET(3),
+ &power_regs->hw_power_thermal);
+
+ writel(CLKCTRL_RESET_EXTERNAL_RESET_ENABLE |
+ CLKCTRL_RESET_THERMAL_RESET_ENABLE,
+ &clkctrl_regs->hw_clkctrl_reset);
+ }
+
+ int checkboard(void)
+ {
+ struct mxs_power_regs *power_regs = (void *)MXS_POWER_BASE;
+ u32 pwr_sts = readl(&power_regs->hw_power_sts);
+ u32 pwrup_src = (pwr_sts >> 24) & 0x3f;
+ const char *dlm = "";
+
+ printf("Board: Ka-Ro TX28-4%sx%d\n", TX28_MOD_SUFFIX,
+ CONFIG_SDRAM_SIZE / SZ_128M +
+ CONFIG_SYS_NAND_BLOCKS / 2048 * 2);
+
+ printf("POWERUP Source: ");
+ if (pwrup_src & (3 << 0)) {
+ printf("%sPSWITCH %s voltage", dlm,
+ pwrup_src & (1 << 1) ? "HIGH" : "MID");
+ dlm = " | ";
+ }
+ if (pwrup_src & (1 << 4)) {
+ printf("%sRTC", dlm);
+ dlm = " | ";
+ }
+ if (pwrup_src & (1 << 5)) {
+ printf("%s5V", dlm);
+ dlm = " | ";
+ }
+ printf("\n");
+
+ if (boot_cause & BOOT_CAUSE_MASK) {
+ dlm="";
+ printf("Last boot cause: ");
+ if (boot_cause & RTC_PERSISTENT0_EXTERNAL_RESET) {
+ printf("%sEXTERNAL", dlm);
+ dlm = " | ";
+ }
+ if (boot_cause & RTC_PERSISTENT0_THERMAL_RESET) {
+ printf("%sTHERMAL", dlm);
+ dlm = " | ";
+ }
+ if (*dlm != '\0')
+ printf(" RESET");
+ if (boot_cause & RTC_PERSISTENT0_ALARM_WAKE) {
+ printf("%sALARM WAKE", dlm);
+ dlm = " | ";
+ }
+ printf("\n");
+ }
+
+ while (pwr_sts & POWER_STS_THERMAL_WARNING) {
+ static int first = 1;
+
+ if (first) {
+ printf("CPU too hot to boot\n");
+ first = 0;
+ }
+ if (tstc())
+ break;
+ pwr_sts = readl(&power_regs->hw_power_sts);
+ }
+
+ if (!(boot_cause & RTC_PERSISTENT0_THERMAL_RESET))
+ thermal_init();
+
+ return 0;
+ }
+
+ #if defined(CONFIG_OF_BOARD_SETUP)
+ #ifdef CONFIG_FDT_FIXUP_PARTITIONS
+ #include <jffs2/jffs2.h>
+ #include <mtd_node.h>
+ static struct node_info tx28_nand_nodes[] = {
+ { "fsl,imx28-gpmi-nand", MTD_DEV_TYPE_NAND, },
+ };
+ #else
+ #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
+ #endif
+
+ static const char *tx28_touchpanels[] = {
+ "ti,tsc2007",
+ "edt,edt-ft5x06",
+ "fsl,imx28-lradc",
+ };
+
- if (ret)
++int ft_board_setup(void *blob, bd_t *bd)
+ {
+ const char *baseboard = getenv("baseboard");
+ int stk5_v5 = baseboard != NULL && (strcmp(baseboard, "stk5-v5") == 0);
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ int ret;
+
+ ret = fdt_increase_size(blob, 4096);
-
++ if (ret) {
+ printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
++ return ret;
++ }
+ #ifdef CONFIG_TX28_S
+ /* TX28-41xx (aka TX28S) has no external RTC
+ * and no I2C GPIO extender
+ */
+ karo_fdt_remove_node(blob, "ds1339");
+ karo_fdt_remove_node(blob, "gpio5");
+ #endif
+ if (stk5_v5)
+ karo_fdt_enable_node(blob, "stk5led", 0);
+
+ fdt_fixup_mtdparts(blob, tx28_nand_nodes, ARRAY_SIZE(tx28_nand_nodes));
+ fdt_fixup_ethernet(blob);
+
+ karo_fdt_fixup_touchpanel(blob, tx28_touchpanels,
+ ARRAY_SIZE(tx28_touchpanels));
+ karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply");
+ karo_fdt_fixup_flexcan(blob, stk5_v5);
+ karo_fdt_update_fb_mode(blob, video_mode);
++
++ return 0;
+ }
+ #endif /* CONFIG_OF_BOARD_SETUP */
--- /dev/null
--- /dev/null
++if TARGET_TX48
++
++config SYS_BOARD
++ default "tx48"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "am33xx"
++
++config SYS_CONFIG_NAME
++ default "tx48"
++
++endif
--- /dev/null
-# Makefile
+ #
-# Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
++# (C) Copyright 2015 Lothar Waßmann <LW@KARO-electronics.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 version 2.
-#
-# This program is distributed "as is" WITHOUT ANY WARRANTY of any
-# kind, whether express or implied; without even the implied warranty
-# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-
-include $(TOPDIR)/config.mk
++# SPDX-License-Identifier: GPL-2.0+
+ #
-LIB = $(obj)lib$(BOARD).o
-
-ifeq ($(CONFIG_SPL_BUILD),)
- COBJS := tx48.o
+
- COBJS := spl.o
++ifneq ($(CONFIG_SPL_BUILD),y)
++ obj-y += tx48.o
+ else
-
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-SOBJS := $(addprefix $(obj),$(SOBJS))
-
-$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(call cmd_link_o_target, $(OBJS) $(SOBJS))
-
-clean:
- rm -f $(SOBJS) $(OBJS)
-
-distclean: clean
- rm -f $(LIB) core *.bak $(obj).depend
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
++ obj-y += spl.o
+ endif
--- /dev/null
- { TX48_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ /*
+ * board/karo/tx48/spl.c
+ * Copyright (C) 2012 Lothar Waßmann <LW@KARO-electronics.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; 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 <errno.h>
+ #include <miiphy.h>
+ #include <netdev.h>
+ #include <serial.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <nand.h>
+ #include <net.h>
+ #include <spl.h>
+ #include <linux/mtd/nand.h>
+ #include <asm/gpio.h>
+ #include <asm/cache.h>
+ #include <asm/omap_common.h>
+ #include <asm/io.h>
+ #include <asm/arch/cpu.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/mmc_host_def.h>
+ #include <asm/arch/ddr_defs.h>
+ #include <asm/arch/sys_proto.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/mem.h>
+ #include <video_fb.h>
+ #include <asm/arch/da8xx-fb.h>
+
+ #include "flash.h"
+
+ #define TX48_LED_GPIO AM33XX_GPIO_NR(1, 26)
+ #define TX48_ETH_PHY_RST_GPIO AM33XX_GPIO_NR(3, 8)
+ #define TX48_LCD_RST_GPIO AM33XX_GPIO_NR(1, 19)
+ #define TX48_LCD_PWR_GPIO AM33XX_GPIO_NR(1, 22)
+ #define TX48_LCD_BACKLIGHT_GPIO AM33XX_GPIO_NR(3, 14)
+
+ #define GMII_SEL (CTRL_BASE + 0x650)
+
+ /* UART Defines */
+ #define UART_SYSCFG_OFFSET 0x54
+ #define UART_SYSSTS_OFFSET 0x58
+
+ #define UART_RESET (0x1 << 1)
+ #define UART_RESETDONE (1 << 0)
+ #define UART_IDLE_MODE(m) (((m) << 3) & UART_IDLE_MODE_MASK)
+ #define UART_IDLE_MODE_MASK (0x3 << 3)
+
+ /* Timer Defines */
+ #define TSICR_REG 0x54
+ #define TIOCP_CFG_REG 0x10
+ #define TCLR_REG 0x38
+
+ /* RGMII mode define */
+ #define RGMII_MODE_ENABLE 0xA
+ #define RMII_MODE_ENABLE 0x5
+ #define MII_MODE_ENABLE 0x0
+
+ #define NO_OF_MAC_ADDR 1
+ #define ETH_ALEN 6
+
+ /* PAD Control Fields */
+ #define SLEWCTRL (0x1 << 6)
+ #define RXACTIVE (0x1 << 5)
+ #define PULLUP_EN (0x1 << 4) /* Pull UP Selection */
+ #define PULLUDEN (0x0 << 3) /* Pull up enabled */
+ #define PULLUDDIS (0x1 << 3) /* Pull up disabled */
+ #define MODE(val) (val)
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /*
+ * PAD CONTROL OFFSETS
+ * Field names corresponds to the pad signal name
+ */
+ struct pad_signals {
+ int gpmc_ad0;
+ int gpmc_ad1;
+ int gpmc_ad2;
+ int gpmc_ad3;
+ int gpmc_ad4;
+ int gpmc_ad5;
+ int gpmc_ad6;
+ int gpmc_ad7;
+ int gpmc_ad8;
+ int gpmc_ad9;
+ int gpmc_ad10;
+ int gpmc_ad11;
+ int gpmc_ad12;
+ int gpmc_ad13;
+ int gpmc_ad14;
+ int gpmc_ad15;
+ int gpmc_a0;
+ int gpmc_a1;
+ int gpmc_a2;
+ int gpmc_a3;
+ int gpmc_a4;
+ int gpmc_a5;
+ int gpmc_a6;
+ int gpmc_a7;
+ int gpmc_a8;
+ int gpmc_a9;
+ int gpmc_a10;
+ int gpmc_a11;
+ int gpmc_wait0;
+ int gpmc_wpn;
+ int gpmc_be1n;
+ int gpmc_csn0;
+ int gpmc_csn1;
+ int gpmc_csn2;
+ int gpmc_csn3;
+ int gpmc_clk;
+ int gpmc_advn_ale;
+ int gpmc_oen_ren;
+ int gpmc_wen;
+ int gpmc_be0n_cle;
+ int lcd_data0;
+ int lcd_data1;
+ int lcd_data2;
+ int lcd_data3;
+ int lcd_data4;
+ int lcd_data5;
+ int lcd_data6;
+ int lcd_data7;
+ int lcd_data8;
+ int lcd_data9;
+ int lcd_data10;
+ int lcd_data11;
+ int lcd_data12;
+ int lcd_data13;
+ int lcd_data14;
+ int lcd_data15;
+ int lcd_vsync;
+ int lcd_hsync;
+ int lcd_pclk;
+ int lcd_ac_bias_en;
+ int mmc0_dat3;
+ int mmc0_dat2;
+ int mmc0_dat1;
+ int mmc0_dat0;
+ int mmc0_clk;
+ int mmc0_cmd;
+ int mii1_col;
+ int mii1_crs;
+ int mii1_rxerr;
+ int mii1_txen;
+ int mii1_rxdv;
+ int mii1_txd3;
+ int mii1_txd2;
+ int mii1_txd1;
+ int mii1_txd0;
+ int mii1_txclk;
+ int mii1_rxclk;
+ int mii1_rxd3;
+ int mii1_rxd2;
+ int mii1_rxd1;
+ int mii1_rxd0;
+ int rmii1_refclk;
+ int mdio_data;
+ int mdio_clk;
+ int spi0_sclk;
+ int spi0_d0;
+ int spi0_d1;
+ int spi0_cs0;
+ int spi0_cs1;
+ int ecap0_in_pwm0_out;
+ int uart0_ctsn;
+ int uart0_rtsn;
+ int uart0_rxd;
+ int uart0_txd;
+ int uart1_ctsn;
+ int uart1_rtsn;
+ int uart1_rxd;
+ int uart1_txd;
+ int i2c0_sda;
+ int i2c0_scl;
+ int mcasp0_aclkx;
+ int mcasp0_fsx;
+ int mcasp0_axr0;
+ int mcasp0_ahclkr;
+ int mcasp0_aclkr;
+ int mcasp0_fsr;
+ int mcasp0_axr1;
+ int mcasp0_ahclkx;
+ int xdma_event_intr0;
+ int xdma_event_intr1;
+ int nresetin_out;
+ int porz;
+ int nnmi;
+ int osc0_in;
+ int osc0_out;
+ int rsvd1;
+ int tms;
+ int tdi;
+ int tdo;
+ int tck;
+ int ntrst;
+ int emu0;
+ int emu1;
+ int osc1_in;
+ int osc1_out;
+ int pmic_power_en;
+ int rtc_porz;
+ int rsvd2;
+ int ext_wakeup;
+ int enz_kaldo_1p8v;
+ int usb0_dm;
+ int usb0_dp;
+ int usb0_ce;
+ int usb0_id;
+ int usb0_vbus;
+ int usb0_drvvbus;
+ int usb1_dm;
+ int usb1_dp;
+ int usb1_ce;
+ int usb1_id;
+ int usb1_vbus;
+ int usb1_drvvbus;
+ int ddr_resetn;
+ int ddr_csn0;
+ int ddr_cke;
+ int ddr_ck;
+ int ddr_nck;
+ int ddr_casn;
+ int ddr_rasn;
+ int ddr_wen;
+ int ddr_ba0;
+ int ddr_ba1;
+ int ddr_ba2;
+ int ddr_a0;
+ int ddr_a1;
+ int ddr_a2;
+ int ddr_a3;
+ int ddr_a4;
+ int ddr_a5;
+ int ddr_a6;
+ int ddr_a7;
+ int ddr_a8;
+ int ddr_a9;
+ int ddr_a10;
+ int ddr_a11;
+ int ddr_a12;
+ int ddr_a13;
+ int ddr_a14;
+ int ddr_a15;
+ int ddr_odt;
+ int ddr_d0;
+ int ddr_d1;
+ int ddr_d2;
+ int ddr_d3;
+ int ddr_d4;
+ int ddr_d5;
+ int ddr_d6;
+ int ddr_d7;
+ int ddr_d8;
+ int ddr_d9;
+ int ddr_d10;
+ int ddr_d11;
+ int ddr_d12;
+ int ddr_d13;
+ int ddr_d14;
+ int ddr_d15;
+ int ddr_dqm0;
+ int ddr_dqm1;
+ int ddr_dqs0;
+ int ddr_dqsn0;
+ int ddr_dqs1;
+ int ddr_dqsn1;
+ int ddr_vref;
+ int ddr_vtp;
+ int ddr_strben0;
+ int ddr_strben1;
+ int ain7;
+ int ain6;
+ int ain5;
+ int ain4;
+ int ain3;
+ int ain2;
+ int ain1;
+ int ain0;
+ int vrefp;
+ int vrefn;
+ };
+
+ struct pin_mux {
+ short reg_offset;
+ uint8_t val;
+ };
+
+ #define PAD_CTRL_BASE 0x800
+ #define OFFSET(x) (unsigned int) (&((struct pad_signals *) \
+ (PAD_CTRL_BASE))->x)
+
+ static struct pin_mux tx48_pins[] = {
+ #ifdef CONFIG_CMD_NAND
+ { OFFSET(gpmc_ad0), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD0 */
+ { OFFSET(gpmc_ad1), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD1 */
+ { OFFSET(gpmc_ad2), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD2 */
+ { OFFSET(gpmc_ad3), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD3 */
+ { OFFSET(gpmc_ad4), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD4 */
+ { OFFSET(gpmc_ad5), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD5 */
+ { OFFSET(gpmc_ad6), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD6 */
+ { OFFSET(gpmc_ad7), MODE(0) | PULLUP_EN | RXACTIVE, }, /* NAND AD7 */
+ { OFFSET(gpmc_wait0), MODE(0) | RXACTIVE | PULLUP_EN, }, /* NAND WAIT */
+ { OFFSET(gpmc_wpn), MODE(7) | PULLUP_EN | RXACTIVE, }, /* NAND_WPN */
+ { OFFSET(gpmc_csn0), MODE(0) | PULLUDEN, }, /* NAND_CS0 */
+ { OFFSET(gpmc_advn_ale), MODE(0) | PULLUDEN, }, /* NAND_ADV_ALE */
+ { OFFSET(gpmc_oen_ren), MODE(0) | PULLUDEN, }, /* NAND_OE */
+ { OFFSET(gpmc_wen), MODE(0) | PULLUDEN, }, /* NAND_WEN */
+ { OFFSET(gpmc_be0n_cle), MODE(0) | PULLUDEN, }, /* NAND_BE_CLE */
+ #endif
+ /* I2C0 */
+ { OFFSET(i2c0_sda), MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL, }, /* I2C_DATA */
+ { OFFSET(i2c0_scl), MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL, }, /* I2C_SCLK */
+
+ #ifndef CONFIG_NO_ETH
+ /* RMII1 */
+ { OFFSET(mii1_crs), MODE(1) | RXACTIVE, }, /* RMII1_CRS */
+ { OFFSET(mii1_rxerr), MODE(1) | RXACTIVE | PULLUDEN, }, /* RMII1_RXERR */
+ { OFFSET(mii1_txen), MODE(1), }, /* RMII1_TXEN */
+ { OFFSET(mii1_txd1), MODE(1), }, /* RMII1_TXD1 */
+ { OFFSET(mii1_txd0), MODE(1), }, /* RMII1_TXD0 */
+ { OFFSET(mii1_rxd1), MODE(1) | RXACTIVE | PULLUP_EN, }, /* RMII1_RXD1 */
+ { OFFSET(mii1_rxd0), MODE(1) | RXACTIVE | PULLUP_EN, }, /* RMII1_RXD0 */
+ { OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN, }, /* MDIO_DATA */
+ { OFFSET(mdio_clk), MODE(0) | PULLUP_EN, }, /* MDIO_CLK */
+ { OFFSET(rmii1_refclk), MODE(0) | RXACTIVE, }, /* RMII1_REFCLK */
+ { OFFSET(emu0), MODE(7) | RXACTIVE}, /* nINT */
+ { OFFSET(emu1), MODE(7), }, /* nRST */
+ #endif
+ };
+
+ static struct gpio tx48_gpios[] = {
+ /* configure this pin early to prevent flicker of the LCD */
++ { TX48_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ };
+
+ static struct pin_mux tx48_mmc_pins[] = {
+ #ifdef CONFIG_OMAP_HSMMC
+ /* MMC1 */
+ { OFFSET(mii1_rxd2), MODE(4) | RXACTIVE | PULLUP_EN, }, /* MMC1_DAT3 */
+ { OFFSET(mii1_rxd3), MODE(4) | RXACTIVE | PULLUP_EN, }, /* MMC1_DAT2 */
+ { OFFSET(mii1_rxclk), MODE(4) | RXACTIVE | PULLUP_EN, }, /* MMC1_DAT1 */
+ { OFFSET(mii1_txclk), MODE(4) | RXACTIVE | PULLUP_EN, }, /* MMC1_DAT0 */
+ { OFFSET(gpmc_csn1), MODE(2) | RXACTIVE | PULLUP_EN, }, /* MMC1_CLK */
+ { OFFSET(gpmc_csn2), MODE(2) | RXACTIVE | PULLUP_EN, }, /* MMC1_CMD */
+ { OFFSET(mcasp0_fsx), MODE(4) | RXACTIVE, }, /* MMC1_CD */
+ #endif
+ };
+
+ /*
+ * Configure the pin mux for the module
+ */
+ static inline void tx48_set_pin_mux(const struct pin_mux *pin_mux,
+ int num_pins)
+ {
+ int i;
+
+ for (i = 0; i < num_pins; i++)
+ writel(pin_mux[i].val, CTRL_BASE + pin_mux[i].reg_offset);
+ }
+
+ static struct pin_mux tx48_uart0_pins[] = {
+ #ifdef CONFIG_SYS_NS16550_COM1
+ /* UART0 for early boot messages */
+ { OFFSET(uart0_rxd), MODE(0) | PULLUP_EN | RXACTIVE, }, /* UART0_RXD */
+ { OFFSET(uart0_txd), MODE(0) | PULLUDEN, }, /* UART0_TXD */
+ { OFFSET(uart0_ctsn), MODE(0) | PULLUP_EN | RXACTIVE, },/* UART0_CTS */
+ { OFFSET(uart0_rtsn), MODE(0) | PULLUDEN, }, /* UART0_RTS */
+ #endif
+ #ifdef CONFIG_SYS_NS16550_COM2
+ /* UART1 */
+ { OFFSET(uart1_rxd), MODE(0) | PULLUP_EN | RXACTIVE, }, /* UART1_RXD */
+ { OFFSET(uart1_txd), MODE(0) | PULLUDEN, }, /* UART1_TXD */
+ { OFFSET(uart1_ctsn), MODE(0) | PULLUP_EN | RXACTIVE, },/* UART1_CTS */
+ { OFFSET(uart1_rtsn), MODE(0) | PULLUDEN, }, /* UART1_RTS */
+ #endif
+ #ifdef CONFIG_SYS_NS16550_COM3
+ /* UART5 */
+ { OFFSET(mii1_rxdv), MODE(3) | PULLUP_EN | RXACTIVE, }, /* UART5_RXD */
+ { OFFSET(mii1_col), MODE(3) | PULLUDEN, }, /* UART5_TXD */
+ { OFFSET(mmc0_dat1), MODE(2) | PULLUP_EN | RXACTIVE, }, /* UART5_CTS */
+ { OFFSET(mmc0_dat0), MODE(2) | PULLUDEN, }, /* UART5_RTS */
+ #endif
+ };
+
+ /*
+ * early system init of muxing and clocks.
+ */
+ static void enable_uart0_pin_mux(void)
+ {
+ tx48_set_pin_mux(tx48_uart0_pins, ARRAY_SIZE(tx48_uart0_pins));
+ }
+
+ static void enable_mmc0_pin_mux(void)
+ {
+ tx48_set_pin_mux(tx48_mmc_pins, ARRAY_SIZE(tx48_mmc_pins));
+ }
+
+ static const u32 gpmc_nand_cfg[GPMC_MAX_REG] = {
+ TX48_NAND_GPMC_CONFIG1,
+ TX48_NAND_GPMC_CONFIG2,
+ TX48_NAND_GPMC_CONFIG3,
+ TX48_NAND_GPMC_CONFIG4,
+ TX48_NAND_GPMC_CONFIG5,
+ TX48_NAND_GPMC_CONFIG6,
+ };
+
+ #define SDRAM_CLK CONFIG_SYS_DDR_CLK
+
+ #define ns_TO_ck(ns) (((ns) * SDRAM_CLK + 999) / 1000)
+ #define ck_TO_ns(ck) ((ck) * 1000 / SDRAM_CLK)
+
+ #ifdef DEBUG
+ static inline unsigned ck_val_check(unsigned ck, unsigned offs, unsigned max,
+ const char *name)
+ {
+ if (ck < offs) {
+ printf("value %u for parameter %s is out of range (min: %u\n",
+ ck, name, offs);
+ hang();
+ }
+ if (ck > max) {
+ printf("value %u for parameter %s is out of range (max: %u\n",
+ ck, name, max);
+ hang();
+ }
+ return ck - offs;
+ }
+ #define CK_VAL(ck, offs, max) ck_val_check(ck, offs, max, #ck)
+ #else
+ #define CK_VAL(ck, offs, max) ((ck) - (offs))
+ #endif
+
+ #define DDR3_NT5CB128 1
+ #define DDR3_H5TQ2G8 2
+
+ #if 1
+ #define SDRAM_TYPE DDR3_NT5CB128
+ #else
+ #define SDRAM_TYPE DDR3_H5TQ2G8
+ #endif
+
+ #ifndef SDRAM_TYPE
+ #error No SDRAM_TYPE specified
+ #elif (SDRAM_TYPE == DDR3_NT5CB128) || (SDRAM_TYPE == DDR3_H5TQ2G8)
+ #define tRP ns_TO_ck(14)
+ #define tRCD ns_TO_ck(14)
+ #define tWR ns_TO_ck(15)
+ #define tRAS ns_TO_ck(35)
+ #define tRC ns_TO_ck(49)
+ #define tRRD max(ns_TO_ck(8), 4)
+ #define tWTR max(ns_TO_ck(8), 4)
+
+ #define tXP max(ns_TO_ck(6), 3)
+ #define tXPR max(5, ns_TO_ck(ck_TO_ns(tRFC + 1) + 10))
+ #define tODT ns_TO_ck(9)
+ #define tXSNR max(5, ns_TO_ck(ck_TO_ns(tRFC + 1) + 10))
+ #define tXSRD 512
+ #define tRTP max(ns_TO_ck(8), 4)
+ #define tCKE max(ns_TO_ck(6), 3)
+
+ #define tPDLL_UL 512
+ #define tZQCS 64
+ #define tRFC ns_TO_ck(160)
+ #define tRAS_MAX 0xf
+
+ static inline int cwl(u32 sdram_clk)
+ {
+ if (sdram_clk <= 300)
+ return 5;
+ else if (sdram_clk > 300 && sdram_clk <= 333)
+ return 5;
+ else if (sdram_clk > 333 && sdram_clk <= 400)
+ return 5;
+ else if (sdram_clk > 400 && sdram_clk <= 533)
+ return 6;
+ else if (sdram_clk > 533 && sdram_clk <= 666)
+ return 7;
+ else if (SDRAM_TYPE != DDR3_H5TQ2G8)
+ ;
+ else if (sdram_clk > 666 && sdram_clk <= 800)
+ return 8;
+
+ printf("SDRAM clock out of range\n");
+ hang();
+ }
+ #define CWL cwl(SDRAM_CLK)
+
+ static inline int cl(u32 sdram_clk)
+ {
+ if (sdram_clk <= 300)
+ return 5;
+ else if (sdram_clk > 300 && sdram_clk <= 333)
+ return 5;
+ else if (sdram_clk > 333 && sdram_clk <= 400)
+ return 6;
+ else if (sdram_clk > 400 && sdram_clk <= 533)
+ return 8;
+ else if (sdram_clk > 533 && sdram_clk <= 666)
+ return (SDRAM_TYPE == DDR3_H5TQ2G8) ? 10 : 9;
+ else if (SDRAM_TYPE != DDR3_H5TQ2G8)
+ ;
+ else if (sdram_clk > 666 && sdram_clk <= 800)
+ return 11;
+
+ printf("SDRAM clock out of range\n");
+ hang();
+ }
+ #define CL cl(SDRAM_CLK)
+
+ #define ROW_ADDR_BITS 14
+ #define SDRAM_PG_SIZE 1024
+ #else
+ #error Unsupported SDRAM_TYPE specified
+ #endif
+
+ #define SDRAM_CONFIG_VAL ( \
+ (3 << 29) /* SDRAM type: 0: DDR1 1: LPDDR1 2: DDR2 3: DDR3 */ | \
+ (0 << 27) /* IBANK pos */ | \
+ (2 << 24) /* termination resistor value 0: disable 1: RZQ/4 2: RZQ/2 3: RZQ/6 4: RZQ/12 5: RZQ/8 */ | \
+ (0 << 23) /* DDR2 differential DQS */ | \
+ (1 << 21) /* dynamic ODT 0: off 1: RZQ/4 2: RZQ/2 */ | \
+ (0 << 20) /* DLL disable */ | \
+ (1 << 18) /* drive strength 0: RZQ/6 1: RZQ/7 */ | \
+ ((CWL - 5) << 16) /* CWL 0: 5 ... 3: 8 */ | \
+ (1 << 14) /* SDRAM data bus width 0: 32 1: 16 */ | \
+ (((CL - 4) * 2) << 10) /* CAS latency 2: 5 4: 6 6: 8 ... 14: 11 (DDR3) */ | \
+ ((ROW_ADDR_BITS - 9) << 7) /* # of row addr bits 0: 9 ... 7: 16 */ | \
+ (3 << 4) /* # of SDRAM internal banks 0: 1 1: 2 2: 4 3: 8 */ | \
+ (0 << 3) /* # of CS lines */ | \
+ ((ffs(SDRAM_PG_SIZE / 256) - 1) << 0) /* page size 0: 256 1: 512 2: 1024 3:2048 */ | \
+ 0)
+
+ #define SDREF_VAL ( \
+ (0 << 31) /* */ | \
+ (1 << 29) /* self refresh temperature range 1: extended temp range */ | \
+ (0 << 28) /* auto self refresh enable */ | \
+ (0 << 24) /* partial array self refresh */ | \
+ ((SDRAM_CLK * 7800 / 1000) << 0) /* refresh interval */ | \
+ 0)
+
+ #define tFAW ns_TO_ck(45)
+
+ #define SDRAM_TIM1_VAL ((CK_VAL(tRP, 1, 16) << 25) | \
+ (CK_VAL(tRCD, 1, 16) << 21) | \
+ (CK_VAL(tWR, 1, 16) << 17) | \
+ (CK_VAL(tRAS, 1, 32) << 12) | \
+ (CK_VAL(tRC, 1, 64) << 6) | \
+ (CK_VAL(tRRD, 1, 8) << 3) | \
+ (CK_VAL(tWTR, 1, 8) << 0))
+
+ #define SDRAM_TIM2_VAL ((CK_VAL(max(tCKE, tXP), 1, 8) << 28) | \
+ (CK_VAL(tODT, 0, 8) << 25) | \
+ (CK_VAL(tXSNR, 1, 128) << 16) | \
+ (CK_VAL(tXSRD, 1, 1024) << 6) | \
+ (CK_VAL(tRTP, 1, 8) << 3) | \
+ (CK_VAL(tCKE, 1, 8) << 0))
+
+ #define SDRAM_TIM3_VAL ((CK_VAL(DIV_ROUND_UP(tPDLL_UL, 128), 0, 16) << 28) | \
+ (CK_VAL(tZQCS, 1, 64) << 15) | \
+ (CK_VAL(tRFC, 1, 1024) << 4) | \
+ (CK_VAL(tRAS_MAX, 0, 16) << 0))
+
+ #define ZQ_CONFIG_VAL ( \
+ (1 << 31) /* ZQ calib for CS1 */ | \
+ (0 << 30) /* ZQ calib for CS0 */ | \
+ (0 << 29) /* dual calib */ | \
+ (1 << 28) /* ZQ calib on SR/PWDN exit */ | \
+ (2 << 18) /* ZQCL intervals for ZQINIT */ | \
+ (4 << 16) /* ZQCS intervals for ZQCL */ | \
+ (80 << 0) /* refr periods between ZQCS commands */ | \
+ 0)
+
+ static struct ddr_data tx48_ddr3_data = {
+ /* reset defaults */
+ .datardsratio0 = 0x04010040,
+ .datawdsratio0 = 0x0,
+ .datafwsratio0 = 0x0,
+ .datawrsratio0 = 0x04010040,
+ .datadldiff0 = 0x4,
+ };
+
+ static struct cmd_control tx48_ddr3_cmd_ctrl_data = {
+ /* reset defaults */
+ .cmd0csratio = 0x80,
+ .cmd0dldiff = 0x04,
+ .cmd1csratio = 0x80,
+ .cmd1dldiff = 0x04,
+ .cmd2csratio = 0x80,
+ .cmd2dldiff = 0x04,
+ };
+
+ static void ddr3_calib_start(void)
+ {
+ static struct emif_reg_struct *emif_reg = (void *)EMIF4_0_CFG_BASE;
+ int loops = 0;
+ u32 regval;
+ u32 emif_status;
+
+ debug("Starting DDR3 calibration\n");
+
+ /* wait for DDR PHY ready */
+ while (!((emif_status = readl(&emif_reg->emif_status)) & (1 << 2))) {
+ if (loops++ > 100000)
+ break;
+ udelay(1);
+ }
+ debug("EMIF status: %08x after %u loops\n", emif_status, loops);
+
+ /* enable DDR3 write levelling */
+ loops = 0;
+ writel(EMIF_REG_RDWRLVLFULL_START_MASK, &emif_reg->emif_rd_wr_lvl_ctl);
+ do {
+ regval = readl(&emif_reg->emif_rd_wr_lvl_ctl);
+ if (!(regval & EMIF_REG_RDWRLVLFULL_START_MASK))
+ break;
+ udelay(1);
+ } while (loops++ < 100000);
+ if (regval & EMIF_REG_RDWRLVLFULL_START_MASK) {
+ printf("Full WRLVL timed out\n");
+ } else {
+ debug("Full Write Levelling done after %u us\n", loops);
+ }
+ writel(0, &emif_reg->emif_rd_wr_lvl_rmp_ctl);
+ writel(0, &emif_reg->emif_rd_wr_lvl_rmp_win);
+ writel(0x0f808080, &emif_reg->emif_rd_wr_lvl_ctl);
+ debug("DDR3 calibration done\n");
+ }
+
+ static void tx48_ddr_init(void)
+ {
+ struct emif_regs r = {0};
+
+ debug("Initialising SDRAM timing for %u MHz DDR clock\n", SDRAM_CLK);
+
+ r.sdram_config = SDRAM_CONFIG_VAL;
+ r.ref_ctrl = SDREF_VAL;
+ r.sdram_tim1 = SDRAM_TIM1_VAL;
+ r.sdram_tim2 = SDRAM_TIM2_VAL;
+ r.sdram_tim3 = SDRAM_TIM3_VAL;
+ r.zq_config = ZQ_CONFIG_VAL;
+ r.emif_ddr_phy_ctlr_1 = 0x0000030b;
+
+ config_ddr(SDRAM_CLK, 0x04, &tx48_ddr3_data,
+ &tx48_ddr3_cmd_ctrl_data, &r, 0);
+
+ ddr3_calib_start();
+
+ debug("%s: config_ddr done\n", __func__);
+ }
+
+ #ifdef CONFIG_HW_WATCHDOG
+ static inline void tx48_wdog_disable(void)
+ {
+ }
+ #else
+ static inline void tx48_wdog_disable(void)
+ {
+ struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
+
+ /* WDT1 is already running when the bootloader gets control
+ * Disable it to avoid "random" resets
+ */
+ writel(0xAAAA, &wdtimer->wdtwspr);
+ while (readl(&wdtimer->wdtwwps) != 0x0)
+ ;
+ writel(0x5555, &wdtimer->wdtwspr);
+ while (readl(&wdtimer->wdtwwps) != 0x0)
+ ;
+ }
+ #endif
+
+ void s_init(void)
+ {
+ struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
+ struct gpmc *gpmc_cfg = (struct gpmc *)GPMC_BASE;
+ int timeout = 1000;
+
+ gd = &gdata;
+
+ /*
+ * Save the boot parameters passed from romcode.
+ * We cannot delay the saving further than this,
+ * to prevent overwrites.
+ */
+ save_omap_boot_params();
+
+ /* Setup the PLLs and the clocks for the peripherals */
+ pll_init();
+
+ tx48_wdog_disable();
+
+ enable_uart0_pin_mux();
+
+ /* UART softreset */
+ writel(readl(&uart_base->uartsyscfg) | UART_RESET,
+ &uart_base->uartsyscfg);
+ while (!(readl(&uart_base->uartsyssts) & UART_RESETDONE)) {
+ udelay(1);
+ if (timeout-- <= 0)
+ break;
+ }
+
+ /* Disable smart idle */
+ writel((readl(&uart_base->uartsyscfg) & ~UART_IDLE_MODE_MASK) |
+ UART_IDLE_MODE(1), &uart_base->uartsyscfg);
+
+ preloader_console_init();
+
+ if (timeout <= 0)
+ printf("Timeout waiting for UART RESET\n");
+
+ timer_init();
+
+ tx48_ddr_init();
+
+ gpmc_init();
+ enable_gpmc_cs_config(gpmc_nand_cfg, &gpmc_cfg->cs[0],
+ CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_SIZE);
+
+ /* Enable MMC0 */
+ enable_mmc0_pin_mux();
+
+ gpio_request_array(tx48_gpios, ARRAY_SIZE(tx48_gpios));
+ tx48_set_pin_mux(tx48_pins, ARRAY_SIZE(tx48_pins));
+ }
--- /dev/null
- { AM33XX_GPIO_NR(3, 5), GPIOF_INPUT, "I2C1_SDA", },
- { AM33XX_GPIO_NR(3, 6), GPIOF_INPUT, "I2C1_SCL", },
- { AM33XX_GPIO_NR(3, 8), GPIOF_OUTPUT_INIT_LOW, "ETH_PHY_RESET", },
+ /*
+ * Copyright (C) 2012-2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * based on evm.c
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; 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 <errno.h>
+ #include <miiphy.h>
+ #include <netdev.h>
+ #include <serial.h>
+ #include <libfdt.h>
+ #include <lcd.h>
+ #include <fdt_support.h>
+ #include <nand.h>
+ #include <net.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/fb.h>
+ #include <asm/gpio.h>
+ #include <asm/cache.h>
+ #include <asm/omap_common.h>
+ #include <asm/io.h>
+ #include <asm/arch/cpu.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/mmc_host_def.h>
+ #include <asm/arch/sys_proto.h>
+ #include <asm/arch/clock.h>
+ #include <video_fb.h>
+ #include <asm/arch/da8xx-fb.h>
+
+ #include "../common/karo.h"
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define TX48_LED_GPIO AM33XX_GPIO_NR(1, 26)
+ #define TX48_ETH_PHY_RST_GPIO AM33XX_GPIO_NR(3, 8)
+ #define TX48_LCD_RST_GPIO AM33XX_GPIO_NR(1, 19)
+ #define TX48_LCD_PWR_GPIO AM33XX_GPIO_NR(1, 22)
+ #define TX48_LCD_BACKLIGHT_GPIO AM33XX_GPIO_NR(3, 14)
+ #define TX48_MMC_CD_GPIO AM33XX_GPIO_NR(3, 15)
+
+ #define GMII_SEL (CTRL_BASE + 0x650)
+
+ /* UART Defines */
+ #define UART_SYSCFG_OFFSET 0x54
+ #define UART_SYSSTS_OFFSET 0x58
+
+ #define UART_RESET (0x1 << 1)
+ #define UART_CLK_RUNNING_MASK 0x1
+ #define UART_SMART_IDLE_EN (0x1 << 0x3)
+
+ /* Timer Defines */
+ #define TSICR_REG 0x54
+ #define TIOCP_CFG_REG 0x10
+ #define TCLR_REG 0x38
+
+ /* RGMII mode define */
+ #define RGMII_MODE_ENABLE 0xA
+ #define RMII_MODE_ENABLE 0x5
+ #define MII_MODE_ENABLE 0x0
+
+ #define NO_OF_MAC_ADDR 1
+ #define ETH_ALEN 6
+
+ /* PAD Control Fields */
+ #define SLEWCTRL (0x1 << 6)
+ #define RXACTIVE (0x1 << 5)
+ #define PULLUP_EN (0x1 << 4) /* Pull UP Selection */
+ #define PULLUDEN (0x0 << 3) /* Pull up enabled */
+ #define PULLUDDIS (0x1 << 3) /* Pull up disabled */
+ #define MODE(val) (val)
+
+ /*
+ * PAD CONTROL OFFSETS
+ * Field names corresponds to the pad signal name
+ */
+ struct pad_signals {
+ int gpmc_ad0;
+ int gpmc_ad1;
+ int gpmc_ad2;
+ int gpmc_ad3;
+ int gpmc_ad4;
+ int gpmc_ad5;
+ int gpmc_ad6;
+ int gpmc_ad7;
+ int gpmc_ad8;
+ int gpmc_ad9;
+ int gpmc_ad10;
+ int gpmc_ad11;
+ int gpmc_ad12;
+ int gpmc_ad13;
+ int gpmc_ad14;
+ int gpmc_ad15;
+ int gpmc_a0;
+ int gpmc_a1;
+ int gpmc_a2;
+ int gpmc_a3;
+ int gpmc_a4;
+ int gpmc_a5;
+ int gpmc_a6;
+ int gpmc_a7;
+ int gpmc_a8;
+ int gpmc_a9;
+ int gpmc_a10;
+ int gpmc_a11;
+ int gpmc_wait0;
+ int gpmc_wpn;
+ int gpmc_be1n;
+ int gpmc_csn0;
+ int gpmc_csn1;
+ int gpmc_csn2;
+ int gpmc_csn3;
+ int gpmc_clk;
+ int gpmc_advn_ale;
+ int gpmc_oen_ren;
+ int gpmc_wen;
+ int gpmc_be0n_cle;
+ int lcd_data0;
+ int lcd_data1;
+ int lcd_data2;
+ int lcd_data3;
+ int lcd_data4;
+ int lcd_data5;
+ int lcd_data6;
+ int lcd_data7;
+ int lcd_data8;
+ int lcd_data9;
+ int lcd_data10;
+ int lcd_data11;
+ int lcd_data12;
+ int lcd_data13;
+ int lcd_data14;
+ int lcd_data15;
+ int lcd_vsync;
+ int lcd_hsync;
+ int lcd_pclk;
+ int lcd_ac_bias_en;
+ int mmc0_dat3;
+ int mmc0_dat2;
+ int mmc0_dat1;
+ int mmc0_dat0;
+ int mmc0_clk;
+ int mmc0_cmd;
+ int mii1_col;
+ int mii1_crs;
+ int mii1_rxerr;
+ int mii1_txen;
+ int mii1_rxdv;
+ int mii1_txd3;
+ int mii1_txd2;
+ int mii1_txd1;
+ int mii1_txd0;
+ int mii1_txclk;
+ int mii1_rxclk;
+ int mii1_rxd3;
+ int mii1_rxd2;
+ int mii1_rxd1;
+ int mii1_rxd0;
+ int rmii1_refclk;
+ int mdio_data;
+ int mdio_clk;
+ int spi0_sclk;
+ int spi0_d0;
+ int spi0_d1;
+ int spi0_cs0;
+ int spi0_cs1;
+ int ecap0_in_pwm0_out;
+ int uart0_ctsn;
+ int uart0_rtsn;
+ int uart0_rxd;
+ int uart0_txd;
+ int uart1_ctsn;
+ int uart1_rtsn;
+ int uart1_rxd;
+ int uart1_txd;
+ int i2c0_sda;
+ int i2c0_scl;
+ int mcasp0_aclkx;
+ int mcasp0_fsx;
+ int mcasp0_axr0;
+ int mcasp0_ahclkr;
+ int mcasp0_aclkr;
+ int mcasp0_fsr;
+ int mcasp0_axr1;
+ int mcasp0_ahclkx;
+ int xdma_event_intr0;
+ int xdma_event_intr1;
+ int nresetin_out;
+ int porz;
+ int nnmi;
+ int osc0_in;
+ int osc0_out;
+ int rsvd1;
+ int tms;
+ int tdi;
+ int tdo;
+ int tck;
+ int ntrst;
+ int emu0;
+ int emu1;
+ int osc1_in;
+ int osc1_out;
+ int pmic_power_en;
+ int rtc_porz;
+ int rsvd2;
+ int ext_wakeup;
+ int enz_kaldo_1p8v;
+ int usb0_dm;
+ int usb0_dp;
+ int usb0_ce;
+ int usb0_id;
+ int usb0_vbus;
+ int usb0_drvvbus;
+ int usb1_dm;
+ int usb1_dp;
+ int usb1_ce;
+ int usb1_id;
+ int usb1_vbus;
+ int usb1_drvvbus;
+ int ddr_resetn;
+ int ddr_csn0;
+ int ddr_cke;
+ int ddr_ck;
+ int ddr_nck;
+ int ddr_casn;
+ int ddr_rasn;
+ int ddr_wen;
+ int ddr_ba0;
+ int ddr_ba1;
+ int ddr_ba2;
+ int ddr_a0;
+ int ddr_a1;
+ int ddr_a2;
+ int ddr_a3;
+ int ddr_a4;
+ int ddr_a5;
+ int ddr_a6;
+ int ddr_a7;
+ int ddr_a8;
+ int ddr_a9;
+ int ddr_a10;
+ int ddr_a11;
+ int ddr_a12;
+ int ddr_a13;
+ int ddr_a14;
+ int ddr_a15;
+ int ddr_odt;
+ int ddr_d0;
+ int ddr_d1;
+ int ddr_d2;
+ int ddr_d3;
+ int ddr_d4;
+ int ddr_d5;
+ int ddr_d6;
+ int ddr_d7;
+ int ddr_d8;
+ int ddr_d9;
+ int ddr_d10;
+ int ddr_d11;
+ int ddr_d12;
+ int ddr_d13;
+ int ddr_d14;
+ int ddr_d15;
+ int ddr_dqm0;
+ int ddr_dqm1;
+ int ddr_dqs0;
+ int ddr_dqsn0;
+ int ddr_dqs1;
+ int ddr_dqsn1;
+ int ddr_vref;
+ int ddr_vtp;
+ int ddr_strben0;
+ int ddr_strben1;
+ int ain7;
+ int ain6;
+ int ain5;
+ int ain4;
+ int ain3;
+ int ain2;
+ int ain1;
+ int ain0;
+ int vrefp;
+ int vrefn;
+ };
+
+ struct pin_mux {
+ short reg_offset;
+ uint8_t val;
+ };
+
+ #define PAD_CTRL_BASE 0x800
+ #define OFFSET(x) (unsigned int) (&((struct pad_signals *) \
+ (PAD_CTRL_BASE))->x)
+
+ /*
+ * Configure the pin mux for the module
+ */
+ static inline void tx48_set_pin_mux(const struct pin_mux *pin_mux,
+ int num_pins)
+ {
+ int i;
+
+ for (i = 0; i < num_pins; i++)
+ writel(pin_mux[i].val, CTRL_BASE + pin_mux[i].reg_offset);
+ }
+
+ #define PRM_RSTST_GLOBAL_COLD_RST (1 << 0)
+ #define PRM_RSTST_GLOBAL_WARM_SW_RST (1 << 1)
+ #define PRM_RSTST_WDT1_RST (1 << 4)
+ #define PRM_RSTST_EXTERNAL_WARM_RST (1 << 5)
+ #define PRM_RSTST_ICEPICK_RST (1 << 9)
+
+ static u32 prm_rstst __attribute__((section(".data")));
+
+ /*
+ * Basic board specific setup
+ */
+ static const struct pin_mux tx48_pads[] = {
+ { OFFSET(i2c0_sda), MODE(7) | RXACTIVE | PULLUDEN | PULLUP_EN, },
+ { OFFSET(i2c0_scl), MODE(7) | RXACTIVE | PULLUDEN | PULLUP_EN, },
+ { OFFSET(emu1), MODE(7), }, /* ETH PHY Reset */
+ };
+
+ static const struct pin_mux tx48_i2c_pads[] = {
+ { OFFSET(i2c0_sda), MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN, },
+ { OFFSET(i2c0_scl), MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN, },
+ };
+
+ static const struct gpio tx48_gpios[] = {
- { TX48_LED_GPIO, GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
- { TX48_MMC_CD_GPIO, GPIOF_INPUT, "MMC0 CD", },
++ { AM33XX_GPIO_NR(3, 5), GPIOFLAG_INPUT, "I2C1_SDA", },
++ { AM33XX_GPIO_NR(3, 6), GPIOFLAG_INPUT, "I2C1_SCL", },
++ { AM33XX_GPIO_NR(3, 8), GPIOFLAG_OUTPUT_INIT_LOW, "ETH_PHY_RESET", },
+ };
+
+ static const struct pin_mux stk5_pads[] = {
+ /* heartbeat LED */
+ { OFFSET(gpmc_a10), MODE(7) | PULLUDEN, },
+ /* LCD RESET */
+ { OFFSET(gpmc_a3), MODE(7) | PULLUDEN, },
+ /* LCD POWER_ENABLE */
+ { OFFSET(gpmc_a6), MODE(7) | PULLUDEN, },
+ /* LCD Backlight (PWM) */
+ { OFFSET(mcasp0_aclkx), MODE(7) | PULLUDEN, },
+ /* MMC CD */
+ { OFFSET(mcasp0_fsx), MODE(7) | PULLUDEN | PULLUP_EN, },
+ };
+
+ static const struct gpio stk5_gpios[] = {
- { AM33XX_GPIO_NR(1, 19), GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
- { AM33XX_GPIO_NR(1, 22), GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
- { AM33XX_GPIO_NR(3, 14), GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
++ { TX48_LED_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
++ { TX48_MMC_CD_GPIO, GPIOFLAG_INPUT, "MMC0 CD", },
+ };
+
+ static const struct pin_mux stk5_lcd_pads[] = {
+ /* LCD data bus */
+ { OFFSET(lcd_data0), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data1), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data2), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data3), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data4), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data5), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data6), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data7), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data8), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data9), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data10), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data11), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data12), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data13), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data14), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_data15), MODE(0) | PULLUDEN, },
+ /* LCD control signals */
+ { OFFSET(lcd_hsync), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_vsync), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_pclk), MODE(0) | PULLUDEN, },
+ { OFFSET(lcd_ac_bias_en), MODE(0) | PULLUDEN, },
+ };
+
+ static const struct gpio stk5_lcd_gpios[] = {
- { AM33XX_GPIO_NR(0, 22), GPIOF_OUTPUT_INIT_HIGH, "CAN XCVR", },
++ { AM33XX_GPIO_NR(1, 19), GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
++ { AM33XX_GPIO_NR(1, 22), GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
++ { AM33XX_GPIO_NR(3, 14), GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ };
+
+ static const struct pin_mux stk5v5_pads[] = {
+ /* CAN transceiver control */
+ { OFFSET(gpmc_ad8), MODE(7) | PULLUDEN, },
+ };
+
+ static const struct gpio stk5v5_gpios[] = {
- .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
++ { AM33XX_GPIO_NR(0, 22), GPIOFLAG_OUTPUT_INIT_HIGH, "CAN XCVR", },
+ };
+
+ #ifdef CONFIG_LCD
+ static u16 tx48_cmap[256];
+ vidinfo_t panel_info = {
+ /* set to max. size supported by SoC */
+ .vl_col = 1366,
+ .vl_row = 768,
+
- panel_info.vl_bpix = LCD_COLOR24;
++ .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
+ .cmap = tx48_cmap,
+ };
+
+ #define FB_SYNC_OE_LOW_ACT (1 << 31)
+ #define FB_SYNC_CLK_LAT_FALL (1 << 30)
+
+ static struct fb_videomode tx48_fb_modes[] = {
+ {
+ /* Standard VGA timing */
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETV570 640 x 480 display. Syncs low active,
+ * DE high active, 115.2 mm x 86.4 mm display area
+ * VGA compatible timing
+ */
+ .name = "ETV570",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 114,
+ .hsync_len = 30,
+ .right_margin = 16,
+ .upper_margin = 32,
+ .vsync_len = 3,
+ .lower_margin = 10,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0350G0DH6 320 x 240 display.
+ * 70.08 mm x 52.56 mm display area.
+ */
+ .name = "ET0350",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6500),
+ .left_margin = 68 - 34,
+ .hsync_len = 34,
+ .right_margin = 20,
+ .upper_margin = 18 - 3,
+ .vsync_len = 3,
+ .lower_margin = 4,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0430G0DH6 480 x 272 display.
+ * 95.04 mm x 53.856 mm display area.
+ */
+ .name = "ET0430",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 272,
+ .pixclock = KHZ2PICOS(9000),
+ .left_margin = 2,
+ .hsync_len = 41,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .vsync_len = 10,
+ .lower_margin = 2,
+ },
+ {
+ /* Emerging ET0500G0DH6 800 x 480 display.
+ * 109.6 mm x 66.4 mm display area.
+ */
+ .name = "ET0500",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETQ570G0DH6 320 x 240 display.
+ * 115.2 mm x 86.4 mm display area.
+ */
+ .name = "ETQ570",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6400),
+ .left_margin = 38,
+ .hsync_len = 30,
+ .right_margin = 30,
+ .upper_margin = 16, /* 15 according to datasheet */
+ .vsync_len = 3, /* TVP -> 1>x>5 */
+ .lower_margin = 4, /* 4.5 according to datasheet */
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0700G0DH6 800 x 480 display.
+ * 152.4 mm x 91.44 mm display area.
+ */
+ .name = "ET0700",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* unnamed entry for assigning parameters parsed from 'video_mode' string */
+ .refresh = 60,
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ };
+
+ void *lcd_base; /* Start of framebuffer memory */
+ void *lcd_console_address; /* Start of console buffer */
+
+ int lcd_color_fg;
+ int lcd_color_bg;
+
+ short console_col;
+ short console_row;
+
+ static int lcd_enabled = 1;
+ static int lcd_bl_polarity;
+
+ static int lcd_backlight_polarity(void)
+ {
+ return lcd_bl_polarity;
+ }
+
+ void lcd_initcolregs(void)
+ {
+ }
+
+ void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
+ {
+ }
+
+ void lcd_enable(void)
+ {
+ /* HACK ALERT:
+ * global variable from common/lcd.c
+ * Set to 0 here to prevent messages from going to LCD
+ * rather than serial console
+ */
+ lcd_is_enabled = 0;
+
+ if (lcd_enabled) {
+ karo_load_splashimage(1);
+
+ debug("Switching LCD on\n");
+ gpio_set_value(TX48_LCD_PWR_GPIO, 1);
+ udelay(100);
+ gpio_set_value(TX48_LCD_RST_GPIO, 1);
+ udelay(300000);
+ gpio_set_value(TX48_LCD_BACKLIGHT_GPIO,
+ lcd_backlight_polarity());
+ }
+ }
+
+ void lcd_disable(void)
+ {
+ if (lcd_enabled) {
+ printf("Disabling LCD\n");
+ da8xx_fb_disable();
+ lcd_enabled = 0;
+ }
+ }
+
+ static void tx48_lcd_panel_setup(struct da8xx_panel *p,
+ struct fb_videomode *fb)
+ {
+ p->pxl_clk = PICOS2KHZ(fb->pixclock) * 1000;
+
+ p->width = fb->xres;
+ p->hbp = fb->left_margin;
+ p->hsw = fb->hsync_len;
+ p->hfp = fb->right_margin;
+
+ p->height = fb->yres;
+ p->vbp = fb->upper_margin;
+ p->vsw = fb->vsync_len;
+ p->vfp = fb->lower_margin;
+
+ p->invert_pxl_clk = !!(fb->sync & FB_SYNC_CLK_LAT_FALL);
+ }
+
+ void lcd_panel_disable(void)
+ {
+ if (lcd_enabled) {
+ debug("Switching LCD off\n");
+ gpio_set_value(TX48_LCD_BACKLIGHT_GPIO,
+ !lcd_backlight_polarity());
+ gpio_set_value(TX48_LCD_PWR_GPIO, 0);
+ gpio_set_value(TX48_LCD_RST_GPIO, 0);
+ }
+ }
+
+ void lcd_ctrl_init(void *lcdbase)
+ {
+ int color_depth = 24;
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ const char *vm;
+ unsigned long val;
+ int refresh = 60;
+ struct fb_videomode *p = &tx48_fb_modes[0];
+ struct fb_videomode fb_mode;
+ int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
+
+ if (!lcd_enabled) {
+ debug("LCD disabled\n");
+ return;
+ }
+
+ if (had_ctrlc() || (prm_rstst & PRM_RSTST_WDT1_RST)) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ setenv("splashimage", NULL);
+ return;
+ }
+
+ karo_fdt_move_fdt();
+
+ if (video_mode == NULL) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ return;
+ }
+
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
+ vm = video_mode;
+ if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
+ p = &fb_mode;
+ debug("Using video mode from FDT\n");
+ vm += strlen(vm);
+ if (fb_mode.xres > panel_info.vl_col ||
+ fb_mode.yres > panel_info.vl_row) {
+ printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+ fb_mode.xres, fb_mode.yres,
+ panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ }
+ if (p->name != NULL)
+ debug("Trying compiled-in video modes\n");
+ while (p->name != NULL) {
+ if (strcmp(p->name, vm) == 0) {
+ debug("Using video mode: '%s'\n", p->name);
+ vm += strlen(vm);
+ break;
+ }
+ p++;
+ }
+ if (*vm != '\0')
+ debug("Trying to decode video_mode: '%s'\n", vm);
+ while (*vm != '\0') {
+ if (*vm >= '0' && *vm <= '9') {
+ char *end;
+
+ val = simple_strtoul(vm, &end, 0);
+ if (end > vm) {
+ if (!xres_set) {
+ if (val > panel_info.vl_col)
+ val = panel_info.vl_col;
+ p->xres = val;
+ panel_info.vl_col = val;
+ xres_set = 1;
+ } else if (!yres_set) {
+ if (val > panel_info.vl_row)
+ val = panel_info.vl_row;
+ p->yres = val;
+ panel_info.vl_row = val;
+ yres_set = 1;
+ } else if (!bpp_set) {
+ switch (val) {
+ case 24:
+ case 16:
+ case 8:
+ color_depth = val;
+ break;
+
+ default:
+ printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
+ end - vm, vm, color_depth);
+ }
+ bpp_set = 1;
+ } else if (!refresh_set) {
+ refresh = val;
+ refresh_set = 1;
+ }
+ }
+ vm = end;
+ }
+ switch (*vm) {
+ case '@':
+ bpp_set = 1;
+ /* fallthru */
+ case '-':
+ yres_set = 1;
+ /* fallthru */
+ case 'x':
+ xres_set = 1;
+ /* fallthru */
+ case 'M':
+ case 'R':
+ vm++;
+ break;
+
+ default:
+ if (*vm != '\0')
+ vm++;
+ }
+ }
+ if (p->xres == 0 || p->yres == 0) {
+ printf("Invalid video mode: %s\n", getenv("video_mode"));
+ lcd_enabled = 0;
+ printf("Supported video modes are:");
+ for (p = &tx48_fb_modes[0]; p->name != NULL; p++) {
+ printf(" %s", p->name);
+ }
+ printf("\n");
+ return;
+ }
+ if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
+ printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
+ p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ panel_info.vl_col = p->xres;
+ panel_info.vl_row = p->yres;
+
+ switch (color_depth) {
+ case 8:
+ panel_info.vl_bpix = LCD_COLOR8;
+ break;
+ case 16:
+ panel_info.vl_bpix = LCD_COLOR16;
+ break;
+ default:
-void ft_board_setup(void *blob, bd_t *bd)
++ panel_info.vl_bpix = LCD_COLOR32;
+ }
+
+ p->pixclock = KHZ2PICOS(refresh *
+ (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
+ (p->yres + p->upper_margin + p->lower_margin + p->vsync_len)
+ / 1000);
+ debug("Pixel clock set to %lu.%03lu MHz\n",
+ PICOS2KHZ(p->pixclock) / 1000,
+ PICOS2KHZ(p->pixclock) % 1000);
+
+ if (p != &fb_mode) {
+ int ret;
+
+ debug("Creating new display-timing node from '%s'\n",
+ video_mode);
+ ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
+ if (ret)
+ printf("Failed to create new display-timing node from '%s': %d\n",
+ video_mode, ret);
+ }
+
+ gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
+ tx48_set_pin_mux(stk5_lcd_pads, ARRAY_SIZE(stk5_lcd_pads));
+
+ if (karo_load_splashimage(0) == 0) {
+ struct da8xx_panel da8xx_panel = { };
+
+ debug("Initializing FB driver\n");
+ tx48_lcd_panel_setup(&da8xx_panel, p);
+ da8xx_video_init(&da8xx_panel, color_depth);
+
+ debug("Initializing LCD controller\n");
+ video_hw_init();
+ } else {
+ debug("Skipping initialization of LCD controller\n");
+ }
+ }
+ #else
+ #define lcd_enabled 0
+ #endif /* CONFIG_LCD */
+
+ static void stk5_board_init(void)
+ {
+ gpio_request_array(stk5_gpios, ARRAY_SIZE(stk5_gpios));
+ tx48_set_pin_mux(stk5_pads, ARRAY_SIZE(stk5_pads));
+ }
+
+ static void stk5v3_board_init(void)
+ {
+ stk5_board_init();
+ }
+
+ static void stk5v5_board_init(void)
+ {
+ stk5_board_init();
+
+ gpio_request_array(stk5v5_gpios, ARRAY_SIZE(stk5v5_gpios));
+ tx48_set_pin_mux(stk5v5_pads, ARRAY_SIZE(stk5v5_pads));
+ }
+
+ /* called with default environment! */
+ int board_init(void)
+ {
+ int i;
+
+ /* mach type passed to kernel */
+ #ifdef CONFIG_OF_LIBFDT
+ gd->bd->bi_arch_number = -1;
+ #endif
+ /* address of boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+ if (ctrlc() || (prm_rstst & PRM_RSTST_WDT1_RST)) {
+ if (prm_rstst & PRM_RSTST_WDT1_RST)
+ printf("WDOG RESET detected\n");
+ else
+ printf("<CTRL-C> detected; safeboot enabled\n");
+ }
+
+ gpio_request_array(tx48_gpios, ARRAY_SIZE(tx48_gpios));
+ tx48_set_pin_mux(tx48_pads, ARRAY_SIZE(tx48_pads));
+
+ for (i = 0; i < ARRAY_SIZE(tx48_gpios); i++) {
+ int gpio = tx48_gpios[i].gpio;
+
+ if (gpio_get_value(gpio) == 0)
+ gpio_direction_output(gpio, 1);
+ }
+
+ tx48_set_pin_mux(tx48_pads, ARRAY_SIZE(tx48_i2c_pads));
+ return 0;
+ }
+
+ static void show_reset_cause(u32 prm_rstst)
+ {
+ const char *dlm = "";
+
+ printf("RESET cause: ");
+ if (prm_rstst & PRM_RSTST_GLOBAL_COLD_RST) {
+ printf("%sPOR", dlm);
+ dlm = " | ";
+ }
+ if (prm_rstst & PRM_RSTST_GLOBAL_WARM_SW_RST) {
+ printf("%sSW", dlm);
+ dlm = " | ";
+ }
+ if (prm_rstst & PRM_RSTST_WDT1_RST) {
+ printf("%sWATCHDOG", dlm);
+ dlm = " | ";
+ }
+ if (prm_rstst & PRM_RSTST_EXTERNAL_WARM_RST) {
+ printf("%sWARM", dlm);
+ dlm = " | ";
+ }
+ if (prm_rstst & PRM_RSTST_ICEPICK_RST) {
+ printf("%sJTAG", dlm);
+ dlm = " | ";
+ }
+ if (*dlm == '\0')
+ printf("unknown");
+
+ printf(" RESET\n");
+ }
+
+ /* called with default environment! */
+ int checkboard(void)
+ {
+ prm_rstst = readl(PRM_RSTST);
+ show_reset_cause(prm_rstst);
+
+ printf("Board: Ka-Ro TX48-7020\n");
+
+ timer_init();
+ return 0;
+ }
+
+ static void tx48_set_cpu_clock(void)
+ {
+ unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
+ unsigned long act_cpu_clk;
+
+ if (cpu_clk == 0 || cpu_clk == mpu_clk_rate() / 1000000)
+ return;
+
+ if (had_ctrlc() || (prm_rstst & PRM_RSTST_WDT1_RST)) {
+ printf("%s detected; skipping cpu clock change\n",
+ (prm_rstst & PRM_RSTST_WDT1_RST) ?
+ "WDOG RESET" : "<CTRL-C>");
+ return;
+ }
+
+ mpu_pll_config_val(cpu_clk);
+
+ act_cpu_clk = mpu_clk_rate();
+ if (cpu_clk * 1000000 != act_cpu_clk) {
+ printf("Failed to set CPU clock to %lu MHz; using %lu.%03lu MHz instead\n",
+ cpu_clk, act_cpu_clk / 1000000,
+ act_cpu_clk / 1000 % 1000);
+ } else {
+ printf("CPU clock set to %lu.%03lu MHz\n",
+ act_cpu_clk / 1000000, act_cpu_clk / 1000 % 1000);
+ }
+ }
+
+ static void tx48_init_mac(void)
+ {
+ uint8_t mac_addr[ETH_ALEN];
+ uint32_t mac_hi, mac_lo;
+
+ /* try reading mac address from efuse */
+ mac_lo = __raw_readl(MAC_ID0_LO);
+ mac_hi = __raw_readl(MAC_ID0_HI);
+
+ mac_addr[0] = mac_hi & 0xFF;
+ mac_addr[1] = (mac_hi & 0xFF00) >> 8;
+ mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
+ mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
+ mac_addr[4] = mac_lo & 0xFF;
+ mac_addr[5] = (mac_lo & 0xFF00) >> 8;
+
+ if (!is_valid_ether_addr(mac_addr)) {
+ printf("No valid MAC address programmed\n");
+ return;
+ }
+ printf("MAC addr from fuse: %pM\n", mac_addr);
+ eth_setenv_enetaddr("ethaddr", mac_addr);
+ }
+
+ /* called with environment from NAND or MMC */
+ int board_late_init(void)
+ {
+ int ret = 0;
+ const char *baseboard;
+
+ env_cleanup();
+
+ tx48_set_cpu_clock();
+
+ if (had_ctrlc())
+ setenv_ulong("safeboot", 1);
+ else if (prm_rstst & PRM_RSTST_WDT1_RST)
+ setenv_ulong("wdreset", 1);
+ else
+ karo_fdt_move_fdt();
+
+ baseboard = getenv("baseboard");
+ if (!baseboard)
+ goto exit;
+
+ if (strncmp(baseboard, "stk5", 4) == 0) {
+ printf("Baseboard: %s\n", baseboard);
+ if ((strlen(baseboard) == 4) ||
+ strcmp(baseboard, "stk5-v3") == 0) {
+ stk5v3_board_init();
+ } else if (strcmp(baseboard, "stk5-v5") == 0) {
+ stk5v5_board_init();
+ } else {
+ printf("WARNING: Unsupported STK5 board rev.: %s\n",
+ baseboard + 4);
+ }
+ } else {
+ printf("WARNING: Unsupported baseboard: '%s'\n",
+ baseboard);
+ ret = -EINVAL;
+ }
+
+ exit:
+ tx48_init_mac();
+ clear_ctrlc();
+ return ret;
+ }
+
+ #ifdef CONFIG_DRIVER_TI_CPSW
+ static void tx48_phy_init(void)
+ {
+ debug("%s: Resetting ethernet PHY\n", __func__);
+
+ gpio_direction_output(TX48_ETH_PHY_RST_GPIO, 0);
+
+ udelay(100);
+
+ /* Release nRST */
+ gpio_set_value(TX48_ETH_PHY_RST_GPIO, 1);
+
+ /* Wait for PHY internal POR signal to deassert */
+ udelay(25000);
+ }
+
+ static void cpsw_control(int enabled)
+ {
+ /* nothing for now */
+ /* TODO : VTP was here before */
+ }
+
+ static struct cpsw_slave_data cpsw_slaves[] = {
+ {
+ .slave_reg_ofs = 0x208,
+ .sliver_reg_ofs = 0xd80,
+ .phy_id = 0,
+ .phy_if = PHY_INTERFACE_MODE_RMII,
+ },
+ };
+
+ void s_init(void)
+ {
+ /* Nothing to be done here */
+ }
+
+ static struct cpsw_platform_data cpsw_data = {
+ .mdio_base = CPSW_MDIO_BASE,
+ .cpsw_base = CPSW_BASE,
+ .mdio_div = 0xff,
+ .channels = 8,
+ .cpdma_reg_ofs = 0x800,
+ .slaves = ARRAY_SIZE(cpsw_slaves),
+ .slave_data = cpsw_slaves,
+ .ale_reg_ofs = 0xd00,
+ .ale_entries = 1024,
+ .host_port_reg_ofs = 0x108,
+ .hw_stats_reg_ofs = 0x900,
+ .mac_control = (1 << 5) /* MIIEN */,
+ .control = cpsw_control,
+ .gigabit_en = 0,
+ .host_port_num = 0,
+ .version = CPSW_CTRL_VERSION_2,
+ };
+
+ int board_eth_init(bd_t *bis)
+ {
+ __raw_writel(RMII_MODE_ENABLE, MAC_MII_SEL);
+ __raw_writel(0x5D, GMII_SEL);
+ tx48_phy_init();
+ return cpsw_register(&cpsw_data);
+ }
+ #endif /* CONFIG_DRIVER_TI_CPSW */
+
+ #if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
+ int cpu_mmc_init(bd_t *bis)
+ {
+ return omap_mmc_init(1, 0, 0, TX48_MMC_CD_GPIO, -1);
+ }
+ #endif
+
+ void tx48_disable_watchdog(void)
+ {
+ struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
+
+ while (readl(&wdtimer->wdtwwps) & (1 << 4))
+ ;
+ writel(0xaaaa, &wdtimer->wdtwspr);
+ while (readl(&wdtimer->wdtwwps) & (1 << 4))
+ ;
+ writel(0x5555, &wdtimer->wdtwspr);
+ }
+
+ enum {
+ LED_STATE_INIT = -1,
+ LED_STATE_OFF,
+ LED_STATE_ON,
+ };
+
+ void show_activity(int arg)
+ {
+ static int led_state = LED_STATE_INIT;
+ static ulong last;
+
+ if (led_state == LED_STATE_INIT) {
+ last = get_timer(0);
+ gpio_set_value(TX48_LED_GPIO, 1);
+ led_state = LED_STATE_ON;
+ } else {
+ if (get_timer(last) > CONFIG_SYS_HZ) {
+ last = get_timer(0);
+ if (led_state == LED_STATE_ON) {
+ gpio_set_value(TX48_LED_GPIO, 0);
+ } else {
+ gpio_set_value(TX48_LED_GPIO, 1);
+ }
+ led_state = 1 - led_state;
+ }
+ }
+ }
+
+ #ifdef CONFIG_OF_BOARD_SETUP
+ #ifdef CONFIG_FDT_FIXUP_PARTITIONS
+ #include <jffs2/jffs2.h>
+ #include <mtd_node.h>
+ static struct node_info nodes[] = {
+ { "ti,omap2-nand", MTD_DEV_TYPE_NAND, },
+ { "ti,am3352-gpmc", MTD_DEV_TYPE_NAND, },
+ };
+
+ #else
+ #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
+ #endif /* CONFIG_FDT_FIXUP_PARTITIONS */
+
+ static const char *tx48_touchpanels[] = {
+ "ti,tsc2007",
+ "edt,edt-ft5x06",
+ "ti,am3359-tscadc",
+ };
+
- if (ret)
++int ft_board_setup(void *blob, bd_t *bd)
+ {
+ const char *baseboard = getenv("baseboard");
+ int stk5_v5 = baseboard != NULL && (strcmp(baseboard, "stk5-v5") == 0);
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ int ret;
+
+ ret = fdt_increase_size(blob, 4096);
-
++ if (ret) {
+ printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
++ return ret;
++ }
+ fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+ fdt_fixup_ethernet(blob);
+
+ karo_fdt_fixup_touchpanel(blob, tx48_touchpanels,
+ ARRAY_SIZE(tx48_touchpanels));
+ karo_fdt_fixup_usb_otg(blob, "usb0", "phys", "vcc-supply");
+ karo_fdt_fixup_flexcan(blob, stk5_v5);
+
+ karo_fdt_update_fb_mode(blob, video_mode);
+
+ tx48_disable_watchdog();
+
+ if (get_cpu_rev() == 0) {
+ karo_fdt_del_prop(blob, "lltc,ltc3589-2", 0x34, "interrupts");
+ karo_fdt_del_prop(blob, "lltc,ltc3589-2", 0x34,
+ "interrupt-parent");
+ }
++
++ return 0;
+ }
+ #endif /* CONFIG_OF_BOARD_SETUP */
--- /dev/null
--- /dev/null
++if TARGET_TX51_8XX0
++
++config SYS_BOARD
++ default "tx51"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mx5"
++
++config SYS_CONFIG_NAME
++ default "tx51-8xx0"
++
++endif
++
++if TARGET_TX51_8XX1_2
++
++config SYS_BOARD
++ default "tx51"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mx5"
++
++config SYS_CONFIG_NAME
++ default "tx51-8xx1_2"
++
++endif
--- /dev/null
-# (C) Copyright 2009 DENX Software Engineering
-# Author: John Rigby <jcrigby@gmail.com>
+ #
-# See file CREDITS for list of people who contributed to this
-# project.
++# (C) Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ #
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-# MA 02111-1307 USA
-#
-
-include $(TOPDIR)/config.mk
-
-LDSCRIPT := $(BOARDDIR)/u-boot.lds
-
-LIB = $(obj)lib$(BOARD).o
-
-COBJS := tx51.o
-SOBJS := lowlevel_init.o
-
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-SOBJS := $(addprefix $(obj),$(SOBJS))
-
-$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(call cmd_link_o_target, $(OBJS) $(SOBJS))
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
++# SPDX-License-Identifier: GPL-2.0+
+ #
-#########################################################################
+
++obj-y += tx51.o lowlevel_init.o
--- /dev/null
- { TX51_RESET_OUT_GPIO, GPIOF_OUTPUT_INIT_LOW, "RESET_OUT", },
+ /*
+ * Copyright (C) 2011-2013 Lothar Waßmann <LW@KARO-electronics.de>
+ * based on: board/freescale/mx28_evk.c (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <errno.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <lcd.h>
+ #include <netdev.h>
+ #include <mmc.h>
+ #include <fsl_esdhc.h>
+ #include <video_fb.h>
+ #include <ipu.h>
+ #include <mxcfb.h>
+ #include <linux/fb.h>
+ #include <asm/io.h>
+ #include <asm/gpio.h>
+ #include <asm/arch/iomux-mx51.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/crm_regs.h>
+ #include <asm/arch/sys_proto.h>
+
+ #include "../common/karo.h"
+
+ #define TX51_FEC_RST_GPIO IMX_GPIO_NR(2, 14)
+ #define TX51_FEC_PWR_GPIO IMX_GPIO_NR(1, 3)
+ #define TX51_FEC_INT_GPIO IMX_GPIO_NR(3, 18)
+ #define TX51_LED_GPIO IMX_GPIO_NR(4, 10)
+
+ #define TX51_LCD_PWR_GPIO IMX_GPIO_NR(4, 14)
+ #define TX51_LCD_RST_GPIO IMX_GPIO_NR(4, 13)
+ #define TX51_LCD_BACKLIGHT_GPIO IMX_GPIO_NR(1, 2)
+
+ #define TX51_RESET_OUT_GPIO IMX_GPIO_NR(2, 15)
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define IOMUX_SION IOMUX_PAD(0, 0, IOMUX_CONFIG_SION, 0, 0, 0)
+
+ #define FEC_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_DSE_HIGH | \
+ PAD_CTL_SRE_FAST)
+ #define FEC_PAD_CTRL2 MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_SRE_FAST)
+ #define GPIO_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DVS | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP)
+
+ static iomux_v3_cfg_t tx51_pads[] = {
+ /* NAND flash pads are set up in lowlevel_init.S */
+
+ /* RESET_OUT */
+ MX51_PAD_EIM_A21__GPIO2_15 | GPIO_PAD_CTRL,
+
+ /* UART pads */
+ #if CONFIG_MXC_UART_BASE == UART1_BASE
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+ #endif
+ #if CONFIG_MXC_UART_BASE == UART2_BASE
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+ MX51_PAD_EIM_D26__UART2_RTS,
+ MX51_PAD_EIM_D25__UART2_CTS,
+ #endif
+ #if CONFIG_MXC_UART_BASE == UART3_BASE
+ MX51_PAD_UART3_RXD__UART3_RXD,
+ MX51_PAD_UART3_TXD__UART3_TXD,
+ MX51_PAD_EIM_D18__UART3_RTS,
+ MX51_PAD_EIM_D17__UART3_CTS,
+ #endif
+ /* internal I2C */
+ MX51_PAD_I2C1_DAT__GPIO4_17 | IOMUX_SION,
+ MX51_PAD_I2C1_CLK__GPIO4_16 | IOMUX_SION,
+
+ /* FEC PHY GPIO functions */
+ MX51_PAD_GPIO1_3__GPIO1_3 | GPIO_PAD_CTRL, /* PHY POWER */
+ MX51_PAD_EIM_A20__GPIO2_14 | GPIO_PAD_CTRL, /* PHY RESET */
+ MX51_PAD_NANDF_CS2__GPIO3_18 | GPIO_PAD_CTRL, /* PHY INT */
+
+ /* FEC functions */
+ MX51_PAD_NANDF_CS3__FEC_MDC | FEC_PAD_CTRL,
+ MX51_PAD_EIM_EB2__FEC_MDIO | FEC_PAD_CTRL,
+ MX51_PAD_NANDF_D11__FEC_RX_DV | FEC_PAD_CTRL2,
+ MX51_PAD_EIM_CS4__FEC_RX_ER | FEC_PAD_CTRL2,
+ MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK | FEC_PAD_CTRL2,
+ MX51_PAD_NANDF_CS7__FEC_TX_EN | FEC_PAD_CTRL,
+ MX51_PAD_NANDF_D8__FEC_TDATA0 | FEC_PAD_CTRL,
+ MX51_PAD_NANDF_CS4__FEC_TDATA1 | FEC_PAD_CTRL,
+ MX51_PAD_NANDF_CS5__FEC_TDATA2 | FEC_PAD_CTRL,
+ MX51_PAD_NANDF_CS6__FEC_TDATA3 | FEC_PAD_CTRL,
+
+ /* strap pins for PHY configuration */
+ MX51_PAD_NANDF_RB3__GPIO3_11 | GPIO_PAD_CTRL, /* RX_CLK/REGOFF */
+ MX51_PAD_NANDF_D9__GPIO3_31 | GPIO_PAD_CTRL, /* RXD0/Mode0 */
+ MX51_PAD_EIM_EB3__GPIO2_23 | GPIO_PAD_CTRL, /* RXD1/Mode1 */
+ MX51_PAD_EIM_CS2__GPIO2_27 | GPIO_PAD_CTRL, /* RXD2/Mode2 */
+ MX51_PAD_EIM_CS3__GPIO2_28 | GPIO_PAD_CTRL, /* RXD3/nINTSEL */
+ MX51_PAD_NANDF_RB2__GPIO3_10 | GPIO_PAD_CTRL, /* COL/RMII/CRSDV */
+ MX51_PAD_EIM_CS5__GPIO2_30 | GPIO_PAD_CTRL, /* CRS/PHYAD4 */
+
+ /* unusable pins on TX51 */
+ MX51_PAD_GPIO1_0__GPIO1_0,
+ MX51_PAD_GPIO1_1__GPIO1_1,
+ };
+
+ static const struct gpio tx51_gpios[] = {
+ /* RESET_OUT */
- { TX51_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC POWER", }, /* PHY POWER */
- { TX51_FEC_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC RESET", }, /* PHY RESET */
- { TX51_FEC_INT_GPIO, GPIOF_INPUT, "FEC PHY INT", }, /* PHY INT (TX_ER) */
++ { TX51_RESET_OUT_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "RESET_OUT", },
+
+ /* FEC PHY control GPIOs */
- { IMX_GPIO_NR(3, 11), GPIOF_OUTPUT_INIT_LOW, "FEC PHY REGOFF", }, /* RX_CLK/REGOFF */
- { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_LOW, "FEC PHY MODE0", }, /* RXD0/Mode0 */
- { IMX_GPIO_NR(2, 23), GPIOF_OUTPUT_INIT_LOW, "FEC PHY MODE1", }, /* RXD1/Mode1 */
- { IMX_GPIO_NR(2, 27), GPIOF_OUTPUT_INIT_LOW, "FEC PHY MODE2", }, /* RXD2/Mode2 */
- { IMX_GPIO_NR(2, 28), GPIOF_OUTPUT_INIT_LOW, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */
- { IMX_GPIO_NR(3, 10), GPIOF_OUTPUT_INIT_LOW, "FEC PHY RMII", }, /* COL/RMII/CRSDV */
- { IMX_GPIO_NR(2, 30), GPIOF_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */
++ { TX51_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC POWER", }, /* PHY POWER */
++ { TX51_FEC_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC RESET", }, /* PHY RESET */
++ { TX51_FEC_INT_GPIO, GPIOFLAG_INPUT, "FEC PHY INT", }, /* PHY INT (TX_ER) */
+
+ /* FEC PHY strap pins */
- { IMX_GPIO_NR(4, 17), GPIOF_INPUT, "I2C1 SDA", },
- { IMX_GPIO_NR(4, 16), GPIOF_INPUT, "I2C1 SCL", },
++ { IMX_GPIO_NR(3, 11), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY REGOFF", }, /* RX_CLK/REGOFF */
++ { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY MODE0", }, /* RXD0/Mode0 */
++ { IMX_GPIO_NR(2, 23), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY MODE1", }, /* RXD1/Mode1 */
++ { IMX_GPIO_NR(2, 27), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY MODE2", }, /* RXD2/Mode2 */
++ { IMX_GPIO_NR(2, 28), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */
++ { IMX_GPIO_NR(3, 10), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY RMII", }, /* COL/RMII/CRSDV */
++ { IMX_GPIO_NR(2, 30), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */
+
+ /* module internal I2C bus */
- { IMX_GPIO_NR(1, 0), GPIOF_OUTPUT_INIT_LOW, "N/C", },
- { IMX_GPIO_NR(1, 1), GPIOF_OUTPUT_INIT_LOW, "N/C", },
++ { IMX_GPIO_NR(4, 17), GPIOFLAG_INPUT, "I2C1 SDA", },
++ { IMX_GPIO_NR(4, 16), GPIOFLAG_INPUT, "I2C1 SCL", },
+
+ /* Unconnected pins */
- GPIOF_INPUT, "MMC CD");
++ { IMX_GPIO_NR(1, 0), GPIOFLAG_OUTPUT_INIT_LOW, "N/C", },
++ { IMX_GPIO_NR(1, 1), GPIOFLAG_OUTPUT_INIT_LOW, "N/C", },
+ };
+
+ /*
+ * Functions
+ */
+ /* placed in section '.data' to prevent overwriting relocation info
+ * overlayed with bss
+ */
+ static u32 wrsr __attribute__((section(".data")));
+
+ #define WRSR_POR (1 << 4)
+ #define WRSR_TOUT (1 << 1)
+ #define WRSR_SFTW (1 << 0)
+
+ static void print_reset_cause(void)
+ {
+ struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+ void __iomem *wdt_base = (void __iomem *)WDOG1_BASE_ADDR;
+ u32 srsr;
+ char *dlm = "";
+
+ printf("Reset cause: ");
+
+ srsr = readl(&src_regs->srsr);
+ wrsr = readw(wdt_base + 4);
+
+ if (wrsr & WRSR_POR) {
+ printf("%sPOR", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00004) {
+ printf("%sCSU", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00008) {
+ printf("%sIPP USER", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00010) {
+ if (wrsr & WRSR_SFTW) {
+ printf("%sSOFT", dlm);
+ dlm = " | ";
+ }
+ if (wrsr & WRSR_TOUT) {
+ printf("%sWDOG", dlm);
+ dlm = " | ";
+ }
+ }
+ if (srsr & 0x00020) {
+ printf("%sJTAG HIGH-Z", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00040) {
+ printf("%sJTAG SW", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x10000) {
+ printf("%sWARM BOOT", dlm);
+ dlm = " | ";
+ }
+ if (dlm[0] == '\0')
+ printf("unknown");
+
+ printf("\n");
+ }
+
+ static void tx51_print_cpuinfo(void)
+ {
+ u32 cpurev;
+
+ cpurev = get_cpu_rev();
+
+ printf("CPU: Freescale i.MX51 rev%d.%d at %d MHz\n",
+ (cpurev & 0x000F0) >> 4,
+ (cpurev & 0x0000F) >> 0,
+ mxc_get_clock(MXC_ARM_CLK) / 1000000);
+
+ print_reset_cause();
+ }
+
+ int board_early_init_f(void)
+ {
+ struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR;
+
+ gpio_request_array(tx51_gpios, ARRAY_SIZE(tx51_gpios));
+ imx_iomux_v3_setup_multiple_pads(tx51_pads, ARRAY_SIZE(tx51_pads));
+
+ writel(0x77777777, AIPS1_BASE_ADDR + 0x00);
+ writel(0x77777777, AIPS1_BASE_ADDR + 0x04);
+
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x40);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x44);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x48);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x4c);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x50);
+
+ writel(0x77777777, AIPS2_BASE_ADDR + 0x00);
+ writel(0x77777777, AIPS2_BASE_ADDR + 0x04);
+
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x40);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x44);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x48);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x4c);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x50);
+
+ writel(0xffcfffff, &ccm_regs->CCGR0);
+ writel(0x003fffff, &ccm_regs->CCGR1);
+ writel(0x030c003c, &ccm_regs->CCGR2);
+ writel(0x000000ff, &ccm_regs->CCGR3);
+ writel(0x00000000, &ccm_regs->CCGR4);
+ writel(0x003fc003, &ccm_regs->CCGR5);
+ writel(0x00000000, &ccm_regs->CCGR6);
+ writel(0x00000000, &ccm_regs->cmeor);
+ #ifdef CONFIG_CMD_BOOTCE
+ /* WinCE fails to enable these clocks */
+ writel(readl(&ccm_regs->CCGR2) | 0x0c000000, &ccm_regs->CCGR2); /* usboh3_ipg_ahb */
+ writel(readl(&ccm_regs->CCGR4) | 0x30000000, &ccm_regs->CCGR4); /* srtc */
+ writel(readl(&ccm_regs->CCGR6) | 0x00000300, &ccm_regs->CCGR6); /* emi_garb */
+ #endif
+ return 0;
+ }
+
+ int board_init(void)
+ {
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000;
+
+ if (ctrlc() || (wrsr & WRSR_TOUT)) {
+ if (wrsr & WRSR_TOUT)
+ printf("WDOG RESET detected\n");
+ else
+ printf("<CTRL-C> detected; safeboot enabled\n");
+ return 1;
+ }
+ return 0;
+ }
+
+ int dram_init(void)
+ {
+ int ret;
+
+ /* dram_init must store complete ramsize in gd->ram_size */
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+ PHYS_SDRAM_1_SIZE);
+
+ ret = mxc_set_clock(CONFIG_SYS_MX5_HCLK,
+ CONFIG_SYS_SDRAM_CLK, MXC_DDR_CLK);
+ if (ret)
+ printf("%s: Failed to set DDR clock to %u MHz: %d\n", __func__,
+ CONFIG_SYS_SDRAM_CLK, ret);
+ else
+ debug("%s: DDR clock set to %u.%03u MHz (desig.: %u.000 MHz)\n",
+ __func__, mxc_get_clock(MXC_DDR_CLK) / 1000000,
+ mxc_get_clock(MXC_DDR_CLK) / 1000 % 1000,
+ CONFIG_SYS_SDRAM_CLK);
+ return ret;
+ }
+
+ void dram_init_banksize(void)
+ {
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = get_ram_size((void *)PHYS_SDRAM_1,
+ PHYS_SDRAM_1_SIZE);
+ #if CONFIG_NR_DRAM_BANKS > 1
+ gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+ gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2,
+ PHYS_SDRAM_2_SIZE);
+ #endif
+ }
+
+ #ifdef CONFIG_CMD_MMC
+ static const iomux_v3_cfg_t mmc0_pads[] = {
+ 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,
+ /* SD1 CD */
+ MX51_PAD_DISPB2_SER_RS__GPIO3_8 | GPIO_PAD_CTRL,
+ };
+
+ static const iomux_v3_cfg_t mmc1_pads[] = {
+ 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,
+ /* SD2 CD */
+ MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | GPIO_PAD_CTRL,
+ };
+
+ static struct tx51_esdhc_cfg {
+ const iomux_v3_cfg_t *pads;
+ int num_pads;
+ struct fsl_esdhc_cfg cfg;
+ int cd_gpio;
+ } tx51_esdhc_cfg[] = {
+ {
+ .pads = mmc0_pads,
+ .num_pads = ARRAY_SIZE(mmc0_pads),
+ .cfg = {
+ .esdhc_base = (void __iomem *)MMC_SDHC1_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = IMX_GPIO_NR(3, 8),
+ },
+ {
+ .pads = mmc1_pads,
+ .num_pads = ARRAY_SIZE(mmc1_pads),
+ .cfg = {
+ .esdhc_base = (void __iomem *)MMC_SDHC2_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = IMX_GPIO_NR(3, 6),
+ },
+ };
+
+ static inline struct tx51_esdhc_cfg *to_tx51_esdhc_cfg(struct fsl_esdhc_cfg *cfg)
+ {
+ return container_of(cfg, struct tx51_esdhc_cfg, cfg);
+ }
+
+ int board_mmc_getcd(struct mmc *mmc)
+ {
+ struct tx51_esdhc_cfg *cfg = to_tx51_esdhc_cfg(mmc->priv);
+
+ if (cfg->cd_gpio < 0)
+ return cfg->cd_gpio;
+
+ debug("SD card %d is %spresent\n",
+ cfg - tx51_esdhc_cfg,
+ gpio_get_value(cfg->cd_gpio) ? "NOT " : "");
+ return !gpio_get_value(cfg->cd_gpio);
+ }
+
+ int board_mmc_init(bd_t *bis)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tx51_esdhc_cfg); i++) {
+ struct mmc *mmc;
+ struct tx51_esdhc_cfg *cfg = &tx51_esdhc_cfg[i];
+ int ret;
+
+ imx_iomux_v3_setup_multiple_pads(cfg->pads,
+ cfg->num_pads);
+ cfg->cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+
+ ret = gpio_request_one(cfg->cd_gpio,
- { TX51_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_HIGH, "FEC PHY POWER", },
- { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY Mode0", }, /* RXD0/Mode0 */
- { IMX_GPIO_NR(2, 23), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY Mode1", }, /* RXD1/Mode1 */
- { IMX_GPIO_NR(2, 27), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY Mode2", }, /* RXD2/Mode2 */
- { IMX_GPIO_NR(2, 28), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */
++ GPIOFLAG_INPUT, "MMC CD");
+ if (ret) {
+ printf("Error %d requesting GPIO%d_%d\n",
+ ret, cfg->cd_gpio / 32, cfg->cd_gpio % 32);
+ continue;
+ }
+
+ debug("%s: Initializing MMC slot %d\n", __func__, i);
+ fsl_esdhc_initialize(bis, &cfg->cfg);
+
+ mmc = find_mmc_device(i);
+ if (mmc == NULL)
+ continue;
+ if (board_mmc_getcd(mmc) > 0)
+ mmc_init(mmc);
+ }
+ return 0;
+ }
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_FEC_MXC
+
+ #ifndef ETH_ALEN
+ #define ETH_ALEN 6
+ #endif
+
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+ {
+ int i;
+ struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+ struct fuse_bank *bank = &iim->bank[1];
+ struct fuse_bank1_regs *fuse = (struct fuse_bank1_regs *)bank->fuse_regs;
+
+ if (dev_id > 0)
+ return;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac[ETH_ALEN - i - 1] = readl(&fuse->mac_addr[i]);
+ }
+
+ static iomux_v3_cfg_t tx51_fec_pads[] = {
+ /* reconfigure strap pins for FEC function */
+ MX51_PAD_NANDF_RB3__FEC_RX_CLK | FEC_PAD_CTRL2,
+ MX51_PAD_NANDF_D9__FEC_RDATA0 | FEC_PAD_CTRL2,
+ MX51_PAD_EIM_EB3__FEC_RDATA1 | FEC_PAD_CTRL2,
+ MX51_PAD_EIM_CS2__FEC_RDATA2 | FEC_PAD_CTRL2,
+ MX51_PAD_EIM_CS3__FEC_RDATA3 | FEC_PAD_CTRL2,
+ MX51_PAD_NANDF_RB2__FEC_COL | FEC_PAD_CTRL2,
+ MX51_PAD_EIM_CS5__FEC_CRS | FEC_PAD_CTRL,
+ };
+
+ /* take bit 4 of PHY address from configured PHY address or
+ * set it to 0 if PHYADDR is -1 (probe for PHY)
+ */
+ #define PHYAD4 ((CONFIG_FEC_MXC_PHYADDR >> 4) & !(CONFIG_FEC_MXC_PHYADDR >> 5))
+
+ static struct gpio tx51_fec_gpios[] = {
- { IMX_GPIO_NR(2, 30), GPIOF_OUTPUT_INIT_HIGH, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */
++ { TX51_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY POWER", },
++ { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY Mode0", }, /* RXD0/Mode0 */
++ { IMX_GPIO_NR(2, 23), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY Mode1", }, /* RXD1/Mode1 */
++ { IMX_GPIO_NR(2, 27), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY Mode2", }, /* RXD2/Mode2 */
++ { IMX_GPIO_NR(2, 28), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY nINTSEL", }, /* RXD3/nINTSEL */
+ #if PHYAD4
- { IMX_GPIO_NR(2, 30), GPIOF_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */
++ { IMX_GPIO_NR(2, 30), GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */
+ #else
- { TX51_LED_GPIO, GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
++ { IMX_GPIO_NR(2, 30), GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY PHYAD4", }, /* CRS/PHYAD4 */
+ #endif
+ };
+
+ int board_eth_init(bd_t *bis)
+ {
+ int ret;
+
+ /* Power up the external phy and assert strap options */
+ gpio_request_array(tx51_fec_gpios, ARRAY_SIZE(tx51_fec_gpios));
+
+ /* delay at least 21ms for the PHY internal POR signal to deassert */
+ udelay(22000);
+
+ /* Deassert RESET to the external phy */
+ gpio_set_value(TX51_FEC_RST_GPIO, 1);
+
+ /* Without this delay the PHY won't work, though nothing in
+ * the datasheets suggests that it should be necessary!
+ */
+ udelay(400);
+ imx_iomux_v3_setup_multiple_pads(tx51_fec_pads,
+ ARRAY_SIZE(tx51_fec_pads));
+
+ ret = cpu_eth_init(bis);
+ if (ret)
+ printf("cpu_eth_init() failed: %d\n", ret);
+
+ return ret;
+ }
+ #endif /* CONFIG_FEC_MXC */
+
+ enum {
+ LED_STATE_INIT = -1,
+ LED_STATE_OFF,
+ LED_STATE_ON,
+ };
+
+ void show_activity(int arg)
+ {
+ static int led_state = LED_STATE_INIT;
+ static ulong last;
+
+ if (led_state == LED_STATE_INIT) {
+ last = get_timer(0);
+ gpio_set_value(TX51_LED_GPIO, 1);
+ led_state = LED_STATE_ON;
+ } else {
+ if (get_timer(last) > CONFIG_SYS_HZ) {
+ last = get_timer(0);
+ if (led_state == LED_STATE_ON) {
+ gpio_set_value(TX51_LED_GPIO, 0);
+ } else {
+ gpio_set_value(TX51_LED_GPIO, 1);
+ }
+ led_state = 1 - led_state;
+ }
+ }
+ }
+
+ static const iomux_v3_cfg_t stk5_pads[] = {
+ /* SW controlled LED on STK5 baseboard */
+ MX51_PAD_CSI2_D13__GPIO4_10 | GPIO_PAD_CTRL,
+
+ /* USB PHY reset */
+ MX51_PAD_GPIO1_4__GPIO1_4 | GPIO_PAD_CTRL,
+ /* USBOTG OC */
+ MX51_PAD_GPIO1_6__GPIO1_6 | GPIO_PAD_CTRL,
+ /* USB PHY clock enable */
+ MX51_PAD_GPIO1_7__GPIO1_7 | GPIO_PAD_CTRL,
+ /* USBH1 VBUS enable */
+ MX51_PAD_GPIO1_8__GPIO1_8 | GPIO_PAD_CTRL,
+ /* USBH1 OC */
+ MX51_PAD_GPIO1_9__GPIO1_9 | GPIO_PAD_CTRL,
+ };
+
+ static const struct gpio stk5_gpios[] = {
- { IMX_GPIO_NR(1, 4), GPIOF_OUTPUT_INIT_LOW, "ULPI PHY clk enable", },
- { IMX_GPIO_NR(1, 6), GPIOF_INPUT, "USBOTG OC", },
- { IMX_GPIO_NR(1, 7), GPIOF_OUTPUT_INIT_LOW, "ULPI PHY reset", },
- { IMX_GPIO_NR(1, 8), GPIOF_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
- { IMX_GPIO_NR(1, 9), GPIOF_INPUT, "USBH1 OC", },
++ { TX51_LED_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
+
- .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
++ { IMX_GPIO_NR(1, 4), GPIOFLAG_OUTPUT_INIT_LOW, "ULPI PHY clk enable", },
++ { IMX_GPIO_NR(1, 6), GPIOFLAG_INPUT, "USBOTG OC", },
++ { IMX_GPIO_NR(1, 7), GPIOFLAG_OUTPUT_INIT_LOW, "ULPI PHY reset", },
++ { IMX_GPIO_NR(1, 8), GPIOFLAG_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
++ { IMX_GPIO_NR(1, 9), GPIOFLAG_INPUT, "USBH1 OC", },
+ };
+
+ #ifdef CONFIG_LCD
+ static u16 tx51_cmap[256];
+ vidinfo_t panel_info = {
+ /* set to max. size supported by SoC */
+ .vl_col = 1600,
+ .vl_row = 1200,
+
- { TX51_LCD_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
- { TX51_LCD_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
- { TX51_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
++ .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
+ .cmap = tx51_cmap,
+ };
+
+ static struct fb_videomode tx51_fb_modes[] = {
+ {
+ /* Standard VGA timing */
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETV570 640 x 480 display. Syncs low active,
+ * DE high active, 115.2 mm x 86.4 mm display area
+ * VGA compatible timing
+ */
+ .name = "ETV570",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 114,
+ .hsync_len = 30,
+ .right_margin = 16,
+ .upper_margin = 32,
+ .vsync_len = 3,
+ .lower_margin = 10,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0350G0DH6 320 x 240 display.
+ * 70.08 mm x 52.56 mm display area.
+ */
+ .name = "ET0350",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6500),
+ .left_margin = 68 - 34,
+ .hsync_len = 34,
+ .right_margin = 20,
+ .upper_margin = 18 - 3,
+ .vsync_len = 3,
+ .lower_margin = 4,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0430G0DH6 480 x 272 display.
+ * 95.04 mm x 53.856 mm display area.
+ */
+ .name = "ET0430",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 272,
+ .pixclock = KHZ2PICOS(9000),
+ .left_margin = 2,
+ .hsync_len = 41,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .vsync_len = 10,
+ .lower_margin = 2,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0500G0DH6 800 x 480 display.
+ * 109.6 mm x 66.4 mm display area.
+ */
+ .name = "ET0500",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETQ570G0DH6 320 x 240 display.
+ * 115.2 mm x 86.4 mm display area.
+ */
+ .name = "ETQ570",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6400),
+ .left_margin = 38,
+ .hsync_len = 30,
+ .right_margin = 30,
+ .upper_margin = 16, /* 15 according to datasheet */
+ .vsync_len = 3, /* TVP -> 1>x>5 */
+ .lower_margin = 4, /* 4.5 according to datasheet */
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0700G0DH6 800 x 480 display.
+ * 152.4 mm x 91.44 mm display area.
+ */
+ .name = "ET0700",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* unnamed entry for assigning parameters parsed from 'video_mode' string */
+ .refresh = 60,
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ };
+
+ static int lcd_enabled = 1;
+ static int lcd_bl_polarity;
+
+ static int lcd_backlight_polarity(void)
+ {
+ return lcd_bl_polarity;
+ }
+
+ void lcd_enable(void)
+ {
+ /* HACK ALERT:
+ * global variable from common/lcd.c
+ * Set to 0 here to prevent messages from going to LCD
+ * rather than serial console
+ */
+ lcd_is_enabled = 0;
+
+ if (lcd_enabled) {
+ karo_load_splashimage(1);
+
+ debug("Switching LCD on\n");
+ gpio_set_value(TX51_LCD_PWR_GPIO, 1);
+ udelay(100);
+ gpio_set_value(TX51_LCD_RST_GPIO, 1);
+ udelay(300000);
+ gpio_set_value(TX51_LCD_BACKLIGHT_GPIO,
+ lcd_backlight_polarity());
+ }
+ }
+
+ void lcd_disable(void)
+ {
+ if (lcd_enabled) {
+ printf("Disabling LCD\n");
+ ipuv3_fb_shutdown();
+ }
+ }
+
+ void lcd_panel_disable(void)
+ {
+ if (lcd_enabled) {
+ debug("Switching LCD off\n");
+ gpio_set_value(TX51_LCD_BACKLIGHT_GPIO,
+ !lcd_backlight_polarity());
+ gpio_set_value(TX51_LCD_RST_GPIO, 0);
+ gpio_set_value(TX51_LCD_PWR_GPIO, 0);
+ }
+ }
+
+ static const iomux_v3_cfg_t stk5_lcd_pads[] = {
+ /* LCD RESET */
+ MX51_PAD_CSI2_VSYNC__GPIO4_13,
+ /* LCD POWER_ENABLE */
+ MX51_PAD_CSI2_HSYNC__GPIO4_14,
+ /* LCD Backlight (PWM) */
+ MX51_PAD_GPIO1_2__GPIO1_2,
+
+ /* Display */
+ MX51_PAD_DISP1_DAT0__DISP1_DAT0,
+ MX51_PAD_DISP1_DAT1__DISP1_DAT1,
+ MX51_PAD_DISP1_DAT2__DISP1_DAT2,
+ MX51_PAD_DISP1_DAT3__DISP1_DAT3,
+ MX51_PAD_DISP1_DAT4__DISP1_DAT4,
+ MX51_PAD_DISP1_DAT5__DISP1_DAT5,
+ MX51_PAD_DISP1_DAT6__DISP1_DAT6,
+ MX51_PAD_DISP1_DAT7__DISP1_DAT7,
+ MX51_PAD_DISP1_DAT8__DISP1_DAT8,
+ MX51_PAD_DISP1_DAT9__DISP1_DAT9,
+ MX51_PAD_DISP1_DAT10__DISP1_DAT10,
+ MX51_PAD_DISP1_DAT11__DISP1_DAT11,
+ MX51_PAD_DISP1_DAT12__DISP1_DAT12,
+ MX51_PAD_DISP1_DAT13__DISP1_DAT13,
+ MX51_PAD_DISP1_DAT14__DISP1_DAT14,
+ MX51_PAD_DISP1_DAT15__DISP1_DAT15,
+ MX51_PAD_DISP1_DAT16__DISP1_DAT16,
+ MX51_PAD_DISP1_DAT17__DISP1_DAT17,
+ MX51_PAD_DISP1_DAT18__DISP1_DAT18,
+ MX51_PAD_DISP1_DAT19__DISP1_DAT19,
+ MX51_PAD_DISP1_DAT20__DISP1_DAT20,
+ MX51_PAD_DISP1_DAT21__DISP1_DAT21,
+ MX51_PAD_DISP1_DAT22__DISP1_DAT22,
+ MX51_PAD_DISP1_DAT23__DISP1_DAT23,
+ MX51_PAD_DI1_PIN2__DI1_PIN2, /* HSYNC */
+ MX51_PAD_DI1_PIN3__DI1_PIN3, /* VSYNC */
+ };
+
+ static const struct gpio stk5_lcd_gpios[] = {
- panel_info.vl_bpix = LCD_COLOR24;
++ { TX51_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
++ { TX51_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
++ { TX51_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ };
+
+ void lcd_ctrl_init(void *lcdbase)
+ {
+ int color_depth = 24;
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ const char *vm;
+ unsigned long val;
+ int refresh = 60;
+ struct fb_videomode *p = &tx51_fb_modes[0];
+ struct fb_videomode fb_mode;
+ int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
+ int pix_fmt;
+ int lcd_bus_width;
+ ipu_di_clk_parent_t di_clk_parent = DI_PCLK_PLL3;
+ unsigned long di_clk_rate = 65000000;
+
+ if (!lcd_enabled) {
+ debug("LCD disabled\n");
+ return;
+ }
+
+ if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ setenv("splashimage", NULL);
+ return;
+ }
+
+ karo_fdt_move_fdt();
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
+
+ if (video_mode == NULL) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ return;
+ }
+ vm = video_mode;
+ if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
+ p = &fb_mode;
+ debug("Using video mode from FDT\n");
+ vm += strlen(vm);
+ if (fb_mode.xres > panel_info.vl_col ||
+ fb_mode.yres > panel_info.vl_row) {
+ printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+ fb_mode.xres, fb_mode.yres,
+ panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ }
+ if (p->name != NULL)
+ debug("Trying compiled-in video modes\n");
+ while (p->name != NULL) {
+ if (strcmp(p->name, vm) == 0) {
+ debug("Using video mode: '%s'\n", p->name);
+ vm += strlen(vm);
+ break;
+ }
+ p++;
+ }
+ if (*vm != '\0')
+ debug("Trying to decode video_mode: '%s'\n", vm);
+ while (*vm != '\0') {
+ if (*vm >= '0' && *vm <= '9') {
+ char *end;
+
+ val = simple_strtoul(vm, &end, 0);
+ if (end > vm) {
+ if (!xres_set) {
+ if (val > panel_info.vl_col)
+ val = panel_info.vl_col;
+ p->xres = val;
+ panel_info.vl_col = val;
+ xres_set = 1;
+ } else if (!yres_set) {
+ if (val > panel_info.vl_row)
+ val = panel_info.vl_row;
+ p->yres = val;
+ panel_info.vl_row = val;
+ yres_set = 1;
+ } else if (!bpp_set) {
+ switch (val) {
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ color_depth = val;
+ break;
+
+ default:
+ printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
+ end - vm, vm, color_depth);
+ }
+ bpp_set = 1;
+ } else if (!refresh_set) {
+ refresh = val;
+ refresh_set = 1;
+ }
+ }
+ vm = end;
+ }
+ switch (*vm) {
+ case '@':
+ bpp_set = 1;
+ /* fallthru */
+ case '-':
+ yres_set = 1;
+ /* fallthru */
+ case 'x':
+ xres_set = 1;
+ /* fallthru */
+ case 'M':
+ case 'R':
+ vm++;
+ break;
+
+ default:
+ if (*vm != '\0')
+ vm++;
+ }
+ }
+ if (p->xres == 0 || p->yres == 0) {
+ printf("Invalid video mode: %s\n", getenv("video_mode"));
+ lcd_enabled = 0;
+ printf("Supported video modes are:");
+ for (p = &tx51_fb_modes[0]; p->name != NULL; p++) {
+ printf(" %s", p->name);
+ }
+ printf("\n");
+ return;
+ }
+ if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
+ printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
+ p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ panel_info.vl_col = p->xres;
+ panel_info.vl_row = p->yres;
+
+ switch (color_depth) {
+ case 8:
+ panel_info.vl_bpix = LCD_COLOR8;
+ break;
+ case 16:
+ panel_info.vl_bpix = LCD_COLOR16;
+ break;
+ default:
-void ft_board_setup(void *blob, bd_t *bd)
++ panel_info.vl_bpix = LCD_COLOR32;
+ }
+
+ p->pixclock = KHZ2PICOS(refresh *
+ (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
+ (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) /
+ 1000);
+ debug("Pixel clock set to %lu.%03lu MHz\n",
+ PICOS2KHZ(p->pixclock) / 1000,
+ PICOS2KHZ(p->pixclock) % 1000);
+
+ if (p != &fb_mode) {
+ int ret;
+
+ debug("Creating new display-timing node from '%s'\n",
+ video_mode);
+ ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
+ if (ret)
+ printf("Failed to create new display-timing node from '%s': %d\n",
+ video_mode, ret);
+ }
+
+ gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
+ imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads,
+ ARRAY_SIZE(stk5_lcd_pads));
+
+ lcd_bus_width = karo_fdt_get_lcd_bus_width(working_fdt, 24);
+ switch (lcd_bus_width) {
+ case 24:
+ pix_fmt = IPU_PIX_FMT_RGB24;
+ break;
+
+ case 18:
+ pix_fmt = IPU_PIX_FMT_RGB666;
+ break;
+
+ case 16:
+ pix_fmt = IPU_PIX_FMT_RGB565;
+ break;
+
+ default:
+ lcd_enabled = 0;
+ printf("Invalid LCD bus width: %d\n", lcd_bus_width);
+ return;
+ }
+ if (karo_load_splashimage(0) == 0) {
+ int ret;
+ struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)MXC_CCM_BASE;
+ u32 ccgr4 = readl(&ccm_regs->CCGR4);
+
+ /* MIPI HSC clock is required for initialization */
+ writel(ccgr4 | (3 << 12), &ccm_regs->CCGR4);
+
+ gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3DEX;
+
+ debug("Initializing LCD controller\n");
+ ret = ipuv3_fb_init(p, 0, pix_fmt, di_clk_parent, di_clk_rate, -1);
+ writel(ccgr4 & ~(3 << 12), &ccm_regs->CCGR4);
+ if (ret) {
+ printf("Failed to initialize FB driver: %d\n", ret);
+ lcd_enabled = 0;
+ }
+ } else {
+ debug("Skipping initialization of LCD controller\n");
+ }
+ }
+ #else
+ #define lcd_enabled 0
+ #endif /* CONFIG_LCD */
+
+ static void stk5_board_init(void)
+ {
+ gpio_request_array(stk5_gpios, ARRAY_SIZE(stk5_gpios));
+ imx_iomux_v3_setup_multiple_pads(stk5_pads, ARRAY_SIZE(stk5_pads));
+ }
+
+ static void stk5v3_board_init(void)
+ {
+ stk5_board_init();
+ }
+
+ static void tx51_set_cpu_clock(void)
+ {
+ unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
+
+ if (had_ctrlc() || (wrsr & WRSR_TOUT))
+ return;
+
+ if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000)
+ return;
+
+ if (mxc_set_clock(CONFIG_SYS_MX5_HCLK, cpu_clk, MXC_ARM_CLK) == 0) {
+ cpu_clk = mxc_get_clock(MXC_ARM_CLK);
+ printf("CPU clock set to %lu.%03lu MHz\n",
+ cpu_clk / 1000000, cpu_clk / 1000 % 1000);
+ } else {
+ printf("Error: Failed to set CPU clock to %lu MHz\n", cpu_clk);
+ }
+ }
+
+ static void tx51_init_mac(void)
+ {
+ u8 mac[ETH_ALEN];
+
+ imx_get_mac_from_fuse(0, mac);
+ if (!is_valid_ether_addr(mac)) {
+ printf("No valid MAC address programmed\n");
+ return;
+ }
+
+ printf("MAC addr from fuse: %pM\n", mac);
+ eth_setenv_enetaddr("ethaddr", mac);
+ }
+
+ int board_late_init(void)
+ {
+ int ret = 0;
+ const char *baseboard;
+
+ env_cleanup();
+
+ tx51_set_cpu_clock();
+
+ if (had_ctrlc())
+ setenv_ulong("safeboot", 1);
+ else if (wrsr & WRSR_TOUT)
+ setenv_ulong("wdreset", 1);
+ else
+ karo_fdt_move_fdt();
+
+ baseboard = getenv("baseboard");
+ if (!baseboard)
+ goto exit;
+
+ printf("Baseboard: %s\n", baseboard);
+
+ if (strncmp(baseboard, "stk5", 4) == 0) {
+ if ((strlen(baseboard) == 4) ||
+ strcmp(baseboard, "stk5-v3") == 0) {
+ stk5v3_board_init();
+ } else if (strcmp(baseboard, "stk5-v5") == 0) {
+ printf("ERROR: Baseboard '%s' incompatible with TX51 module!\n",
+ baseboard);
+ stk5v3_board_init();
+ } else {
+ printf("WARNING: Unsupported STK5 board rev.: %s\n",
+ baseboard + 4);
+ }
+ } else {
+ printf("WARNING: Unsupported baseboard: '%s'\n",
+ baseboard);
+ ret = -EINVAL;
+ }
+
+ exit:
+ tx51_init_mac();
+
+ gpio_set_value(TX51_RESET_OUT_GPIO, 1);
+ clear_ctrlc();
+ return ret;
+ }
+
+ int checkboard(void)
+ {
+ tx51_print_cpuinfo();
+ #if CONFIG_NR_DRAM_BANKS > 1
+ printf("Board: Ka-Ro TX51-8xx1 | TX51-8xx2\n");
+ #else
+ printf("Board: Ka-Ro TX51-8xx0\n");
+ #endif
+ return 0;
+ }
+
+ #if defined(CONFIG_OF_BOARD_SETUP)
+ #ifdef CONFIG_FDT_FIXUP_PARTITIONS
+ #include <jffs2/jffs2.h>
+ #include <mtd_node.h>
+ static struct node_info nodes[] = {
+ { "fsl,imx51-nand", MTD_DEV_TYPE_NAND, },
+ };
+ #else
+ #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
+ #endif
+
+ static const char *tx51_touchpanels[] = {
+ "ti,tsc2007",
+ "edt,edt-ft5x06",
+ };
+
- if (ret)
++int ft_board_setup(void *blob, bd_t *bd)
+ {
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ int ret;
+
+ ret = fdt_increase_size(blob, 4096);
-
++ if (ret) {
+ printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
++ return ret;
++ }
+ fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+ fdt_fixup_ethernet(blob);
+
+ karo_fdt_fixup_touchpanel(blob, tx51_touchpanels,
+ ARRAY_SIZE(tx51_touchpanels));
+ karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply");
+ karo_fdt_update_fb_mode(blob, video_mode);
++
++ return 0;
+ }
+ #endif /* CONFIG_OF_BOARD_SETUP */
--- /dev/null
--- /dev/null
++if TARGET_TX53
++
++config SYS_BOARD
++ default "tx53"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mx5"
++
++config SYS_CONFIG_NAME
++ default "tx53"
++
++config CMD_ROMUPDATE
++ bool
++
++config MX5
++ bool
++
++config MX53
++ bool
++ default y
++ select CPU_V7
++ select MX5
++
++config TX53
++ bool
++ default y
++ select CC_OPTIMIZE_LIBS_FOR_SPEED
++ select CMD_BMP if LCD
++ select CMD_BOOTCE
++ select CMD_BOOTZ
++ select CMD_CACHE
++ select CMD_I2C if I2C
++ select CMD_MEMINFO
++ select CMD_MEMTEST
++ select CMD_NAND
++ select CMD_NAND_TRIMFFS
++ select CMD_ROMUPDATE
++ select CMD_TIME
++ select DM
++ select DM_GPIO
++ select FDT_FIXUP_PARTITIONS if OF_LIBFDT
++ select GET_FEC_MAC_ADDR_FROM_IIM
++ select IMX_WATCHDOG
++ select MTD_PARTITIONS
++ select MTD_DEVICE
++ select MX53
++ select NAND
++ select NAND_MXC
++ select OF_LIBFDT
++ select OF_BOARD_SETUP
++ select PHYLIB
++ select PHY_SMSC
++ select SYS_I2C
++ select SYS_I2C_MXC
++ select SYS_NAND_USE_FLASH_BBT if NAND_MXC
++
++#
++# variables selected depending on module variant
++#
++
++config SYS_LVDS_IF
++ bool
++
++config NR_DRAM_BANKS
++ int
++ default 1
++
++choice
++ prompt "TX53 module variant"
++
++config TARGET_TX53_X030
++ bool "TX53-8030 and TX53-1030"
++
++config TARGET_TX53_X130
++ bool "TX53-8030 and TX53-1030"
++
++config TARGET_TX53_X131
++ bool "TX53-8131 and TX53-1131"
++
++config TARGET_TX53_1232
++ bool "TX53-1232
++
++endchoice
++
++choice
++ prompt "U-Boot image variant"
++
++config TX53_UBOOT
++ bool "Standard U-Boot image"
++
++config TX53_UBOOT_NOENV
++ bool "U-Boot using only built-in environment"
++
++endchoice
++
++endif
--- /dev/null
-# (C) Copyright 2012 Lothar Waßmann <LW@KARO-electronics.de>
+ #
-# See file CREDITS for list of people who contributed to this
-# project.
++# (C) Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ #
-# 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 $(TOPDIR)/config.mk
++# SPDX-License-Identifier: GPL-2.0+
+ #
-LIB = $(obj)lib$(BOARD).o
-
-COBJS := tx53.o
-ifeq ($(CONFIG_CMD_ROMUPDATE),y)
- COBJS += flash.o
-endif
-SOBJS := lowlevel_init.o
-
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-SOBJS := $(addprefix $(obj),$(SOBJS))
-
-$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(call cmd_link_o_target, $(OBJS) $(SOBJS))
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+
+ LDSCRIPT := $(BOARDDIR)/u-boot.lds
+
++obj-y += lowlevel_init.o tx53.o
++obj-$(CONFIG_CMD_ROMUPDATE) += flash.o
--- /dev/null
- ret = chip->write_page(mtd, chip, buf, 1, page, 0, 1);
+ /*
+ * Copyright (C) 2011-2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <malloc.h>
+ #include <nand.h>
+ #include <errno.h>
+
+ #include <linux/err.h>
+ #include <jffs2/load_kernel.h>
+
+ struct mx53_fcb {
+ u32 rsrvd0;
+ u32 fingerprint;
+ u32 version;
+ u32 rsrvd1[23];
+ u32 fw1_start_page;
+ u32 fw2_start_page;
+ u32 rsrvd2[2];
+ u32 dbbt_search_area;
+ u32 bb_mark_phys_offset;
+ u32 rsrvd3[11];
+ u32 bb_swap;
+ u32 bb_mark_byte;
+ u32 rsrvd4[83];
+ };
+
+ static nand_info_t *mtd = &nand_info[0];
+ static bool doit;
+
+ static inline int calc_bb_offset(struct mx53_fcb *fcb)
+ {
+ int ecc_block_size = 512;
+ int ecc_size = mtd->oobsize / (mtd->writesize / ecc_block_size);
+ int bb_mark_chunk, bb_mark_chunk_offs;
+
+ bb_mark_chunk = mtd->writesize / (ecc_block_size + ecc_size);
+ bb_mark_chunk_offs = mtd->writesize % (ecc_block_size + ecc_size);
+ if (bb_mark_chunk_offs > ecc_block_size) {
+ printf("Unsupported ECC layout; BB mark resides in ECC data: %u\n",
+ bb_mark_chunk_offs);
+ return -EINVAL;
+ }
+ printf("BB mark is in block %d offset %d\n",
+ bb_mark_chunk, bb_mark_chunk_offs);
+
+ return bb_mark_chunk * ecc_block_size + bb_mark_chunk_offs;
+ }
+
+ /*
+ * return number of blocks to skip for a contiguous partition
+ * of given # blocks
+ */
+ static int find_contig_space(int block, int num_blocks, int max_blocks)
+ {
+ int skip = 0;
+ int found = 0;
+ int last = block + max_blocks;
+
+ debug("Searching %u contiguous blocks from %d..%d\n",
+ num_blocks, block, block + max_blocks - 1);
+ for (; block < last; block++) {
+ if (nand_block_isbad(mtd, block * mtd->erasesize)) {
+ skip += found + 1;
+ found = 0;
+ debug("Skipping %u blocks to %u\n",
+ skip, block + 1);
+ } else {
+ found++;
+ if (found >= num_blocks) {
+ debug("Found %u good blocks from %d..%d\n",
+ found, block - found + 1, block);
+ return skip;
+ }
+ }
+ }
+ return -ENOSPC;
+ }
+
+ #define offset_of(p, m) ((void *)&(p)->m - (void *)(p))
+ #define pr_fcb_val(p, n) debug("%-24s[%02x]=%08x(%d)\n", #n, offset_of(p, n), (p)->n, (p)->n)
+
+ static struct mx53_fcb *create_fcb(void *buf, int fw1_start_block,
+ int fw2_start_block, int fw_num_blocks)
+ {
+ struct mx53_fcb *fcb;
+ u32 sectors_per_block = mtd->erasesize / mtd->writesize;
+
+ fcb = buf;
+
+ memset(fcb, 0x00, sizeof(*fcb));
+ memset(fcb + 1, 0xff, mtd->erasesize - sizeof(*fcb));
+
+ strncpy((char *)&fcb->fingerprint, "FCB ", 4);
+ fcb->version = 1;
+
+ fcb->fw1_start_page = fw1_start_block * sectors_per_block;
+ pr_fcb_val(fcb, fw1_start_page);
+
+ if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) {
+ fcb->fw2_start_page = fw2_start_block * sectors_per_block;
+ pr_fcb_val(fcb, fw2_start_page);
+ }
+
+ return fcb;
+ }
+
+ static int find_fcb(void *ref, int page)
+ {
+ int ret = 0;
+ struct nand_chip *chip = mtd->priv;
+ void *buf = malloc(mtd->erasesize);
+
+ if (buf == NULL) {
+ return -ENOMEM;
+ }
+ chip->select_chip(mtd, 0);
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+ ret = chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
+ if (ret) {
+ printf("Failed to read FCB from page %u: %d\n", page, ret);
+ goto out;
+ }
+ if (memcmp(buf, ref, mtd->writesize) == 0) {
+ debug("Found FCB in page %u (%08x)\n",
+ page, page * mtd->writesize);
+ ret = 1;
+ }
+ out:
+ chip->select_chip(mtd, -1);
+ free(buf);
+ return ret;
+ }
+
+ static int write_fcb(void *buf, int block)
+ {
+ int ret;
+ struct nand_chip *chip = mtd->priv;
+ int page = block * mtd->erasesize / mtd->writesize;
+
+ ret = find_fcb(buf, page);
+ if (ret > 0) {
+ printf("FCB at block %d is up to date\n", block);
+ return 0;
+ }
+
+ printf("Erasing FCB block %08x..%08x\n", block * mtd->erasesize,
+ block * mtd->erasesize + mtd->erasesize - 1);
+ if (doit) {
+ ret = nand_erase(mtd, block * mtd->erasesize, mtd->erasesize);
+ if (ret) {
+ printf("Failed to erase FCB block %u\n", block);
+ return ret;
+ }
+ }
+
+ printf("Writing FCB to block %d @ %08llx\n", block,
+ (u64)block * mtd->erasesize);
+ if (doit) {
+ chip->select_chip(mtd, 0);
++ ret = chip->write_page(mtd, chip, 0, mtd->writesize,
++ buf, 1, page, 0, 0);
+ if (ret) {
+ printf("Failed to write FCB to block %u: %d\n", block, ret);
+ }
+ chip->select_chip(mtd, -1);
+ }
+ return ret;
+ }
+
+ #define chk_overlap(a,b) \
+ ((a##_start_block <= b##_end_block && \
+ a##_end_block >= b##_start_block) || \
+ (b##_start_block <= a##_end_block && \
+ b##_end_block >= a##_start_block))
+
+ #define fail_if_overlap(a,b,m1,m2) do { \
+ if (!doit) \
+ printf("check: %s[%lu..%lu] <> %s[%lu..%lu]\n", \
+ m1, a##_start_block, a##_end_block, \
+ m2, b##_start_block, b##_end_block); \
+ if (a##_end_block < a##_start_block) \
+ printf("Invalid start/end block # for %s\n", m1); \
+ if (b##_end_block < b##_start_block) \
+ printf("Invalid start/end block # for %s\n", m2); \
+ if (chk_overlap(a, b)) { \
+ printf("%s blocks %lu..%lu overlap %s in blocks %lu..%lu!\n", \
+ m1, a##_start_block, a##_end_block, \
+ m2, b##_start_block, b##_end_block); \
+ return -EINVAL; \
+ } \
+ } while (0)
+
+ static int tx53_prog_uboot(void *addr, int start_block, int skip,
+ size_t size, size_t max_len)
+ {
+ int ret;
+ nand_erase_options_t erase_opts = { 0, };
+ size_t actual;
+ size_t prg_length = max_len - skip * mtd->erasesize;
+ int prg_start = start_block * mtd->erasesize;
+
+ erase_opts.offset = (start_block - skip) * mtd->erasesize;
+ erase_opts.length = max_len;
+ erase_opts.quiet = 1;
+
+ printf("Erasing flash @ %08llx..%08llx\n", erase_opts.offset,
+ erase_opts.offset + erase_opts.length - 1);
+ if (doit) {
+ ret = nand_erase_opts(mtd, &erase_opts);
+ if (ret) {
+ printf("Failed to erase flash: %d\n", ret);
+ return ret;
+ }
+ }
+
+ printf("Programming flash @ %08x..%08x from %p\n",
+ prg_start, prg_start + size - 1, addr);
+ if (doit) {
+ actual = size;
+ ret = nand_write_skip_bad(mtd, prg_start, &actual, NULL,
+ prg_length, addr, WITH_DROP_FFS);
+ if (ret) {
+ printf("Failed to program flash: %d\n", ret);
+ return ret;
+ }
+ if (actual < size) {
+ printf("Could only write %u of %u bytes\n", actual, size);
+ return -EIO;
+ }
+ }
+ return 0;
+ }
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #ifndef CONFIG_ENV_OFFSET_REDUND
+ #define TOTAL_ENV_SIZE CONFIG_ENV_RANGE
+ #else
+ #define TOTAL_ENV_SIZE (CONFIG_ENV_RANGE * 2)
+ #endif
+ #endif
+
+ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int ret;
+ const unsigned long fcb_start_block = 0, fcb_end_block = 0;
+ int erase_size = mtd->erasesize;
+ int page_size = mtd->writesize;
+ void *buf;
+ char *load_addr;
+ char *file_size;
+ size_t size = 0;
+ void *addr = NULL;
+ struct mx53_fcb *fcb;
+ unsigned long mtd_num_blocks = mtd->size / mtd->erasesize;
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ unsigned long env_start_block = CONFIG_ENV_OFFSET / mtd->erasesize;
+ unsigned long env_end_block = env_start_block +
+ DIV_ROUND_UP(TOTAL_ENV_SIZE, mtd->erasesize) - 1;
+ #endif
+ int optind;
+ int fw2_set = 0;
+ unsigned long fw1_start_block = 0, fw1_end_block;
+ unsigned long fw2_start_block = 0, fw2_end_block;
+ unsigned long fw_num_blocks;
+ int fw1_skip, fw2_skip;
+ unsigned long extra_blocks = 0;
+ size_t max_len1, max_len2;
+ struct mtd_device *dev;
+ struct part_info *part_info;
+ struct part_info *redund_part_info;
+ const char *uboot_part = "u-boot";
+ const char *redund_part = NULL;
+ u8 part_num;
+ u8 redund_part_num;
+
+ ret = mtdparts_init();
+ if (ret)
+ return ret;
+
+ doit = true;
+ for (optind = 1; optind < argc; optind++) {
+ char *endp;
+
+ if (strcmp(argv[optind], "-f") == 0) {
+ if (optind >= argc - 1) {
+ printf("Option %s requires an argument\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+ optind++;
+ fw1_start_block = simple_strtoul(argv[optind], &endp, 0);
+ if (*endp != '\0') {
+ uboot_part = argv[optind];
+ continue;
+ }
+ uboot_part = NULL;
+ if (fw1_start_block >= mtd_num_blocks) {
+ printf("Block number %lu is out of range: 0..%lu\n",
+ fw1_start_block, mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ } else if (strcmp(argv[optind], "-r") == 0) {
+ fw2_set = 1;
+ if (optind < argc - 1 && argv[optind + 1][0] != '-') {
+ optind++;
+ fw2_start_block = simple_strtoul(argv[optind],
+ &endp, 0);
+ if (*endp != '\0') {
+ redund_part = argv[optind];
+ continue;
+ }
+ if (fw2_start_block >= mtd_num_blocks) {
+ printf("Block number %lu is out of range: 0..%lu\n",
+ fw2_start_block,
+ mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ }
+ } else if (strcmp(argv[optind], "-e") == 0) {
+ if (optind >= argc - 1) {
+ printf("Option %s requires an argument\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+ optind++;
+ extra_blocks = simple_strtoul(argv[optind], NULL, 0);
+ if (extra_blocks >= mtd_num_blocks) {
+ printf("Extra block count %lu is out of range: 0..%lu\n",
+ extra_blocks,
+ mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ } else if (strcmp(argv[optind], "-n") == 0) {
+ doit = false;
+ } else if (argv[optind][0] == '-') {
+ printf("Unrecognized option %s\n", argv[optind]);
+ return -EINVAL;
+ } else {
+ break;
+ }
+ }
+
+ load_addr = getenv("fileaddr");
+ file_size = getenv("filesize");
+
+ if (argc - optind < 1 && load_addr == NULL) {
+ printf("Load address not specified\n");
+ return -EINVAL;
+ }
+ if (argc - optind < 2 && file_size == NULL) {
+ if (uboot_part) {
+ printf("WARNING: Image size not specified; overwriting whole '%s' partition\n",
+ uboot_part);
+ printf("This will only work, if there are no bad blocks inside this partition!\n");
+ } else {
+ printf("ERROR: Image size must be specified\n");
+ return -EINVAL;
+ }
+ }
+ if (argc > optind) {
+ load_addr = NULL;
+ addr = (void *)simple_strtoul(argv[optind], NULL, 16);
+ optind++;
+ }
+ if (argc > optind) {
+ file_size = NULL;
+ size = simple_strtoul(argv[optind], NULL, 16);
+ optind++;
+ }
+ if (load_addr != NULL) {
+ addr = (void *)simple_strtoul(load_addr, NULL, 16);
+ printf("Using default load address %p\n", addr);
+ }
+ if (file_size != NULL) {
+ size = simple_strtoul(file_size, NULL, 16);
+ printf("Using default file size %08x\n", size);
+ }
+ if (size > 0)
+ fw_num_blocks = DIV_ROUND_UP(size, mtd->erasesize);
+ else
+ fw_num_blocks = 0;
+
+ if (uboot_part) {
+ ret = find_dev_and_part(uboot_part, &dev, &part_num,
+ &part_info);
+ if (ret) {
+ printf("Failed to find '%s' partition: %d\n",
+ uboot_part, ret);
+ return ret;
+ }
+ fw1_start_block = part_info->offset / mtd->erasesize;
+ max_len1 = part_info->size;
+ /*
+ * Skip one block, if the U-Boot image resides in the
+ * same partition as the FCB
+ */
+ if (fw1_start_block == fcb_start_block) {
+ fw1_start_block++;
+ max_len1 -= mtd->erasesize;
+ }
+ if (size == 0)
+ fw_num_blocks = max_len1 / mtd->erasesize;
+ } else {
+ max_len1 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ }
+
+ if (redund_part) {
+ ret = find_dev_and_part(redund_part, &dev, &redund_part_num,
+ &redund_part_info);
+ if (ret) {
+ printf("Failed to find '%s' partition: %d\n",
+ redund_part, ret);
+ return ret;
+ }
+ fw2_start_block = redund_part_info->offset / mtd->erasesize;
+ max_len2 = redund_part_info->size;
+ if (fw2_start_block == fcb_start_block) {
+ fw2_start_block++;
+ max_len2 -= mtd->erasesize;
+ }
+ if (size == 0)
+ fw_num_blocks = max_len2 / mtd->erasesize;
+ } else if (fw2_set) {
+ max_len2 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ } else {
+ max_len2 = 0;
+ }
+
+ fw1_skip = find_contig_space(fw1_start_block, fw_num_blocks,
+ max_len1 / mtd->erasesize);
+ if (fw1_skip < 0) {
+ printf("Could not find %lu contiguous good blocks for fw image in blocks %lu..%lu\n",
+ fw_num_blocks, fw1_start_block,
+ fw1_start_block + max_len1 / mtd->erasesize - 1);
+ if (uboot_part) {
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ if (part_info->offset <= CONFIG_ENV_OFFSET + TOTAL_ENV_SIZE) {
+ printf("Use a different partition\n");
+ } else {
+ printf("Increase the size of the '%s' partition\n",
+ uboot_part);
+ }
+ #else
+ printf("Increase the size of the '%s' partition\n",
+ uboot_part);
+ #endif
+ } else {
+ printf("Increase the number of spare blocks to use with the '-e' option\n");
+ }
+ return -ENOSPC;
+ }
+ if (extra_blocks)
+ fw1_end_block = fw1_start_block + fw_num_blocks + extra_blocks - 1;
+ else
+ fw1_end_block = fw1_start_block + fw_num_blocks + fw1_skip - 1;
+
+ if (fw2_set && fw2_start_block == 0)
+ fw2_start_block = fw1_end_block + 1;
+ if (fw2_start_block > 0) {
+ fw2_skip = find_contig_space(fw2_start_block, fw_num_blocks,
+ max_len2 / mtd->erasesize);
+ if (fw2_skip < 0) {
+ printf("Could not find %lu contiguous good blocks for redundant fw image in blocks %lu..%lu\n",
+ fw_num_blocks, fw2_start_block,
+ fw2_start_block + max_len2 / mtd->erasesize - 1);
+ if (redund_part) {
+ printf("Increase the size of the '%s' partition or use a different partition\n",
+ redund_part);
+ } else {
+ printf("Increase the number of spare blocks to use with the '-e' option\n");
+ }
+ return -ENOSPC;
+ }
+ } else {
+ fw2_skip = 0;
+ }
+ if (extra_blocks)
+ fw2_end_block = fw2_start_block + fw_num_blocks + extra_blocks - 1;
+ else
+ fw2_end_block = fw2_start_block + fw_num_blocks + fw2_skip - 1;
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ fail_if_overlap(fcb, env, "FCB", "Environment");
+ fail_if_overlap(fw1, env, "FW1", "Environment");
+ #endif
+ fail_if_overlap(fw1, fcb, "FW1", "FCB");
+ if (fw2_set) {
+ fail_if_overlap(fw2, fcb, "FW2", "FCB");
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ fail_if_overlap(fw2, env, "FW2", "Environment");
+ #endif
+ fail_if_overlap(fw1, fw2, "FW1", "FW2");
+ }
+ fw1_start_block += fw1_skip;
+ fw2_start_block += fw2_skip;
+
+ buf = malloc(erase_size);
+ if (buf == NULL) {
+ printf("Failed to allocate buffer\n");
+ return -ENOMEM;
+ }
+
+ fcb = create_fcb(buf, fw1_start_block,
+ fw2_start_block, fw_num_blocks);
+ if (IS_ERR(fcb)) {
+ printf("Failed to initialize FCB: %ld\n", PTR_ERR(fcb));
+ free(buf);
+ return PTR_ERR(fcb);
+ }
+
+ ret = write_fcb(buf, fcb_start_block);
+ free(buf);
+ if (ret) {
+ printf("Failed to write FCB to block %lu\n", fcb_start_block);
+ return ret;
+ }
+
+ if (size & (page_size - 1)) {
+ memset(addr + size, 0xff, size & (page_size - 1));
+ size = ALIGN(size, page_size);
+ }
+
+ printf("Programming U-Boot image from %p to block %lu @ %08llx\n",
+ addr, fw1_start_block, (u64)fw1_start_block * mtd->erasesize);
+ ret = tx53_prog_uboot(addr, fw1_start_block, fw1_skip, size,
+ max_len1);
+ if (ret || fw2_start_block == 0)
+ return ret;
+
+ printf("Programming redundant U-Boot image to block %lu @ %08llx\n",
+ fw2_start_block, (u64)fw2_start_block * mtd->erasesize);
+ ret = tx53_prog_uboot(addr, fw2_start_block, fw2_skip, size,
+ max_len2);
+ return ret;
+ }
+
+ U_BOOT_CMD(romupdate, 11, 0, do_update,
+ "Creates an FCB data structure and writes an U-Boot image to flash",
+ "[-f {<part>|block#}] [-r [{<part>|block#}]] [-e #] [<address>] [<length>]\n"
+ "\t-f <part>\twrite bootloader image to partition <part>\n"
+ "\t-f #\t\twrite bootloader image at block # (decimal)\n"
+ "\t-r\t\twrite redundant bootloader image at next free block after first image\n"
+ "\t-r <part>\twrite redundant bootloader image to partition <part>\n"
+ "\t-r #\t\twrite redundant bootloader image at block # (decimal)\n"
+ "\t-e #\t\tspecify number of redundant blocks per boot loader image\n"
+ "\t\t\t(only valid if -f or -r specify a flash address rather than a partition name)\n"
+ "\t-n\t\tshow what would be done without actually updating the flash\n"
+ "\t<address>\tRAM address of bootloader image (default: ${fileaddr})\n"
+ "\t<length>\tlength of bootloader image in RAM (default: ${filesize})"
+ );
--- /dev/null
- { TX53_RESET_OUT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "#RESET_OUT", },
- { TX53_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_HIGH, "FEC PHY PWR", },
- { TX53_FEC_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC PHY RESET", },
- { TX53_FEC_INT_GPIO, GPIOF_INPUT, "FEC PHY INT", },
+ /*
+ * Copyright (C) 2011-2013 Lothar Waßmann <LW@KARO-electronics.de>
+ * based on: board/freescale/mx28_evk.c (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <errno.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <i2c.h>
+ #include <lcd.h>
+ #include <netdev.h>
+ #include <mmc.h>
+ #include <fsl_esdhc.h>
+ #include <video_fb.h>
+ #include <ipu.h>
+ #include <mxcfb.h>
+ #include <linux/fb.h>
+ #include <asm/io.h>
+ #include <asm/gpio.h>
+ #include <asm/arch/iomux-mx53.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/crm_regs.h>
+ #include <asm/arch/sys_proto.h>
+
+ #include "../common/karo.h"
+
+ #define TX53_FEC_RST_GPIO IMX_GPIO_NR(7, 6)
+ #define TX53_FEC_PWR_GPIO IMX_GPIO_NR(3, 20)
+ #define TX53_FEC_INT_GPIO IMX_GPIO_NR(2, 4)
+ #define TX53_LED_GPIO IMX_GPIO_NR(2, 20)
+
+ #define TX53_LCD_PWR_GPIO IMX_GPIO_NR(2, 31)
+ #define TX53_LCD_RST_GPIO IMX_GPIO_NR(3, 29)
+ #define TX53_LCD_BACKLIGHT_GPIO IMX_GPIO_NR(1, 1)
+
+ #define TX53_RESET_OUT_GPIO IMX_GPIO_NR(7, 12)
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define MX53_GPIO_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_PKE | PAD_CTL_PUE | \
+ PAD_CTL_DSE_HIGH | PAD_CTL_PUS_22K_UP)
+
+ #define TX53_SDHC_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_HYS | PAD_CTL_DSE_HIGH | \
+ PAD_CTL_SRE_FAST | PAD_CTL_PUS_47K_UP)
+
+ char __uboot_img_end[0] __attribute__((section(".__uboot_img_end")));
+
+ static iomux_v3_cfg_t tx53_pads[] = {
+ /* NAND flash pads are set up in lowlevel_init.S */
+
+ /* UART pads */
+ #if CONFIG_MXC_UART_BASE == UART1_BASE
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+ MX53_PAD_PATA_IORDY__UART1_RTS,
+ MX53_PAD_PATA_RESET_B__UART1_CTS,
+ #endif
+ #if CONFIG_MXC_UART_BASE == UART2_BASE
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+ MX53_PAD_PATA_DIOR__UART2_RTS,
+ MX53_PAD_PATA_INTRQ__UART2_CTS,
+ #endif
+ #if CONFIG_MXC_UART_BASE == UART3_BASE
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+ MX53_PAD_PATA_DA_2__UART3_RTS,
+ MX53_PAD_PATA_DA_1__UART3_CTS,
+ #endif
+ /* internal I2C */
+ MX53_PAD_EIM_D28__I2C1_SDA | MX53_GPIO_PAD_CTRL,
+ MX53_PAD_EIM_D21__I2C1_SCL | MX53_GPIO_PAD_CTRL,
+
+ /* FEC PHY GPIO functions */
+ MX53_PAD_EIM_D20__GPIO3_20, /* PHY POWER */
+ MX53_PAD_PATA_DA_0__GPIO7_6, /* PHY RESET */
+ MX53_PAD_PATA_DATA4__GPIO2_4, /* PHY INT */
+
+ /* FEC functions */
+ MX53_PAD_FEC_MDC__FEC_MDC,
+ MX53_PAD_FEC_MDIO__FEC_MDIO,
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1,
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0,
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1,
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0,
+ };
+
+ static const struct gpio tx53_gpios[] = {
- GPIOF_INPUT, "MMC CD");
++ { TX53_RESET_OUT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "#RESET_OUT", },
++ { TX53_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY PWR", },
++ { TX53_FEC_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY RESET", },
++ { TX53_FEC_INT_GPIO, GPIOFLAG_INPUT, "FEC PHY INT", },
+ };
+
+ /*
+ * Functions
+ */
+ /* placed in section '.data' to prevent overwriting relocation info
+ * overlayed with bss
+ */
+ static u32 wrsr __attribute__((section(".data")));
+
+ #define WRSR_POR (1 << 4)
+ #define WRSR_TOUT (1 << 1)
+ #define WRSR_SFTW (1 << 0)
+
+ static void print_reset_cause(void)
+ {
+ struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+ void __iomem *wdt_base = (void __iomem *)WDOG1_BASE_ADDR;
+ u32 srsr;
+ char *dlm = "";
+
+ printf("Reset cause: ");
+
+ srsr = readl(&src_regs->srsr);
+ wrsr = readw(wdt_base + 4);
+
+ if (wrsr & WRSR_POR) {
+ printf("%sPOR", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00004) {
+ printf("%sCSU", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00008) {
+ printf("%sIPP USER", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00010) {
+ if (wrsr & WRSR_SFTW) {
+ printf("%sSOFT", dlm);
+ dlm = " | ";
+ }
+ if (wrsr & WRSR_TOUT) {
+ printf("%sWDOG", dlm);
+ dlm = " | ";
+ }
+ }
+ if (srsr & 0x00020) {
+ printf("%sJTAG HIGH-Z", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00040) {
+ printf("%sJTAG SW", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x10000) {
+ printf("%sWARM BOOT", dlm);
+ dlm = " | ";
+ }
+ if (dlm[0] == '\0')
+ printf("unknown");
+
+ printf("\n");
+ }
+
+ #define pr_lpgr_val(v, n, b, c) do { \
+ u32 __v = ((v) >> (b)) & ((1 << (c)) - 1); \
+ if (__v) \
+ printf(" %s=%0*x", #n, DIV_ROUND_UP(c, 4), __v); \
+ } while (0)
+
+ static inline void print_lpgr(u32 lpgr)
+ {
+ if (!lpgr)
+ return;
+
+ printf("LPGR=%08x:", lpgr);
+ pr_lpgr_val(lpgr, SW_ISO, 31, 1);
+ pr_lpgr_val(lpgr, SECONDARY_BOOT, 30, 1);
+ pr_lpgr_val(lpgr, BLOCK_REWRITE, 29, 1);
+ pr_lpgr_val(lpgr, WDOG_BOOT, 28, 1);
+ pr_lpgr_val(lpgr, SBMR_SHADOW, 0, 26);
+ printf("\n");
+ }
+
+ static void tx53_print_cpuinfo(void)
+ {
+ u32 cpurev;
+ struct srtc_regs *srtc_regs = (void *)SRTC_BASE_ADDR;
+ u32 lpgr = readl(&srtc_regs->lpgr);
+
+ cpurev = get_cpu_rev();
+
+ printf("CPU: Freescale i.MX53 rev%d.%d at %d MHz\n",
+ (cpurev & 0x000F0) >> 4,
+ (cpurev & 0x0000F) >> 0,
+ mxc_get_clock(MXC_ARM_CLK) / 1000000);
+
+ print_reset_cause();
+
+ print_lpgr(lpgr);
+
+ if (lpgr & (1 << 30))
+ printf("WARNING: U-Boot started from secondary bootstrap image\n");
+
+ if (lpgr) {
+ struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR;
+ u32 ccgr4 = readl(&ccm_regs->CCGR4);
+
+ writel(ccgr4 | MXC_CCM_CCGR4_SRTC(3), &ccm_regs->CCGR4);
+ writel(0, &srtc_regs->lpgr);
+ writel(ccgr4, &ccm_regs->CCGR4);
+ }
+ }
+
+ enum LTC3589_REGS {
+ LTC3589_SCR1 = 0x07,
+ LTC3589_SCR2 = 0x12,
+ LTC3589_VCCR = 0x20,
+ LTC3589_CLIRQ = 0x21,
+ LTC3589_B1DTV1 = 0x23,
+ LTC3589_B1DTV2 = 0x24,
+ LTC3589_VRRCR = 0x25,
+ LTC3589_B2DTV1 = 0x26,
+ LTC3589_B2DTV2 = 0x27,
+ LTC3589_B3DTV1 = 0x29,
+ LTC3589_B3DTV2 = 0x2a,
+ LTC3589_L2DTV1 = 0x32,
+ LTC3589_L2DTV2 = 0x33,
+ };
+
+ #define LTC3589_BnDTV1_PGOOD_MASK (1 << 5)
+ #define LTC3589_BnDTV1_SLEW(n) (((n) & 3) << 6)
+
+ #define LTC3589_CLK_RATE_LOW (1 << 5)
+
+ #define LTC3589_SCR2_PGOOD_SHUTDWN (1 << 7)
+
+ #define VDD_LDO2_VAL mV_to_regval(vout_to_vref(1325 * 10, 2))
+ #define VDD_CORE_VAL mV_to_regval(vout_to_vref(1100 * 10, 3))
+ #define VDD_SOC_VAL mV_to_regval(vout_to_vref(1325 * 10, 4))
+ #define VDD_BUCK3_VAL mV_to_regval(vout_to_vref(2500 * 10, 5))
+
+ #ifndef CONFIG_SYS_TX53_HWREV_2
+ /* LDO2 vref divider */
+ #define R1_2 180
+ #define R2_2 191
+ /* BUCK1 vref divider */
+ #define R1_3 150
+ #define R2_3 180
+ /* BUCK2 vref divider */
+ #define R1_4 180
+ #define R2_4 191
+ /* BUCK3 vref divider */
+ #define R1_5 270
+ #define R2_5 100
+ #else
+ /* no dividers on vref */
+ #define R1_2 0
+ #define R2_2 1
+ #define R1_3 0
+ #define R2_3 1
+ #define R1_4 0
+ #define R2_4 1
+ #define R1_5 0
+ #define R2_5 1
+ #endif
+
+ /* calculate voltages in 10mV */
+ #define R1(idx) R1_##idx
+ #define R2(idx) R2_##idx
+
+ #define vout_to_vref(vout, idx) ((vout) * R2(idx) / (R1(idx) + R2(idx)))
+ #define vref_to_vout(vref, idx) DIV_ROUND_UP((vref) * (R1(idx) + R2(idx)), R2(idx))
+
+ #define mV_to_regval(mV) DIV_ROUND(((((mV) < 3625) ? 3625 : (mV)) - 3625), 125)
+ #define regval_to_mV(v) (((v) * 125 + 3625))
+
+ static struct pmic_regs {
+ enum LTC3589_REGS addr;
+ u8 val;
+ } ltc3589_regs[] = {
+ { LTC3589_SCR1, 0x15, }, /* burst mode for all regulators except buck boost */
+ { LTC3589_SCR2, LTC3589_SCR2_PGOOD_SHUTDWN, }, /* enable shutdown on PGOOD Timeout */
+
+ { LTC3589_L2DTV1, VDD_LDO2_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
+ { LTC3589_L2DTV2, VDD_LDO2_VAL | LTC3589_CLK_RATE_LOW, },
+
+ { LTC3589_B1DTV1, VDD_CORE_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
+ { LTC3589_B1DTV2, VDD_CORE_VAL, },
+
+ { LTC3589_B2DTV1, VDD_SOC_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
+ { LTC3589_B2DTV2, VDD_SOC_VAL, },
+
+ { LTC3589_B3DTV1, VDD_BUCK3_VAL | LTC3589_BnDTV1_SLEW(3) | LTC3589_BnDTV1_PGOOD_MASK, },
+ { LTC3589_B3DTV2, VDD_BUCK3_VAL, },
+
+ /* Select ref 0 for all regulators and enable slew */
+ { LTC3589_VCCR, 0x55, },
+
+ { LTC3589_CLIRQ, 0, }, /* clear all interrupt flags */
+ };
+
+ static int setup_pmic_voltages(void)
+ {
+ int ret;
+ unsigned char value;
+ int i;
+
+ ret = i2c_probe(CONFIG_SYS_I2C_SLAVE);
+ if (ret != 0) {
+ printf("Failed to initialize I2C\n");
+ return ret;
+ }
+
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE, 0x11, 1, &value, 1);
+ if (ret) {
+ printf("%s: i2c_read error: %d\n", __func__, ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ltc3589_regs); i++) {
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE, ltc3589_regs[i].addr, 1,
+ &value, 1);
+ debug("Writing %02x to reg %02x (%02x)\n",
+ ltc3589_regs[i].val, ltc3589_regs[i].addr, value);
+ ret = i2c_write(CONFIG_SYS_I2C_SLAVE, ltc3589_regs[i].addr, 1,
+ <c3589_regs[i].val, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, ltc3589_regs[i].addr, ret);
+ return ret;
+ }
+ }
+ printf("VDDCORE set to %umV\n",
+ DIV_ROUND(vref_to_vout(regval_to_mV(VDD_CORE_VAL), 3), 10));
+
+ printf("VDDSOC set to %umV\n",
+ DIV_ROUND(vref_to_vout(regval_to_mV(VDD_SOC_VAL), 4), 10));
+ return 0;
+ }
+
+ static struct {
+ u32 max_freq;
+ u32 mV;
+ } tx53_core_voltages[] = {
+ { 800000000, 1100, },
+ { 1000000000, 1240, },
+ { 1200000000, 1350, },
+ };
+
+ int adjust_core_voltage(u32 freq)
+ {
+ int ret;
+ int i;
+
+ printf("%s@%d\n", __func__, __LINE__);
+
+ for (i = 0; i < ARRAY_SIZE(tx53_core_voltages); i++) {
+ if (freq <= tx53_core_voltages[i].max_freq) {
+ int retries = 0;
+ const int max_tries = 10;
+ const int delay_us = 1;
+ u32 mV = tx53_core_voltages[i].mV;
+ u8 val = mV_to_regval(vout_to_vref(mV * 10, 3));
+ u8 v;
+
+ debug("regval[%umV]=%02x\n", mV, val);
+
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE, LTC3589_B1DTV1, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, LTC3589_B1DTV1, ret);
+ return ret;
+ }
+ debug("Changing reg %02x from %02x to %02x\n",
+ LTC3589_B1DTV1, v, (v & ~0x1f) |
+ mV_to_regval(vout_to_vref(mV * 10, 3)));
+ v &= ~0x1f;
+ v |= mV_to_regval(vout_to_vref(mV * 10, 3));
+ ret = i2c_write(CONFIG_SYS_I2C_SLAVE, LTC3589_B1DTV1, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, LTC3589_B1DTV1, ret);
+ return ret;
+ }
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE, LTC3589_VCCR, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, LTC3589_VCCR, ret);
+ return ret;
+ }
+ v |= 0x1;
+ ret = i2c_write(CONFIG_SYS_I2C_SLAVE, LTC3589_VCCR, 1,
+ &v, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, LTC3589_VCCR, ret);
+ return ret;
+ }
+ for (retries = 0; retries < max_tries; retries++) {
+ ret = i2c_read(CONFIG_SYS_I2C_SLAVE,
+ LTC3589_VCCR, 1, &v, 1);
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, LTC3589_VCCR, ret);
+ return ret;
+ }
+ if (!(v & 1))
+ break;
+ udelay(delay_us);
+ }
+ if (v & 1) {
+ printf("change of VDDCORE did not complete after %uµs\n",
+ retries * delay_us);
+ return -ETIMEDOUT;
+ }
+
+ printf("VDDCORE set to %umV after %u loops\n",
+ DIV_ROUND(vref_to_vout(regval_to_mV(val & 0x1f), 3),
+ 10), retries);
+ return 0;
+ }
+ }
+ return -EINVAL;
+ }
+
+ int board_early_init_f(void)
+ {
+ struct mxc_ccm_reg *ccm_regs = (void *)CCM_BASE_ADDR;
+
+ gpio_request_array(tx53_gpios, ARRAY_SIZE(tx53_gpios));
+ imx_iomux_v3_setup_multiple_pads(tx53_pads, ARRAY_SIZE(tx53_pads));
+
+ writel(0x77777777, AIPS1_BASE_ADDR + 0x00);
+ writel(0x77777777, AIPS1_BASE_ADDR + 0x04);
+
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x40);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x44);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x48);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x4c);
+ writel(0x00000000, AIPS1_BASE_ADDR + 0x50);
+
+ writel(0x77777777, AIPS2_BASE_ADDR + 0x00);
+ writel(0x77777777, AIPS2_BASE_ADDR + 0x04);
+
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x40);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x44);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x48);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x4c);
+ writel(0x00000000, AIPS2_BASE_ADDR + 0x50);
+
+ writel(0xffcf0fff, &ccm_regs->CCGR0);
+ writel(0x000fffcf, &ccm_regs->CCGR1);
+ writel(0x033c0000, &ccm_regs->CCGR2);
+ writel(0x000000ff, &ccm_regs->CCGR3);
+ writel(0x00000000, &ccm_regs->CCGR4);
+ writel(0x00fff033, &ccm_regs->CCGR5);
+ writel(0x0f00030f, &ccm_regs->CCGR6);
+ writel(0xfff00000, &ccm_regs->CCGR7);
+ writel(0x00000000, &ccm_regs->cmeor);
+
+ return 0;
+ }
+
+ int board_init(void)
+ {
+ int ret;
+
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000;
+
+ if (ctrlc() || (wrsr & WRSR_TOUT)) {
+ if (wrsr & WRSR_TOUT)
+ printf("WDOG RESET detected; Skipping PMIC setup\n");
+ else
+ printf("<CTRL-C> detected; safeboot enabled\n");
+ return 1;
+ }
+
+ ret = setup_pmic_voltages();
+ if (ret) {
+ printf("Failed to setup PMIC voltages\n");
+ hang();
+ }
+ return 0;
+ }
+
+ int dram_init(void)
+ {
+ int ret;
+
+ /*
+ * U-Boot doesn't support RAM banks with intervening holes,
+ * so let U-Boot only know about the first bank for its
+ * internal data structures. The size reported to Linux is
+ * determined from the individual bank sizes.
+ */
+ gd->ram_size = get_ram_size((void *)PHYS_SDRAM_1, SZ_1G);
+
+ ret = mxc_set_clock(CONFIG_SYS_MX5_HCLK,
+ CONFIG_SYS_SDRAM_CLK, MXC_DDR_CLK);
+ if (ret)
+ printf("%s: Failed to set DDR clock to %u MHz: %d\n", __func__,
+ CONFIG_SYS_SDRAM_CLK, ret);
+ else
+ debug("%s: DDR clock set to %u.%03u MHz (desig.: %u.000 MHz)\n",
+ __func__, mxc_get_clock(MXC_DDR_CLK) / 1000000,
+ mxc_get_clock(MXC_DDR_CLK) / 1000 % 1000,
+ CONFIG_SYS_SDRAM_CLK);
+ return ret;
+ }
+
+ void dram_init_banksize(void)
+ {
+ long total_size = gd->ram_size;
+
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+
+ #if CONFIG_NR_DRAM_BANKS > 1
+ gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2, SZ_1G);
+
+ if (gd->bd->bi_dram[1].size) {
+ debug("Found %luMiB SDRAM in bank 2\n",
+ gd->bd->bi_dram[1].size / SZ_1M);
+ gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+ total_size += gd->bd->bi_dram[1].size;
+ }
+ #endif
+ if (total_size != CONFIG_SYS_SDRAM_SIZE)
+ printf("WARNING: SDRAM size mismatch: %uMiB configured; %luMiB detected\n",
+ CONFIG_SYS_SDRAM_SIZE / SZ_1M, total_size / SZ_1M);
+ }
+
+ #ifdef CONFIG_CMD_MMC
+ static const iomux_v3_cfg_t mmc0_pads[] = {
+ MX53_PAD_SD1_CMD__ESDHC1_CMD | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD1_CLK__ESDHC1_CLK | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 | TX53_SDHC_PAD_CTRL,
+ /* SD1 CD */
+ MX53_PAD_EIM_D24__GPIO3_24 | MX53_GPIO_PAD_CTRL,
+ };
+
+ static const iomux_v3_cfg_t mmc1_pads[] = {
+ MX53_PAD_SD2_CMD__ESDHC2_CMD | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD2_CLK__ESDHC2_CLK | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD2_DATA0__ESDHC2_DAT0 | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD2_DATA1__ESDHC2_DAT1 | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD2_DATA2__ESDHC2_DAT2 | TX53_SDHC_PAD_CTRL,
+ MX53_PAD_SD2_DATA3__ESDHC2_DAT3 | TX53_SDHC_PAD_CTRL,
+ /* SD2 CD */
+ MX53_PAD_EIM_D25__GPIO3_25 | MX53_GPIO_PAD_CTRL,
+ };
+
+ static struct tx53_esdhc_cfg {
+ const iomux_v3_cfg_t *pads;
+ int num_pads;
+ struct fsl_esdhc_cfg cfg;
+ int cd_gpio;
+ } tx53_esdhc_cfg[] = {
+ {
+ .pads = mmc0_pads,
+ .num_pads = ARRAY_SIZE(mmc0_pads),
+ .cfg = {
+ .esdhc_base = (void __iomem *)MMC_SDHC1_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = IMX_GPIO_NR(3, 24),
+ },
+ {
+ .pads = mmc1_pads,
+ .num_pads = ARRAY_SIZE(mmc1_pads),
+ .cfg = {
+ .esdhc_base = (void __iomem *)MMC_SDHC2_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = IMX_GPIO_NR(3, 25),
+ },
+ };
+
+ static inline struct tx53_esdhc_cfg *to_tx53_esdhc_cfg(struct fsl_esdhc_cfg *cfg)
+ {
+ return container_of(cfg, struct tx53_esdhc_cfg, cfg);
+ }
+
+ int board_mmc_getcd(struct mmc *mmc)
+ {
+ struct tx53_esdhc_cfg *cfg = to_tx53_esdhc_cfg(mmc->priv);
+
+ if (cfg->cd_gpio < 0)
+ return cfg->cd_gpio;
+
+ debug("SD card %d is %spresent\n",
+ cfg - tx53_esdhc_cfg,
+ gpio_get_value(cfg->cd_gpio) ? "NOT " : "");
+ return !gpio_get_value(cfg->cd_gpio);
+ }
+
+ int board_mmc_init(bd_t *bis)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tx53_esdhc_cfg); i++) {
+ struct mmc *mmc;
+ struct tx53_esdhc_cfg *cfg = &tx53_esdhc_cfg[i];
+ int ret;
+
+ imx_iomux_v3_setup_multiple_pads(cfg->pads, cfg->num_pads);
+ cfg->cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+
+ ret = gpio_request_one(cfg->cd_gpio,
- { TX53_LED_GPIO, GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
++ GPIOFLAG_INPUT, "MMC CD");
+ if (ret) {
+ printf("Error %d requesting GPIO%d_%d\n",
+ ret, cfg->cd_gpio / 32, cfg->cd_gpio % 32);
+ continue;
+ }
+
+ debug("%s: Initializing MMC slot %d\n", __func__, i);
+ fsl_esdhc_initialize(bis, &cfg->cfg);
+
+ mmc = find_mmc_device(i);
+ if (mmc == NULL)
+ continue;
+ if (board_mmc_getcd(mmc) > 0)
+ mmc_init(mmc);
+ }
+ return 0;
+ }
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_FEC_MXC
+
+ #ifndef ETH_ALEN
+ #define ETH_ALEN 6
+ #endif
+
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+ {
+ int i;
+ struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+ struct fuse_bank *bank = &iim->bank[1];
+ struct fuse_bank1_regs *fuse = (struct fuse_bank1_regs *)bank->fuse_regs;
+
+ if (dev_id > 0)
+ return;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac[i] = readl(&fuse->mac_addr[i]);
+ }
+
+ #define FEC_PAD_CTL (PAD_CTL_DVS | PAD_CTL_DSE_HIGH | \
+ PAD_CTL_SRE_FAST)
+ #define FEC_PAD_CTL2 (PAD_CTL_DVS | PAD_CTL_SRE_FAST)
+ #define GPIO_PAD_CTL (PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
+
+ int board_eth_init(bd_t *bis)
+ {
+ int ret;
+
+ /* delay at least 21ms for the PHY internal POR signal to deassert */
+ udelay(22000);
+
+ /* Deassert RESET to the external phy */
+ gpio_set_value(TX53_FEC_RST_GPIO, 1);
+
+ ret = cpu_eth_init(bis);
+ if (ret)
+ printf("cpu_eth_init() failed: %d\n", ret);
+
+ return ret;
+ }
+ #endif /* CONFIG_FEC_MXC */
+
+ enum {
+ LED_STATE_INIT = -1,
+ LED_STATE_OFF,
+ LED_STATE_ON,
+ };
+
+ void show_activity(int arg)
+ {
+ static int led_state = LED_STATE_INIT;
+ static ulong last;
+
+ if (led_state == LED_STATE_INIT) {
+ last = get_timer(0);
+ gpio_set_value(TX53_LED_GPIO, 1);
+ led_state = LED_STATE_ON;
+ } else {
+ if (get_timer(last) > CONFIG_SYS_HZ) {
+ last = get_timer(0);
+ if (led_state == LED_STATE_ON) {
+ gpio_set_value(TX53_LED_GPIO, 0);
+ } else {
+ gpio_set_value(TX53_LED_GPIO, 1);
+ }
+ led_state = 1 - led_state;
+ }
+ }
+ }
+
+ static const iomux_v3_cfg_t stk5_pads[] = {
+ /* SW controlled LED on STK5 baseboard */
+ MX53_PAD_EIM_A18__GPIO2_20,
+
+ /* I2C bus on DIMM pins 40/41 */
+ MX53_PAD_GPIO_6__I2C3_SDA | MX53_GPIO_PAD_CTRL,
+ MX53_PAD_GPIO_3__I2C3_SCL | MX53_GPIO_PAD_CTRL,
+
+ /* TSC200x PEN IRQ */
+ MX53_PAD_EIM_D26__GPIO3_26 | MX53_GPIO_PAD_CTRL,
+
+ /* EDT-FT5x06 Polytouch panel */
+ MX53_PAD_NANDF_CS2__GPIO6_15 | MX53_GPIO_PAD_CTRL, /* IRQ */
+ MX53_PAD_EIM_A16__GPIO2_22 | MX53_GPIO_PAD_CTRL, /* RESET */
+ MX53_PAD_EIM_A17__GPIO2_21 | MX53_GPIO_PAD_CTRL, /* WAKE */
+
+ /* USBH1 */
+ MX53_PAD_EIM_D31__GPIO3_31 | MX53_GPIO_PAD_CTRL, /* VBUSEN */
+ MX53_PAD_EIM_D30__GPIO3_30 | MX53_GPIO_PAD_CTRL, /* OC */
+ /* USBOTG */
+ MX53_PAD_GPIO_7__GPIO1_7, /* VBUSEN */
+ MX53_PAD_GPIO_8__GPIO1_8, /* OC */
+
+ /* DS1339 Interrupt */
+ MX53_PAD_DI0_PIN4__GPIO4_20 | MX53_GPIO_PAD_CTRL,
+ };
+
+ static const struct gpio stk5_gpios[] = {
- { IMX_GPIO_NR(1, 8), GPIOF_INPUT, "USBOTG OC", },
- { IMX_GPIO_NR(1, 7), GPIOF_OUTPUT_INIT_LOW, "USBOTG VBUS enable", },
- { IMX_GPIO_NR(3, 30), GPIOF_INPUT, "USBH1 OC", },
- { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
++ { TX53_LED_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
+
- .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
++ { IMX_GPIO_NR(1, 8), GPIOFLAG_INPUT, "USBOTG OC", },
++ { IMX_GPIO_NR(1, 7), GPIOFLAG_OUTPUT_INIT_LOW, "USBOTG VBUS enable", },
++ { IMX_GPIO_NR(3, 30), GPIOFLAG_INPUT, "USBH1 OC", },
++ { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
+ };
+
+ #ifdef CONFIG_LCD
+ static u16 tx53_cmap[256];
+ vidinfo_t panel_info = {
+ /* set to max. size supported by SoC */
+ .vl_col = 1600,
+ .vl_row = 1200,
+
- { TX53_LCD_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
- { TX53_LCD_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
- { TX53_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
++ .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
+ .cmap = tx53_cmap,
+ };
+
+ static struct fb_videomode tx53_fb_modes[] = {
+ #ifndef CONFIG_SYS_LVDS_IF
+ {
+ /* Standard VGA timing */
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETV570 640 x 480 display. Syncs low active,
+ * DE high active, 115.2 mm x 86.4 mm display area
+ * VGA compatible timing
+ */
+ .name = "ETV570",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 114,
+ .hsync_len = 30,
+ .right_margin = 16,
+ .upper_margin = 32,
+ .vsync_len = 3,
+ .lower_margin = 10,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0350G0DH6 320 x 240 display.
+ * 70.08 mm x 52.56 mm display area.
+ */
+ .name = "ET0350",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6500),
+ .left_margin = 68 - 34,
+ .hsync_len = 34,
+ .right_margin = 20,
+ .upper_margin = 18 - 3,
+ .vsync_len = 3,
+ .lower_margin = 4,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0430G0DH6 480 x 272 display.
+ * 95.04 mm x 53.856 mm display area.
+ */
+ .name = "ET0430",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 272,
+ .pixclock = KHZ2PICOS(9000),
+ .left_margin = 2,
+ .hsync_len = 41,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .vsync_len = 10,
+ .lower_margin = 2,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0500G0DH6 800 x 480 display.
+ * 109.6 mm x 66.4 mm display area.
+ */
+ .name = "ET0500",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETQ570G0DH6 320 x 240 display.
+ * 115.2 mm x 86.4 mm display area.
+ */
+ .name = "ETQ570",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6400),
+ .left_margin = 38,
+ .hsync_len = 30,
+ .right_margin = 30,
+ .upper_margin = 16, /* 15 according to datasheet */
+ .vsync_len = 3, /* TVP -> 1>x>5 */
+ .lower_margin = 4, /* 4.5 according to datasheet */
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0700G0DH6 800 x 480 display.
+ * 152.4 mm x 91.44 mm display area.
+ */
+ .name = "ET0700",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ #else
+ {
+ /* HannStar HSD100PXN1
+ * 202.7m mm x 152.06 mm display area.
+ */
+ .name = "HSD100PXN1",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = KHZ2PICOS(65000),
+ .left_margin = 0,
+ .hsync_len = 0,
+ .right_margin = 320,
+ .upper_margin = 0,
+ .vsync_len = 0,
+ .lower_margin = 38,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ #endif
+ {
+ /* unnamed entry for assigning parameters parsed from 'video_mode' string */
+ .refresh = 60,
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ };
+
+ static int lcd_enabled = 1;
+ static int lcd_bl_polarity;
+
+ static int lcd_backlight_polarity(void)
+ {
+ return lcd_bl_polarity;
+ }
+
+ void lcd_enable(void)
+ {
+ /* HACK ALERT:
+ * global variable from common/lcd.c
+ * Set to 0 here to prevent messages from going to LCD
+ * rather than serial console
+ */
+ lcd_is_enabled = 0;
+
+ if (lcd_enabled) {
+ karo_load_splashimage(1);
+
+ debug("Switching LCD on\n");
+ gpio_set_value(TX53_LCD_PWR_GPIO, 1);
+ udelay(100);
+ gpio_set_value(TX53_LCD_RST_GPIO, 1);
+ udelay(300000);
+ gpio_set_value(TX53_LCD_BACKLIGHT_GPIO,
+ lcd_backlight_polarity());
+ }
+ }
+
+ void lcd_disable(void)
+ {
+ if (lcd_enabled) {
+ printf("Disabling LCD\n");
+ ipuv3_fb_shutdown();
+ }
+ }
+
+ void lcd_panel_disable(void)
+ {
+ if (lcd_enabled) {
+ debug("Switching LCD off\n");
+ gpio_set_value(TX53_LCD_BACKLIGHT_GPIO,
+ !lcd_backlight_polarity());
+ gpio_set_value(TX53_LCD_RST_GPIO, 0);
+ gpio_set_value(TX53_LCD_PWR_GPIO, 0);
+ }
+ }
+
+ static const iomux_v3_cfg_t stk5_lcd_pads[] = {
+ /* LCD RESET */
+ MX53_PAD_EIM_D29__GPIO3_29 | MX53_GPIO_PAD_CTRL,
+ /* LCD POWER_ENABLE */
+ MX53_PAD_EIM_EB3__GPIO2_31 | MX53_GPIO_PAD_CTRL,
+ /* LCD Backlight (PWM) */
+ MX53_PAD_GPIO_1__GPIO1_1 | MX53_GPIO_PAD_CTRL,
+
+ /* Display */
+ #ifndef CONFIG_SYS_LVDS_IF
+ /* LCD option */
+ MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+ MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+ MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+ MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+ MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+ MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+ MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+ MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+ MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+ MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+ MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+ MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+ MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+ MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+ MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+ MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+ MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+ MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+ MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+ MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+ MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+ MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+ MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+ MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+ MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+ MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+ MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+ MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+ #else
+ /* LVDS option */
+ MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+ MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+ MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+ MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+ MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+ MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+ MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+ MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+ MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+ MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+ #endif
+ };
+
+ static const struct gpio stk5_lcd_gpios[] = {
- panel_info.vl_bpix = LCD_COLOR24;
++ { TX53_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
++ { TX53_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
++ { TX53_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ };
+
+ void lcd_ctrl_init(void *lcdbase)
+ {
+ int color_depth = 24;
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ const char *vm;
+ unsigned long val;
+ int refresh = 60;
+ struct fb_videomode *p = &tx53_fb_modes[0];
+ struct fb_videomode fb_mode;
+ int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
+ int pix_fmt;
+ int lcd_bus_width;
+ ipu_di_clk_parent_t di_clk_parent = is_lvds() ? DI_PCLK_LDB : DI_PCLK_PLL3;
+ unsigned long di_clk_rate = 65000000;
+
+ if (!lcd_enabled) {
+ debug("LCD disabled\n");
+ return;
+ }
+
+ if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ setenv("splashimage", NULL);
+ return;
+ }
+
+ karo_fdt_move_fdt();
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
+
+ if (video_mode == NULL) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ return;
+ }
+ vm = video_mode;
+ if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
+ p = &fb_mode;
+ debug("Using video mode from FDT\n");
+ vm += strlen(vm);
+ if (fb_mode.xres > panel_info.vl_col ||
+ fb_mode.yres > panel_info.vl_row) {
+ printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+ fb_mode.xres, fb_mode.yres,
+ panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ }
+ if (p->name != NULL)
+ debug("Trying compiled-in video modes\n");
+ while (p->name != NULL) {
+ if (strcmp(p->name, vm) == 0) {
+ debug("Using video mode: '%s'\n", p->name);
+ vm += strlen(vm);
+ break;
+ }
+ p++;
+ }
+ if (*vm != '\0')
+ debug("Trying to decode video_mode: '%s'\n", vm);
+ while (*vm != '\0') {
+ if (*vm >= '0' && *vm <= '9') {
+ char *end;
+
+ val = simple_strtoul(vm, &end, 0);
+ if (end > vm) {
+ if (!xres_set) {
+ if (val > panel_info.vl_col)
+ val = panel_info.vl_col;
+ p->xres = val;
+ panel_info.vl_col = val;
+ xres_set = 1;
+ } else if (!yres_set) {
+ if (val > panel_info.vl_row)
+ val = panel_info.vl_row;
+ p->yres = val;
+ panel_info.vl_row = val;
+ yres_set = 1;
+ } else if (!bpp_set) {
+ switch (val) {
+ case 32:
+ case 24:
+ if (is_lvds())
+ pix_fmt = IPU_PIX_FMT_LVDS888;
+ /* fallthru */
+ case 16:
+ case 8:
+ color_depth = val;
+ break;
+
+ case 18:
+ if (is_lvds()) {
+ color_depth = val;
+ break;
+ }
+ /* fallthru */
+ default:
+ printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
+ end - vm, vm, color_depth);
+ }
+ bpp_set = 1;
+ } else if (!refresh_set) {
+ refresh = val;
+ refresh_set = 1;
+ }
+ }
+ vm = end;
+ }
+ switch (*vm) {
+ case '@':
+ bpp_set = 1;
+ /* fallthru */
+ case '-':
+ yres_set = 1;
+ /* fallthru */
+ case 'x':
+ xres_set = 1;
+ /* fallthru */
+ case 'M':
+ case 'R':
+ vm++;
+ break;
+
+ default:
+ if (*vm != '\0')
+ vm++;
+ }
+ }
+ if (p->xres == 0 || p->yres == 0) {
+ printf("Invalid video mode: %s\n", getenv("video_mode"));
+ lcd_enabled = 0;
+ printf("Supported video modes are:");
+ for (p = &tx53_fb_modes[0]; p->name != NULL; p++) {
+ printf(" %s", p->name);
+ }
+ printf("\n");
+ return;
+ }
+ if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
+ printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
+ p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ panel_info.vl_col = p->xres;
+ panel_info.vl_row = p->yres;
+
+ switch (color_depth) {
+ case 8:
+ panel_info.vl_bpix = LCD_COLOR8;
+ break;
+ case 16:
+ panel_info.vl_bpix = LCD_COLOR16;
+ break;
+ default:
- gpio_request_one(IMX_GPIO_NR(4, 21), GPIOF_OUTPUT_INIT_HIGH,
++ panel_info.vl_bpix = LCD_COLOR32;
+ }
+
+ p->pixclock = KHZ2PICOS(refresh *
+ (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
+ (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) /
+ 1000);
+ debug("Pixel clock set to %lu.%03lu MHz\n",
+ PICOS2KHZ(p->pixclock) / 1000, PICOS2KHZ(p->pixclock) % 1000);
+
+ if (p != &fb_mode) {
+ int ret;
+
+ debug("Creating new display-timing node from '%s'\n",
+ video_mode);
+ ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
+ if (ret)
+ printf("Failed to create new display-timing node from '%s': %d\n",
+ video_mode, ret);
+ }
+
+ gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
+ imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads,
+ ARRAY_SIZE(stk5_lcd_pads));
+
+ lcd_bus_width = karo_fdt_get_lcd_bus_width(working_fdt, 24);
+ switch (lcd_bus_width) {
+ case 24:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS888 : IPU_PIX_FMT_RGB24;
+ break;
+
+ case 18:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS666 : IPU_PIX_FMT_RGB666;
+ break;
+
+ case 16:
+ if (!is_lvds()) {
+ pix_fmt = IPU_PIX_FMT_RGB565;
+ break;
+ }
+ /* fallthru */
+ default:
+ lcd_enabled = 0;
+ printf("Invalid %s bus width: %d\n", is_lvds() ? "LVDS" : "LCD",
+ lcd_bus_width);
+ return;
+ }
+ if (is_lvds()) {
+ int lvds_mapping = karo_fdt_get_lvds_mapping(working_fdt, 0);
+ int lvds_chan_mask = karo_fdt_get_lvds_channels(working_fdt);
+ uint32_t gpr2;
+
+ if (lvds_chan_mask == 0) {
+ printf("No LVDS channel active\n");
+ lcd_enabled = 0;
+ return;
+ }
+
+ gpr2 = (lvds_mapping << 6) | (lvds_mapping << 8);
+ if (lcd_bus_width == 24)
+ gpr2 |= (1 << 5) | (1 << 7);
+ gpr2 |= (lvds_chan_mask & 1) ? 1 << 0 : 0;
+ gpr2 |= (lvds_chan_mask & 2) ? 3 << 2 : 0;
+ debug("writing %08x to GPR2[%08x]\n", gpr2, IOMUXC_BASE_ADDR + 8);
+ writel(gpr2, IOMUXC_BASE_ADDR + 8);
+ }
+ if (karo_load_splashimage(0) == 0) {
+ int ret;
+
+ gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3M;
+
+ debug("Initializing LCD controller\n");
+ ret = ipuv3_fb_init(p, 0, pix_fmt, di_clk_parent, di_clk_rate, -1);
+ if (ret) {
+ printf("Failed to initialize FB driver: %d\n", ret);
+ lcd_enabled = 0;
+ }
+ } else {
+ debug("Skipping initialization of LCD controller\n");
+ }
+ }
+ #else
+ #define lcd_enabled 0
+ #endif /* CONFIG_LCD */
+
+ static void stk5_board_init(void)
+ {
+ gpio_request_array(stk5_gpios, ARRAY_SIZE(stk5_gpios));
+ imx_iomux_v3_setup_multiple_pads(stk5_pads, ARRAY_SIZE(stk5_pads));
+ }
+
+ static void stk5v3_board_init(void)
+ {
+ stk5_board_init();
+ }
+
+ static void stk5v5_board_init(void)
+ {
+ stk5_board_init();
+
-void ft_board_setup(void *blob, bd_t *bd)
++ gpio_request_one(IMX_GPIO_NR(4, 21), GPIOFLAG_OUTPUT_INIT_HIGH,
+ "Flexcan Transceiver");
+ imx_iomux_v3_setup_pad(MX53_PAD_DISP0_DAT0__GPIO4_21);
+ }
+
+ static void tx53_set_cpu_clock(void)
+ {
+ unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
+
+ if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000)
+ return;
+
+ if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
+ printf("%s detected; skipping cpu clock change\n",
+ (wrsr & WRSR_TOUT) ? "WDOG RESET" : "<CTRL-C>");
+ return;
+ }
+
+ if (mxc_set_clock(CONFIG_SYS_MX5_HCLK, cpu_clk, MXC_ARM_CLK) == 0) {
+ cpu_clk = mxc_get_clock(MXC_ARM_CLK);
+ printf("CPU clock set to %lu.%03lu MHz\n",
+ cpu_clk / 1000000, cpu_clk / 1000 % 1000);
+ } else {
+ printf("Error: Failed to set CPU clock to %lu MHz\n", cpu_clk);
+ }
+ }
+
+ static void tx53_init_mac(void)
+ {
+ u8 mac[ETH_ALEN];
+
+ imx_get_mac_from_fuse(0, mac);
+ if (!is_valid_ether_addr(mac)) {
+ printf("No valid MAC address programmed\n");
+ return;
+ }
+
+ printf("MAC addr from fuse: %pM\n", mac);
+ eth_setenv_enetaddr("ethaddr", mac);
+ }
+
+ int board_late_init(void)
+ {
+ int ret = 0;
+ const char *baseboard;
+
+ env_cleanup();
+
+ tx53_set_cpu_clock();
+
+ if (had_ctrlc())
+ setenv_ulong("safeboot", 1);
+ else if (wrsr & WRSR_TOUT)
+ setenv_ulong("wdreset", 1);
+ else
+ karo_fdt_move_fdt();
+
+ baseboard = getenv("baseboard");
+ if (!baseboard)
+ goto exit;
+
+ printf("Baseboard: %s\n", baseboard);
+
+ if (strncmp(baseboard, "stk5", 4) == 0) {
+ if ((strlen(baseboard) == 4) ||
+ strcmp(baseboard, "stk5-v3") == 0) {
+ stk5v3_board_init();
+ } else if (strcmp(baseboard, "stk5-v5") == 0) {
+ const char *otg_mode = getenv("otg_mode");
+
+ if (otg_mode && strcmp(otg_mode, "host") == 0) {
+ printf("otg_mode='%s' is incompatible with baseboard %s; setting to 'none'\n",
+ otg_mode, baseboard);
+ setenv("otg_mode", "none");
+ }
+ stk5v5_board_init();
+ } else {
+ printf("WARNING: Unsupported STK5 board rev.: %s\n",
+ baseboard + 4);
+ }
+ } else {
+ printf("WARNING: Unsupported baseboard: '%s'\n",
+ baseboard);
+ ret = -EINVAL;
+ }
+
+ exit:
+ tx53_init_mac();
+
+ gpio_set_value(TX53_RESET_OUT_GPIO, 1);
+ clear_ctrlc();
+ return ret;
+ }
+
+ int checkboard(void)
+ {
+ tx53_print_cpuinfo();
+ #if CONFIG_SYS_SDRAM_SIZE < SZ_1G
+ printf("Board: Ka-Ro TX53-8%d3%c\n",
+ is_lvds(), '0' + CONFIG_SYS_SDRAM_SIZE / SZ_1G);
+ #elif CONFIG_SYS_SDRAM_SIZE < SZ_2G
+ printf("Board: Ka-Ro TX53-1%d3%c\n",
+ is_lvds() + 2, '0' + CONFIG_SYS_SDRAM_SIZE / SZ_1G);
+ #else
+ printf("Board: Ka-Ro TX53-123%c\n",
+ '0' + CONFIG_SYS_SDRAM_SIZE / SZ_1G);
+ #endif
+ return 0;
+ }
+
+ #if defined(CONFIG_OF_BOARD_SETUP)
+ #ifdef CONFIG_FDT_FIXUP_PARTITIONS
+ #include <jffs2/jffs2.h>
+ #include <mtd_node.h>
+ static struct node_info nodes[] = {
+ { "fsl,imx53-nand", MTD_DEV_TYPE_NAND, },
+ };
+ #else
+ #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
+ #endif
+
+ #ifdef CONFIG_SYS_TX53_HWREV_2
+ static void tx53_fixup_rtc(void *blob)
+ {
+ karo_fdt_del_prop(blob, "dallas,ds1339", 0x68, "interrupt-parent");
+ karo_fdt_del_prop(blob, "dallas,ds1339", 0x68, "interrupts");
+ }
+ #else
+ static inline void tx53_fixup_rtc(void *blob)
+ {
+ }
+ #endif /* CONFIG_SYS_TX53_HWREV_2 */
+
+ static const char *tx53_touchpanels[] = {
+ "ti,tsc2007",
+ "edt,edt-ft5x06",
+ "eeti,egalax_ts",
+ };
+
- if (ret)
++int ft_board_setup(void *blob, bd_t *bd)
+ {
+ const char *baseboard = getenv("baseboard");
+ int stk5_v5 = baseboard != NULL && (strcmp(baseboard, "stk5-v5") == 0);
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ int ret;
+
+ ret = fdt_increase_size(blob, 4096);
-
++ if (ret) {
+ printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
++ return ret;
++ }
+ if (stk5_v5)
+ karo_fdt_enable_node(blob, "stk5led", 0);
+
+ fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+ fdt_fixup_ethernet(blob);
+
+ karo_fdt_fixup_touchpanel(blob, tx53_touchpanels,
+ ARRAY_SIZE(tx53_touchpanels));
+ karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply");
+ karo_fdt_fixup_flexcan(blob, stk5_v5);
+ tx53_fixup_rtc(blob);
+ karo_fdt_update_fb_mode(blob, video_mode);
++
++ return 0;
+ }
+ #endif /* CONFIG_OF_BOARD_SETUP */
--- /dev/null
--- /dev/null
++if TARGET_TX6
++
++config MX6
++ bool
++ default y
++
++config MX6Q
++ bool
++
++config MX6DL
++ bool
++
++config MX6QDL
++ bool
++
++config MX6S
++ bool
++
++config MX6SL
++ bool
++
++config MX6SX
++ bool
++
++config SYS_BOARD
++ default "tx6"
++
++config SYS_VENDOR
++ default "karo"
++
++config SYS_SOC
++ default "mx6"
++
++config SYS_CONFIG_NAME
++ default "tx6"
++
++config CMD_ROMUPDATE
++ bool
++
++config TX6
++ bool
++ default y
++ select MX6
++ select CMD_BMP if LCD
++ select CMD_BOOTCE
++ select CMD_BOOTZ
++ select CMD_CACHE
++ select CMD_I2C if I2C
++ select CMD_MEMTEST
++ select CMD_TIME
++ select DM
++ select DM_GPIO
++ select SYS_I2C
++ select SYS_I2C_MXC
++ select GET_FEC_MAC_ADDR_FROM_IIM
++
++config TX6_NAND
++ bool
++ default ! TX6_EMMC
++ select CMD_NAND
++ select CMD_NAND_TRIMFFS
++ select CMD_MTDPARTS
++ select CMD_ROMUPDATE
++ select FDT_FIXUP_PARTITIONS if OF_LIBFDT
++ select MTD_PARTITIONS
++ select NAND_MXS_NO_BBM_SWAP if NAND_MXS
++ select SYS_NAND_USE_FLASH_BBT if NAND_MXS
++ select APBH_DMA
++ select APBH_DMA_BURST
++ select APBH_DMA_BURST8
++ select MTD_DEVICE
++
++config TX6_EMMC
++ bool
++ select SUPPORT_EMMC_BOOT
++
++#
++# variables selected depending on module variant
++#
++config SYS_LVDS_IF
++ bool
++
++config SYS_SDRAM_BUS_WIDTH_16
++ bool
++
++config SYS_SDRAM_BUS_WIDTH_32
++ bool
++
++
++choice
++ prompt "TX6 module variant"
++
++config TARGET_TX6Q_10X0
++ bool "TX6Q-1010 and TX6Q-1030"
++ select MX6Q
++
++config TARGET_TX6Q_1020
++ bool "TX6Q-1020"
++ select MX6Q
++ select TX6_EMMC
++ select TX6_REV_2
++
++config TARGET_TX6Q_11X0
++ bool "TX6Q-1110 and TX6Q-1130"
++ select MX6Q
++ select SYS_LVDS_IF
++
++config TARGET_TX6S_8034
++ bool "TX6S-8034"
++ select MX6S
++ select SYS_SDRAM_BUS_WIDTH_16
++
++config TARGET_TX6S_8035
++ bool "TX6S-8035"
++ select MX6S
++ select TX6_EMMC
++ select SYS_SDRAM_BUS_WIDTH_32
++
++config TARGET_TX6U_8010
++ bool "TX6U-8010 and TX6U-8030"
++ select MX6DL
++
++config TARGET_TX6U_8011
++ bool "TX6U-8011"
++ select MX6DL
++ select SYS_SDRAM_BUS_WIDTH_32
++ select TX6_REV_1
++
++config TARGET_TX6U_8012
++ bool "TX6U-8012"
++ select MX6DL
++ select TX6_REV_1
++
++config TARGET_TX6U_81X0
++ bool "TX6U-8110 and TX6U-8130"
++ select MX6DL
++ select SYS_LVDS_IF
++
++config TARGET_TX6U_8111
++ bool "TX6U-8111"
++ select MX6DL
++ select SYS_SDRAM_BUS_WIDTH_32
++ select SYS_LVDS_IF
++ select TX6_REV_1
++
++config TARGET_TX6U_8033
++ bool "TX6U-8033"
++ select MX6DL
++ select TX6_EMMC
++ select TX6_REV_3
++
++endchoice
++
++choice
++ prompt "U-Boot image variant"
++ default TX6_UBOOT
++
++config TX6_UBOOT
++ bool "Standard U-Boot image"
++
++config TX6_UBOOT_MFG
++ bool "U-Boot image for use with Freescale's MfGTool"
++
++config TX6_UBOOT_NOENV
++ bool "U-Boot using only built-in environment"
++
++endchoice
++
++endif
--- /dev/null
-# (C) Copyright 2009 DENX Software Engineering
-# Author: John Rigby <jcrigby@gmail.com>
+ #
-include $(TOPDIR)/config.mk
++# (C) Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ #
+ # SPDX-License-Identifier: GPL-2.0+
+ #
+
-LIB = $(obj)lib$(BOARD).o
++LDSCRIPT := $(BOARDDIR)/u-boot.lds
+
-COBJS-y := tx6qdl.o
-COBJS-$(CONFIG_LTC3676) += ltc3676.o
-COBJS-$(CONFIG_RN5T567) += rn5t567.o
-COBJS-$(CONFIG_RN5T618) += rn5t618.o
-
-COBJS-$(CONFIG_CMD_ROMUPDATE) += flash.o
-
-SOBJS-y := lowlevel_init.o
-
-SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS-y))
-SOBJS := $(addprefix $(obj),$(SOBJS-y))
-
-$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(call cmd_link_o_target, $(OBJS) $(SOBJS))
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
++obj-y += lowlevel_init.o pmic.o tx6qdl.o
++obj-$(CONFIG_LTC3676) += ltc3676.o
++obj-$(CONFIG_RN5T567) += rn5t567.o
++obj-$(CONFIG_RN5T618) += rn5t618.o
+
++obj-$(CONFIG_CMD_ROMUPDATE) += flash.o
--- /dev/null
-ifeq ($(CONFIG_NO_NAND),)
+ # stack is allocated below CONFIG_SYS_TEXT_BASE
+ CONFIG_SYS_TEXT_BASE := 0x10100000
+
++__HAVE_ARCH_GENERIC_BOARD := y
++
+ LOGO_BMP = logos/karo.bmp
+ #PLATFORM_CPPFLAGS += -DDEBUG
+ #PLATFORM_CPPFLAGS += -Wno-unused-but-set-variable
+ PLATFORM_CPPFLAGS += -Werror
+
-endif # CONFIG_NO_NAND
++ifeq ($(CONFIG_TX6_NAND),y)
+ # calculate U_BOOT_IMG_SIZE to be at least 3 eraseblocks larger than the maximum expected image size
+ CONFIG_SYS_NAND_BLOCK_SIZE := 131072
+ ifeq ($(CONFIG_SYS_NAND_BLOCKS),)
+ CONFIG_SYS_NAND_BLOCKS := 1024
+ endif
+ ifneq ($(CONFIG_SYS_NAND_BLOCK_SIZE),)
+ CONFIG_U_BOOT_IMG_SIZE := $(shell echo 'e=$(CONFIG_SYS_NAND_BLOCK_SIZE);s=640*1024;s + (e - s % e) % e + 3*e' | bc)
+ CONFIG_SYS_USERFS_SIZE := $(shell expr \( $(CONFIG_SYS_NAND_BLOCKS) - 12 \) \* $(CONFIG_SYS_NAND_BLOCK_SIZE) - $(CONFIG_U_BOOT_IMG_SIZE) - 38 \* 1048576)
+ CONFIG_SYS_USERFS_SIZE2 := $(shell expr \( $(CONFIG_SYS_NAND_BLOCKS) - 15 \) \* $(CONFIG_SYS_NAND_BLOCK_SIZE) - $(CONFIG_U_BOOT_IMG_SIZE) - 38 \* 1048576)
+ CONFIG_SYS_NAND_BBT_BLOCKS := 4
+ CONFIG_SYS_NAND_DTB_BLOCKS := 4
+
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_NAND_BLOCKS=$(CONFIG_SYS_NAND_BLOCKS)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_NAND_BLOCK_SIZE=$(CONFIG_SYS_NAND_BLOCK_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_U_BOOT_IMG_SIZE=$(CONFIG_U_BOOT_IMG_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_U_BOOT_PART_SIZE=$(shell printf "%uk" `expr $(CONFIG_U_BOOT_IMG_SIZE) / 1024`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_NAND_U_BOOT_OFFS=$(shell printf "0x%x" `expr $(CONFIG_SYS_NAND_BLOCK_SIZE)`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_ENV_PART_SIZE=$(shell printf "%uk" `expr 3 \* $(CONFIG_SYS_NAND_BLOCK_SIZE) / 1024`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_USERFS_PART_SIZE=$(shell printf "%uk" `expr $(CONFIG_SYS_USERFS_SIZE) / 1024`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_USERFS_PART_SIZE2=$(shell printf "%uk" `expr $(CONFIG_SYS_USERFS_SIZE) / 1024`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_DTB_PART_SIZE=$(shell printf "%uk" `expr $(CONFIG_SYS_NAND_BLOCK_SIZE) \* $(CONFIG_SYS_NAND_BBT_BLOCKS) / 1024`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_NAND_DTB_OFFSET=$(shell printf "0x%x" `expr \( $(CONFIG_SYS_NAND_BLOCKS) - $(CONFIG_SYS_NAND_DTB_BLOCKS) - $(CONFIG_SYS_NAND_BBT_BLOCKS) \) \* $(CONFIG_SYS_NAND_BLOCK_SIZE)`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_NAND_BBT_SIZE=$(shell printf "%uk" `expr $(CONFIG_SYS_NAND_BBT_BLOCKS) \* $(CONFIG_SYS_NAND_BLOCK_SIZE) / 1024`)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_NAND_BBT_OFFSET=$(shell printf "0x%x" `expr \( $(CONFIG_SYS_NAND_BLOCKS) - $(CONFIG_SYS_NAND_BBT_BLOCKS) \) \* $(CONFIG_SYS_NAND_BLOCK_SIZE)`)
+ endif # CONFIG_SYS_NAND_BLOCK_SIZE
+ else
+ ifneq ($(CONFIG_MMC_BOOT_SIZE),)
+ CONFIG_SYS_MMC_BOOT_PART_SIZE := $(shell expr $(CONFIG_MMC_BOOT_SIZE) \* 1024)
+ else
+ CONFIG_SYS_MMC_BOOT_PART_SIZE := $(shell expr 4096 \* 1024)
+ endif
+ CONFIG_U_BOOT_IMG_SIZE := $(shell expr 1 \* 1048576)
+ CONFIG_MAX_DTB_SIZE := $(shell expr 64 \* 1024)
+ CONFIG_ENV_SIZE := $(shell expr 128 \* 1024)
+ CONFIG_ENV_OFFSET := $(shell expr $(CONFIG_SYS_MMC_BOOT_PART_SIZE) - $(CONFIG_ENV_SIZE))
+ CONFIG_SYS_DTB_OFFSET := $(shell expr $(CONFIG_ENV_OFFSET) - $(CONFIG_MAX_DTB_SIZE))
+
+ PLATFORM_CPPFLAGS += -DCONFIG_ENV_SIZE=$(CONFIG_ENV_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_U_BOOT_IMG_SIZE=$(CONFIG_U_BOOT_IMG_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_MAX_DTB_SIZE=$(CONFIG_MAX_DTB_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_DTB_PART_SIZE=$(CONFIG_MAX_DTB_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_MMC_BOOT_PART_SIZE=$(CONFIG_SYS_MMC_BOOT_PART_SIZE)
+ PLATFORM_CPPFLAGS += -DCONFIG_ENV_OFFSET=$(shell printf "0x%x" $(CONFIG_ENV_OFFSET))
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_DTB_OFFSET=$(shell printf "0x%x" $(CONFIG_SYS_DTB_OFFSET))
+ PLATFORM_CPPFLAGS += -DCONFIG_SYS_DTB_BLKNO=$(shell printf "0x%x" `expr $(CONFIG_SYS_DTB_OFFSET) / 512`)
++endif # CONFIG_TX6_NAND
--- /dev/null
-#include <asm/sizes.h>
+ /*
+ * Copyright (C) 2012-2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <malloc.h>
+ #include <nand.h>
+ #include <errno.h>
+
+ #include <linux/err.h>
+ #include <jffs2/load_kernel.h>
+
+ #include <asm/io.h>
- ret = chip->write_page(mtd, chip, buf, 1, page, 0, 1);
++#include <linux/sizes.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/imx-common/regs-gpmi.h>
+ #include <asm/imx-common/regs-bch.h>
+
+ struct mx6_nand_timing {
+ u8 data_setup;
+ u8 data_hold;
+ u8 address_setup;
+ u8 dsample_time;
+ u8 nand_timing_state;
+ u8 tREA;
+ u8 tRLOH;
+ u8 tRHOH;
+ };
+
+ struct mx6_fcb {
+ u32 checksum;
+ u32 fingerprint;
+ u32 version;
+ struct mx6_nand_timing timing;
+ u32 page_data_size;
+ u32 total_page_size;
+ u32 sectors_per_block;
+ u32 number_of_nands; /* not used by ROM code */
+ u32 total_internal_die; /* not used by ROM code */
+ u32 cell_type; /* not used by ROM code */
+ u32 ecc_blockn_type;
+ u32 ecc_block0_size;
+ u32 ecc_blockn_size;
+ u32 ecc_block0_type;
+ u32 metadata_size;
+ u32 ecc_blocks_per_page;
+ u32 rsrvd1[6]; /* not used by ROM code */
+ u32 bch_mode; /* erase_threshold */
+ u32 rsrvd2[2];
+ u32 fw1_start_page;
+ u32 fw2_start_page;
+ u32 fw1_sectors;
+ u32 fw2_sectors;
+ u32 dbbt_search_area;
+ u32 bb_mark_byte;
+ u32 bb_mark_startbit;
+ u32 bb_mark_phys_offset;
+ u32 bch_type;
+ u32 rsrvd3[8]; /* Toggle NAND timing parameters */
+ u32 disbbm;
+ u32 bb_mark_spare_offset;
+ u32 rsrvd4[9]; /* ONFI NAND parameters */
+ u32 disbb_search;
+ };
+
+ struct mx6_dbbt_header {
+ u32 checksum;
+ u32 fingerprint;
+ u32 version;
+ u32 number_bb;
+ u32 number_pages;
+ u8 spare[492];
+ };
+
+ struct mx6_dbbt {
+ u32 nand_number;
+ u32 number_bb;
+ u32 bb_num[2040 / 4];
+ };
+
+ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
+
+ static nand_info_t *mtd = &nand_info[0];
+
+ extern void *_start;
+
+ #define BIT(v,n) (((v) >> (n)) & 0x1)
+
+ static u8 calculate_parity_13_8(u8 d)
+ {
+ u8 p = 0;
+
+ p |= (BIT(d, 6) ^ BIT(d, 5) ^ BIT(d, 3) ^ BIT(d, 2)) << 0;
+ p |= (BIT(d, 7) ^ BIT(d, 5) ^ BIT(d, 4) ^ BIT(d, 2) ^ BIT(d, 1)) << 1;
+ p |= (BIT(d, 7) ^ BIT(d, 6) ^ BIT(d, 5) ^ BIT(d, 1) ^ BIT(d, 0)) << 2;
+ p |= (BIT(d, 7) ^ BIT(d, 4) ^ BIT(d, 3) ^ BIT(d, 0)) << 3;
+ p |= (BIT(d, 6) ^ BIT(d, 4) ^ BIT(d, 3) ^ BIT(d, 2) ^ BIT(d, 1) ^ BIT(d, 0)) << 4;
+ return p;
+ }
+
+ static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
+ {
+ int i;
+ u8 *src = _src;
+ u8 *ecc = _ecc;
+
+ for (i = 0; i < size; i++)
+ ecc[i] = calculate_parity_13_8(src[i]);
+ }
+
+ static u32 calc_chksum(void *buf, size_t size)
+ {
+ u32 chksum = 0;
+ u8 *bp = buf;
+ size_t i;
+
+ for (i = 0; i < size; i++) {
+ chksum += bp[i];
+ }
+ return ~chksum;
+ }
+
+ /*
+ Physical organisation of data in NAND flash:
+ metadata
+ payload chunk 0 (may be empty)
+ ecc for metadata + payload chunk 0
+ payload chunk 1
+ ecc for payload chunk 1
+ ...
+ payload chunk n
+ ecc for payload chunk n
+ */
+
+ static inline int calc_bb_offset(nand_info_t *mtd, struct mx6_fcb *fcb)
+ {
+ int bb_mark_offset;
+ int chunk_data_size = fcb->ecc_blockn_size * 8;
+ int chunk_ecc_size = (fcb->ecc_blockn_type << 1) * 13;
+ int chunk_total_size = chunk_data_size + chunk_ecc_size;
+ int bb_mark_chunk, bb_mark_chunk_offs;
+
+ bb_mark_offset = (mtd->writesize - fcb->metadata_size) * 8;
+ if (fcb->ecc_block0_size == 0)
+ bb_mark_offset -= (fcb->ecc_block0_type << 1) * 13;
+
+ bb_mark_chunk = bb_mark_offset / chunk_total_size;
+ bb_mark_chunk_offs = bb_mark_offset - (bb_mark_chunk * chunk_total_size);
+ if (bb_mark_chunk_offs > chunk_data_size) {
+ printf("Unsupported ECC layout; BB mark resides in ECC data: %u\n",
+ bb_mark_chunk_offs);
+ return -EINVAL;
+ }
+ bb_mark_offset -= bb_mark_chunk * chunk_ecc_size;
+ return bb_mark_offset;
+ }
+
+ /*
+ * return number of blocks to skip for a contiguous partition
+ * of given # blocks
+ */
+ static int find_contig_space(int block, int num_blocks, int max_blocks)
+ {
+ int skip = 0;
+ int found = 0;
+ int last = block + max_blocks;
+
+ debug("Searching %u contiguous blocks from %d..%d\n",
+ num_blocks, block, block + max_blocks - 1);
+ for (; block < last; block++) {
+ if (nand_block_isbad(mtd, block * mtd->erasesize)) {
+ skip += found + 1;
+ found = 0;
+ debug("Skipping %u blocks to %u\n",
+ skip, block + 1);
+ } else {
+ found++;
+ if (found >= num_blocks) {
+ debug("Found %u good blocks from %d..%d\n",
+ found, block - found + 1, block);
+ return skip;
+ }
+ }
+ }
+ return -ENOSPC;
+ }
+
+ #define pr_fcb_val(p, n) debug("%s=%08x(%d)\n", #n, (p)->n, (p)->n)
+
+ static struct mx6_fcb *create_fcb(void *buf, int fw1_start_block,
+ int fw2_start_block, int fw_num_blocks)
+ {
+ struct gpmi_regs *gpmi_base = (void *)GPMI_BASE_ADDRESS;
+ struct bch_regs *bch_base = (void *)BCH_BASE_ADDRESS;
+ u32 fl0, fl1;
+ u32 t0;
+ int metadata_size;
+ int bb_mark_bit_offs;
+ struct mx6_fcb *fcb;
+ int fcb_offs;
+
+ if (gpmi_base == NULL || bch_base == NULL) {
+ return ERR_PTR(-ENOMEM);
+ }
+
+ fl0 = readl(&bch_base->hw_bch_flash0layout0);
+ fl1 = readl(&bch_base->hw_bch_flash0layout1);
+ t0 = readl(&gpmi_base->hw_gpmi_timing0);
+
+ metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+
+ fcb = buf + ALIGN(metadata_size, 4);
+ fcb_offs = (void *)fcb - buf;
+
+ memset(buf, 0xff, fcb_offs);
+ memset(fcb, 0x00, sizeof(*fcb));
+ memset(fcb + 1, 0xff, mtd->erasesize - fcb_offs - sizeof(*fcb));
+
+ strncpy((char *)&fcb->fingerprint, "FCB ", 4);
+ fcb->version = cpu_to_be32(1);
+
+ fcb->disbb_search = 0;
+ fcb->disbbm = 1;
+
+ /* ROM code assumes GPMI clock of 25 MHz */
+ fcb->timing.data_setup = BF_VAL(t0, GPMI_TIMING0_DATA_SETUP) * 40;
+ fcb->timing.data_hold = BF_VAL(t0, GPMI_TIMING0_DATA_HOLD) * 40;
+ fcb->timing.address_setup = BF_VAL(t0, GPMI_TIMING0_ADDRESS_SETUP) * 40;
+
+ fcb->page_data_size = mtd->writesize;
+ fcb->total_page_size = mtd->writesize + mtd->oobsize;
+ fcb->sectors_per_block = mtd->erasesize / mtd->writesize;
+
+ fcb->ecc_block0_type = BF_VAL(fl0, BCH_FLASHLAYOUT0_ECC0);
+ fcb->ecc_block0_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_DATA0_SIZE) * 4;
+ fcb->ecc_blockn_type = BF_VAL(fl1, BCH_FLASHLAYOUT1_ECCN);
+ fcb->ecc_blockn_size = BF_VAL(fl1, BCH_FLASHLAYOUT1_DATAN_SIZE) * 4;
+
+ pr_fcb_val(fcb, ecc_block0_type);
+ pr_fcb_val(fcb, ecc_blockn_type);
+ pr_fcb_val(fcb, ecc_block0_size);
+ pr_fcb_val(fcb, ecc_blockn_size);
+
+ fcb->metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+ fcb->ecc_blocks_per_page = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
+ fcb->bch_mode = readl(&bch_base->hw_bch_mode);
+ fcb->bch_type = 0; /* BCH20 */
+
+ fcb->fw1_start_page = fw1_start_block * fcb->sectors_per_block;
+ fcb->fw1_sectors = fw_num_blocks * fcb->sectors_per_block;
+ pr_fcb_val(fcb, fw1_start_page);
+ pr_fcb_val(fcb, fw1_sectors);
+
+ if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) {
+ fcb->fw2_start_page = fw2_start_block * fcb->sectors_per_block;
+ fcb->fw2_sectors = fcb->fw1_sectors;
+ pr_fcb_val(fcb, fw2_start_page);
+ pr_fcb_val(fcb, fw2_sectors);
+ }
+
+ fcb->dbbt_search_area = 0;
+
+ bb_mark_bit_offs = calc_bb_offset(mtd, fcb);
+ if (bb_mark_bit_offs < 0)
+ return ERR_PTR(bb_mark_bit_offs);
+ fcb->bb_mark_byte = bb_mark_bit_offs / 8;
+ fcb->bb_mark_startbit = bb_mark_bit_offs % 8;
+ fcb->bb_mark_phys_offset = mtd->writesize;
+
+ pr_fcb_val(fcb, bb_mark_byte);
+ pr_fcb_val(fcb, bb_mark_startbit);
+ pr_fcb_val(fcb, bb_mark_phys_offset);
+
+ fcb->checksum = calc_chksum(&fcb->fingerprint, 512 - 4);
+ return fcb;
+ }
+
+ static int find_fcb(void *ref, int page)
+ {
+ int ret = 0;
+ struct nand_chip *chip = mtd->priv;
+ void *buf = malloc(mtd->erasesize);
+
+ if (buf == NULL) {
+ return -ENOMEM;
+ }
+ chip->select_chip(mtd, 0);
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+ ret = chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
+ if (ret) {
+ printf("Failed to read FCB from page %u: %d\n", page, ret);
+ goto out;
+ }
+ if (memcmp(buf, ref, mtd->writesize) == 0) {
+ debug("Found FCB in page %u (%08x)\n",
+ page, page * mtd->writesize);
+ ret = 1;
+ }
+ out:
+ chip->select_chip(mtd, -1);
+ free(buf);
+ return ret;
+ }
+
+ static int write_fcb(void *buf, int block)
+ {
+ int ret;
+ struct nand_chip *chip = mtd->priv;
+ int page = block * mtd->erasesize / mtd->writesize;
+
+ ret = find_fcb(buf, page);
+ if (ret > 0) {
+ printf("FCB at block %d is up to date\n", block);
+ return 0;
+ }
+
+ ret = nand_erase(mtd, block * mtd->erasesize, mtd->erasesize);
+ if (ret) {
+ printf("Failed to erase FCB block %u\n", block);
+ return ret;
+ }
+
+ printf("Writing FCB to block %d @ %08llx\n", block,
+ (u64)block * mtd->erasesize);
+ chip->select_chip(mtd, 0);
++ ret = chip->write_page(mtd, chip, 0, mtd->writesize,
++ buf, 1, page, 0, 1);
+ if (ret) {
+ printf("Failed to write FCB to block %u: %d\n", block, ret);
+ }
+ chip->select_chip(mtd, -1);
+ return ret;
+ }
+
+ struct mx6_ivt {
+ u32 magic;
+ u32 entry;
+ u32 rsrvd1;
+ void *dcd;
+ void *boot_data;
+ void *self;
+ void *csf;
+ u32 rsrvd2;
+ };
+
+ struct mx6_boot_data {
+ u32 start;
+ u32 length;
+ u32 plugin;
+ };
+
+ static int find_ivt(void *buf)
+ {
+ struct mx6_ivt *ivt_hdr = buf + 0x400;
+
+ if ((ivt_hdr->magic & 0xff0000ff) != 0x400000d1)
+ return 0;
+
+ return 1;
+ }
+
+ static inline void *reloc(void *dst, void *base, void *ptr)
+ {
+ return dst + (ptr - base);
+ }
+
+ static int patch_ivt(void *buf, size_t fsize)
+ {
+ struct mx6_ivt *ivt_hdr = buf + 0x400;
+ struct mx6_boot_data *boot_data;
+
+ if (!find_ivt(buf)) {
+ printf("No IVT found in image at %p\n", buf);
+ return -EINVAL;
+ }
+ boot_data = reloc(ivt_hdr, ivt_hdr->self, ivt_hdr->boot_data);
+ boot_data->length = fsize;
+
+ return 0;
+ }
+
+ #define chk_overlap(a,b) \
+ ((a##_start_block <= b##_end_block && \
+ a##_end_block >= b##_start_block) || \
+ (b##_start_block <= a##_end_block && \
+ b##_end_block >= a##_start_block))
+
+ #define fail_if_overlap(a,b,m1,m2) do { \
+ if (chk_overlap(a, b)) { \
+ printf("%s blocks %lu..%lu overlap %s in blocks %lu..%lu!\n", \
+ m1, a##_start_block, a##_end_block, \
+ m2, b##_start_block, b##_end_block); \
+ return -EINVAL; \
+ } \
+ } while (0)
+
+ static int tx6_prog_uboot(void *addr, int start_block, int skip,
+ size_t size, size_t max_len)
+ {
+ int ret;
+ nand_erase_options_t erase_opts = { 0, };
+ size_t actual;
+ size_t prg_length = max_len - skip * mtd->erasesize;
+ int prg_start = (start_block + skip) * mtd->erasesize;
+
+ erase_opts.offset = start_block * mtd->erasesize;
+ erase_opts.length = max_len;
+ erase_opts.quiet = 1;
+
+ printf("Erasing flash @ %08llx..%08llx\n", erase_opts.offset,
+ erase_opts.offset + erase_opts.length - 1);
+ ret = nand_erase_opts(mtd, &erase_opts);
+ if (ret) {
+ printf("Failed to erase flash: %d\n", ret);
+ return ret;
+ }
+
+ printf("Programming flash @ %08llx..%08llx from %p\n",
+ (u64)start_block * mtd->erasesize,
+ (u64)start_block * mtd->erasesize + size - 1, addr);
+ actual = size;
+ ret = nand_write_skip_bad(mtd, prg_start, &actual, NULL,
+ prg_length, addr, WITH_DROP_FFS);
+ if (ret) {
+ printf("Failed to program flash: %d\n", ret);
+ return ret;
+ }
+ if (actual < size) {
+ printf("Could only write %u of %u bytes\n", actual, size);
+ return -EIO;
+ }
+ return 0;
+ }
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #ifndef CONFIG_ENV_OFFSET_REDUND
+ #define TOTAL_ENV_SIZE CONFIG_ENV_RANGE
+ #else
+ #define TOTAL_ENV_SIZE (CONFIG_ENV_RANGE * 2)
+ #endif
+ #endif
+
+ int do_update(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int ret;
+ const unsigned long fcb_start_block = 0, fcb_end_block = 0;
+ int erase_size = mtd->erasesize;
+ int page_size = mtd->writesize;
+ void *buf;
+ char *load_addr;
+ char *file_size;
+ size_t size = 0;
+ void *addr = NULL;
+ struct mx6_fcb *fcb;
+ unsigned long mtd_num_blocks = mtd->size / mtd->erasesize;
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ unsigned long env_start_block = CONFIG_ENV_OFFSET / mtd->erasesize;
+ unsigned long env_end_block = env_start_block +
+ DIV_ROUND_UP(TOTAL_ENV_SIZE, mtd->erasesize) - 1;
+ #endif
+ int optind;
+ int fw2_set = 0;
+ unsigned long fw1_start_block = 0, fw1_end_block;
+ unsigned long fw2_start_block = 0, fw2_end_block;
+ unsigned long fw_num_blocks;
+ int fw1_skip, fw2_skip;
+ unsigned long extra_blocks = 0;
+ size_t max_len1, max_len2;
+ struct mtd_device *dev;
+ struct part_info *part_info;
+ struct part_info *redund_part_info;
+ const char *uboot_part = "u-boot";
+ const char *redund_part = NULL;
+ u8 part_num;
+ u8 redund_part_num;
+
+ ret = mtdparts_init();
+ if (ret)
+ return ret;
+
+ for (optind = 1; optind < argc; optind++) {
+ char *endp;
+
+ if (strcmp(argv[optind], "-f") == 0) {
+ if (optind >= argc - 1) {
+ printf("Option %s requires an argument\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+ optind++;
+ fw1_start_block = simple_strtoul(argv[optind], &endp, 0);
+ if (*endp != '\0') {
+ uboot_part = argv[optind];
+ continue;
+ }
+ uboot_part = NULL;
+ if (fw1_start_block >= mtd_num_blocks) {
+ printf("Block number %lu is out of range: 0..%lu\n",
+ fw1_start_block, mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ } else if (strcmp(argv[optind], "-r") == 0) {
+ fw2_set = 1;
+ if (optind < argc - 1 && argv[optind + 1][0] != '-') {
+ optind++;
+ fw2_start_block = simple_strtoul(argv[optind],
+ &endp, 0);
+ if (*endp != '\0') {
+ redund_part = argv[optind];
+ continue;
+ }
+ if (fw2_start_block >= mtd_num_blocks) {
+ printf("Block number %lu is out of range: 0..%lu\n",
+ fw2_start_block,
+ mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ }
+ } else if (strcmp(argv[optind], "-e") == 0) {
+ if (optind >= argc - 1) {
+ printf("Option %s requires an argument\n",
+ argv[optind]);
+ return -EINVAL;
+ }
+ optind++;
+ extra_blocks = simple_strtoul(argv[optind], NULL, 0);
+ if (extra_blocks >= mtd_num_blocks) {
+ printf("Extra block count %lu is out of range: 0..%lu\n",
+ extra_blocks,
+ mtd_num_blocks - 1);
+ return -EINVAL;
+ }
+ } else if (argv[optind][0] == '-') {
+ printf("Unrecognized option %s\n", argv[optind]);
+ return -EINVAL;
+ } else {
+ break;
+ }
+ }
+
+ load_addr = getenv("fileaddr");
+ file_size = getenv("filesize");
+
+ if (argc - optind < 1 && load_addr == NULL) {
+ printf("Load address not specified\n");
+ return -EINVAL;
+ }
+ if (argc - optind < 2 && file_size == NULL) {
+ printf("WARNING: Image size not specified; overwriting whole uboot partition\n");
+ }
+ if (argc > optind) {
+ load_addr = NULL;
+ addr = (void *)simple_strtoul(argv[optind], NULL, 16);
+ optind++;
+ }
+ if (argc > optind) {
+ file_size = NULL;
+ size = simple_strtoul(argv[optind], NULL, 16);
+ optind++;
+ }
+ if (load_addr != NULL) {
+ addr = (void *)simple_strtoul(load_addr, NULL, 16);
+ printf("Using default load address %p\n", addr);
+ }
+ if (file_size != NULL) {
+ size = simple_strtoul(file_size, NULL, 16);
+ printf("Using default file size %08x\n", size);
+ }
+ if (size > 0) {
+ fw_num_blocks = DIV_ROUND_UP(size, mtd->erasesize);
+ } else {
+ fw_num_blocks = part_info->size / mtd->erasesize -
+ extra_blocks;
+ size = fw_num_blocks * mtd->erasesize;
+ }
+
+ if (uboot_part) {
+ ret = find_dev_and_part(uboot_part, &dev, &part_num,
+ &part_info);
+ if (ret) {
+ printf("Failed to find '%s' partition: %d\n",
+ uboot_part, ret);
+ return ret;
+ }
+ fw1_start_block = part_info->offset / mtd->erasesize;
+ max_len1 = part_info->size;
+ } else {
+ max_len1 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ }
+
+ if (redund_part) {
+ ret = find_dev_and_part(redund_part, &dev, &redund_part_num,
+ &redund_part_info);
+ if (ret) {
+ printf("Failed to find '%s' partition: %d\n",
+ redund_part, ret);
+ return ret;
+ }
+ fw2_start_block = redund_part_info->offset / mtd->erasesize;
+ max_len2 = redund_part_info->size;
+ } else if (fw2_set) {
+ max_len2 = (fw_num_blocks + extra_blocks) * mtd->erasesize;
+ } else {
+ max_len2 = 0;
+ }
+
+ fw1_skip = find_contig_space(fw1_start_block, fw_num_blocks,
+ max_len1 / mtd->erasesize);
+ if (fw1_skip < 0) {
+ printf("Could not find %lu contiguous good blocks for fw image\n",
+ fw_num_blocks);
+ if (uboot_part) {
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ if (part_info->offset <= CONFIG_ENV_OFFSET + TOTAL_ENV_SIZE) {
+ printf("Use a different partition\n");
+ } else {
+ printf("Increase the size of the '%s' partition\n",
+ uboot_part);
+ }
+ #else
+ printf("Increase the size of the '%s' partition\n",
+ uboot_part);
+ #endif
+ } else {
+ printf("Increase the number of spare blocks to use with the '-e' option\n");
+ }
+ return -ENOSPC;
+ }
+ fw1_end_block = fw1_start_block + fw1_skip + fw_num_blocks - 1;
+
+ if (fw2_set && fw2_start_block == 0)
+ fw2_start_block = fw1_end_block + 1;
+ if (fw2_start_block > 0) {
+ fw2_skip = find_contig_space(fw2_start_block, fw_num_blocks,
+ max_len2 / mtd->erasesize);
+ if (fw2_skip < 0) {
+ printf("Could not find %lu contiguous good blocks for redundant fw image\n",
+ fw_num_blocks);
+ if (redund_part) {
+ printf("Increase the size of the '%s' partition or use a different partition\n",
+ redund_part);
+ } else {
+ printf("Increase the number of spare blocks to use with the '-e' option\n");
+ }
+ return -ENOSPC;
+ }
+ } else {
+ fw2_skip = 0;
+ }
+ fw2_end_block = fw2_start_block + fw2_skip + fw_num_blocks - 1;
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ fail_if_overlap(fcb, env, "FCB", "Environment");
+ fail_if_overlap(fw1, env, "FW1", "Environment");
+ #endif
+ fail_if_overlap(fcb, fw1, "FCB", "FW1");
+ if (fw2_set) {
+ fail_if_overlap(fcb, fw2, "FCB", "FW2");
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ fail_if_overlap(fw2, env, "FW2", "Environment");
+ #endif
+ fail_if_overlap(fw1, fw2, "FW1", "FW2");
+ }
+
+ buf = malloc(erase_size);
+ if (buf == NULL) {
+ printf("Failed to allocate buffer\n");
+ return -ENOMEM;
+ }
+
+ fcb = create_fcb(buf, fw1_start_block + fw1_skip,
+ fw2_start_block + fw2_skip, fw_num_blocks);
+ if (IS_ERR(fcb)) {
+ printf("Failed to initialize FCB: %ld\n", PTR_ERR(fcb));
+ free(buf);
+ return PTR_ERR(fcb);
+ }
+ encode_hamming_13_8(fcb, (void *)fcb + 512, 512);
+
+ ret = write_fcb(buf, fcb_start_block);
+ free(buf);
+ if (ret) {
+ printf("Failed to write FCB to block %lu\n", fcb_start_block);
+ return ret;
+ }
+ ret = patch_ivt(addr, size);
+ if (ret) {
+ return ret;
+ }
+
+ if (size & (page_size - 1)) {
+ memset(addr + size, 0xff, size & (page_size - 1));
+ size = ALIGN(size, page_size);
+ }
+
+ printf("Programming U-Boot image from %p to block %lu @ %08llx\n",
+ addr, fw1_start_block + fw1_skip,
+ (u64)(fw1_start_block + fw1_skip) * mtd->erasesize);
+ ret = tx6_prog_uboot(addr, fw1_start_block, fw1_skip, size,
+ max_len1);
+
+ if (fw2_start_block == 0) {
+ return ret;
+ }
+
+ printf("Programming redundant U-Boot image to block %lu @ %08llx\n",
+ fw2_start_block + fw2_skip,
+ (u64)(fw2_start_block + fw2_skip) * mtd->erasesize);
+ ret = tx6_prog_uboot(addr, fw2_start_block, fw2_skip, fw_num_blocks,
+ max_len2);
+ return ret;
+ }
+
+ U_BOOT_CMD(romupdate, 11, 0, do_update,
+ "Creates an FCB data structure and writes an U-Boot image to flash",
+ "[-f {<part>|block#}] [-r [{<part>|block#}]] [-e #] [<address>] [<length>]\n"
+ "\t-f <part>\twrite bootloader image to partition <part>\n"
+ "\t-f #\twrite bootloader image at block # (decimal)\n"
+ "\t-r\twrite redundant bootloader image at next free block after first image\n"
+ "\t-r <part>\twrite redundant bootloader image to partition <part>\n"
+ "\t-r #\twrite redundant bootloader image at block # (decimal)\n"
+ "\t-e #\tspecify number of redundant blocks per boot loader image\n"
+ "\t\tonly valid if -f or -r specify a flash address rather than a partition name\n"
+ "\t<address>\tRAM address of bootloader image (default: ${fileaddr}\n"
+ "\t<length>\tlength of bootloader image in RAM (default: ${filesize}"
+ );
--- /dev/null
-#define VDD_IO_VAL mV_to_regval(vout_to_vref(3300 * 10, 5))
-#define VDD_IO_VAL_LP mV_to_regval(vout_to_vref(3100 * 10, 5))
-#define VDD_IO_VAL_2 mV_to_regval(vout_to_vref(3300 * 10, 5_2))
-#define VDD_IO_VAL_2_LP mV_to_regval(vout_to_vref(3100 * 10, 5_2))
-#define VDD_SOC_VAL mV_to_regval(vout_to_vref(1425 * 10, 6))
-#define VDD_SOC_VAL_LP mV_to_regval(vout_to_vref(900 * 10, 6))
-#define VDD_DDR_VAL mV_to_regval(vout_to_vref(1500 * 10, 7))
-#define VDD_DDR_VAL_LP mV_to_regval(vout_to_vref(1500 * 10, 7))
-#define VDD_CORE_VAL mV_to_regval(vout_to_vref(1425 * 10, 8))
-#define VDD_CORE_VAL_LP mV_to_regval(vout_to_vref(900 * 10, 8))
+ /*
+ * Copyright (C) 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <i2c.h>
+ #include <asm/io.h>
++#include <asm/arch/imx-regs.h>
+
+ #include "pmic.h"
+
+ #define LTC3676_BUCK1 0x01
+ #define LTC3676_BUCK2 0x02
+ #define LTC3676_BUCK3 0x03
+ #define LTC3676_BUCK4 0x04
+ #define LTC3676_DVB1A 0x0A
+ #define LTC3676_DVB1B 0x0B
+ #define LTC3676_DVB2A 0x0C
+ #define LTC3676_DVB2B 0x0D
+ #define LTC3676_DVB3A 0x0E
+ #define LTC3676_DVB3B 0x0F
+ #define LTC3676_DVB4A 0x10
+ #define LTC3676_DVB4B 0x11
+ #define LTC3676_MSKPG 0x13
+ #define LTC3676_CLIRQ 0x1f
+
+ #define LTC3676_BUCK_DVDT_FAST (1 << 0)
+ #define LTC3676_BUCK_KEEP_ALIVE (1 << 1)
+ #define LTC3676_BUCK_CLK_RATE_LOW (1 << 2)
+ #define LTC3676_BUCK_PHASE_SEL (1 << 3)
+ #define LTC3676_BUCK_ENABLE_300 (1 << 4)
+ #define LTC3676_BUCK_PULSE_SKIP (0 << 5)
+ #define LTC3676_BUCK_BURST_MODE (1 << 5)
+ #define LTC3676_BUCK_CONTINUOUS (2 << 5)
+ #define LTC3676_BUCK_ENABLE (1 << 7)
+
+ #define LTC3676_PGOOD_MASK (1 << 5)
+
+ #define LTC3676_MSKPG_BUCK1 (1 << 0)
+ #define LTC3676_MSKPG_BUCK2 (1 << 1)
+ #define LTC3676_MSKPG_BUCK3 (1 << 2)
+ #define LTC3676_MSKPG_BUCK4 (1 << 3)
+ #define LTC3676_MSKPG_LDO2 (1 << 5)
+ #define LTC3676_MSKPG_LDO3 (1 << 6)
+ #define LTC3676_MSKPG_LDO4 (1 << 7)
+
-#define mV_to_regval(mV) DIV_ROUND(((((mV) < 4125) ? 4125 : (mV)) - 4125), 125)
-#define regval_to_mV(v) (((v) * 125 + 4125))
++#define VDD_IO_VAL mV_to_regval(vout_to_vref(3300, 5))
++#define VDD_IO_VAL_LP mV_to_regval(vout_to_vref(3100, 5))
++#define VDD_IO_VAL_2 mV_to_regval(vout_to_vref(3300, 5_2))
++#define VDD_IO_VAL_2_LP mV_to_regval(vout_to_vref(3100, 5_2))
++#define VDD_SOC_VAL mV_to_regval(vout_to_vref(1425, 6))
++#define VDD_SOC_VAL_LP mV_to_regval(vout_to_vref(900, 6))
++#define VDD_DDR_VAL mV_to_regval(vout_to_vref(1500, 7))
++#define VDD_DDR_VAL_LP mV_to_regval(vout_to_vref(1500, 7))
++#define VDD_CORE_VAL mV_to_regval(vout_to_vref(1425, 8))
++#define VDD_CORE_VAL_LP mV_to_regval(vout_to_vref(900, 8))
+
+ /* LDO1 */
+ #define R1_1 470
+ #define R2_1 150
+ /* LDO4 */
+ #define R1_4 470
+ #define R2_4 150
+ /* Buck1 */
+ #define R1_5 390
+ #define R2_5 110
+ #define R1_5_2 470
+ #define R2_5_2 150
+ /* Buck2 (SOC) */
+ #define R1_6 150
+ #define R2_6 180
+ /* Buck3 (DDR) */
+ #define R1_7 150
+ #define R2_7 140
+ /* Buck4 (CORE) */
+ #define R1_8 150
+ #define R2_8 180
+
+ /* calculate voltages in 10mV */
+ #define R1(idx) R1_##idx
+ #define R2(idx) R2_##idx
+
++#define v2r(v,n,m) DIV_ROUND_UP(((((v) < (n)) ? (n) : (v)) - (n)), (m))
++#define r2v(r,n,m) (((r) * (m) + (n)) / 10)
++
+ #define vout_to_vref(vout, idx) ((vout) * R2(idx) / (R1(idx) + R2(idx)))
+ #define vref_to_vout(vref, idx) DIV_ROUND_UP((vref) * (R1(idx) + R2(idx)), R2(idx))
+
-static int ltc3676_setup_regs(struct ltc3676_regs *r, size_t count)
++#define mV_to_regval(mV) v2r((mV) * 10, 4125, 125)
++#define regval_to_mV(r) r2v(r, 4125, 125)
+
+ static struct ltc3676_regs {
+ u8 addr;
+ u8 val;
+ u8 mask;
+ } ltc3676_regs[] = {
+ { LTC3676_MSKPG, ~LTC3676_MSKPG_BUCK1, },
+ { LTC3676_DVB2B, VDD_SOC_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB3B, VDD_DDR_VAL_LP, ~0x3f, },
+ { LTC3676_DVB4B, VDD_CORE_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB2A, VDD_SOC_VAL, ~0x3f, },
+ { LTC3676_DVB3A, VDD_DDR_VAL, ~0x3f, },
+ { LTC3676_DVB4A, VDD_CORE_VAL, ~0x3f, },
+ { LTC3676_BUCK1, LTC3676_BUCK_BURST_MODE | LTC3676_BUCK_CLK_RATE_LOW, },
+ { LTC3676_BUCK2, LTC3676_BUCK_BURST_MODE, },
+ { LTC3676_BUCK3, LTC3676_BUCK_BURST_MODE, },
+ { LTC3676_BUCK4, LTC3676_BUCK_BURST_MODE, },
+ { LTC3676_CLIRQ, 0, }, /* clear interrupt status */
+ };
+
+ static struct ltc3676_regs ltc3676_regs_1[] = {
+ { LTC3676_DVB1B, VDD_IO_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB1A, VDD_IO_VAL, ~0x3f, },
+ };
+
+ static struct ltc3676_regs ltc3676_regs_2[] = {
+ { LTC3676_DVB1B, VDD_IO_VAL_2_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB1A, VDD_IO_VAL_2, ~0x3f, },
+ };
+
+ static int tx6_rev_2(void)
+ {
+ struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+ struct fuse_bank5_regs *fuse = (void *)ocotp->bank[5].fuse_regs;
+ u32 pad_settings = readl(&fuse->pad_settings);
+
+ debug("Fuse pad_settings @ %p = %02x\n",
+ &fuse->pad_settings, pad_settings);
+ return pad_settings & 1;
+ }
+
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
++static int ltc3676_setup_regs(uchar slave_addr, struct ltc3676_regs *r,
++ size_t count)
+ {
+ int ret;
+ int i;
+
+ for (i = 0; i < count; i++, r++) {
+ #ifdef DEBUG
+ unsigned char value;
+
- ret = i2c_write(CONFIG_SYS_I2C_SLAVE,
- r->addr, 1, &r->val, 1);
++ ret = i2c_read(slave_addr, r->addr, 1, &value, 1);
+ if ((value & ~r->mask) != r->val) {
+ printf("Changing PMIC reg %02x from %02x to %02x\n",
+ r->addr, value, r->val);
+ }
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, r->addr, ret);
+ return ret;
+ }
+ #endif
-int setup_pmic_voltages(void)
++ ret = i2c_write(slave_addr, r->addr, 1, &r->val, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, r->addr, ret);
+ return ret;
+ }
+ }
+ return 0;
+ }
+
- ret = i2c_probe(CONFIG_SYS_I2C_SLAVE);
- if (ret != 0) {
- printf("Failed to initialize I2C\n");
- return ret;
- }
-
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, 0x11, 1, &value, 1);
++int ltc3676_pmic_setup(uchar slave_addr)
+ {
+ int ret;
+ unsigned char value;
+
- ret = ltc3676_setup_regs(ltc3676_regs, ARRAY_SIZE(ltc3676_regs));
++ ret = i2c_read(slave_addr, 0x11, 1, &value, 1);
+ if (ret) {
+ printf("%s: i2c_read error: %d\n", __func__, ret);
+ return ret;
+ }
+
- printf("VDDCORE set to %umV\n",
- DIV_ROUND(vref_to_vout(regval_to_mV(VDD_CORE_VAL), 8), 10));
- printf("VDDSOC set to %umV\n",
- DIV_ROUND(vref_to_vout(regval_to_mV(VDD_SOC_VAL), 6), 10));
++ ret = ltc3676_setup_regs(slave_addr, ltc3676_regs,
++ ARRAY_SIZE(ltc3676_regs));
+ if (ret)
+ return ret;
+
- ret = ltc3676_setup_regs(ltc3676_regs_2,
++ ret = i2c_read(slave_addr, LTC3676_DVB4A, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDCORE set to %umV\n",
++ vref_to_vout(regval_to_mV(value), 8));
++ } else {
++ printf("Failed to read VDDCORE register setting\n");
++ }
++
++ ret = i2c_read(slave_addr, LTC3676_DVB2A, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDSOC set to %umV\n",
++ vref_to_vout(regval_to_mV(value), 6));
++ } else {
++ printf("Failed to read VDDSOC register setting\n");
++ }
+
+ if (tx6_rev_2()) {
- printf("VDDIO set to %umV\n",
- DIV_ROUND(vref_to_vout(
- regval_to_mV(VDD_IO_VAL_2), 5_2), 10));
++ ret = ltc3676_setup_regs(slave_addr, ltc3676_regs_2,
+ ARRAY_SIZE(ltc3676_regs_2));
- ret = ltc3676_setup_regs(ltc3676_regs_1,
++
++ ret = i2c_read(slave_addr, LTC3676_DVB1A, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDIO set to %umV\n",
++ vref_to_vout(regval_to_mV(value), 5_2));
++ } else {
++ printf("Failed to read VDDIO register setting\n");
++ }
+ } else {
++ ret = ltc3676_setup_regs(slave_addr, ltc3676_regs_1,
+ ARRAY_SIZE(ltc3676_regs_1));
+ }
+ return ret;
+ }
--- /dev/null
--- /dev/null
++/*
++ * Copyright (C) 2015 Lothar Waßmann <LW@KARO-electronics.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * 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 <errno.h>
++#include <i2c.h>
++
++#include "pmic.h"
++
++static struct {
++ uchar addr;
++ int (*init)(uchar addr);
++} i2c_addrs[] = {
++#ifdef CONFIG_LTC3676
++ { 0x3c, ltc3676_pmic_setup, },
++#endif
++#ifdef CONFIG_RN5T618
++ { 0x32, rn5t618_pmic_setup, },
++#endif
++#ifdef CONFIG_RN5T567
++ { 0x33, rn5t567_pmic_setup, },
++#endif
++};
++
++int tx6_pmic_init(void)
++{
++ int ret = -ENODEV;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(i2c_addrs); i++) {
++ ret = i2c_probe(i2c_addrs[i].addr);
++ if (ret == 0) {
++ i2c_addrs[i].init(i2c_addrs[i].addr);
++ break;
++ }
++ }
++ return ret;
++}
--- /dev/null
-int setup_pmic_voltages(void);
+ /*
+ * Copyright (C) 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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.
+ *
+ */
+
++int ltc3676_pmic_setup(uchar addr);
++int rn5t618_pmic_setup(uchar addr);
++int rn5t567_pmic_setup(uchar addr);
++
++int tx6_pmic_init(void);
--- /dev/null
-#define VDD_RTC_VAL mV_to_regval_rtc(3000 * 10)
-#define VDD_HIGH_VAL mV_to_regval3(3000 * 10)
-#define VDD_HIGH_VAL_LP mV_to_regval3(3000 * 10)
-#define VDD_CORE_VAL mV_to_regval(1425 * 10)
-#define VDD_CORE_VAL_LP mV_to_regval(900 * 10)
-#define VDD_SOC_VAL mV_to_regval(1425 * 10)
-#define VDD_SOC_VAL_LP mV_to_regval(900 * 10)
-#define VDD_DDR_VAL mV_to_regval(1500 * 10)
-#define VDD_DDR_VAL_LP mV_to_regval(1500 * 10)
+ /*
+ * Copyright (C) 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <i2c.h>
+
+ #include "pmic.h"
+
+ #define RN5T567_NOETIMSET 0x11
+ #define RN5T567_LDORTC1_SLOT 0x2a
+ #define RN5T567_DC1CTL 0x2c
+ #define RN5T567_DC1CTL2 0x2d
+ #define RN5T567_DC2CTL 0x2e
+ #define RN5T567_DC2CTL2 0x2f
+ #define RN5T567_DC3CTL 0x30
+ #define RN5T567_DC3CTL2 0x31
+ #define RN5T567_DC1DAC 0x36 /* CORE */
+ #define RN5T567_DC2DAC 0x37 /* SOC */
+ #define RN5T567_DC3DAC 0x38 /* DDR */
+ #define RN5T567_DC1DAC_SLP 0x3b
+ #define RN5T567_DC2DAC_SLP 0x3c
+ #define RN5T567_DC3DAC_SLP 0x3d
+ #define RN5T567_LDOEN1 0x44
+ #define RN5T567_LDODIS 0x46
+ #define RN5T567_LDOEN2 0x48
+ #define RN5T567_LDO3DAC 0x4e /* IO */
+ #define RN5T567_LDORTC1DAC 0x56 /* VBACKUP */
+
+ #define NOETIMSET_DIS_OFF_NOE_TIM (1 << 3)
+
-#define mV_to_regval(mV) DIV_ROUND(((((mV) < 6000) ? 6000 : (mV)) - 6000), 125)
-#define regval_to_mV(v) (((v) * 125 + 6000))
++#define VDD_RTC_VAL mV_to_regval_rtc(3000)
++#define VDD_HIGH_VAL mV_to_regval3(3000)
++#define VDD_HIGH_VAL_LP mV_to_regval3(3000)
++#define VDD_CORE_VAL mV_to_regval(1350) /* DCDC1 */
++#define VDD_CORE_VAL_LP mV_to_regval(900)
++#define VDD_SOC_VAL mV_to_regval(1350) /* DCDC2 */
++#define VDD_SOC_VAL_LP mV_to_regval(900)
++#define VDD_DDR_VAL mV_to_regval(1350) /* DCDC3 */
++#define VDD_DDR_VAL_LP mV_to_regval(1350)
+
+ /* calculate voltages in 10mV */
++#define v2r(v,n,m) DIV_ROUND_UP(((((v) < (n)) ? (n) : (v)) - (n)), (m))
++#define r2v(r,n,m) (((r) * (m) + (n)) / 10)
++
+ /* DCDC1-3 */
-#define mV_to_regval2(mV) DIV_ROUND(((((mV) < 9000) ? 9000 : (mV)) - 9000), 250)
-#define regval2_to_mV(v) (((v) * 250 + 9000))
++#define mV_to_regval(mV) v2r((mV) * 10, 6000, 125)
++#define regval_to_mV(r) r2v(r, 6000, 125)
+
+ /* LDO1-2 */
-#define mV_to_regval3(mV) DIV_ROUND(((((mV) < 6000) ? 6000 : (mV)) - 6000), 250)
-#define regval3_to_mV(v) (((v) * 250 + 6000))
++#define mV_to_regval2(mV) v2r((mV) * 10, 9000, 250)
++#define regval2_to_mV(r) r2v(r, 9000, 250)
+
+ /* LDO3 */
-#define mV_to_regval_rtc(mV) DIV_ROUND(((((mV) < 17000) ? 17000 : (mV)) - 17000), 250)
-#define regval_rtc_to_mV(v) (((v) * 250 + 17000))
++#define mV_to_regval3(mV) v2r((mV) * 10, 6000, 250)
++#define regval3_to_mV(r) r2v(r, 6000, 250)
+
+ /* LDORTC */
-#if 0
++#define mV_to_regval_rtc(mV) v2r((mV) * 10, 17000, 250)
++#define regval_rtc_to_mV(r) r2v(r, 17000, 250)
+
+ static struct rn5t567_regs {
+ u8 addr;
+ u8 val;
+ u8 mask;
+ } rn5t567_regs[] = {
+ { RN5T567_NOETIMSET, NOETIMSET_DIS_OFF_NOE_TIM | 0x5, },
- { RN5T567_LDORTCDAC, VDD_RTC_VAL, },
+ { RN5T567_DC1DAC, VDD_CORE_VAL, },
+ { RN5T567_DC2DAC, VDD_SOC_VAL, },
+ { RN5T567_DC3DAC, VDD_DDR_VAL, },
+ { RN5T567_DC1DAC_SLP, VDD_CORE_VAL_LP, },
+ { RN5T567_DC2DAC_SLP, VDD_SOC_VAL_LP, },
+ { RN5T567_DC3DAC_SLP, VDD_DDR_VAL_LP, },
+ { RN5T567_LDOEN1, 0x01f, ~0x1f, },
+ { RN5T567_LDOEN2, 0x10, ~0x30, },
+ { RN5T567_LDODIS, 0x00, },
+ { RN5T567_LDO3DAC, VDD_HIGH_VAL, },
-#endif
++ { RN5T567_LDORTC1DAC, VDD_RTC_VAL, },
+ { RN5T567_LDORTC1_SLOT, 0x0f, ~0x3f, },
-static struct rn5t567_regs debug_regs[] __maybe_unused = {
- { 0x00, 4, },
- { 0x09, 4, },
- { 0x10, 16, },
- { 0x25, 26, },
- { 0x44, 3, },
- { 0x4c, 5, },
- { 0x56, 1, },
- { 0x58, 5, },
- { 0x97, 2, },
- { 0xb0, 1, },
- { 0xbc, 1, },
-};
-
-static int rn5t567_setup_regs(struct rn5t567_regs *r, size_t count)
+ };
+
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
++static int rn5t567_setup_regs(uchar slave_addr, struct rn5t567_regs *r,
++ size_t count)
+ {
+ int ret;
+ int i;
+
+ for (i = 0; i < count; i++, r++) {
+ #ifdef DEBUG
+ unsigned char value;
+
-// value = (value & ~r->mask) | r->val;
- ret = i2c_write(CONFIG_SYS_I2C_SLAVE,
- r->addr, 1, &r->val, 1);
++ ret = i2c_read(slave_addr, r->addr, 1, &value, 1);
+ if ((value & ~r->mask) != r->val) {
+ printf("Changing PMIC reg %02x from %02x to %02x\n",
+ r->addr, value, r->val);
+ }
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, r->addr, ret);
+ return ret;
+ }
+ #endif
-#ifdef DEBUG
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
- printf("PMIC reg %02x is %02x\n", r->addr, value);
-#endif
++ ret = i2c_write(slave_addr, r->addr, 1, &r->val, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, r->addr, ret);
+ return ret;
+ }
-#if 0
- for (i = 0; i < ARRAY_SIZE(debug_regs); i++) {
- int j;
-
- r = &debug_regs[i];
- for (j = r->addr; j < r->addr + r->val; j++) {
- unsigned char value;
-
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, j, 1, &value, 1);
- printf("PMIC reg %02x = %02x\n",
- j, value);
- }
- }
-#endif
- debug("%s() complete\n", __func__);
+ }
-int setup_pmic_voltages(void)
+ return 0;
+ }
+
- ret = i2c_probe(CONFIG_SYS_I2C_SLAVE);
- if (ret != 0) {
- printf("Failed to initialize I2C\n");
- return ret;
- }
-
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, 0x11, 1, &value, 1);
++int rn5t567_pmic_setup(uchar slave_addr)
+ {
+ int ret;
+ unsigned char value;
+
- ret = rn5t567_setup_regs(rn5t567_regs, ARRAY_SIZE(rn5t567_regs));
++ ret = i2c_read(slave_addr, 0x11, 1, &value, 1);
+ if (ret) {
+ printf("%s: i2c_read error: %d\n", __func__, ret);
+ return ret;
+ }
+
- printf("VDDCORE set to %umV\n",
- DIV_ROUND(regval_to_mV(VDD_CORE_VAL), 10));
- printf("VDDSOC set to %umV\n",
- DIV_ROUND(regval_to_mV(VDD_SOC_VAL), 10));
++ ret = rn5t567_setup_regs(slave_addr, rn5t567_regs,
++ ARRAY_SIZE(rn5t567_regs));
+ if (ret)
+ return ret;
+
++ ret = i2c_read(slave_addr, RN5T567_DC1DAC, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDCORE set to %umV\n", regval_to_mV(value));
++ } else {
++ printf("Failed to read VDDCORE register setting\n");
++ }
++
++ ret = i2c_read(slave_addr, RN5T567_DC2DAC, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDSOC set to %umV\n", regval_to_mV(value));
++ } else {
++ printf("Failed to read VDDSOC register setting\n");
++ }
+
+ return ret;
+ }
--- /dev/null
-#define VDD_RTC_VAL mV_to_regval_rtc(3000 * 10)
-#define VDD_HIGH_VAL mV_to_regval3(3000 * 10)
-#define VDD_HIGH_VAL_LP mV_to_regval3(3000 * 10)
-#define VDD_CORE_VAL mV_to_regval(1425 * 10)
-#define VDD_CORE_VAL_LP mV_to_regval(900 * 10)
-#define VDD_SOC_VAL mV_to_regval(1425 * 10)
-#define VDD_SOC_VAL_LP mV_to_regval(900 * 10)
-#define VDD_DDR_VAL mV_to_regval(1500 * 10)
-#define VDD_DDR_VAL_LP mV_to_regval(1500 * 10)
+ /*
+ * Copyright (C) 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <i2c.h>
+
+ #include "pmic.h"
+
+ #define RN5T618_NOETIMSET 0x11
+ #define RN5T618_LDORTC1_SLOT 0x2a
+ #define RN5T618_DC1CTL 0x2c
+ #define RN5T618_DC1CTL2 0x2d
+ #define RN5T618_DC2CTL 0x2e
+ #define RN5T618_DC2CTL2 0x2f
+ #define RN5T618_DC3CTL 0x30
+ #define RN5T618_DC3CTL2 0x31
+ #define RN5T618_DC1DAC 0x36 /* CORE */
+ #define RN5T618_DC2DAC 0x37 /* SOC */
+ #define RN5T618_DC3DAC 0x38 /* DDR */
+ #define RN5T618_DC1DAC_SLP 0x3b
+ #define RN5T618_DC2DAC_SLP 0x3c
+ #define RN5T618_DC3DAC_SLP 0x3d
+ #define RN5T618_LDOEN1 0x44
+ #define RN5T618_LDODIS 0x46
+ #define RN5T618_LDOEN2 0x48
+ #define RN5T618_LDO3DAC 0x4e /* IO */
+ #define RN5T618_LDORTCDAC 0x56 /* VBACKUP */
+
-#define mV_to_regval(mV) DIV_ROUND(((((mV) < 6000) ? 6000 : (mV)) - 6000), 125)
-#define regval_to_mV(v) (((v) * 125 + 6000))
++#define VDD_RTC_VAL mV_to_regval_rtc(3000)
++#define VDD_HIGH_VAL mV_to_regval3(3000)
++#define VDD_HIGH_VAL_LP mV_to_regval3(3000)
++#define VDD_CORE_VAL mV_to_regval(1425) /* DCDC1 */
++#define VDD_CORE_VAL_LP mV_to_regval(900)
++#define VDD_SOC_VAL mV_to_regval(1425) /* DCDC2 */
++#define VDD_SOC_VAL_LP mV_to_regval(900)
++#define VDD_DDR_VAL mV_to_regval(1500) /* DCDC3 */
++#define VDD_DDR_VAL_LP mV_to_regval(1500)
+
+ /* calculate voltages in 10mV */
++#define v2r(v,n,m) DIV_ROUND_UP(((((v) < (n)) ? (n) : (v)) - (n)), (m))
++#define r2v(r,n,m) (((r) * (m) + (n)) / 10)
++
+ /* DCDC1-3 */
-#define mV_to_regval2(mV) DIV_ROUND(((((mV) < 9000) ? 9000 : (mV)) - 9000), 250)
-#define regval2_to_mV(v) (((v) * 250 + 9000))
++#define mV_to_regval(mV) v2r((mV) * 10, 6000, 125)
++#define regval_to_mV(r) r2v(r, 6000, 125)
+
+ /* LDO1-2 */
-#define mV_to_regval3(mV) DIV_ROUND(((((mV) < 6000) ? 6000 : (mV)) - 6000), 250)
-#define regval3_to_mV(v) (((v) * 250 + 6000))
++#define mV_to_regval2(mV) v2r((mV) * 10, 9000, 250)
++#define regval2_to_mV(r) r2v(r, 9000, 250)
+
+ /* LDO3 */
-#define mV_to_regval_rtc(mV) DIV_ROUND(((((mV) < 17000) ? 17000 : (mV)) - 17000), 250)
-#define regval_rtc_to_mV(v) (((v) * 250 + 17000))
++#define mV_to_regval3(mV) v2r((mV) * 10, 6000, 250)
++#define regval3_to_mV(r) r2v(r, 6000, 250)
+
+ /* LDORTC */
-#if CONFIG_TX6_REV == 2
- { RN5T618_NOETIMSET, 0, },
- { RN5T618_DC1DAC, VDD_CORE_VAL, },
- { RN5T618_DC2DAC, VDD_SOC_VAL, },
- { RN5T618_DC3DAC, VDD_DDR_VAL, },
- { RN5T618_DC1DAC_SLP, VDD_CORE_VAL_LP, },
- { RN5T618_DC2DAC_SLP, VDD_SOC_VAL_LP, },
- { RN5T618_DC3DAC_SLP, VDD_DDR_VAL_LP, },
- { RN5T618_LDOEN1, 0x01f, ~0x1f, },
- { RN5T618_LDOEN2, 0x10, ~0x30, },
- { RN5T618_LDODIS, 0x00, },
- { RN5T618_LDO3DAC, VDD_HIGH_VAL, },
- { RN5T618_LDORTCDAC, VDD_RTC_VAL, },
- { RN5T618_LDORTC1_SLOT, 0x0f, ~0x3f, },
-#elif CONFIG_TX6_REV == 3
++#define mV_to_regval_rtc(mV) v2r((mV) * 10, 17000, 250)
++#define regval_rtc_to_mV(r) r2v(r, 17000, 250)
+
+ static struct rn5t618_regs {
+ u8 addr;
+ u8 val;
+ u8 mask;
+ } rn5t618_regs[] = {
-#else
-#error Unsupported TX6 module revision
-#endif
+ { RN5T618_NOETIMSET, 0, },
+ { RN5T618_DC1DAC, VDD_CORE_VAL, },
+ { RN5T618_DC2DAC, VDD_SOC_VAL, },
+ { RN5T618_DC3DAC, VDD_DDR_VAL, },
+ { RN5T618_DC1DAC_SLP, VDD_CORE_VAL_LP, },
+ { RN5T618_DC2DAC_SLP, VDD_SOC_VAL_LP, },
+ { RN5T618_DC3DAC_SLP, VDD_DDR_VAL_LP, },
+ { RN5T618_LDOEN1, 0x01f, ~0x1f, },
+ { RN5T618_LDOEN2, 0x10, ~0x30, },
+ { RN5T618_LDODIS, 0x00, },
+ { RN5T618_LDO3DAC, VDD_HIGH_VAL, },
+ { RN5T618_LDORTCDAC, VDD_RTC_VAL, },
+ { RN5T618_LDORTC1_SLOT, 0x0f, ~0x3f, },
-static int rn5t618_setup_regs(struct rn5t618_regs *r, size_t count)
+ };
+
- for (i = 0; i < count; i++, r++) {
- unsigned char value;
-
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
- printf("PMIC reg %02x = %02x\n",
- r->addr, value);
- }
++static int rn5t618_setup_regs(uchar slave_addr, struct rn5t618_regs *r,
++ size_t count)
+ {
+ int ret;
+ int i;
+
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
+ for (i = 0; i < count; i++, r++) {
+ #ifdef DEBUG
+ unsigned char value;
+
- ret = i2c_write(CONFIG_SYS_I2C_SLAVE,
- r->addr, 1, &r->val, 1);
++ ret = i2c_read(slave_addr, r->addr, 1, &value, 1);
+ if ((value & ~r->mask) != r->val) {
+ printf("Changing PMIC reg %02x from %02x to %02x\n",
+ r->addr, value, r->val);
+ }
+ if (ret) {
+ printf("%s: failed to read PMIC register %02x: %d\n",
+ __func__, r->addr, ret);
+ return ret;
+ }
+ #endif
-#ifdef DEBUG
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, r->addr, 1, &value, 1);
- printf("PMIC reg %02x is %02x\n", r->addr, value);
-#endif
++ ret = i2c_write(slave_addr, r->addr, 1, &r->val, 1);
+ if (ret) {
+ printf("%s: failed to write PMIC register %02x: %d\n",
+ __func__, r->addr, ret);
+ return ret;
+ }
-int setup_pmic_voltages(void)
+ }
+ return 0;
+ }
+
- ret = i2c_probe(CONFIG_SYS_I2C_SLAVE);
- if (ret != 0) {
- printf("Failed to initialize I2C\n");
- return ret;
- }
-
- ret = i2c_read(CONFIG_SYS_I2C_SLAVE, 0x11, 1, &value, 1);
++int rn5t618_pmic_setup(uchar slave_addr)
+ {
+ int ret;
+ unsigned char value;
+
- ret = rn5t618_setup_regs(rn5t618_regs, ARRAY_SIZE(rn5t618_regs));
++ ret = i2c_read(slave_addr, 0x11, 1, &value, 1);
+ if (ret) {
+ printf("%s: i2c_read error: %d\n", __func__, ret);
+ return ret;
+ }
+
- printf("VDDCORE set to %umV\n",
- DIV_ROUND(regval_to_mV(VDD_CORE_VAL), 10));
- printf("VDDSOC set to %umV\n",
- DIV_ROUND(regval_to_mV(VDD_SOC_VAL), 10));
++ ret = rn5t618_setup_regs(slave_addr, rn5t618_regs,
++ ARRAY_SIZE(rn5t618_regs));
+ if (ret)
+ return ret;
+
++ ret = i2c_read(slave_addr, RN5T618_DC1DAC, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDCORE set to %umV\n", regval_to_mV(value));
++ } else {
++ printf("Failed to read VDDCORE register setting\n");
++ }
++
++ ret = i2c_read(slave_addr, RN5T618_DC2DAC, 1, &value, 1);
++ if (ret == 0) {
++ printf("VDDSOC set to %umV\n", regval_to_mV(value));
++ } else {
++ printf("Failed to read VDDSOC register setting\n");
++ }
+
+ return ret;
+ }
--- /dev/null
- * Copyright (C) 2012,2013 Lothar Waßmann <LW@KARO-electronics.de>
+ /*
-
++ * Copyright (C) 2012-2015 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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.
+ *
+ */
-static const iomux_v3_cfg_t tx6qdl_pads[] = {
-#ifndef CONFIG_NO_NAND
+ #include <common.h>
+ #include <errno.h>
+ #include <libfdt.h>
+ #include <fdt_support.h>
+ #include <lcd.h>
+ #include <netdev.h>
+ #include <mmc.h>
+ #include <fsl_esdhc.h>
+ #include <video_fb.h>
+ #include <ipu.h>
+ #include <mxcfb.h>
+ #include <i2c.h>
+ #include <linux/fb.h>
+ #include <asm/io.h>
+ #include <asm/gpio.h>
+ #include <asm/arch/mx6-pins.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/crm_regs.h>
+ #include <asm/arch/sys_proto.h>
+
+ #include "../common/karo.h"
+ #include "pmic.h"
+
++#define __data __attribute__((section(".data")))
++
+ #define TX6_FEC_RST_GPIO IMX_GPIO_NR(7, 6)
+ #define TX6_FEC_PWR_GPIO IMX_GPIO_NR(3, 20)
+ #define TX6_FEC_INT_GPIO IMX_GPIO_NR(7, 1)
+ #define TX6_LED_GPIO IMX_GPIO_NR(2, 20)
+
+ #define TX6_LCD_PWR_GPIO IMX_GPIO_NR(2, 31)
+ #define TX6_LCD_RST_GPIO IMX_GPIO_NR(3, 29)
+ #define TX6_LCD_BACKLIGHT_GPIO IMX_GPIO_NR(1, 1)
+
+ #define TX6_RESET_OUT_GPIO IMX_GPIO_NR(7, 12)
+
+ #ifdef CONFIG_MX6_TEMPERATURE_MIN
+ #define TEMPERATURE_MIN CONFIG_MX6_TEMPERATURE_MIN
+ #else
+ #define TEMPERATURE_MIN (-40)
+ #endif
+ #ifdef CONFIG_MX6_TEMPERATURE_HOT
+ #define TEMPERATURE_HOT CONFIG_MX6_TEMPERATURE_HOT
+ #else
+ #define TEMPERATURE_HOT 80
+ #endif
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define MUX_CFG_SION IOMUX_PAD(0, 0, IOMUX_CONFIG_SION, 0, 0, 0)
+
- MX6_PAD_NANDF_CLE__RAWNAND_CLE,
- MX6_PAD_NANDF_ALE__RAWNAND_ALE,
- MX6_PAD_NANDF_WP_B__RAWNAND_RESETN,
- MX6_PAD_NANDF_RB0__RAWNAND_READY0,
- MX6_PAD_NANDF_CS0__RAWNAND_CE0N,
- MX6_PAD_SD4_CMD__RAWNAND_RDN,
- MX6_PAD_SD4_CLK__RAWNAND_WRN,
- MX6_PAD_NANDF_D0__RAWNAND_D0,
- MX6_PAD_NANDF_D1__RAWNAND_D1,
- MX6_PAD_NANDF_D2__RAWNAND_D2,
- MX6_PAD_NANDF_D3__RAWNAND_D3,
- MX6_PAD_NANDF_D4__RAWNAND_D4,
- MX6_PAD_NANDF_D5__RAWNAND_D5,
- MX6_PAD_NANDF_D6__RAWNAND_D6,
- MX6_PAD_NANDF_D7__RAWNAND_D7,
++enum {
++ MX6_PAD_DECL(GARBAGE, 0, 0, 0, 0, 0, 0)
++};
++
++static const iomux_v3_cfg_t const tx6qdl_pads[] = {
++ MX6_PAD_GARBAGE,
++#ifdef CONFIG_TX6_NAND_
+ /* NAND flash pads */
- MX6_PAD_GPIO_17__GPIO_7_12,
++ MX6_PAD_NANDF_CLE__NAND_CLE,
++ MX6_PAD_NANDF_ALE__NAND_ALE,
++ MX6_PAD_NANDF_WP_B__NAND_RESETN,
++ MX6_PAD_NANDF_RB0__NAND_READY0,
++ MX6_PAD_NANDF_CS0__NAND_CE0N,
++ MX6_PAD_SD4_CMD__NAND_RDN,
++ MX6_PAD_SD4_CLK__NAND_WRN,
++ MX6_PAD_NANDF_D0__NAND_D0,
++ MX6_PAD_NANDF_D1__NAND_D1,
++ MX6_PAD_NANDF_D2__NAND_D2,
++ MX6_PAD_NANDF_D3__NAND_D3,
++ MX6_PAD_NANDF_D4__NAND_D4,
++ MX6_PAD_NANDF_D5__NAND_D5,
++ MX6_PAD_NANDF_D6__NAND_D6,
++ MX6_PAD_NANDF_D7__NAND_D7,
+ #endif
+ /* RESET_OUT */
- MX6_PAD_SD3_DAT7__UART1_TXD,
- MX6_PAD_SD3_DAT6__UART1_RXD,
- MX6_PAD_SD3_DAT1__UART1_RTS,
- MX6_PAD_SD3_DAT0__UART1_CTS,
++ MX6_PAD_GPIO_17__GPIO7_IO12,
+
+ /* UART pads */
+ #if CONFIG_MXC_UART_BASE == UART1_BASE
- MX6_PAD_SD4_DAT4__UART2_RXD,
- MX6_PAD_SD4_DAT7__UART2_TXD,
- MX6_PAD_SD4_DAT5__UART2_RTS,
- MX6_PAD_SD4_DAT6__UART2_CTS,
++ MX6_PAD_SD3_DAT7__UART1_TX_DATA,
++ MX6_PAD_SD3_DAT6__UART1_RX_DATA,
++ MX6_PAD_SD3_DAT1__UART1_RTS_B,
++ MX6_PAD_SD3_DAT0__UART1_CTS_B,
+ #endif
+ #if CONFIG_MXC_UART_BASE == UART2_BASE
- MX6_PAD_EIM_D24__UART3_TXD,
- MX6_PAD_EIM_D25__UART3_RXD,
- MX6_PAD_SD3_RST__UART3_RTS,
- MX6_PAD_SD3_DAT3__UART3_CTS,
++ MX6_PAD_SD4_DAT4__UART2_RX_DATA,
++ MX6_PAD_SD4_DAT7__UART2_TX_DATA,
++ MX6_PAD_SD4_DAT5__UART2_RTS_B,
++ MX6_PAD_SD4_DAT6__UART2_CTS_B,
+ #endif
+ #if CONFIG_MXC_UART_BASE == UART3_BASE
- MX6_PAD_EIM_D20__GPIO_3_20 | MUX_CFG_SION, /* PHY POWER */
- MX6_PAD_SD3_DAT2__GPIO_7_6 | MUX_CFG_SION, /* PHY RESET */
- MX6_PAD_SD3_DAT4__GPIO_7_1, /* PHY INT */
++ MX6_PAD_EIM_D24__UART3_TX_DATA,
++ MX6_PAD_EIM_D25__UART3_RX_DATA,
++ MX6_PAD_SD3_RST__UART3_RTS_B,
++ MX6_PAD_SD3_DAT3__UART3_CTS_B,
+ #endif
+ /* internal I2C */
+ MX6_PAD_EIM_D28__I2C1_SDA,
+ MX6_PAD_EIM_D21__I2C1_SCL,
+
+ /* FEC PHY GPIO functions */
-static const iomux_v3_cfg_t tx6qdl_fec_pads[] = {
++ MX6_PAD_EIM_D20__GPIO3_IO20 | MUX_CFG_SION, /* PHY POWER */
++ MX6_PAD_SD3_DAT2__GPIO7_IO06 | MUX_CFG_SION, /* PHY RESET */
++ MX6_PAD_SD3_DAT4__GPIO7_IO01, /* PHY INT */
+ };
+
- MX6_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT,
++static const iomux_v3_cfg_t const tx6qdl_fec_pads[] = {
+ /* FEC functions */
+ MX6_PAD_ENET_MDC__ENET_MDC,
+ MX6_PAD_ENET_MDIO__ENET_MDIO,
- MX6_PAD_ENET_RXD1__ENET_RDATA_1,
- MX6_PAD_ENET_RXD0__ENET_RDATA_0,
++ MX6_PAD_GPIO_16__ENET_REF_CLK,
+ MX6_PAD_ENET_RX_ER__ENET_RX_ER,
+ MX6_PAD_ENET_CRS_DV__ENET_RX_EN,
- MX6_PAD_ENET_TXD1__ENET_TDATA_1,
- MX6_PAD_ENET_TXD0__ENET_TDATA_0,
++ MX6_PAD_ENET_RXD1__ENET_RX_DATA1,
++ MX6_PAD_ENET_RXD0__ENET_RX_DATA0,
+ MX6_PAD_ENET_TX_EN__ENET_TX_EN,
-static const struct gpio tx6qdl_gpios[] = {
- { TX6_RESET_OUT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "#RESET_OUT", },
- { TX6_FEC_PWR_GPIO, GPIOF_OUTPUT_INIT_HIGH, "FEC PHY PWR", },
- { TX6_FEC_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "FEC PHY RESET", },
- { TX6_FEC_INT_GPIO, GPIOF_INPUT, "FEC PHY INT", },
++ MX6_PAD_ENET_TXD1__ENET_TX_DATA1,
++ MX6_PAD_ENET_TXD0__ENET_TX_DATA0,
+ };
+
-static const char *tx6_mod_suffix;
++static const struct gpio const tx6qdl_gpios[] = {
++ { TX6_RESET_OUT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "#RESET_OUT", },
++ { TX6_FEC_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "FEC PHY PWR", },
++ { TX6_FEC_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "FEC PHY RESET", },
++ { TX6_FEC_INT_GPIO, GPIOFLAG_INPUT, "FEC PHY INT", },
+ };
+
+ /*
+ * Functions
+ */
+ /* placed in section '.data' to prevent overwriting relocation info
+ * overlayed with bss
+ */
+ static u32 wrsr __attribute__((section(".data")));
+
+ #define WRSR_POR (1 << 4)
+ #define WRSR_TOUT (1 << 1)
+ #define WRSR_SFTW (1 << 0)
+
+ static void print_reset_cause(void)
+ {
+ struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+ void __iomem *wdt_base = (void __iomem *)WDOG1_BASE_ADDR;
+ u32 srsr;
+ char *dlm = "";
+
+ printf("Reset cause: ");
+
+ srsr = readl(&src_regs->srsr);
+ wrsr = readw(wdt_base + 4);
+
+ if (wrsr & WRSR_POR) {
+ printf("%sPOR", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00004) {
+ printf("%sCSU", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00008) {
+ printf("%sIPP USER", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00010) {
+ if (wrsr & WRSR_SFTW) {
+ printf("%sSOFT", dlm);
+ dlm = " | ";
+ }
+ if (wrsr & WRSR_TOUT) {
+ printf("%sWDOG", dlm);
+ dlm = " | ";
+ }
+ }
+ if (srsr & 0x00020) {
+ printf("%sJTAG HIGH-Z", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x00040) {
+ printf("%sJTAG SW", dlm);
+ dlm = " | ";
+ }
+ if (srsr & 0x10000) {
+ printf("%sWARM BOOT", dlm);
+ dlm = " | ";
+ }
+ if (dlm[0] == '\0')
+ printf("unknown");
+
+ printf("\n");
+ }
+
- ret = setup_pmic_voltages();
++static const char __data *tx6_mod_suffix;
+
+ static void tx6qdl_print_cpuinfo(void)
+ {
+ u32 cpurev = get_cpu_rev();
+ char *cpu_str = "?";
+
+ switch ((cpurev >> 12) & 0xff) {
+ case MXC_CPU_MX6SL:
+ cpu_str = "SL";
+ tx6_mod_suffix = "?";
+ break;
+ case MXC_CPU_MX6DL:
+ cpu_str = "DL";
+ tx6_mod_suffix = "U";
+ break;
+ case MXC_CPU_MX6SOLO:
+ cpu_str = "SOLO";
+ tx6_mod_suffix = "S";
+ break;
+ case MXC_CPU_MX6Q:
+ cpu_str = "Q";
+ tx6_mod_suffix = "Q";
+ break;
+ }
+
+ printf("CPU: Freescale i.MX6%s rev%d.%d at %d MHz\n",
+ cpu_str,
+ (cpurev & 0x000F0) >> 4,
+ (cpurev & 0x0000F) >> 0,
+ mxc_get_clock(MXC_ARM_CLK) / 1000000);
+
+ print_reset_cause();
+ #ifdef CONFIG_MX6_TEMPERATURE_HOT
+ check_cpu_temperature(1);
+ #endif
+ }
+
+ int board_early_init_f(void)
+ {
+ gpio_request_array(tx6qdl_gpios, ARRAY_SIZE(tx6qdl_gpios));
+ imx_iomux_v3_setup_multiple_pads(tx6qdl_pads, ARRAY_SIZE(tx6qdl_pads));
+
+ return 0;
+ }
+
+ #ifndef CONFIG_MX6_TEMPERATURE_HOT
+ static bool tx6_temp_check_enabled = true;
+ #else
+ #define tx6_temp_check_enabled 0
+ #endif
+
+ int board_init(void)
+ {
+ int ret;
+
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000;
+ gd->bd->bi_arch_number = -1;
+
+ if (ctrlc() || (wrsr & WRSR_TOUT)) {
+ if (wrsr & WRSR_TOUT)
+ printf("WDOG RESET detected; Skipping PMIC setup\n");
+ else
+ printf("<CTRL-C> detected; safeboot enabled\n");
+ #ifndef CONFIG_MX6_TEMPERATURE_HOT
+ tx6_temp_check_enabled = false;
+ #endif
+ return 1;
+ }
+
-#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
++ ret = tx6_pmic_init();
+ if (ret) {
+ printf("Failed to setup PMIC voltages\n");
+ hang();
+ }
+ return 0;
+ }
+
+ int dram_init(void)
+ {
+ /* dram_init must store complete ramsize in gd->ram_size */
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+ PHYS_SDRAM_1_SIZE);
+ return 0;
+ }
+
+ void dram_init_banksize(void)
+ {
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = get_ram_size((void *)PHYS_SDRAM_1,
+ PHYS_SDRAM_1_SIZE);
+ #if CONFIG_NR_DRAM_BANKS > 1
+ gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+ gd->bd->bi_dram[1].size = get_ram_size((void *)PHYS_SDRAM_2,
+ PHYS_SDRAM_2_SIZE);
+ #endif
+ }
+
+ #ifdef CONFIG_CMD_MMC
- MX6_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
++#define SD_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
+ PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
+ PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+
+ static const iomux_v3_cfg_t mmc0_pads[] = {
- MX6_PAD_SD3_CMD__GPIO_7_2,
++ MX6_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD1_DAT0__SD1_DATA0 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD1_DAT1__SD1_DATA1 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD1_DAT2__SD1_DATA2 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD1_DAT3__SD1_DATA3 | MUX_PAD_CTRL(SD_PAD_CTRL),
+ /* SD1 CD */
- MX6_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
++ MX6_PAD_SD3_CMD__GPIO7_IO02,
+ };
+
+ static const iomux_v3_cfg_t mmc1_pads[] = {
- MX6_PAD_SD3_CLK__GPIO_7_3,
++ MX6_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(SD_PAD_CTRL),
+ /* SD2 CD */
-#ifdef CONFIG_MMC_BOOT_SIZE
++ MX6_PAD_SD3_CLK__GPIO7_IO03,
+ };
+
- MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
++#ifdef CONFIG_TX6_EMMC
+ static const iomux_v3_cfg_t mmc3_pads[] = {
- MX6_PAD_NANDF_ALE__USDHC4_RST,
++ MX6_PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(SD_PAD_CTRL),
++ MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(SD_PAD_CTRL),
+ /* eMMC RESET */
-#ifdef CONFIG_MMC_BOOT_SIZE
++ MX6_PAD_NANDF_ALE__SD4_RESET,
+ };
+ #endif
+
+ static struct tx6_esdhc_cfg {
+ const iomux_v3_cfg_t *pads;
+ int num_pads;
+ enum mxc_clock clkid;
+ struct fsl_esdhc_cfg cfg;
+ int cd_gpio;
+ } tx6qdl_esdhc_cfg[] = {
- debug("SD card %d is %spresent\n",
++#ifdef CONFIG_TX6_EMMC
+ {
+ .pads = mmc3_pads,
+ .num_pads = ARRAY_SIZE(mmc3_pads),
+ .clkid = MXC_ESDHC4_CLK,
+ .cfg = {
+ .esdhc_base = (void __iomem *)USDHC4_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = -EINVAL,
+ },
+ #endif
+ {
+ .pads = mmc0_pads,
+ .num_pads = ARRAY_SIZE(mmc0_pads),
+ .clkid = MXC_ESDHC_CLK,
+ .cfg = {
+ .esdhc_base = (void __iomem *)USDHC1_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = IMX_GPIO_NR(7, 2),
+ },
+ {
+ .pads = mmc1_pads,
+ .num_pads = ARRAY_SIZE(mmc1_pads),
+ .clkid = MXC_ESDHC2_CLK,
+ .cfg = {
+ .esdhc_base = (void __iomem *)USDHC2_BASE_ADDR,
+ .max_bus_width = 4,
+ },
+ .cd_gpio = IMX_GPIO_NR(7, 3),
+ },
+ };
+
+ static inline struct tx6_esdhc_cfg *to_tx6_esdhc_cfg(struct fsl_esdhc_cfg *cfg)
+ {
+ return container_of(cfg, struct tx6_esdhc_cfg, cfg);
+ }
+
+ int board_mmc_getcd(struct mmc *mmc)
+ {
+ struct tx6_esdhc_cfg *cfg = to_tx6_esdhc_cfg(mmc->priv);
+
+ if (cfg->cd_gpio < 0)
+ return 1;
+
- gpio_get_value(cfg->cd_gpio) ? "NOT " : "");
++ debug("SD card %d is %spresent (GPIO %d)\n",
+ cfg - tx6qdl_esdhc_cfg,
- GPIOF_INPUT, "MMC CD");
++ gpio_get_value(cfg->cd_gpio) ? "NOT " : "",
++ cfg->cd_gpio);
+ return !gpio_get_value(cfg->cd_gpio);
+ }
+
+ int board_mmc_init(bd_t *bis)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tx6qdl_esdhc_cfg); i++) {
+ struct mmc *mmc;
+ struct tx6_esdhc_cfg *cfg = &tx6qdl_esdhc_cfg[i];
+ int ret;
+
+ cfg->cfg.sdhc_clk = mxc_get_clock(cfg->clkid);
+ imx_iomux_v3_setup_multiple_pads(cfg->pads, cfg->num_pads);
+
+ if (cfg->cd_gpio >= 0) {
+ ret = gpio_request_one(cfg->cd_gpio,
- imx_iomux_v3_setup_multiple_pads(tx6qdl_fec_pads, ARRAY_SIZE(tx6qdl_fec_pads));
++ GPIOFLAG_INPUT, "MMC CD");
+ if (ret) {
+ printf("Error %d requesting GPIO%d_%d\n",
+ ret, cfg->cd_gpio / 32, cfg->cd_gpio % 32);
+ continue;
+ }
+ }
+
+ debug("%s: Initializing MMC slot %d\n", __func__, i);
+ fsl_esdhc_initialize(bis, &cfg->cfg);
+
+ mmc = find_mmc_device(i);
+ if (mmc == NULL)
+ continue;
+ if (board_mmc_getcd(mmc))
+ mmc_init(mmc);
+ }
+ return 0;
+ }
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_FEC_MXC
+
+ #define FEC_PAD_CTL (PAD_CTL_DVS | PAD_CTL_DSE_HIGH | \
+ PAD_CTL_SRE_FAST)
+ #define FEC_PAD_CTL2 (PAD_CTL_DVS | PAD_CTL_SRE_FAST)
+ #define GPIO_PAD_CTL (PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
+
+ #ifndef ETH_ALEN
+ #define ETH_ALEN 6
+ #endif
+
+ int board_eth_init(bd_t *bis)
+ {
+ int ret;
+
+ /* delay at least 21ms for the PHY internal POR signal to deassert */
+ udelay(22000);
+
- MX6_PAD_EIM_A18__GPIO_2_20,
++ imx_iomux_v3_setup_multiple_pads(tx6qdl_fec_pads,
++ ARRAY_SIZE(tx6qdl_fec_pads));
+
+ /* Deassert RESET to the external phy */
+ gpio_set_value(TX6_FEC_RST_GPIO, 1);
+
+ ret = cpu_eth_init(bis);
+ if (ret)
+ printf("cpu_eth_init() failed: %d\n", ret);
+
+ return ret;
+ }
++
++static void tx6_init_mac(void)
++{
++ u8 mac[ETH_ALEN];
++
++ imx_get_mac_from_fuse(-1, mac);
++ if (!is_valid_ether_addr(mac)) {
++ printf("No valid MAC address programmed\n");
++ return;
++ }
++
++ printf("MAC addr from fuse: %pM\n", mac);
++ eth_setenv_enetaddr("ethaddr", mac);
++}
++#else
++static inline void tx6_init_mac(void)
++{
++}
+ #endif /* CONFIG_FEC_MXC */
+
+ enum {
+ LED_STATE_INIT = -1,
+ LED_STATE_OFF,
+ LED_STATE_ON,
+ };
+
+ static inline int calc_blink_rate(void)
+ {
+ if (!tx6_temp_check_enabled)
+ return CONFIG_SYS_HZ;
+
+ return CONFIG_SYS_HZ + CONFIG_SYS_HZ / 10 -
+ (check_cpu_temperature(0) - TEMPERATURE_MIN) * CONFIG_SYS_HZ /
+ (TEMPERATURE_HOT - TEMPERATURE_MIN);
+ }
+
+ void show_activity(int arg)
+ {
+ static int led_state = LED_STATE_INIT;
+ static int blink_rate;
+ static ulong last;
+
+ if (led_state == LED_STATE_INIT) {
+ last = get_timer(0);
+ gpio_set_value(TX6_LED_GPIO, 1);
+ led_state = LED_STATE_ON;
+ blink_rate = calc_blink_rate();
+ } else {
+ if (get_timer(last) > blink_rate) {
+ blink_rate = calc_blink_rate();
+ last = get_timer_masked();
+ if (led_state == LED_STATE_ON) {
+ gpio_set_value(TX6_LED_GPIO, 0);
+ } else {
+ gpio_set_value(TX6_LED_GPIO, 1);
+ }
+ led_state = 1 - led_state;
+ }
+ }
+ }
+
+ static const iomux_v3_cfg_t stk5_pads[] = {
+ /* SW controlled LED on STK5 baseboard */
- MX6_PAD_EIM_D26__GPIO_3_26,
++ MX6_PAD_EIM_A18__GPIO2_IO20,
+
+ /* I2C bus on DIMM pins 40/41 */
+ MX6_PAD_GPIO_6__I2C3_SDA,
+ MX6_PAD_GPIO_3__I2C3_SCL,
+
+ /* TSC200x PEN IRQ */
- MX6_PAD_NANDF_CS2__GPIO_6_15, /* IRQ */
- MX6_PAD_EIM_A16__GPIO_2_22, /* RESET */
- MX6_PAD_EIM_A17__GPIO_2_21, /* WAKE */
++ MX6_PAD_EIM_D26__GPIO3_IO26,
+
+ /* EDT-FT5x06 Polytouch panel */
- MX6_PAD_EIM_D31__GPIO_3_31, /* VBUSEN */
- MX6_PAD_EIM_D30__GPIO_3_30, /* OC */
++ MX6_PAD_NANDF_CS2__GPIO6_IO15, /* IRQ */
++ MX6_PAD_EIM_A16__GPIO2_IO22, /* RESET */
++ MX6_PAD_EIM_A17__GPIO2_IO21, /* WAKE */
+
+ /* USBH1 */
- MX6_PAD_EIM_D23__GPIO_3_23, /* USBOTG ID */
- MX6_PAD_GPIO_7__GPIO_1_7, /* VBUSEN */
- MX6_PAD_GPIO_8__GPIO_1_8, /* OC */
++ MX6_PAD_EIM_D31__GPIO3_IO31, /* VBUSEN */
++ MX6_PAD_EIM_D30__GPIO3_IO30, /* OC */
+ /* USBOTG */
- { TX6_LED_GPIO, GPIOF_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
++ MX6_PAD_EIM_D23__GPIO3_IO23, /* USBOTG ID */
++ MX6_PAD_GPIO_7__GPIO1_IO07, /* VBUSEN */
++ MX6_PAD_GPIO_8__GPIO1_IO08, /* OC */
+ };
+
+ static const struct gpio stk5_gpios[] = {
- { IMX_GPIO_NR(3, 23), GPIOF_INPUT, "USBOTG ID", },
- { IMX_GPIO_NR(1, 8), GPIOF_INPUT, "USBOTG OC", },
- { IMX_GPIO_NR(1, 7), GPIOF_OUTPUT_INIT_LOW, "USBOTG VBUS enable", },
- { IMX_GPIO_NR(3, 30), GPIOF_INPUT, "USBH1 OC", },
- { IMX_GPIO_NR(3, 31), GPIOF_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
++ { TX6_LED_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "HEARTBEAT LED", },
+
- .vl_bpix = LCD_COLOR24, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
++ { IMX_GPIO_NR(3, 23), GPIOFLAG_INPUT, "USBOTG ID", },
++ { IMX_GPIO_NR(1, 8), GPIOFLAG_INPUT, "USBOTG OC", },
++ { IMX_GPIO_NR(1, 7), GPIOFLAG_OUTPUT_INIT_LOW, "USBOTG VBUS enable", },
++ { IMX_GPIO_NR(3, 30), GPIOFLAG_INPUT, "USBH1 OC", },
++ { IMX_GPIO_NR(3, 31), GPIOFLAG_OUTPUT_INIT_LOW, "USBH1 VBUS enable", },
+ };
+
+ #ifdef CONFIG_LCD
+ static u16 tx6_cmap[256];
+ vidinfo_t panel_info = {
+ /* set to max. size supported by SoC */
+ .vl_col = 1920,
+ .vl_row = 1080,
+
- MX6_PAD_EIM_D29__GPIO_3_29,
++ .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */
+ .cmap = tx6_cmap,
+ };
+
+ static struct fb_videomode tx6_fb_modes[] = {
+ #ifndef CONFIG_SYS_LVDS_IF
+ {
+ /* Standard VGA timing */
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETV570 640 x 480 display. Syncs low active,
+ * DE high active, 115.2 mm x 86.4 mm display area
+ * VGA compatible timing
+ */
+ .name = "ETV570",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(25175),
+ .left_margin = 114,
+ .hsync_len = 30,
+ .right_margin = 16,
+ .upper_margin = 32,
+ .vsync_len = 3,
+ .lower_margin = 10,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0350G0DH6 320 x 240 display.
+ * 70.08 mm x 52.56 mm display area.
+ */
+ .name = "ET0350",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6500),
+ .left_margin = 68 - 34,
+ .hsync_len = 34,
+ .right_margin = 20,
+ .upper_margin = 18 - 3,
+ .vsync_len = 3,
+ .lower_margin = 4,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0430G0DH6 480 x 272 display.
+ * 95.04 mm x 53.856 mm display area.
+ */
+ .name = "ET0430",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 272,
+ .pixclock = KHZ2PICOS(9000),
+ .left_margin = 2,
+ .hsync_len = 41,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .vsync_len = 10,
+ .lower_margin = 2,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0500G0DH6 800 x 480 display.
+ * 109.6 mm x 66.4 mm display area.
+ */
+ .name = "ET0500",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ETQ570G0DH6 320 x 240 display.
+ * 115.2 mm x 86.4 mm display area.
+ */
+ .name = "ETQ570",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6400),
+ .left_margin = 38,
+ .hsync_len = 30,
+ .right_margin = 30,
+ .upper_margin = 16, /* 15 according to datasheet */
+ .vsync_len = 3, /* TVP -> 1>x>5 */
+ .lower_margin = 4, /* 4.5 according to datasheet */
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET0700G0DH6 800 x 480 display.
+ * 152.4 mm x 91.44 mm display area.
+ */
+ .name = "ET0700",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ {
+ /* Emerging ET070001DM6 800 x 480 display.
+ * 152.4 mm x 91.44 mm display area.
+ */
+ .name = "ET070001DM6",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+ .left_margin = 216 - 128,
+ .hsync_len = 128,
+ .right_margin = 1056 - 800 - 216,
+ .upper_margin = 35 - 2,
+ .vsync_len = 2,
+ .lower_margin = 525 - 480 - 35,
+ .sync = 0,
+ },
+ #else
+ {
+ /* HannStar HSD100PXN1
+ * 202.7m mm x 152.06 mm display area.
+ */
+ .name = "HSD100PXN1",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = KHZ2PICOS(65000),
+ .left_margin = 0,
+ .hsync_len = 0,
+ .right_margin = 320,
+ .upper_margin = 0,
+ .vsync_len = 0,
+ .lower_margin = 38,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ #endif
+ {
+ /* unnamed entry for assigning parameters parsed from 'video_mode' string */
+ .refresh = 60,
+ .left_margin = 48,
+ .hsync_len = 96,
+ .right_margin = 16,
+ .upper_margin = 31,
+ .vsync_len = 2,
+ .lower_margin = 12,
+ .sync = FB_SYNC_CLK_LAT_FALL,
+ },
+ };
+
+ static int lcd_enabled = 1;
+ static int lcd_bl_polarity;
+
+ static int lcd_backlight_polarity(void)
+ {
+ return lcd_bl_polarity;
+ }
+
+ void lcd_enable(void)
+ {
+ /* HACK ALERT:
+ * global variable from common/lcd.c
+ * Set to 0 here to prevent messages from going to LCD
+ * rather than serial console
+ */
+ lcd_is_enabled = 0;
+
+ karo_load_splashimage(1);
+
+ if (lcd_enabled) {
+ debug("Switching LCD on\n");
+ gpio_set_value(TX6_LCD_PWR_GPIO, 1);
+ udelay(100);
+ gpio_set_value(TX6_LCD_RST_GPIO, 1);
+ udelay(300000);
+ gpio_set_value(TX6_LCD_BACKLIGHT_GPIO,
+ lcd_backlight_polarity());
+ }
+ }
+
+ void lcd_disable(void)
+ {
+ if (lcd_enabled) {
+ printf("Disabling LCD\n");
+ ipuv3_fb_shutdown();
+ }
+ }
+
+ void lcd_panel_disable(void)
+ {
+ if (lcd_enabled) {
+ debug("Switching LCD off\n");
+ gpio_set_value(TX6_LCD_BACKLIGHT_GPIO,
+ !lcd_backlight_polarity());
+ gpio_set_value(TX6_LCD_RST_GPIO, 0);
+ gpio_set_value(TX6_LCD_PWR_GPIO, 0);
+ }
+ }
+
+ static const iomux_v3_cfg_t stk5_lcd_pads[] = {
+ /* LCD RESET */
- MX6_PAD_EIM_EB3__GPIO_2_31,
++ MX6_PAD_EIM_D29__GPIO3_IO29,
+ /* LCD POWER_ENABLE */
- MX6_PAD_GPIO_1__GPIO_1_1,
++ MX6_PAD_EIM_EB3__GPIO2_IO31,
+ /* LCD Backlight (PWM) */
- MX6_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0,
- MX6_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1,
- MX6_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2,
- MX6_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3,
- MX6_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4,
- MX6_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5,
- MX6_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6,
- MX6_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7,
- MX6_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8,
- MX6_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9,
- MX6_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10,
- MX6_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11,
- MX6_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12,
- MX6_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13,
- MX6_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14,
- MX6_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15,
- MX6_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16,
- MX6_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17,
- MX6_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18,
- MX6_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19,
- MX6_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20,
- MX6_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21,
- MX6_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22,
- MX6_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23,
- MX6_PAD_DI0_PIN2__IPU1_DI0_PIN2, /* HSYNC */
- MX6_PAD_DI0_PIN3__IPU1_DI0_PIN3, /* VSYNC */
++ MX6_PAD_GPIO_1__GPIO1_IO01,
+
+ #ifndef CONFIG_SYS_LVDS_IF
+ /* Display */
- { TX6_LCD_RST_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD RESET", },
- { TX6_LCD_PWR_GPIO, GPIOF_OUTPUT_INIT_LOW, "LCD POWER", },
- { TX6_LCD_BACKLIGHT_GPIO, GPIOF_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
++ MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00,
++ MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01,
++ MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02,
++ MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03,
++ MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04,
++ MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05,
++ MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06,
++ MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07,
++ MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08,
++ MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09,
++ MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10,
++ MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11,
++ MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12,
++ MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13,
++ MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14,
++ MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15,
++ MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16,
++ MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17,
++ MX6_PAD_DISP0_DAT18__IPU1_DISP0_DATA18,
++ MX6_PAD_DISP0_DAT19__IPU1_DISP0_DATA19,
++ MX6_PAD_DISP0_DAT20__IPU1_DISP0_DATA20,
++ MX6_PAD_DISP0_DAT21__IPU1_DISP0_DATA21,
++ MX6_PAD_DISP0_DAT22__IPU1_DISP0_DATA22,
++ MX6_PAD_DISP0_DAT23__IPU1_DISP0_DATA23,
++ MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02, /* HSYNC */
++ MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03, /* VSYNC */
+ MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15, /* OE_ACD */
+ MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, /* LSCLK */
+ #endif
+ };
+
+ static const struct gpio stk5_lcd_gpios[] = {
- panel_info.vl_bpix = LCD_COLOR24;
++ { TX6_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
++ { TX6_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
++ { TX6_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+ };
+
+ void lcd_ctrl_init(void *lcdbase)
+ {
+ int color_depth = 24;
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ const char *vm;
+ unsigned long val;
+ int refresh = 60;
+ struct fb_videomode *p = &tx6_fb_modes[0];
+ struct fb_videomode fb_mode;
+ int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
+ int pix_fmt;
+ int lcd_bus_width;
+ unsigned long di_clk_rate = 65000000;
+
+ if (!lcd_enabled) {
+ debug("LCD disabled\n");
+ return;
+ }
+
+ if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ setenv("splashimage", NULL);
+ return;
+ }
+
+ karo_fdt_move_fdt();
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
+
+ if (video_mode == NULL) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ return;
+ }
+ vm = video_mode;
+ if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
+ p = &fb_mode;
+ debug("Using video mode from FDT\n");
+ vm += strlen(vm);
+ if (fb_mode.xres > panel_info.vl_col ||
+ fb_mode.yres > panel_info.vl_row) {
+ printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+ fb_mode.xres, fb_mode.yres,
+ panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ }
+ if (p->name != NULL)
+ debug("Trying compiled-in video modes\n");
+ while (p->name != NULL) {
+ if (strcmp(p->name, vm) == 0) {
+ debug("Using video mode: '%s'\n", p->name);
+ vm += strlen(vm);
+ break;
+ }
+ p++;
+ }
+ if (*vm != '\0')
+ debug("Trying to decode video_mode: '%s'\n", vm);
+ while (*vm != '\0') {
+ if (*vm >= '0' && *vm <= '9') {
+ char *end;
+
+ val = simple_strtoul(vm, &end, 0);
+ if (end > vm) {
+ if (!xres_set) {
+ if (val > panel_info.vl_col)
+ val = panel_info.vl_col;
+ p->xres = val;
+ panel_info.vl_col = val;
+ xres_set = 1;
+ } else if (!yres_set) {
+ if (val > panel_info.vl_row)
+ val = panel_info.vl_row;
+ p->yres = val;
+ panel_info.vl_row = val;
+ yres_set = 1;
+ } else if (!bpp_set) {
+ switch (val) {
+ case 32:
+ case 24:
+ if (is_lvds())
+ pix_fmt = IPU_PIX_FMT_LVDS888;
+ /* fallthru */
+ case 16:
+ case 8:
+ color_depth = val;
+ break;
+
+ case 18:
+ if (is_lvds()) {
+ color_depth = val;
+ break;
+ }
+ /* fallthru */
+ default:
+ printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
+ end - vm, vm, color_depth);
+ }
+ bpp_set = 1;
+ } else if (!refresh_set) {
+ refresh = val;
+ refresh_set = 1;
+ }
+ }
+ vm = end;
+ }
+ switch (*vm) {
+ case '@':
+ bpp_set = 1;
+ /* fallthru */
+ case '-':
+ yres_set = 1;
+ /* fallthru */
+ case 'x':
+ xres_set = 1;
+ /* fallthru */
+ case 'M':
+ case 'R':
+ vm++;
+ break;
+
+ default:
+ if (*vm != '\0')
+ vm++;
+ }
+ }
+ if (p->xres == 0 || p->yres == 0) {
+ printf("Invalid video mode: %s\n", getenv("video_mode"));
+ lcd_enabled = 0;
+ printf("Supported video modes are:");
+ for (p = &tx6_fb_modes[0]; p->name != NULL; p++) {
+ printf(" %s", p->name);
+ }
+ printf("\n");
+ return;
+ }
+ if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) {
+ printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n",
+ p->xres, p->yres, panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ panel_info.vl_col = p->xres;
+ panel_info.vl_row = p->yres;
+
+ switch (color_depth) {
+ case 8:
+ panel_info.vl_bpix = LCD_COLOR8;
+ break;
+ case 16:
+ panel_info.vl_bpix = LCD_COLOR16;
+ break;
+ default:
- gpio_request_one(IMX_GPIO_NR(4, 21), GPIOF_OUTPUT_INIT_HIGH,
++ panel_info.vl_bpix = LCD_COLOR32;
+ }
+
+ p->pixclock = KHZ2PICOS(refresh *
+ (p->xres + p->left_margin + p->right_margin + p->hsync_len) *
+ (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) /
+ 1000);
+ debug("Pixel clock set to %lu.%03lu MHz\n",
+ PICOS2KHZ(p->pixclock) / 1000, PICOS2KHZ(p->pixclock) % 1000);
+
+ if (p != &fb_mode) {
+ int ret;
+
+ debug("Creating new display-timing node from '%s'\n",
+ video_mode);
+ ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p);
+ if (ret)
+ printf("Failed to create new display-timing node from '%s': %d\n",
+ video_mode, ret);
+ }
+
+ gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios));
+ imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads,
+ ARRAY_SIZE(stk5_lcd_pads));
+
+ lcd_bus_width = karo_fdt_get_lcd_bus_width(working_fdt, 24);
+ switch (lcd_bus_width) {
+ case 24:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS888 : IPU_PIX_FMT_RGB24;
+ break;
+
+ case 18:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS666 : IPU_PIX_FMT_RGB666;
+ break;
+
+ case 16:
+ if (!is_lvds()) {
+ pix_fmt = IPU_PIX_FMT_RGB565;
+ break;
+ }
+ /* fallthru */
+ default:
+ lcd_enabled = 0;
+ printf("Invalid %s bus width: %d\n", is_lvds() ? "LVDS" : "LCD",
+ lcd_bus_width);
+ return;
+ }
+ if (is_lvds()) {
+ int lvds_mapping = karo_fdt_get_lvds_mapping(working_fdt, 0);
+ int lvds_chan_mask = karo_fdt_get_lvds_channels(working_fdt);
+ uint32_t gpr2;
++ uint32_t gpr3;
+
+ if (lvds_chan_mask == 0) {
+ printf("No LVDS channel active\n");
+ lcd_enabled = 0;
+ return;
+ }
+
+ gpr2 = (lvds_mapping << 6) | (lvds_mapping << 8);
+ if (lcd_bus_width == 24)
+ gpr2 |= (1 << 5) | (1 << 7);
+ gpr2 |= (lvds_chan_mask & 1) ? 1 << 0 : 0;
+ gpr2 |= (lvds_chan_mask & 2) ? 3 << 2 : 0;
+ debug("writing %08x to GPR2[%08x]\n", gpr2, IOMUXC_BASE_ADDR + 8);
+ writel(gpr2, IOMUXC_BASE_ADDR + 8);
++
++ gpr3 = readl(IOMUXC_BASE_ADDR + 0xc);
++ gpr3 &= ~((3 << 8) | (3 << 6));
++ writel(gpr3, IOMUXC_BASE_ADDR + 0xc);
+ }
+ if (karo_load_splashimage(0) == 0) {
+ int ret;
+
+ debug("Initializing LCD controller\n");
+ ret = ipuv3_fb_init(p, 0, pix_fmt,
+ is_lvds() ? DI_PCLK_LDB : DI_PCLK_PLL3,
+ di_clk_rate, -1);
+ if (ret) {
+ printf("Failed to initialize FB driver: %d\n", ret);
+ lcd_enabled = 0;
+ }
+ } else {
+ debug("Skipping initialization of LCD controller\n");
+ }
+ }
+ #else
+ #define lcd_enabled 0
+ #endif /* CONFIG_LCD */
+
+ static void stk5_board_init(void)
+ {
+ gpio_request_array(stk5_gpios, ARRAY_SIZE(stk5_gpios));
+ imx_iomux_v3_setup_multiple_pads(stk5_pads, ARRAY_SIZE(stk5_pads));
+ }
+
+ static void stk5v3_board_init(void)
+ {
+ stk5_board_init();
+ }
+
+ static void stk5v5_board_init(void)
+ {
+ stk5_board_init();
+
- imx_iomux_v3_setup_pad(MX6_PAD_DISP0_DAT0__GPIO_4_21);
++ gpio_request_one(IMX_GPIO_NR(4, 21), GPIOFLAG_OUTPUT_INIT_HIGH,
+ "Flexcan Transceiver");
-static void tx6_init_mac(void)
-{
- u8 mac[ETH_ALEN];
-
- imx_get_mac_from_fuse(-1, mac);
- if (!is_valid_ether_addr(mac)) {
- printf("No valid MAC address programmed\n");
- return;
- }
-
- printf("MAC addr from fuse: %pM\n", mac);
- eth_setenv_enetaddr("ethaddr", mac);
-}
-
++ imx_iomux_v3_setup_pad(MX6_PAD_DISP0_DAT0__GPIO4_IO21);
+ }
+
+ static void tx6qdl_set_cpu_clock(void)
+ {
+ unsigned long cpu_clk = getenv_ulong("cpu_clk", 10, 0);
+
+ if (cpu_clk == 0 || cpu_clk == mxc_get_clock(MXC_ARM_CLK) / 1000000)
+ return;
+
+ if (had_ctrlc() || (wrsr & WRSR_TOUT)) {
+ printf("%s detected; skipping cpu clock change\n",
+ (wrsr & WRSR_TOUT) ? "WDOG RESET" : "<CTRL-C>");
+ return;
+ }
+ if (mxc_set_clock(CONFIG_SYS_MX6_HCLK, cpu_clk, MXC_ARM_CLK) == 0) {
+ cpu_clk = mxc_get_clock(MXC_ARM_CLK);
+ printf("CPU clock set to %lu.%03lu MHz\n",
+ cpu_clk / 1000000, cpu_clk / 1000 % 1000);
+ } else {
+ printf("Error: Failed to set CPU clock to %lu MHz\n", cpu_clk);
+ }
+ }
+
-#ifdef CONFIG_NO_NAND
+ int board_late_init(void)
+ {
+ int ret = 0;
+ const char *baseboard;
+
+ env_cleanup();
+
+ if (tx6_temp_check_enabled)
+ check_cpu_temperature(1);
+
+ tx6qdl_set_cpu_clock();
+
+ if (had_ctrlc())
+ setenv_ulong("safeboot", 1);
+ else if (wrsr & WRSR_TOUT)
+ setenv_ulong("wdreset", 1);
+ else
+ karo_fdt_move_fdt();
+
+ baseboard = getenv("baseboard");
+ if (!baseboard)
+ goto exit;
+
+ printf("Baseboard: %s\n", baseboard);
+
+ if (strncmp(baseboard, "stk5", 4) == 0) {
+ if ((strlen(baseboard) == 4) ||
+ strcmp(baseboard, "stk5-v3") == 0) {
+ stk5v3_board_init();
+ } else if (strcmp(baseboard, "stk5-v5") == 0) {
+ const char *otg_mode = getenv("otg_mode");
+
+ if (otg_mode && strcmp(otg_mode, "host") == 0) {
+ printf("otg_mode='%s' is incompatible with baseboard %s; setting to 'none'\n",
+ otg_mode, baseboard);
+ setenv("otg_mode", "none");
+ }
+ stk5v5_board_init();
+ } else {
+ printf("WARNING: Unsupported STK5 board rev.: %s\n",
+ baseboard + 4);
+ }
+ } else {
+ printf("WARNING: Unsupported baseboard: '%s'\n",
+ baseboard);
+ ret = -EINVAL;
+ }
+
+ exit:
+ tx6_init_mac();
+
+ gpio_set_value(TX6_RESET_OUT_GPIO, 1);
+ clear_ctrlc();
+ return ret;
+ }
+
-#define TX6_FLASH_SZ (CONFIG_MMC_BOOT_SIZE / 1024 - 1 + 2)
++#ifdef CONFIG_TX6_NAND
++#define TX6_FLASH_SZ (CONFIG_SYS_NAND_BLOCKS / 1024 - 1)
++#else
+ #ifdef CONFIG_MMC_BOOT_SIZE
-#define TX6_FLASH_SZ 3
++#define TX6_FLASH_SZ (CONFIG_MMC_BOOT_SIZE / 4096 + 2)
+ #else
-#else /* CONFIG_NO_NAND */
-#define TX6_FLASH_SZ (CONFIG_SYS_NAND_BLOCKS / 1024 - 1)
-#endif /* CONFIG_NO_NAND */
++#define TX6_FLASH_SZ 2
+ #endif
-#ifdef CONFIG_SYS_SDRAM_BUS_WIDTH
-#define TX6_DDR_SZ (ffs(CONFIG_SYS_SDRAM_BUS_WIDTH / 16) - 1)
-#else
-#define TX6_DDR_SZ 2
-#endif
++#endif /* CONFIG_TX6_NAND */
+
-#if CONFIG_TX6_REV >= 0x3
++#define TX6_DDR_SZ (ffs(PHYS_SDRAM_1_WIDTH / 16) - 1)
+
- '4', /* 256MiB SDRAM; 128MiB NAND */
- '1', /* 512MiB SDRAM; 128MiB NAND */
- '0', /* 1GiB SDRAM; 128MiB NAND */
- '?', /* 256MiB SDRAM; 256MiB NAND */
- '?', /* 512MiB SDRAM; 256MiB NAND */
- '2', /* 1GiB SDRAM; 256MiB NAND */
- '?', /* 256MiB SDRAM; 4GiB eMMC */
- '5', /* 512MiB SDRAM; 4GiB eMMC */
- '3', /* 1GiB SDRAM; 4GiB eMMC */
- '?', /* 256MiB SDRAM; 8GiB eMMC */
- '?', /* 512MiB SDRAM; 8GiB eMMC */
- '?', /* 1GiB SDRAM; 8GiB eMMC */
+ static char tx6_mem_table[] = {
-#else /* CONFIG_TX6_REV >= 0x3 */
-static inline char tx6_mem_suffix(void)
++ '4', /* 256MiB SDRAM 16bit; 128MiB NAND */
++ '1', /* 512MiB SDRAM 32bit; 128MiB NAND */
++ '0', /* 1GiB SDRAM 64bit; 128MiB NAND */
++ '?', /* 256MiB SDRAM 16bit; 256MiB NAND */
++ '?', /* 512MiB SDRAM 32bit; 256MiB NAND */
++ '2', /* 1GiB SDRAM 64bit; 256MiB NAND */
++ '?', /* 256MiB SDRAM 16bit; 4GiB eMMC */
++ '5', /* 512MiB SDRAM 32bit; 4GiB eMMC */
++ '3', /* 1GiB SDRAM 64bit; 4GiB eMMC */
++ '?', /* 256MiB SDRAM 16bit; 8GiB eMMC */
++ '?', /* 512MiB SDRAM 32bit; 8GiB eMMC */
++ '0', /* 1GiB SDRAM 64bit; 8GiB eMMC */
+ };
+
+ static inline char tx6_mem_suffix(void)
+ {
+ size_t mem_idx = (TX6_FLASH_SZ * 3) + TX6_DDR_SZ;
+
+ debug("TX6_DDR_SZ=%d TX6_FLASH_SZ=%d idx=%d\n",
+ TX6_DDR_SZ, TX6_FLASH_SZ, mem_idx);
+
+ if (mem_idx >= ARRAY_SIZE(tx6_mem_table))
+ return '?';
+
+ return tx6_mem_table[mem_idx];
+ };
-#ifdef CONFIG_SYS_SDRAM_BUS_WIDTH
- if (CONFIG_SYS_SDRAM_BUS_WIDTH == 32)
- return '1';
-#endif
-#ifdef CONFIG_SYS_NAND_BLOCKS
- if (CONFIG_SYS_NAND_BLOCKS == 2048)
- return '2';
-#endif
- return '0';
++
++static struct {
++ uchar addr;
++ uchar rev;
++} tx6_mod_revs[] = {
++ { 0x3c, 1, },
++ { 0x32, 2, },
++ { 0x33, 3, },
++};
++
++static int tx6_get_mod_rev(void)
+ {
-#endif /* CONFIG_TX6_REV >= 0x3 */
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(tx6_mod_revs); i++) {
++ int ret = i2c_probe(tx6_mod_revs[i].addr);
++ if (ret == 0) {
++ debug("I2C probe succeeded for addr %02x\n", tx6_mod_revs[i].addr);
++ return tx6_mod_revs[i].rev;
++ }
++ debug("I2C probe returned %d for addr %02x\n", ret,
++ tx6_mod_revs[i].addr);
++ }
++ return 0;
+ }
- is_lvds(), CONFIG_TX6_REV,
+
+ int checkboard(void)
+ {
+ u32 cpurev = get_cpu_rev();
+ int cpu_variant = (cpurev >> 12) & 0xff;
+
+ tx6qdl_print_cpuinfo();
+
++ i2c_init(CONFIG_SYS_I2C_SPEED, 0 /* unused */);
++
+ printf("Board: Ka-Ro TX6%s-%d%d%d%c\n",
+ tx6_mod_suffix,
+ cpu_variant == MXC_CPU_MX6Q ? 1 : 8,
-void ft_board_setup(void *blob, bd_t *bd)
++ is_lvds(), tx6_get_mod_rev(),
+ tx6_mem_suffix());
+
+ return 0;
+ }
+
+ #ifdef CONFIG_SERIAL_TAG
+ void get_board_serial(struct tag_serialnr *serialnr)
+ {
+ struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+ struct fuse_bank0_regs *fuse = (void *)ocotp->bank[0].fuse_regs;
+
+ serialnr->low = readl(&fuse->cfg0);
+ serialnr->high = readl(&fuse->cfg1);
+ }
+ #endif
+
+ #if defined(CONFIG_OF_BOARD_SETUP)
+ #ifdef CONFIG_FDT_FIXUP_PARTITIONS
+ #include <jffs2/jffs2.h>
+ #include <mtd_node.h>
+ static struct node_info nodes[] = {
+ { "fsl,imx6q-gpmi-nand", MTD_DEV_TYPE_NAND, },
+ };
+ #else
+ #define fdt_fixup_mtdparts(b,n,c) do { } while (0)
+ #endif
+
+ static const char *tx6_touchpanels[] = {
+ "ti,tsc2007",
+ "edt,edt-ft5x06",
+ "eeti,egalax_ts",
+ };
+
- if (ret)
++int ft_board_setup(void *blob, bd_t *bd)
+ {
+ const char *baseboard = getenv("baseboard");
+ int stk5_v5 = baseboard != NULL && (strcmp(baseboard, "stk5-v5") == 0);
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ int ret;
+
+ ret = fdt_increase_size(blob, 4096);
-
++ if (ret) {
+ printf("Failed to increase FDT size: %s\n", fdt_strerror(ret));
++ return ret;
++ }
+ if (stk5_v5)
+ karo_fdt_enable_node(blob, "stk5led", 0);
+
+ fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+ fdt_fixup_ethernet(blob);
+
+ karo_fdt_fixup_touchpanel(blob, tx6_touchpanels,
+ ARRAY_SIZE(tx6_touchpanels));
+ karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply");
+ karo_fdt_fixup_flexcan(blob, stk5_v5);
+
+ karo_fdt_update_fb_mode(blob, video_mode);
++
++ return 0;
+ }
+ #endif /* CONFIG_OF_BOARD_SETUP */
--- /dev/null
- _end = .;
+ /*
+ * (C) Copyright 2012 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+ OUTPUT_ARCH(arm)
+ ENTRY(_start)
+ SECTIONS
+ {
+ . = 0x00000000;
+ .text :
+ {
+ *(.__image_copy_start)
++ *(.vectors)
+ CPUDIR/start.o (.text*)
+ . = 0x400;
+ KEEP(board/karo/tx6/lowlevel_init.o (.text*))
+ *(.text*)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : {
+ *(.data*)
+ }
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = ALIGN(4);
+ .image_copy_end :
+ {
+ *(.__image_copy_end)
+ }
+
+ .rel_dyn_start :
+ {
+ *(.__rel_dyn_start)
+ }
+
+ .rel.dyn :
+ {
+ *(.rel*)
+ }
+
+ .rel_dyn_end :
+ {
+ *(.__rel_dyn_end)
+ }
+
++ .end :
++ {
++ *(.__end)
++ }
++
++ _image_binary_end = .;
+
+ /*
+ * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
+ * __bss_base and __bss_limit are for linker only (overlay ordering)
+ */
+
+ .bss_start __rel_dyn_start (OVERLAY) : {
+ KEEP(*(.__bss_start));
+ __bss_base = .;
+ }
+
+ .bss __bss_base (OVERLAY) : {
+ *(.bss*)
+ . = ALIGN(4);
+ __bss_limit = .;
+ }
+ .bss_end __bss_limit (OVERLAY) : {
+ KEEP(*(.__bss_end));
+ }
+
++ .dynsym _image_binary_end : { *(.dynsym) }
++ .dynbss : { *(.dynbss) }
++ .dynstr : { *(.dynstr*) }
++ .dynamic : { *(.dynamic*) }
++ .plt : { *(.plt*) }
++ .interp : { *(.interp*) }
++ .gnu.hash : { *(.gnu.hash) }
++ .gnu : { *(.gnu*) }
++ .ARM.exidx : { *(.ARM.exidx*) }
++ .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
++
++/*
+ /DISCARD/ : { *(.bss*) }
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynsym*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.hash*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
++*/
+ }
/*
* Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2014 O.S. Systems Software LTDA.
*
* Author: Fabio Estevam <fabio.estevam@freescale.com>
*
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/video.h>
#include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
#include <common.h>
#include <fsl_esdhc.h>
-#include <ipu_pixfmt.h>
#include <mmc.h>
#include <miiphy.h>
#include <netdev.h>
-#include <linux/fb.h>
+#include <phy.h>
+#include <input.h>
+#include <i2c.h>
DECLARE_GLOBAL_DATA_PTR;
#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
+ PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+
#define USDHC1_CD_GPIO IMX_GPIO_NR(1, 2)
#define USDHC3_CD_GPIO IMX_GPIO_NR(3, 9)
#define ETH_PHY_RESET IMX_GPIO_NR(3, 29)
}
static iomux_v3_cfg_t const uart1_pads[] = {
- MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
-iomux_v3_cfg_t const usdhc1_pads[] = {
- MX6_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+static iomux_v3_cfg_t const usdhc1_pads[] = {
+ MX6_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD1_DAT0__SD1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD1_DAT1__SD1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD1_DAT2__SD1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD1_DAT3__SD1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
/* Carrier MicroSD Card Detect */
- MX6_PAD_GPIO_2__GPIO1_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_GPIO_2__GPIO_1_2,
++ MX6_PAD_GPIO_2__GPIO1_IO02,
};
static iomux_v3_cfg_t const usdhc3_pads[] = {
- MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
/* SOM MicroSD Card Detect */
- MX6_PAD_EIM_DA9__GPIO3_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_EIM_DA9__GPIO_3_9,
++ MX6_PAD_EIM_DA9__GPIO3_IO09,
};
static iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
/* AR8031 PHY Reset */
- MX6_PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
- MX6_PAD_EIM_D29__GPIO_3_29,
++ MX6_PAD_EIM_D29__GPIO3_IO29,
};
static void setup_iomux_uart(void)
int board_mmc_init(bd_t *bis)
{
- s32 status = 0;
+ int ret;
u32 index = 0;
/*
printf("Warning: you configured more USDHC controllers"
"(%d) then supported by the board (%d)\n",
index + 1, CONFIG_SYS_FSL_USDHC_NUM);
- return status;
+ return -EINVAL;
}
- status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ ret = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+ if (ret)
+ return ret;
}
- return status;
+ return 0;
}
static int mx6_rgmii_rework(struct phy_device *phydev)
}
#if defined(CONFIG_VIDEO_IPUV3)
-static void enable_hdmi(void)
-{
- struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
- u8 reg;
- reg = readb(&hdmi->phy_conf0);
- reg |= HDMI_PHY_CONF0_PDZ_MASK;
- writeb(reg, &hdmi->phy_conf0);
-
- udelay(3000);
- reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
- writeb(reg, &hdmi->phy_conf0);
- udelay(3000);
- reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
- writeb(reg, &hdmi->phy_conf0);
- writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
-}
+struct i2c_pads_info i2c2_pad_info = {
+ .scl = {
+ .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL
+ | MUX_PAD_CTRL(I2C_PAD_CTRL),
+ .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12
+ | MUX_PAD_CTRL(I2C_PAD_CTRL),
+ .gp = IMX_GPIO_NR(4, 12)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA
+ | MUX_PAD_CTRL(I2C_PAD_CTRL),
+ .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13
+ | MUX_PAD_CTRL(I2C_PAD_CTRL),
+ .gp = IMX_GPIO_NR(4, 13)
+ }
+};
-static struct fb_videomode const hdmi = {
- .name = "HDMI",
- .refresh = 60,
- .xres = 1024,
- .yres = 768,
- .pixclock = 15385,
- .left_margin = 220,
- .right_margin = 40,
- .upper_margin = 21,
- .lower_margin = 7,
- .hsync_len = 60,
- .vsync_len = 10,
- .sync = FB_SYNC_EXT,
- .vmode = FB_VMODE_NONINTERLACED
+static iomux_v3_cfg_t const fwadapt_7wvga_pads[] = {
+ MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,
+ MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02, /* HSync */
+ MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03, /* VSync */
+ MX6_PAD_DI0_PIN4__IPU1_DI0_PIN04
+ | MUX_PAD_CTRL(PAD_CTL_DSE_120ohm), /* Contrast */
+ MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15, /* DISP0_DRDY */
+
+ MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00,
+ MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01,
+ MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02,
+ MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03,
+ MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04,
+ MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05,
+ MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06,
+ MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07,
+ MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08,
+ MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09,
+ MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10,
+ MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11,
+ MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12,
+ MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13,
+ MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14,
+ MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15,
+ MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16,
+ MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17,
+
- MX6_PAD_SD4_DAT2__GPIO2_IO10
- | MUX_PAD_CTRL(NO_PAD_CTRL), /* DISP0_BKLEN */
- MX6_PAD_SD4_DAT3__GPIO2_IO11
- | MUX_PAD_CTRL(NO_PAD_CTRL), /* DISP0_VDDEN */
++ MX6_PAD_SD4_DAT2__GPIO2_IO10, /* DISP0_BKLEN */
++ MX6_PAD_SD4_DAT3__GPIO2_IO11, /* DISP0_VDDEN */
};
-int board_video_skip(void)
+static void do_enable_hdmi(struct display_info_t const *dev)
{
- int ret;
-
- ret = ipuv3_fb_init(&hdmi, 0, IPU_PIX_FMT_RGB24);
+ imx_enable_hdmi_phy();
+}
- if (ret)
- printf("HDMI cannot be configured: %d\n", ret);
+static int detect_i2c(struct display_info_t const *dev)
+{
+ return (0 == i2c_set_bus_num(dev->bus)) &&
+ (0 == i2c_probe(dev->addr));
+}
- enable_hdmi();
+static void enable_fwadapt_7wvga(struct display_info_t const *dev)
+{
+ imx_iomux_v3_setup_multiple_pads(
+ fwadapt_7wvga_pads,
+ ARRAY_SIZE(fwadapt_7wvga_pads));
- return ret;
+ gpio_direction_output(IMX_GPIO_NR(2, 10), 1);
+ gpio_direction_output(IMX_GPIO_NR(2, 11), 1);
}
+struct display_info_t const displays[] = {{
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = detect_hdmi,
+ .enable = do_enable_hdmi,
+ .mode = {
+ .name = "HDMI",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15385,
+ .left_margin = 220,
+ .right_margin = 40,
+ .upper_margin = 21,
+ .lower_margin = 7,
+ .hsync_len = 60,
+ .vsync_len = 10,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+} }, {
+ .bus = 1,
+ .addr = 0x10,
+ .pixfmt = IPU_PIX_FMT_RGB666,
+ .detect = detect_i2c,
+ .enable = enable_fwadapt_7wvga,
+ .mode = {
+ .name = "FWBADAPT-LCD-F07A-0102",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 33260,
+ .left_margin = 128,
+ .right_margin = 128,
+ .upper_margin = 22,
+ .lower_margin = 22,
+ .hsync_len = 1,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+} } };
+size_t display_count = ARRAY_SIZE(displays);
+
static void setup_display(void)
{
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
- struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
int reg;
- /* Turn on IPU clock */
- reg = readl(&mxc_ccm->CCGR3);
- reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET;
- writel(reg, &mxc_ccm->CCGR3);
-
- /* Turn on HDMI PHY clock */
- reg = readl(&mxc_ccm->CCGR2);
- reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
- | MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
- writel(reg, &mxc_ccm->CCGR2);
-
- /* clear HDMI PHY reset */
- writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
+ enable_ipu_clock();
+ imx_setup_hdmi();
reg = readl(&mxc_ccm->chsccdr);
- reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK
- | MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK
- | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
reg |= (CHSCCDR_CLK_SEL_LDB_DI0
- << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)
- | (CHSCCDR_PODF_DIVIDE_BY_3
- << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
- | (CHSCCDR_IPU_PRE_CLK_540M_PFD
- << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+ << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
writel(reg, &mxc_ccm->chsccdr);
+
+ /* Disable LCD backlight */
+ imx_iomux_v3_setup_pad(MX6_PAD_DI0_PIN4__GPIO4_IO20);
+ gpio_direction_input(IMX_GPIO_NR(4, 20));
}
#endif /* CONFIG_VIDEO_IPUV3 */
int board_eth_init(bd_t *bis)
{
- int ret;
-
setup_iomux_enet();
- ret = cpu_eth_init(bis);
- if (ret)
- printf("FEC MXC: %s:failed\n", __func__);
-
- return 0;
+ return cpu_eth_init(bis);
}
int board_early_init_f(void)
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+ setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c2_pad_info);
+
return 0;
}
--- /dev/null
+menu "Command line interface"
+ depends on !SPL_BUILD
+
+config HUSH_PARSER
+ bool "Use hush shell"
+ select SYS_HUSH_PARSER
+ help
+ This option enables the "hush" shell (from Busybox) as command line
+ interpreter, thus enabling powerful command line syntax like
+ if...then...else...fi conditionals or `&&' and '||'
+ constructs ("shell scripts").
+
+ If disabled, you get the old, much simpler behaviour with a somewhat
+ smaller memory footprint.
+
+config SYS_HUSH_PARSER
+ bool
+ help
+ Backward compatibility.
+
+comment "Commands"
+
+menu "Info commands"
+
+config CMD_BDI
+ bool "bdinfo"
+ help
+ Print board info
+
+config CMD_CONSOLE
+ bool "coninfo"
+ help
+ Print console devices and information.
+
+config CMD_LICENSE
+ bool "license"
+ help
+ Print GPL license text
+
+endmenu
+
+menu "Boot commands"
+
+config CMD_BOOTD
+ bool "bootd"
+ help
+ Run the command stored in the environment "bootcmd", i.e.
+ "bootd" does the same thing as "run bootcmd".
+
+config CMD_BOOTM
+ bool "bootm"
+ default y
+ help
+ Boot an application image from the memory.
+
++config CMD_BOOTZ
++ bool "bootz"
++ default y
++ help
++ Boot a Linux kernel zImage.
++
++config CMD_BOOTCE
++ bool "bootce"
++ help
++ Boot a WindowsCE image.
++
+config CMD_GO
+ bool "go"
+ default y
+ help
+ Start an application at a given address.
+
+config CMD_RUN
+ bool "run"
+ help
+ Run the command in the given environment variable.
+
+config CMD_IMI
+ bool "iminfo"
+ help
+ Print header information for application image.
+
+config CMD_IMLS
+ bool "imls"
+ help
+ List all images found in flash
+
+config CMD_XIMG
+ bool "imxtract"
+ help
+ Extract a part of a multi-image.
+
+endmenu
+
++menu "DTB support"
++
++config OF_LIBFDT
++ bool "Enable FDT commands"
++
++config OF_BOARD_SETUP
++ bool "Support DT modifications by board code"
++ depends on OF_LIBFDT
++
++endmenu
++
+menu "Environment commands"
+
+config CMD_EXPORTENV
+ bool "env export"
+ default y
+ help
+ Export environments.
+
+config CMD_IMPORTENV
+ bool "env import"
+ default y
+ help
+ Import environments.
+
+config CMD_EDITENV
+ bool "editenv"
+ help
+ Edit environment variable.
+
+config CMD_SAVEENV
+ bool "saveenv"
+ help
+ Run the command in the given environment variable.
+
+endmenu
+
++menu "Environment configuration settings"
++
++choice
++ prompt "Select environment non-volatile storage"
++
++config ENV_IS_NOWHERE
++ bool "do not store environment"
++
++config ENV_IS_IN_NAND
++ bool "store environment in NAND"
++ depends on NAND
++
++config ENV_IS_IN_MMC
++ bool "store environment in MMC"
++ depends on MMC
++
++endchoice
++
++endmenu
++
+menu "Memory commands"
+
+config CMD_MEMORY
+ bool "md, mm, nm, mw, cp, cmp, base, loop"
+ help
+ Memeory commands.
+ md - memory display
+ mm - memory modify (auto-incrementing address)
+ nm - memory modify (constant address)
+ mw - memory write (fill)
+ cp - memory copy
+ cmp - memory compare
+ base - print or set address offset
+ loop - initinite loop on address range
+
+config CMD_CRC32
+ bool "crc32"
+ default y
+ help
+ Compute CRC32.
+
+config LOOPW
+ bool "loopw"
+ help
+ Infinite write loop on address range
+
+config CMD_MEMTEST
+ bool "crc32"
+ help
+ Simple RAM read/write test.
+
+config CMD_MX_CYCLIC
+ bool "mdc, mwc"
+ help
+ mdc - memory display cyclic
+ mwc - memory write cyclic
+
+config CMD_MEMINFO
+ bool "meminfo"
+ help
+ Display memory information.
+
+endmenu
+
+menu "Device access commands"
+
+config CMD_LOADB
+ bool "loadb"
+ help
+ Load a binary file over serial line.
+
+config CMD_LOADS
+ bool "loads"
+ help
+ Load an S-Record file over serial line
+
+config CMD_FLASH
+ bool "flinfo, erase, protect"
+ help
+ NOR flash support.
+ flinfo - print FLASH memory information
+ erase - FLASH memory
+ protect - enable or disable FLASH write protection
+
++config MTD_DEVICE
++ bool "MTD device support"
++
++config CMD_MTDPARTS
++ bool "MTD partitioning support"
++ default y
++ depends on MTD_DEVICE && (CMD_FLASH || CMD_NAND)
++
+config CMD_NAND
+ bool "nand"
+ help
+ NAND support.
+
++config CMD_NAND_TRIMFFS
++ bool "Enable nand write.trimffs command"
++ help
++ Enable command to leave page sized runs of 0xff patterns in
++ erased state rather than overwriting them. This is required
++ for using NAND flash filesystems on NAND controllers with
++ a non-0xff ECC code for all 0xff data.
++
++config CMD_MMC
++ bool "mmc/sd"
++ help
++ MMC/SD support.
++
+config CMD_SPI
+ bool "sspi"
+ help
+ SPI utility command.
+
+config CMD_I2C
+ bool "i2c"
+ help
+ I2C support.
+
+config CMD_USB
+ bool "usb"
+ help
+ USB support.
+
+config CMD_FPGA
+ bool "fpga"
+ help
+ FPGA support.
+
+endmenu
+
+
+menu "Shell scripting commands"
+
+config CMD_ECHO
+ bool "echo"
+ help
+ Echo args to console
+
+config CMD_ITEST
+ bool "itest"
+ help
+ Return true/false on integer compare.
+
+config CMD_SOURCE
+ bool "source"
+ help
+ Run script from memory
+
+endmenu
+
+menu "Network commands"
+
+config CMD_NET
+ bool "bootp, tftpboot"
+ help
+ Network commands.
+ bootp - boot image via network using BOOTP/TFTP protocol
+ tftpboot - boot image via network using TFTP protocol
+
+config CMD_TFTPPUT
+ bool "tftp put"
+ help
+ TFTP put command, for uploading files to a server
+
+config CMD_TFTPSRV
+ bool "tftpsrv"
+ help
+ Act as a TFTP server and boot the first received file
+
+config CMD_RARP
+ bool "rarpboot"
+ help
+ Boot image via network using RARP/TFTP protocol
+
+config CMD_DHCP
+ bool "dhcp"
+ help
+ Boot image via network using DHCP/TFTP protocol
+
+config CMD_NFS
+ bool "nfs"
+ help
+ Boot image via network using NFS protocol.
+
+config CMD_PING
+ bool "ping"
+ help
+ Send ICMP ECHO_REQUEST to network host
+
+config CMD_CDP
+ bool "cdp"
+ help
+ Perform CDP network configuration
+
+config CMD_SNTP
+ bool "sntp"
+ help
+ Synchronize RTC via network
+
+config CMD_DNS
+ bool "dns"
+ help
+ Lookup the IP of a hostname
+
+config CMD_DNS
+ bool "dns"
+ help
+ Lookup the IP of a hostname
+
+config CMD_LINK_LOCAL
+ bool "linklocal"
+ help
+ Acquire a network IP address using the link-local protocol
+
+endmenu
+
+menu "Misc commands"
+
++config CMD_CACHE
++ bool "cache control"
++ help
++ Enable commands to switch data cache on/off.
++
+config CMD_TIME
+ bool "time"
+ help
+ Run commands and summarize execution time.
+
+# TODO: rename to CMD_SLEEP
+config CMD_MISC
+ bool "sleep"
+ help
+ Delay execution for some time
+
+config CMD_TIMER
+ bool "timer"
+ help
+ Access the system timer.
+
+config CMD_SETGETDCR
+ bool "getdcr, setdcr, getidcr, setidcr"
+ depends on 4xx
+ help
+ getdcr - Get an AMCC PPC 4xx DCR's value
+ setdcr - Set an AMCC PPC 4xx DCR's value
+ getidcr - Get a register value via indirect DCR addressing
+ setidcr - Set a register value via indirect DCR addressing
+
+endmenu
+
+endmenu
# SPDX-License-Identifier: GPL-2.0+
#
-include $(TOPDIR)/config.mk
-
-LIB = $(obj)libcommon.o
-
# core
ifndef CONFIG_SPL_BUILD
-COBJS-y += main.o
-COBJS-y += command.o
-COBJS-y += exports.o
-COBJS-y += hash.o
-COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o
-COBJS-y += s_record.o
-COBJS-y += xyzModem.o
-COBJS-y += cmd_disk.o
+obj-y += main.o
+obj-y += exports.o
+obj-y += hash.o
+ifdef CONFIG_SYS_HUSH_PARSER
+obj-y += cli_hush.o
+endif
+
+# This option is not just y/n - it can have a numeric value
+ifdef CONFIG_BOOTDELAY
+obj-y += autoboot.o
+endif
+
+# This option is not just y/n - it can have a numeric value
+ifdef CONFIG_BOOT_RETRY_TIME
+obj-y += bootretry.o
+endif
# boards
-COBJS-$(CONFIG_SYS_GENERIC_BOARD) += board_f.o
-COBJS-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o
+obj-$(CONFIG_SYS_GENERIC_BOARD) += board_f.o
+obj-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o
# core command
-COBJS-y += cmd_boot.o
-COBJS-$(CONFIG_CMD_BOOTM) += cmd_bootm.o
-COBJS-y += cmd_help.o
-COBJS-y += cmd_version.o
+obj-y += cmd_boot.o
+obj-$(CONFIG_CMD_BOOTM) += cmd_bootm.o bootm.o bootm_os.o
+obj-y += cmd_help.o
+obj-y += cmd_version.o
# environment
-COBJS-y += env_attr.o
-COBJS-y += env_callback.o
-COBJS-y += env_flags.o
-COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
-COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
-XCOBJS-$(CONFIG_ENV_IS_EMBEDDED) += env_embedded.o
-COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_embedded.o
-XCOBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_embedded.o
-COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_embedded.o
-COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
-COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
-COBJS-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o
-COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
-COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o
-COBJS-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o
-COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
-COBJS-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o
-COBJS-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
-COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
+obj-y += env_attr.o
+obj-y += env_callback.o
+obj-y += env_flags.o
+obj-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
+obj-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
+extra-$(CONFIG_ENV_IS_EMBEDDED) += env_embedded.o
+obj-$(CONFIG_ENV_IS_IN_EEPROM) += env_embedded.o
+extra-$(CONFIG_ENV_IS_IN_FLASH) += env_embedded.o
+obj-$(CONFIG_ENV_IS_IN_NVRAM) += env_embedded.o
+obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
+obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
+obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o
+obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
+obj-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o
+obj-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o
+obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
+obj-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o
+obj-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
+obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
# command
-COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o
-COBJS-$(CONFIG_SOURCE) += cmd_source.o
-COBJS-$(CONFIG_CMD_SOURCE) += cmd_source.o
-COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o
-COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o
-COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o
-COBJS-$(CONFIG_CMD_BOOTCE) += cmd_bootce.o
-COBJS-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o
-COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o
-COBJS-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o
-COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o
-COBJS-$(CONFIG_CMD_CBFS) += cmd_cbfs.o
-COBJS-$(CONFIG_CMD_CONSOLE) += cmd_console.o
-COBJS-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o
-COBJS-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o
-COBJS-$(CONFIG_CMD_DATE) += cmd_date.o
-COBJS-$(CONFIG_CMD_SOUND) += cmd_sound.o
+obj-$(CONFIG_CMD_AES) += cmd_aes.o
+obj-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o
+obj-$(CONFIG_SOURCE) += cmd_source.o
+obj-$(CONFIG_CMD_SOURCE) += cmd_source.o
+obj-$(CONFIG_CMD_BDI) += cmd_bdinfo.o
+obj-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o
+obj-$(CONFIG_CMD_BMP) += cmd_bmp.o
++obj-$(CONFIG_CMD_BOOTCE) += cmd_bootce.o
+obj-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o
+obj-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o
+obj-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o
+obj-$(CONFIG_CMD_CACHE) += cmd_cache.o
+obj-$(CONFIG_CMD_CBFS) += cmd_cbfs.o
+obj-$(CONFIG_CMD_CLK) += cmd_clk.o
+obj-$(CONFIG_CMD_CONSOLE) += cmd_console.o
+obj-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o
+obj-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o
+obj-$(CONFIG_CMD_DATE) += cmd_date.o
+obj-$(CONFIG_CMD_DEMO) += cmd_demo.o
+obj-$(CONFIG_CMD_SOUND) += cmd_sound.o
ifdef CONFIG_4xx
-COBJS-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
+obj-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
endif
ifdef CONFIG_POST
-COBJS-$(CONFIG_CMD_DIAG) += cmd_diag.o
+obj-$(CONFIG_CMD_DIAG) += cmd_diag.o
endif
-COBJS-$(CONFIG_CMD_DISPLAY) += cmd_display.o
-COBJS-$(CONFIG_CMD_DTT) += cmd_dtt.o
-COBJS-$(CONFIG_CMD_ECHO) += cmd_echo.o
-COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o
-COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
-COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
-COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
-COBJS-$(CONFIG_CMD_EXT4) += cmd_ext4.o
-COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
-COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
-COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o
-COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
-COBJS-$(CONFIG_CMD_FDOS) += cmd_fdos.o
-COBJS-$(CONFIG_CMD_FITUPD) += cmd_fitupd.o
-COBJS-$(CONFIG_CMD_FLASH) += cmd_flash.o
+obj-$(CONFIG_CMD_DISPLAY) += cmd_display.o
+obj-$(CONFIG_CMD_DTT) += cmd_dtt.o
+obj-$(CONFIG_CMD_ECHO) += cmd_echo.o
+obj-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o
+obj-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
+obj-$(CONFIG_CMD_ELF) += cmd_elf.o
+obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
+obj-$(CONFIG_CMD_EXT4) += cmd_ext4.o
+obj-$(CONFIG_CMD_EXT2) += cmd_ext2.o
+obj-$(CONFIG_CMD_FAT) += cmd_fat.o
+obj-$(CONFIG_CMD_FDC) += cmd_fdc.o
+obj-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
+obj-$(CONFIG_CMD_FITUPD) += cmd_fitupd.o
+obj-$(CONFIG_CMD_FLASH) += cmd_flash.o
ifdef CONFIG_FPGA
-COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
+obj-$(CONFIG_CMD_FPGA) += cmd_fpga.o
endif
-COBJS-$(CONFIG_CMD_FPGAD) += cmd_fpgad.o
-COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
-COBJS-$(CONFIG_CMD_FUSE) += cmd_fuse.o
-COBJS-$(CONFIG_CMD_GETTIME) += cmd_gettime.o
-COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o
-COBJS-$(CONFIG_CMD_IIM) += cmd_iim.o
-COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
-COBJS-$(CONFIG_CMD_HASH) += cmd_hash.o
-COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o
-COBJS-$(CONFIG_CMD_IMMAP) += cmd_immap.o
-COBJS-$(CONFIG_CMD_INI) += cmd_ini.o
-COBJS-$(CONFIG_CMD_IRQ) += cmd_irq.o
-COBJS-$(CONFIG_CMD_ITEST) += cmd_itest.o
-COBJS-$(CONFIG_CMD_JFFS2) += cmd_jffs2.o
-COBJS-$(CONFIG_CMD_CRAMFS) += cmd_cramfs.o
-COBJS-$(CONFIG_CMD_LDRINFO) += cmd_ldrinfo.o
-COBJS-$(CONFIG_CMD_LED) += cmd_led.o
-COBJS-$(CONFIG_CMD_LICENSE) += cmd_license.o
-COBJS-y += cmd_load.o
-COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o
-COBJS-$(CONFIG_ID_EEPROM) += cmd_mac.o
-COBJS-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o
-COBJS-$(CONFIG_CMD_MEMORY) += cmd_mem.o
-COBJS-$(CONFIG_CMD_IO) += cmd_io.o
-COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
-COBJS-$(CONFIG_MII) += miiphyutil.o
-COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
-COBJS-$(CONFIG_PHYLIB) += miiphyutil.o
-COBJS-$(CONFIG_CMD_MII) += cmd_mii.o
+obj-$(CONFIG_CMD_FPGAD) += cmd_fpgad.o
+obj-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
+obj-$(CONFIG_CMD_FUSE) += cmd_fuse.o
+obj-$(CONFIG_CMD_GETTIME) += cmd_gettime.o
+obj-$(CONFIG_CMD_GPIO) += cmd_gpio.o
+obj-$(CONFIG_CMD_I2C) += cmd_i2c.o
+obj-$(CONFIG_CMD_IOTRACE) += cmd_iotrace.o
+obj-$(CONFIG_CMD_HASH) += cmd_hash.o
+obj-$(CONFIG_CMD_IDE) += cmd_ide.o
+obj-$(CONFIG_CMD_IMMAP) += cmd_immap.o
+obj-$(CONFIG_CMD_INI) += cmd_ini.o
+obj-$(CONFIG_CMD_IRQ) += cmd_irq.o
+obj-$(CONFIG_CMD_ITEST) += cmd_itest.o
+obj-$(CONFIG_CMD_JFFS2) += cmd_jffs2.o
+obj-$(CONFIG_CMD_CRAMFS) += cmd_cramfs.o
+obj-$(CONFIG_CMD_LDRINFO) += cmd_ldrinfo.o
+obj-$(CONFIG_CMD_LED) += cmd_led.o
+obj-$(CONFIG_CMD_LICENSE) += cmd_license.o
+obj-y += cmd_load.o
+obj-$(CONFIG_LOGBUFFER) += cmd_log.o
+obj-$(CONFIG_ID_EEPROM) += cmd_mac.o
+obj-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o
+obj-$(CONFIG_CMD_MEMORY) += cmd_mem.o
+obj-$(CONFIG_CMD_IO) += cmd_io.o
+obj-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
+obj-$(CONFIG_MII) += miiphyutil.o
+obj-$(CONFIG_CMD_MII) += miiphyutil.o
+obj-$(CONFIG_PHYLIB) += miiphyutil.o
+obj-$(CONFIG_CMD_MII) += cmd_mii.o
ifdef CONFIG_PHYLIB
-COBJS-$(CONFIG_CMD_MII) += cmd_mdio.o
+obj-$(CONFIG_CMD_MII) += cmd_mdio.o
endif
-COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
-COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
-COBJS-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o
-COBJS-$(CONFIG_MP) += cmd_mp.o
-COBJS-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
-COBJS-$(CONFIG_CMD_NAND) += cmd_nand.o
-COBJS-$(CONFIG_CMD_NET) += cmd_net.o
-COBJS-$(CONFIG_CMD_ONENAND) += cmd_onenand.o
-COBJS-$(CONFIG_CMD_OTP) += cmd_otp.o
-COBJS-$(CONFIG_CMD_PART) += cmd_part.o
-COBJS-$(CONFIG_CMD_PATA) += cmd_pata.o
+obj-$(CONFIG_CMD_MISC) += cmd_misc.o
+obj-$(CONFIG_CMD_MMC) += cmd_mmc.o
+obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o
+obj-$(CONFIG_MP) += cmd_mp.o
+obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
+obj-$(CONFIG_CMD_NAND) += cmd_nand.o
+obj-$(CONFIG_CMD_NET) += cmd_net.o
+obj-$(CONFIG_CMD_ONENAND) += cmd_onenand.o
+obj-$(CONFIG_CMD_OTP) += cmd_otp.o
+obj-$(CONFIG_CMD_PART) += cmd_part.o
ifdef CONFIG_PCI
-COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o
+obj-$(CONFIG_CMD_PCI) += cmd_pci.o
+endif
+obj-y += cmd_pcmcia.o
+obj-$(CONFIG_CMD_PORTIO) += cmd_portio.o
+obj-$(CONFIG_CMD_PXE) += cmd_pxe.o
+obj-$(CONFIG_CMD_READ) += cmd_read.o
+obj-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
+obj-$(CONFIG_CMD_REISER) += cmd_reiser.o
+obj-$(CONFIG_SANDBOX) += cmd_sandbox.o
+obj-$(CONFIG_CMD_SATA) += cmd_sata.o
+obj-$(CONFIG_CMD_SF) += cmd_sf.o
+obj-$(CONFIG_CMD_SCSI) += cmd_scsi.o
+obj-$(CONFIG_CMD_SHA1SUM) += cmd_sha1sum.o
+obj-$(CONFIG_CMD_SETEXPR) += cmd_setexpr.o
+obj-$(CONFIG_CMD_SOFTSWITCH) += cmd_softswitch.o
+obj-$(CONFIG_CMD_SPI) += cmd_spi.o
+obj-$(CONFIG_CMD_SPIBOOTLDR) += cmd_spibootldr.o
+obj-$(CONFIG_CMD_STRINGS) += cmd_strings.o
+obj-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o
+obj-$(CONFIG_CMD_TIME) += cmd_time.o
+obj-$(CONFIG_CMD_TRACE) += cmd_trace.o
+obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o
+obj-$(CONFIG_CMD_TPM) += cmd_tpm.o
+obj-$(CONFIG_CMD_TSI148) += cmd_tsi148.o
+obj-$(CONFIG_CMD_UBI) += cmd_ubi.o
+obj-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o
+obj-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o
+obj-$(CONFIG_CMD_UNZIP) += cmd_unzip.o
+ifdef CONFIG_LZMA
+obj-$(CONFIG_CMD_LZMADEC) += cmd_lzmadec.o
endif
-COBJS-y += cmd_pcmcia.o
-COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
-COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o
-COBJS-$(CONFIG_CMD_READ) += cmd_read.o
-COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
-COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o
-COBJS-$(CONFIG_SANDBOX) += cmd_sandbox.o
-COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o
-COBJS-$(CONFIG_CMD_SF) += cmd_sf.o
-COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o
-COBJS-$(CONFIG_CMD_SHA1SUM) += cmd_sha1sum.o
-COBJS-$(CONFIG_CMD_SETEXPR) += cmd_setexpr.o
-COBJS-$(CONFIG_CMD_SOFTSWITCH) += cmd_softswitch.o
-COBJS-$(CONFIG_CMD_SPI) += cmd_spi.o
-COBJS-$(CONFIG_CMD_SPIBOOTLDR) += cmd_spibootldr.o
-COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o
-COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o
-COBJS-$(CONFIG_CMD_TIME) += cmd_time.o
-COBJS-$(CONFIG_CMD_TRACE) += cmd_trace.o
-COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o
-COBJS-$(CONFIG_CMD_TPM) += cmd_tpm.o
-COBJS-$(CONFIG_CMD_TSI148) += cmd_tsi148.o
-COBJS-$(CONFIG_CMD_UBI) += cmd_ubi.o
-COBJS-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o
-COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o
-COBJS-$(CONFIG_CMD_UNZIP) += cmd_unzip.o
ifdef CONFIG_CMD_USB
-COBJS-y += cmd_usb.o
-COBJS-y += usb.o usb_hub.o
-COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o
+obj-y += cmd_usb.o
+obj-y += usb.o usb_hub.o
+obj-$(CONFIG_USB_STORAGE) += usb_storage.o
endif
-COBJS-$(CONFIG_CMD_USB_MASS_STORAGE) += cmd_usb_mass_storage.o
-COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o
-COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o
-COBJS-$(CONFIG_CMD_SPL) += cmd_spl.o
-COBJS-$(CONFIG_CMD_ZIP) += cmd_zip.o
-COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o
+obj-$(CONFIG_CMD_FASTBOOT) += cmd_fastboot.o
+obj-$(CONFIG_CMD_FS_UUID) += cmd_fs_uuid.o
+
+obj-$(CONFIG_CMD_USB_MASS_STORAGE) += cmd_usb_mass_storage.o
+obj-$(CONFIG_CMD_THOR_DOWNLOAD) += cmd_thordown.o
+obj-$(CONFIG_CMD_XIMG) += cmd_ximg.o
+obj-$(CONFIG_YAFFS2) += cmd_yaffs2.o
+obj-$(CONFIG_CMD_SPL) += cmd_spl.o
+obj-$(CONFIG_CMD_ZIP) += cmd_zip.o
+obj-$(CONFIG_CMD_ZFS) += cmd_zfs.o
# others
-COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o
-COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
-COBJS-y += flash.o
-COBJS-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o
-COBJS-$(CONFIG_I2C_EDID) += edid.o
-COBJS-$(CONFIG_KALLSYMS) += kallsyms.o
-COBJS-y += splash.o
-COBJS-$(CONFIG_LCD) += lcd.o
-COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
-COBJS-$(CONFIG_MENU) += menu.o
-COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
-COBJS-$(CONFIG_UPDATE_TFTP) += update.o
-COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
-COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
-COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o
+obj-$(CONFIG_BOOTSTAGE) += bootstage.o
+obj-$(CONFIG_CONSOLE_MUX) += iomux.o
+obj-y += flash.o
+obj-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o
+obj-$(CONFIG_I2C_EDID) += edid.o
+obj-$(CONFIG_KALLSYMS) += kallsyms.o
+obj-y += splash.o
+obj-$(CONFIG_LCD) += lcd.o
+obj-$(CONFIG_LYNXKDI) += lynxkdi.o
+obj-$(CONFIG_MENU) += menu.o
+obj-$(CONFIG_MODEM_SUPPORT) += modem.o
+obj-$(CONFIG_UPDATE_TFTP) += update.o
+obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+obj-$(CONFIG_CMD_DFU) += cmd_dfu.o
+obj-$(CONFIG_CMD_GPT) += cmd_gpt.o
endif
ifdef CONFIG_SPL_BUILD
-COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
-COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
+obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
+obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
+obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
+ifdef CONFIG_SPL_USB_HOST_SUPPORT
+obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o
+obj-$(CONFIG_USB_STORAGE) += usb_storage.o
+endif
+ifdef CONFIG_SPL_SATA_SUPPORT
+obj-$(CONFIG_CMD_SCSI) += cmd_scsi.o
+endif
# environment
-COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
-COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
-COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
-ifneq ($(CONFIG_SPL_NET_SUPPORT),y)
-COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
-COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
-COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
-COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
-COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
-else
-COBJS-y += env_nowhere.o
+ifdef CONFIG_SPL_ENV_SUPPORT
+obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
+obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
+obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
+obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
+obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
+obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o
+obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
+obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
+obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
endif
endif
# core command
-COBJS-y += cmd_nvedit.o
+obj-y += cmd_nvedit.o
#environment
-COBJS-y += env_common.o
+obj-y += env_common.o
#others
-ifdef CONFIG_DDR_SPD
-SPD := y
-endif
-ifdef CONFIG_SPD_EEPROM
-SPD := y
+obj-$(CONFIG_DDR_SPD) += ddr_spd.o
+obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o
+obj-$(CONFIG_HWCONFIG) += hwconfig.o
+obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
+obj-y += console.o
+obj-$(CONFIG_CROS_EC) += cros_ec.o
+obj-y += dlmalloc.o
+ifdef CONFIG_SYS_MALLOC_F_LEN
+obj-y += malloc_simple.o
endif
-COBJS-$(SPD) += ddr_spd.o
-COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
-COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
-COBJS-y += console.o
-COBJS-y += dlmalloc.o
-COBJS-y += image.o
-COBJS-$(CONFIG_OF_LIBFDT) += image-fdt.o
-COBJS-$(CONFIG_FIT) += image-fit.o
-COBJS-$(CONFIG_FIT_SIGNATURE) += image-sig.o
-COBJS-y += memsize.o
-COBJS-y += stdio.o
-
-
-COBJS := $(sort $(COBJS-y))
-XCOBJS := $(sort $(XCOBJS-y))
-SRCS := $(COBJS:.o=.c) $(XCOBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-XOBJS := $(addprefix $(obj),$(XCOBJS))
-
-CPPFLAGS += -I..
-
-all: $(LIB) $(XOBJS)
-
-$(LIB): $(obj).depend $(OBJS)
- $(call cmd_link_o_target, $(OBJS))
-
-$(obj)env_embedded.o: $(src)env_embedded.c $(obj)../tools/envcrc
- $(CC) $(AFLAGS) -Wa,--no-warn \
- -DENV_CRC=$(shell $(obj)../tools/envcrc) \
- -c -o $@ $(src)env_embedded.c
-
-$(obj)../tools/envcrc:
- $(MAKE) -C ../tools
+obj-y += image.o
+obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
+obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
+obj-$(CONFIG_FIT) += image-fit.o
+obj-$(CONFIG_FIT_SIGNATURE) += image-sig.o
+obj-$(CONFIG_IO_TRACE) += iotrace.o
+obj-y += memsize.o
+obj-y += stdio.o
-# SEE README.arm-unaligned-accesses
-$(obj)cmd_bmp.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
-$(obj)fdt_support.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
-$(obj)hush.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
-ifneq ($(CONFIG_CMD_BMP)$(CONFIG_SPLASH_SCREEN),)
-$(obj)lcd.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
+# This option is not just y/n - it can have a numeric value
+ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+obj-y += aboot.o
+obj-y += fb_mmc.o
endif
-#########################################################################
+obj-$(CONFIG_CMD_BLOB) += cmd_blob.o
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
+# We always have this since drivers/ddr/fs/interactive.c needs it
+obj-y += cli_simple.o
-sinclude $(obj).depend
+obj-y += cli.o
+obj-y += cli_readline.o
+obj-y += command.o
+obj-y += s_record.o
+obj-y += xyzModem.o
+obj-y += cmd_disk.o
-#########################################################################
+CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null)
--- /dev/null
-#define UINT_MAX ~0UL
-
+ /*
+ * Copyright (C) 2012 Lothar Waßmann <LW@KARO-electronics.de>
+ * based on: code from RedBoot (C) Uwe Steinkohl <US@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <command.h>
+ #include <net.h>
+ #include <wince.h>
+ #include <nand.h>
+ #include <malloc.h>
+ #include <asm/errno.h>
+ #include <jffs2/load_kernel.h>
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ #define WINCE_VRAM_BASE 0x80000000
+ #define CE_FIX_ADDRESS(a) ((void *)((a) - WINCE_VRAM_BASE + CONFIG_SYS_SDRAM_BASE))
+
+ #ifndef INT_MAX
+ #define INT_MAX ((int)(~0U >> 1))
+ #endif
+
+ /* Bin image parse states */
+ #define CE_PS_RTI_ADDR 0
+ #define CE_PS_RTI_LEN 1
+ #define CE_PS_E_ADDR 2
+ #define CE_PS_E_LEN 3
+ #define CE_PS_E_CHKSUM 4
+ #define CE_PS_E_DATA 5
+
+ #define CE_MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #define CE_MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+ static ce_bin __attribute__ ((aligned (32))) g_bin;
+ static ce_net __attribute__ ((aligned (32))) g_net;
+ static IPaddr_t server_ip;
+
+ static void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer)
+ {
+ memset(bin, 0, sizeof(*bin));
+
+ bin->data = dataBuffer;
+ bin->parseState = CE_PS_RTI_ADDR;
+ bin->parsePtr = (unsigned char *)bin;
+ }
+
+ static int ce_is_bin_image(void *image, int imglen)
+ {
+ if (imglen < CE_BIN_SIGN_LEN) {
+ return 0;
+ }
+
+ return memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0;
+ }
+
+ static const struct ce_magic {
+ char magic[8];
+ size_t size;
+ ce_std_driver_globals drv_glb;
+ } ce_magic_template = {
+ .magic = "KARO_CE6",
+ .size = sizeof(ce_std_driver_globals),
+ .drv_glb = {
+ .header = {
+ .signature = STD_DRV_GLB_SIGNATURE,
+ .oalVersion = 1,
+ .bspVersion = 2,
+ },
+ },
+ };
+
+ #ifdef DEBUG
+ static void __attribute__((unused)) ce_dump_block(void *ptr, int length)
+ {
+ char *p = ptr;
+ int i;
+ int j;
+
+ for (i = 0; i < length; i++) {
+ if (!(i % 16)) {
+ printf("\n%p: ", ptr + i);
+ }
+
+ printf("%02x ", p[i]);
+ if (!((i + 1) % 16)){
+ printf(" ");
+ for (j = i - 15; j <= i; j++){
+ if((p[j] > 0x1f) && (p[j] < 0x7f)) {
+ printf("%c", p[j]);
+ } else {
+ printf(".");
+ }
+ }
+ }
+ }
+ printf("\n");
+ }
+ #else
+ static inline void ce_dump_block(void *ptr, int length)
+ {
+ }
+ #endif
+
+ static void ce_setup_std_drv_globals(ce_std_driver_globals *std_drv_glb)
+ {
+ char *mtdparts = getenv("mtdparts");
+ size_t max_len = ALIGN((unsigned long)std_drv_glb, SZ_4K) -
+ (unsigned long)&std_drv_glb->mtdparts;
+
+ if (eth_get_dev()) {
+ memcpy(&std_drv_glb->kitl.mac, eth_get_dev()->enetaddr,
+ sizeof(std_drv_glb->kitl.mac));
+ }
+ snprintf(std_drv_glb->deviceId, sizeof(std_drv_glb->deviceId),
+ "Triton%02X", eth_get_dev()->enetaddr[5]);
+
+ NetCopyIP(&std_drv_glb->kitl.ipAddress, &NetOurIP);
+ std_drv_glb->kitl.ipMask = getenv_IPaddr("netmask");
+ std_drv_glb->kitl.ipRoute = getenv_IPaddr("gatewayip");
+
+ if (mtdparts) {
+ strncpy(std_drv_glb->mtdparts, mtdparts, max_len);
+ std_drv_glb->mtdparts[max_len - 1] = '\0';
+ } else {
+ printf("Failed to get mtdparts environment variable\n");
+ }
+ }
+
+ static void ce_init_drv_globals(void)
+ {
+ struct ce_magic *ce_magic = (void *)CONFIG_SYS_SDRAM_BASE + 0x160;
+ ce_std_driver_globals *std_drv_glb = &ce_magic->drv_glb;
+
+ debug("Copying CE MAGIC from %p to %p..%p\n",
+ &ce_magic_template, ce_magic,
+ (void *)ce_magic + sizeof(*ce_magic) - 1);
+ memcpy(ce_magic, &ce_magic_template, sizeof(*ce_magic));
+
+ ce_setup_std_drv_globals(std_drv_glb);
+ ce_magic->size = sizeof(*std_drv_glb) +
+ strlen(std_drv_glb->mtdparts) + 1;
+ ce_dump_block(ce_magic, offsetof(struct ce_magic, drv_glb) +
+ ce_magic->size);
+ }
+
+ static void ce_prepare_run_bin(ce_bin *bin)
+ {
+ /* Clear os RAM area (if needed) */
+ if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
+ debug("cleaning memory from %p to %p\n",
+ bin->eRamStart, bin->eRamStart + bin->eRamLen);
+
+ printf("Preparing clean boot ... ");
+ memset(bin->eRamStart, 0, bin->eRamLen);
+ printf("ok\n");
+ }
+
+ ce_init_drv_globals();
+
+ /*
+ * Make sure, all the above makes it into SDRAM because
+ * WinCE switches the cache & MMU off, obviously without
+ * flushing it first!
+ */
+ flush_dcache_all();
+ }
+
+ static int ce_lookup_ep_bin(ce_bin *bin)
+ {
+ ce_rom_hdr *header;
+ ce_toc_entry *tentry;
+ e32_rom *e32;
+ unsigned int i;
+ uint32_t *sig = (uint32_t *)(bin->rtiPhysAddr + ROM_SIGNATURE_OFFSET);
+
+ debug("Looking for TOC signature at %p\n", sig);
+
+ /* Check image Table Of Contents (TOC) signature */
+ if (*sig != ROM_SIGNATURE) {
+ printf("Error: Did not find image TOC signature!\n");
+ printf("Expected %08x at address %p; found %08x instead\n",
+ ROM_SIGNATURE, sig, *sig);
+ return 0;
+ }
+
+ /* Lookup entry point */
+ header = CE_FIX_ADDRESS(*(unsigned int *)(bin->rtiPhysAddr +
+ ROM_SIGNATURE_OFFSET +
+ sizeof(unsigned int)));
+ tentry = (ce_toc_entry *)(header + 1);
+
+ for (i = 0; i < header->nummods; i++) {
+ // Look for 'nk.exe' module
+ if (strcmp(CE_FIX_ADDRESS(tentry[i].fileName), "nk.exe") == 0) {
+ // Save entry point and RAM addresses
+
+ e32 = CE_FIX_ADDRESS(tentry[i].e32Offset);
+
+ bin->eEntryPoint = CE_FIX_ADDRESS(tentry[i].loadOffset) +
+ e32->e32_entryrva;
+ bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
+ bin->eRamLen = header->ramEnd - header->ramStart;
+ return 1;
+ }
+ }
+
+ // Error: Did not find 'nk.exe' module
+ return 0;
+ }
+
+ static int ce_parse_bin(ce_bin *bin)
+ {
+ unsigned char *pbData = bin->data;
+ int len = bin->dataLen;
+ int copyLen;
+
+ debug("starting ce image parsing:\n\tbin->binLen: 0x%08X\n", bin->binLen);
+
+ if (len) {
+ if (bin->binLen == 0) {
+ // Check for the .BIN signature first
+ if (!ce_is_bin_image(pbData, len)) {
+ printf("Error: Invalid or corrupted .BIN image!\n");
+ return CE_PR_ERROR;
+ }
+
+ printf("Loading Windows CE .BIN image ...\n");
+ // Skip signature
+ len -= CE_BIN_SIGN_LEN;
+ pbData += CE_BIN_SIGN_LEN;
+ }
+
+ while (len) {
+ switch (bin->parseState) {
+ case CE_PS_RTI_ADDR:
+ case CE_PS_RTI_LEN:
+ case CE_PS_E_ADDR:
+ case CE_PS_E_LEN:
+ case CE_PS_E_CHKSUM:
+ copyLen = CE_MIN(sizeof(unsigned int) - bin->parseLen, len);
+ memcpy(&bin->parsePtr[bin->parseLen], pbData, copyLen);
+
+ bin->parseLen += copyLen;
+ len -= copyLen;
+ pbData += copyLen;
+
+ if (bin->parseLen == sizeof(unsigned int)) {
+ if (bin->parseState == CE_PS_RTI_ADDR)
+ bin->rtiPhysAddr = CE_FIX_ADDRESS(bin->rtiPhysAddr);
+ else if (bin->parseState == CE_PS_E_ADDR &&
+ bin->ePhysAddr)
+ bin->ePhysAddr = CE_FIX_ADDRESS(bin->ePhysAddr);
+
+ bin->parseState++;
+ bin->parseLen = 0;
+ bin->parsePtr += sizeof(unsigned int);
+
+ if (bin->parseState == CE_PS_E_DATA) {
+ if (bin->ePhysAddr) {
+ bin->parsePtr = bin->ePhysAddr;
+ bin->parseChkSum = 0;
+ } else {
+ /* EOF */
+ len = 0;
+ bin->endOfBin = 1;
+ }
+ }
+ }
+ break;
+
+ case CE_PS_E_DATA:
+ debug("ePhysAddr=%p physlen=%08x parselen=%08x\n",
+ bin->ePhysAddr, bin->ePhysLen, bin->parseLen);
+ if (bin->ePhysAddr) {
+ copyLen = CE_MIN(bin->ePhysLen - bin->parseLen, len);
+ bin->parseLen += copyLen;
+ len -= copyLen;
+
+ while (copyLen--) {
+ bin->parseChkSum += *pbData;
+ *bin->parsePtr++ = *pbData++;
+ }
+
+ if (bin->parseLen == bin->ePhysLen) {
+ printf("Section [%02d]: address %p, size 0x%08X, checksum %s\n",
+ bin->section,
+ bin->ePhysAddr,
+ bin->ePhysLen,
+ (bin->eChkSum == bin->parseChkSum) ? "ok" : "fail");
+
+ if (bin->eChkSum != bin->parseChkSum) {
+ printf("Error: Checksum error, corrupted .BIN file!\n");
+ printf("checksum calculated: 0x%08x from file: 0x%08x\n",
+ bin->parseChkSum, bin->eChkSum);
+ bin->binLen = 0;
+ return CE_PR_ERROR;
+ }
+
+ bin->section++;
+ bin->parseState = CE_PS_E_ADDR;
+ bin->parseLen = 0;
+ bin->parsePtr = (unsigned char *)&bin->ePhysAddr;
+ }
+ } else {
+ bin->parseLen = 0;
+ bin->endOfBin = 1;
+ len = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ if (bin->endOfBin) {
+ if (!ce_lookup_ep_bin(bin)) {
+ printf("Error: entry point not found!\n");
+ bin->binLen = 0;
+ return CE_PR_ERROR;
+ }
+
+ printf("Entry point: %p, address range: %p-%p\n",
+ bin->eEntryPoint,
+ bin->rtiPhysAddr,
+ bin->rtiPhysAddr + bin->rtiPhysLen);
+
+ return CE_PR_EOF;
+ }
+
+ /* Need more data */
+ bin->binLen += bin->dataLen;
+ return CE_PR_MORE;
+ }
+
+ static int ce_bin_load(void *image, int imglen)
+ {
+ ce_init_bin(&g_bin, image);
+ g_bin.dataLen = imglen;
+ if (ce_parse_bin(&g_bin) == CE_PR_EOF) {
+ ce_prepare_run_bin(&g_bin);
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static void ce_run_bin(void (*entry)(void))
+ {
+ printf("Launching Windows CE ...\n");
+ #ifdef TEST_LAUNCH
+ return;
+ #endif
+ entry();
+ }
+
+ static int do_bootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ void *addr;
+ size_t image_size;
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "-i") == 0) {
+ ce_init_drv_globals();
+ return CMD_RET_SUCCESS;
+ }
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ image_size = INT_MAX; /* actually we do not know the image size */
+ } else if (getenv("fileaddr") != NULL) {
+ addr = (void *)getenv_ulong("fileaddr", 16, 0);
+ image_size = getenv_ulong("filesize", 16, INT_MAX);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ printf ("## Booting Windows CE Image from address %p ...\n", addr);
+
+ /* check if there is a valid windows CE image */
+ if (ce_is_bin_image(addr, image_size)) {
+ if (!ce_bin_load(addr, image_size)) {
+ /* Ops! Corrupted .BIN image! */
+ /* Handle error here ... */
+ printf("corrupted .BIN image !!!\n");
+ return CMD_RET_FAILURE;
+ }
+ if (getenv_yesno("autostart") != 1) {
+ /*
+ * just use bootce to load the image to SDRAM;
+ * Do not start it automatically.
+ */
+ setenv_addr("fileaddr", g_bin.eEntryPoint);
+ return CMD_RET_SUCCESS;
+ }
+ ce_run_bin(g_bin.eEntryPoint); /* start the image */
+ } else {
+ printf("Image does not seem to be a valid Windows CE image!\n");
+ return CMD_RET_FAILURE;
+ }
+ return CMD_RET_FAILURE; /* never reached - just to keep compiler happy */
+ }
+ U_BOOT_CMD(
+ bootce, 2, 0, do_bootce,
+ "Boot a Windows CE image from RAM",
+ "[addr]\n"
+ "\taddr\t\tboot image from address addr (default ${fileaddr})\n"
+ "or\n"
+ "\t-i\t\tinitialize the WinCE globals data structure (before loading a .nb0 image)"
+ );
+
+ #ifdef CONFIG_CMD_NAND
+ static int ce_nand_load(ce_bin *bin, loff_t *offset, void *buf, size_t max_len)
+ {
+ int ret;
+ size_t len = max_len;
+ nand_info_t *nand = &nand_info[0];
+
+ while (nand_block_isbad(nand, *offset & ~(max_len - 1))) {
+ printf("Skipping bad block 0x%08llx\n",
+ *offset & ~(max_len - 1));
+ *offset += max_len;
+ if (*offset + max_len > nand->size)
+ return -EINVAL;
+ }
+
+ ret = nand_read(nand, *offset, &len, buf);
+ if (ret < 0)
+ return ret;
+
+ bin->dataLen = len;
+ return len;
+ }
+
+ static int do_nbootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int ret;
+ struct mtd_device *dev;
+ struct part_info *part_info;
+ u8 part_num;
+ loff_t offset;
+ char *end;
+ void *buffer;
+ size_t bufsize = nand_info[0].erasesize, len;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ ret = mtdparts_init();
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ offset = simple_strtoul(argv[1], &end, 16);
+ if (*end != '\0') {
+ ret = find_dev_and_part(argv[1], &dev, &part_num,
+ &part_info);
+ if (ret != 0) {
+ printf("Partition '%s' not found\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+ offset = part_info->offset;
+ printf ("## Booting Windows CE Image from NAND partition %s at offset %08llx\n",
+ argv[1], offset);
+ } else {
+ printf ("## Booting Windows CE Image from NAND offset %08llx\n",
+ offset);
+ }
+
+ buffer = malloc(bufsize);
+ if (buffer == NULL) {
+ printf("Failed to allocate %u byte buffer\n", bufsize);
+ return CMD_RET_FAILURE;
+ }
+
+ ce_init_bin(&g_bin, buffer);
+
+ ret = ce_nand_load(&g_bin, &offset, buffer, bufsize);
+ if (ret < 0) {
+ printf("Failed to read NAND: %d\n", ret);
+ goto err;
+ }
+ len = ret;
+ /* check if there is a valid windows CE image header */
+ if (ce_is_bin_image(buffer, len)) {
+ do {
+ ret = ce_parse_bin(&g_bin);
+ switch (ret) {
+ case CE_PR_MORE:
+ {
+ if (ctrlc()) {
+ printf("NBOOTCE - canceled by user\n");
+ goto err;
+ }
+ offset += len;
+ len = ce_nand_load(&g_bin, &offset, buffer,
+ bufsize);
+ if (len < 0) {
+ printf("Nand read error: %d\n", len);
+ ret = len;
+ goto err;
+ }
+ }
+ break;
+
+ case CE_PR_EOF:
+ ce_prepare_run_bin(&g_bin);
+ break;
+
+ case CE_PR_ERROR:
+ break;
+ }
+ } while (ret == CE_PR_MORE);
+ free(buffer);
+ if (ret != CE_PR_EOF)
+ return CMD_RET_FAILURE;
+
+ if (getenv_yesno("autostart") != 1) {
+ /*
+ * just use bootce to load the image to SDRAM;
+ * Do not start it automatically.
+ */
+ setenv_addr("fileaddr", g_bin.eEntryPoint);
+ return CMD_RET_SUCCESS;
+ }
+ ce_run_bin(g_bin.eEntryPoint); /* start the image */
+ } else {
+ printf("Image does not seem to be a valid Windows CE image!\n");
+ }
+ err:
+ free(buffer);
+ return CMD_RET_FAILURE;
+ }
+ U_BOOT_CMD(
+ nbootce, 2, 0, do_nbootce,
+ "Boot a Windows CE image from NAND",
+ "off|partitition\n"
+ "\toff\t\t- flash offset (hex)\n"
+ "\tpartition\t- partition name"
+ );
+ #endif
+
+ static int ce_send_write_ack(ce_net *net)
+ {
+ int ret;
+ unsigned short wdata[2];
+ int retries = 0;
+
+ wdata[0] = htons(EDBG_CMD_WRITE_ACK);
+ wdata[1] = htons(net->blockNum);
+ net->dataLen = sizeof(wdata);
+ memcpy(net->data, wdata, net->dataLen);
+
+ do {
+ ret = bootme_send_frame(net->data, net->dataLen);
+ if (ret) {
+ printf("Failed to send write ack %d; retries=%d\n",
+ ret, retries);
+ }
+ } while (ret != 0 && retries-- > 0);
+ return ret;
+ }
+
+ static enum bootme_state ce_process_download(ce_net *net, ce_bin *bin)
+ {
+ int ret = net->state;
+
+ if (net->dataLen >= 4) {
+ unsigned short command;
+ unsigned short blknum;
+
+ memcpy(&command, net->data, sizeof(command));
+ command = ntohs(command);
+ debug("command found: 0x%04X\n", command);
+
+ if (net->state == BOOTME_DOWNLOAD) {
+ unsigned short nxt = net->blockNum + 1;
+
+ memcpy(&blknum, &net->data[2], sizeof(blknum));
+ blknum = ntohs(blknum);
+ if (blknum == nxt) {
+ net->blockNum = blknum;
+ } else {
+ int rc = ce_send_write_ack(net);
+
+ if (net->verbose)
+ printf("Dropping out of sequence packet with ID %d (expected %d)\n",
+ blknum, nxt);
+ if (rc != 0)
+ return rc;
+
+ return ret;
+ }
+ }
+
+ switch (command) {
+ case EDBG_CMD_WRITE_REQ:
+ if (net->state == BOOTME_INIT) {
+ // Check file name for WRITE request
+ // CE EShell uses "boot.bin" file name
+ if (strncmp((char *)&net->data[2],
+ "boot.bin", 8) == 0) {
+ // Some diag output
+ if (net->verbose) {
+ printf("Locked Down download link, IP: %pI4\n",
+ &NetServerIP);
+ printf("Sending BOOTME request [%d] to %pI4\n",
+ net->seqNum, &NetServerIP);
+ }
+
+ // Lock down EShell download link
+ ret = BOOTME_DOWNLOAD;
+ } else {
+ // Unknown link
+ printf("Unknown link\n");
+ }
+
+ if (ret == BOOTME_DOWNLOAD) {
+ int rc = ce_send_write_ack(net);
+ if (rc != 0)
+ return rc;
+ }
+ }
+ break;
+
+ case EDBG_CMD_WRITE:
+ /* Fixup data len */
+ bin->data = &net->data[4];
+ bin->dataLen = net->dataLen - 4;
+ ret = ce_parse_bin(bin);
+ if (ret != CE_PR_ERROR) {
+ int rc = ce_send_write_ack(net);
+ if (rc)
+ return rc;
+ if (ret == CE_PR_EOF)
+ ret = BOOTME_DONE;
+ } else {
+ ret = BOOTME_ERROR;
+ }
+ break;
+
+ case EDBG_CMD_READ_REQ:
+ printf("Ignoring EDBG_CMD_READ_REQ\n");
+ /* Read requests are not supported
+ * Do nothing ...
+ */
+ break;
+
+ case EDBG_CMD_ERROR:
+ printf("Error: unknown error on the host side\n");
+
+ bin->binLen = 0;
+ ret = BOOTME_ERROR;
+ break;
+
+ default:
+ printf("unknown command 0x%04X\n", command);
+ net->state = BOOTME_ERROR;
+ }
+ }
+ return ret;
+ }
+
+ static enum bootme_state ce_process_edbg(ce_net *net, ce_bin *bin)
+ {
+ enum bootme_state ret = net->state;
+ eth_dbg_hdr header;
+
+ if (net->dataLen < sizeof(header)) {
+ /* Bad packet */
+ printf("Invalid packet size %u\n", net->dataLen);
+ net->dataLen = 0;
+ return ret;
+ }
+ memcpy(&header, net->data, sizeof(header));
+ if (header.id != EDBG_ID) {
+ /* Bad packet */
+ printf("Bad EDBG ID %08x\n", header.id);
+ net->dataLen = 0;
+ return ret;
+ }
+
+ if (header.service != EDBG_SVC_ADMIN) {
+ /* Unknown service */
+ printf("Bad EDBG service %02x\n", header.service);
+ net->dataLen = 0;
+ return ret;
+ }
+
+ if (net->state == BOOTME_INIT) {
+ /* Some diag output */
+ if (net->verbose) {
+ printf("Locked Down EDBG service link, IP: %pI4\n",
+ &NetServerIP);
+ }
+
+ /* Lock down EDBG link */
+ net->state = BOOTME_DEBUG;
+ }
+
+ switch (header.cmd) {
+ case EDBG_CMD_JUMPIMG:
+ net->gotJumpingRequest = 1;
+
+ if (net->verbose) {
+ printf("Received JUMPING command\n");
+ }
+ /* Just pass through and copy CONFIG structure */
+ ret = BOOTME_DONE;
+ case EDBG_CMD_OS_CONFIG:
+ /* Copy config structure */
+ memcpy(&bin->edbgConfig, &net->data[sizeof(header)],
+ sizeof(edbg_os_config_data));
+ if (net->verbose) {
+ printf("Received CONFIG command\n");
+ if (bin->edbgConfig.flags & EDBG_FL_DBGMSG) {
+ printf("--> Enabling DBGMSG service, IP: %pI4, port: %d\n",
+ &bin->edbgConfig.dbgMsgIPAddr,
+ ntohs(bin->edbgConfig.dbgMsgPort));
+ }
+
+ if (bin->edbgConfig.flags & EDBG_FL_PPSH) {
+ printf("--> Enabling PPSH service, IP: %pI4, port: %d\n",
+ &bin->edbgConfig.ppshIPAddr,
+ ntohs(bin->edbgConfig.ppshPort));
+ }
+
+ if (bin->edbgConfig.flags & EDBG_FL_KDBG) {
+ printf("--> Enabling KDBG service, IP: %pI4, port: %d\n",
+ &bin->edbgConfig.kdbgIPAddr,
+ ntohs(bin->edbgConfig.kdbgPort));
+ }
+
+ if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
+ printf("--> Force clean boot\n");
+ }
+ }
+ break;
+
+ default:
+ if (net->verbose) {
+ printf("Received unknown command: %08X\n", header.cmd);
+ }
+ return BOOTME_ERROR;
+ }
+
+ /* Respond with ack */
+ header.flags = EDBG_FL_FROM_DEV | EDBG_FL_ACK;
+ memcpy(net->data, &header, sizeof(header));
+ net->dataLen = EDBG_DATA_OFFSET;
+
+ int retries = 10;
+ int rc;
+ do {
+ rc = bootme_send_frame(net->data, net->dataLen);
+ if (rc != 0) {
+ printf("Failed to send ACK: %d\n", rc);
+ }
+ } while (rc && retries-- > 0);
+ return rc ?: ret;
+ }
+
+ static enum bootme_state ce_edbg_handler(const void *buf, size_t len)
+ {
+ if (len == 0)
+ return BOOTME_DONE;
+
+ g_net.data = (void *)buf;
+ g_net.dataLen = len;
+
+ return ce_process_edbg(&g_net, &g_bin);
+ }
+
+ static void ce_init_edbg_link(ce_net *net)
+ {
+ /* Initialize EDBG link for commands */
+ net->state = BOOTME_INIT;
+ }
+
+ static enum bootme_state ce_download_handler(const void *buf, size_t len)
+ {
+ g_net.data = (void *)buf;
+ g_net.dataLen = len;
+
+ g_net.state = ce_process_download(&g_net, &g_bin);
+ return g_net.state;
+ }
+
+ static int ce_send_bootme(ce_net *net)
+ {
+ eth_dbg_hdr *header;
+ edbg_bootme_data *data;
+ unsigned char txbuf[PKTSIZE_ALIGN];
+ #ifdef DEBUG
+ int i;
+ unsigned char *pkt;
+ #endif
+ /* Fill out BOOTME packet */
+ net->data = txbuf;
+
+ memset(net->data, 0, PKTSIZE);
+ header = (eth_dbg_hdr *)net->data;
+ data = (edbg_bootme_data *)header->data;
+
+ header->id = EDBG_ID;
+ header->service = EDBG_SVC_ADMIN;
+ header->flags = EDBG_FL_FROM_DEV;
+ header->seqNum = net->seqNum++;
+ header->cmd = EDBG_CMD_BOOTME;
+
+ data->versionMajor = 0;
+ data->versionMinor = 0;
+ data->cpuId = EDBG_CPU_TYPE_ARM;
+ data->bootmeVer = EDBG_CURRENT_BOOTME_VERSION;
+ data->bootFlags = 0;
+ data->downloadPort = 0;
+ data->svcPort = 0;
+
+ /* MAC address from environment*/
+ if (!eth_getenv_enetaddr("ethaddr", data->macAddr)) {
+ printf("'ethaddr' is not set or invalid\n");
+ memset(data->macAddr, 0, sizeof(data->macAddr));
+ }
+
+ /* IP address from active config */
+ NetCopyIP(&data->ipAddr, &NetOurIP);
+
+ // Device name string (NULL terminated). Should include
+ // platform and number based on Ether address (e.g. Odo42, CEPCLS2346, etc)
+
+ // We will use lower MAC address segment to create device name
+ // eg. MAC '00-0C-C6-69-09-05', device name 'Triton05'
+
+ strncpy(data->platformId, "Triton", sizeof(data->platformId));
+ snprintf(data->deviceName, sizeof(data->deviceName), "%s%02X",
+ data->platformId, data->macAddr[5]);
+
+ #ifdef DEBUG
+ printf("header->id: %08X\n", header->id);
+ printf("header->service: %08X\n", header->service);
+ printf("header->flags: %08X\n", header->flags);
+ printf("header->seqNum: %08X\n", header->seqNum);
+ printf("header->cmd: %08X\n\n", header->cmd);
+
+ printf("data->versionMajor: %08X\n", data->versionMajor);
+ printf("data->versionMinor: %08X\n", data->versionMinor);
+ printf("data->cpuId: %08X\n", data->cpuId);
+ printf("data->bootmeVer: %08X\n", data->bootmeVer);
+ printf("data->bootFlags: %08X\n", data->bootFlags);
+ printf("data->svcPort: %08X\n\n", ntohs(data->svcPort));
+
+ printf("data->macAddr: %pM\n", data->macAddr);
+ printf("data->ipAddr: %pI4\n", &data->ipAddr);
+ printf("data->platformId: %s\n", data->platformId);
+ printf("data->deviceName: %s\n", data->deviceName);
+ #endif
+ // Some diag output ...
+ if (net->verbose) {
+ printf("Sending BOOTME request [%d] to %pI4\n", net->seqNum,
+ &server_ip);
+ }
+
+ net->dataLen = BOOTME_PKT_SIZE;
+ // net->status = CE_PR_MORE;
+ net->state = BOOTME_INIT;
+ #ifdef DEBUG
+ debug("Start of buffer: %p\n", net->data);
+ debug("Start of ethernet buffer: %p\n", net->data);
+ debug("Start of CE header: %p\n", header);
+ debug("Start of CE data: %p\n", data);
+
+ pkt = net->data;
+ debug("packet to send (ceconnect): \n");
+ for (i = 0; i < net->dataLen; i++) {
+ debug("0x%02X ", pkt[i]);
+ if (!((i + 1) % 16))
+ debug("\n");
+ }
+ debug("\n");
+ #endif
+ return BootMeRequest(server_ip, net->data, net->dataLen, 1);
+ }
+
+ static inline int ce_init_download_link(ce_net *net, ce_bin *bin, int verbose)
+ {
+ if (!eth_get_dev()) {
+ printf("No network interface available\n");
+ return -ENODEV;
+ }
+ printf("Using device '%s'\n", eth_get_name());
+
+ /* Initialize EDBG link for download */
+ memset(net, 0, sizeof(*net));
+
+ net->verbose = verbose;
+
+ /* buffer will be dynamically assigned in ce_download_handler() */
+ ce_init_bin(bin, NULL);
+ return 0;
+ }
+
- printf("Timeout value %lu out of range (max.: %lu)\n",
+ static inline int ce_download_file(ce_net *net, ulong timeout)
+ {
+ ulong start = get_timer_masked();
+
+ while (net->state == BOOTME_INIT) {
+ int ret;
+
+ if (timeout && get_timer(start) > timeout) {
+ printf("CELOAD - Canceled, timeout\n");
+ return 1;
+ }
+
+ if (ctrlc()) {
+ printf("CELOAD - canceled by user\n");
+ return 1;
+ }
+
+ if (ce_send_bootme(&g_net)) {
+ printf("CELOAD - error while sending BOOTME request\n");
+ return 1;
+ }
+ if (net->verbose) {
+ if (timeout) {
+ printf("Waiting for connection, timeout %lu sec\n",
+ DIV_ROUND_UP(timeout - get_timer(start),
+ CONFIG_SYS_HZ));
+ } else {
+ printf("Waiting for connection, enter ^C to abort\n");
+ }
+ }
+
+ ret = BootMeDownload(ce_download_handler);
+ if (ret == BOOTME_ERROR) {
+ printf("CELOAD - aborted\n");
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ static void ce_disconnect(void)
+ {
+ net_set_udp_handler(NULL);
+ eth_halt();
+ }
+
+ static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ int verbose = 0;
+ ulong timeout = 0;
+ int ret = 1;
+ int i;
+
+ server_ip = 0;
+
+ for (i = 1; i < argc; i++){
+ if (*argv[i] != '-')
+ break;
+ if (argv[i][1] == 'v') {
+ verbose = 1;
+ } else if (argv[i][1] == 't') {
+ i++;
+ if (argc > i) {
+ timeout = simple_strtoul(argv[i],
+ NULL, 0);
+ if (timeout >= UINT_MAX / CONFIG_SYS_HZ) {
++ printf("Timeout value %lu out of range (max.: %u)\n",
+ timeout, UINT_MAX / CONFIG_SYS_HZ - 1);
+ return CMD_RET_USAGE;
+ }
+ timeout *= CONFIG_SYS_HZ;
+ } else {
+ printf("Option requires an argument - t\n");
+ return CMD_RET_USAGE;
+ }
+ } else if (argv[i][1] == 'h') {
+ i++;
+ if (argc > i) {
+ server_ip = string_to_ip(argv[i]);
+ printf("Using server %pI4\n", &server_ip);
+ } else {
+ printf("Option requires an argument - h\n");
+ return CMD_RET_USAGE;
+ }
+ }
+ }
+
+ if (ce_init_download_link(&g_net, &g_bin, verbose) != 0)
+ goto err;
+
+ if (ce_download_file(&g_net, timeout))
+ goto err;
+
+ if (g_bin.binLen) {
+ // Try to receive edbg commands from host
+ ce_init_edbg_link(&g_net);
+ if (verbose)
+ printf("Waiting for EDBG commands ...\n");
+
+ ret = BootMeDebugStart(ce_edbg_handler);
+ if (ret != BOOTME_DONE)
+ goto err;
+
+ // Prepare WinCE image for execution
+ ce_prepare_run_bin(&g_bin);
+
+ // Launch WinCE, if necessary
+ if (g_net.gotJumpingRequest)
+ ce_run_bin(g_bin.eEntryPoint);
+ }
+ ret = 0;
+ err:
+ ce_disconnect();
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+ }
+ U_BOOT_CMD(
+ ceconnect, 6, 1, do_ceconnect,
+ "Set up a connection to the CE host PC over TCP/IP and download the run-time image",
+ "[-v] [-t <timeout>] [-h host]\n"
+ " -v - verbose operation\n"
+ " -t <timeout> - max wait time (#sec) for the connection\n"
+ " -h <host> - send BOOTME requests to <host> (default: broadcast address 255.255.255.255)"
+ );
#include <common.h>
#include <malloc.h>
#include <command.h>
-#include <mmc.h>
#include <part_efi.h>
#include <exports.h>
#include <linux/ctype.h>
*
* @return - zero on successful expand and env is set
*/
-static char extract_env(const char *str, char **env)
+static int extract_env(const char *str, char **env)
{
+ int ret = -1;
char *e, *s;
+#ifdef CONFIG_RANDOM_UUID
+ char uuid_str[UUID_STR_LEN + 1];
+#endif
if (!str || strlen(str) < 4)
return -1;
- if ((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')) {
- s = strdup(str);
- if (s == NULL)
- return -1;
- memset(s + strlen(s) - 1, '\0', 1);
- memmove(s, s + 2, strlen(s) - 1);
+ if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')))
+ return -1;
+
+ s = strdup(str);
+ if (s == NULL)
+ return -1;
+
+ memset(s + strlen(s) - 1, '\0', 1);
+ memmove(s, s + 2, strlen(s) - 1);
+
+ e = getenv(s);
+ if (e == NULL) {
+#ifdef CONFIG_RANDOM_UUID
+ debug("%s unset. ", str);
+ gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_STD);
+ setenv(s, uuid_str);
+
e = getenv(s);
- free(s);
- if (e == NULL) {
- printf("Environmental '%s' not set\n", str);
- return -1; /* env not set */
+ if (e) {
+ debug("Set to random.\n");
+ ret = 0;
+ } else {
+ debug("Can't get random UUID.\n");
}
- *env = e;
- return 0;
+#else
+ debug("%s unset.\n", str);
+#endif
+ } else {
+ debug("%s get from environment.\n", str);
+ ret = 0;
}
- return -1;
+ *env = e;
+ free(s);
+
+ return ret;
}
/**
char *val, *p;
int p_count;
disk_partition_t *parts;
+ char *guid_str;
int errno = 0;
uint64_t size_ll, start_ll;
- debug("%s: MMC lba num: 0x%x %d\n", __func__,
+ debug("%s: lba num: 0x%x %d\n", __func__,
(unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
if (str_part == NULL)
tok = strsep(&s, ";");
val = extract_val(tok, "uuid_disk");
if (!val) {
- free(str);
- return -2;
+ errno = -2;
+ goto free_str;
}
- if (extract_env(val, &p))
- p = val;
- *str_disk_guid = strdup(p);
+ if (extract_env(val, &p) == 0)
+ guid_str = strdup(p);
+ else
+ guid_str = strdup(val);
+
free(val);
- if (strlen(s) == 0)
- return -3;
+ if (strlen(s) == 0) {
+ errno = -3;
+ goto free_guid;
+ }
i = strlen(s) - 1;
if (s[i] == ';')
/* allocate memory for partitions */
parts = calloc(sizeof(disk_partition_t), p_count);
- /* retrive partions data from string */
+ /* retrieve partitions data from string */
for (i = 0; i < p_count; i++) {
tok = strsep(&s, ";");
}
}
+ *str_disk_guid = guid_str;
*parts_count = p_count;
*partitions = parts;
free(str);
return 0;
+
err:
- free(str);
- free(*str_disk_guid);
free(parts);
+ free_guid:
+ free(guid_str);
+ free_str:
+ free(str);
+ *str_disk_guid = NULL;
+ *parts_count = 0;
+ *partitions = NULL;
return errno;
}
-static int gpt_mmc_default(int dev, const char *str_part)
+static int gpt_default(block_dev_desc_t *blk_dev_desc, const char *str_part)
{
int ret;
char *str_disk_guid;
u8 part_count = 0;
disk_partition_t *partitions = NULL;
- struct mmc *mmc = find_mmc_device(dev);
-
- if (mmc == NULL) {
- printf("%s: mmc dev %d NOT available\n", __func__, dev);
- return CMD_RET_FAILURE;
- }
-
if (!str_part)
return -1;
/* fill partitions */
- ret = set_gpt_info(&mmc->block_dev, str_part,
+ ret = set_gpt_info(blk_dev_desc, str_part,
&str_disk_guid, &partitions, &part_count);
if (ret) {
if (ret == -1)
}
/* save partitions layout to disk */
- gpt_restore(&mmc->block_dev, str_disk_guid, partitions, part_count);
+ gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count);
free(str_disk_guid);
free(partitions);
{
int ret = CMD_RET_SUCCESS;
int dev = 0;
- char *pstr;
+ char *ep;
+ block_dev_desc_t *blk_dev_desc;
if (argc < 5)
return CMD_RET_USAGE;
/* command: 'write' */
if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
- /* device: 'mmc' */
- if (strcmp(argv[2], "mmc") == 0) {
- /* check if 'dev' is a number */
- for (pstr = argv[3]; *pstr != '\0'; pstr++)
- if (!isdigit(*pstr)) {
- printf("'%s' is not a number\n",
- argv[3]);
- return CMD_RET_USAGE;
- }
- dev = (int)simple_strtoul(argv[3], NULL, 10);
- /* write to mmc */
- if (gpt_mmc_default(dev, argv[4]))
- return CMD_RET_FAILURE;
+ dev = (int)simple_strtoul(argv[3], &ep, 10);
+ if (!ep || ep[0] != '\0') {
+ printf("'%s' is not a number\n", argv[3]);
+ return CMD_RET_USAGE;
+ }
+ blk_dev_desc = get_dev(argv[2], dev);
+ if (!blk_dev_desc) {
+ printf("%s: %s dev %d NOT available\n",
+ __func__, argv[2], dev);
+ return CMD_RET_FAILURE;
+ }
+
+ puts("Writing GPT: ");
+
+ ret = gpt_default(blk_dev_desc, argv[4]);
+ if (!ret) {
+ puts("success!\n");
+ return CMD_RET_SUCCESS;
+ } else {
+ puts("error!\n");
+ return CMD_RET_FAILURE;
}
} else {
return CMD_RET_USAGE;
U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
"GUID Partition Table",
- "<command> <interface> <dev> <partions_list>\n"
+ "<command> <interface> <dev> <partitions_list>\n"
" - GUID partition table restoration\n"
" Restore GPT information on a device connected\n"
" to interface\n"
if (mmc_legacy_init(dev) != 0) {
puts("No MMC card found\n");
- return 1;
+ return CMD_RET_FAILURE;
}
curr_device = dev;
if (argc == 2) {
if (curr_device < 0) {
puts("No MMC device available\n");
- return 1;
+ return CMD_RET_FAILURE;
}
} else if (argc == 3) {
dev = (int)simple_strtoul(argv[2], NULL, 10);
#ifdef CONFIG_SYS_MMC_SET_DEV
if (mmc_set_dev(dev) != 0)
- return 1;
+ return CMD_RET_FAILURE;
#endif
curr_device = dev;
} else {
return CMD_RET_USAGE;
}
- return 0;
+ return CMD_RET_SUCCESS;
}
U_BOOT_CMD(
);
#else /* !CONFIG_GENERIC_MMC */
-enum mmc_state {
- MMC_INVALID,
- MMC_READ,
- MMC_WRITE,
- MMC_ERASE,
-};
static void print_mmcinfo(struct mmc *mmc)
{
- printf("Device: %s\n", mmc->name);
+ printf("Device: %s\n", mmc->cfg->name);
printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
puts("Capacity: ");
print_size(mmc->capacity, "\n");
- printf("Bus Width: %d-bit\n", mmc->bus_width);
+ printf("Bus Width: %d-bit%s\n", mmc->bus_width,
+ mmc->ddr_mode ? " DDR" : "");
+}
+static struct mmc *init_mmc_device(int dev, bool force_init)
+{
+ struct mmc *mmc;
+ mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("no mmc device at slot %x\n", dev);
+ return NULL;
+ }
+ if (force_init)
+ mmc->has_init = 0;
+ if (mmc_init(mmc))
+ return NULL;
+ return mmc;
}
-
static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct mmc *mmc;
curr_device = 0;
else {
puts("No MMC device available\n");
- return 1;
+ return CMD_RET_FAILURE;
}
}
- mmc = find_mmc_device(curr_device);
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
- if (mmc) {
- mmc_init(mmc);
+ print_mmcinfo(mmc);
+ return CMD_RET_SUCCESS;
+}
- print_mmcinfo(mmc);
- return CMD_RET_SUCCESS;
- } else {
- printf("no mmc device at slot %x\n", curr_device);
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+static int confirm_key_prog(void)
+{
+ puts("Warning: Programming authentication key can be done only once !\n"
+ " Use this command only if you are sure of what you are doing,\n"
+ "Really perform the key programming? <y/N> ");
+ if (confirm_yesno())
+ return 1;
+
+ puts("Authentication key programming aborted\n");
+ return 0;
+}
+static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ void *key_addr;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ if (!confirm_key_prog())
+ return CMD_RET_FAILURE;
+ if (mmc_rpmb_set_key(mmc, key_addr)) {
+ printf("ERROR - Key already programmed ?\n");
return CMD_RET_FAILURE;
}
+ return CMD_RET_SUCCESS;
}
+static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ u16 blk, cnt;
+ void *addr;
+ int n;
+ void *key_addr = NULL;
+ struct mmc *mmc = find_mmc_device(curr_device);
-U_BOOT_CMD(
- mmcinfo, 1, 0, do_mmcinfo,
- "display MMC info",
- "- display info of the current MMC device"
-);
+ if (argc < 4)
+ return CMD_RET_USAGE;
-#ifdef CONFIG_SUPPORT_EMMC_BOOT
-static int boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+
+ if (argc == 5)
+ key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
+
+ printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+ n = mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
+
+ printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+ if (n != cnt)
+ return CMD_RET_FAILURE;
+ return CMD_RET_SUCCESS;
+}
+static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
{
- int err;
- err = mmc_boot_part_access(mmc, ack, part_num, access);
+ u16 blk, cnt;
+ void *addr;
+ int n;
+ void *key_addr;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
- if ((err == 0) && (access != 0)) {
- printf("Notice!\n");
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+ key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
- printf("You must close EMMC boot Partition after all images are written\n");
- printf("EMMC boot partition has continuity at image writing time.\n");
- printf("So, do not close the boot partition before all images are written.\n");
- return CMD_RET_SUCCESS;
- } else if ((err == 0) && (access == 0))
+ printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+ n = mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
+
+ printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+ if (n != cnt)
+ return CMD_RET_FAILURE;
+ return CMD_RET_SUCCESS;
+}
+static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ unsigned long counter;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (mmc_rpmb_get_counter(mmc, &counter))
+ return CMD_RET_FAILURE;
+ printf("RPMB Write counter= %lx\n", counter);
+ return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_rpmb[] = {
+ U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
+ U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
+ U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
+};
+
+static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ cmd_tbl_t *cp;
+ struct mmc *mmc;
+ char original_part;
+ int ret;
+
+ cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
+
+ /* Drop the rpmb subcommand */
+ argc--;
+ argv++;
+
+ if (cp == NULL || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
return CMD_RET_SUCCESS;
- else if ((err != 0) && (access != 0)) {
- printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
return CMD_RET_FAILURE;
- } else {
- printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+
+ if (!(mmc->version & MMC_VERSION_MMC)) {
+ printf("It is not a EMMC device\n");
+ return CMD_RET_FAILURE;
+ }
+ if (mmc->version < MMC_VERSION_4_41) {
+ printf("RPMB not supported before version 4.41\n");
return CMD_RET_FAILURE;
}
+ /* Switch to the RPMB partition */
+ original_part = mmc->part_num;
+ if (mmc->part_num != MMC_PART_RPMB) {
+ if (mmc_switch_part(curr_device, MMC_PART_RPMB) != 0)
+ return CMD_RET_FAILURE;
+ mmc->part_num = MMC_PART_RPMB;
+ }
+ ret = cp->cmd(cmdtp, flag, argc, argv);
+
+ /* Return to original partition */
+ if (mmc->part_num != original_part) {
+ if (mmc_switch_part(curr_device, original_part) != 0)
+ return CMD_RET_FAILURE;
+ mmc->part_num = original_part;
+ }
+ return ret;
}
#endif
-static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
{
- enum mmc_state state;
+ struct mmc *mmc;
+ u32 blk, cnt, n;
+ void *addr;
- if (argc < 2)
+ if (argc != 4)
return CMD_RET_USAGE;
- if (curr_device < 0) {
- if (get_mmc_num() > 0)
- curr_device = 0;
- else {
- puts("No MMC device available\n");
- return CMD_RET_FAILURE;
- }
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC read: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+
+ n = mmc->block_dev.block_read(curr_device, blk, cnt, addr);
+ /* flush cache after read */
+ flush_cache((ulong)addr, cnt * 512); /* FIXME */
+ printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+
+ return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct mmc *mmc;
+ u32 blk, cnt, n;
+ void *addr;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC write: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return CMD_RET_FAILURE;
}
+ n = mmc->block_dev.block_write(curr_device, blk, cnt, addr);
+ printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
- if (strcmp(argv[1], "rescan") == 0) {
- struct mmc *mmc;
+ return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct mmc *mmc;
+ u32 blk, cnt, n;
- if (argc != 2)
- return CMD_RET_USAGE;
+ if (argc != 3)
+ return CMD_RET_USAGE;
- mmc = find_mmc_device(curr_device);
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return CMD_RET_FAILURE;
- }
+ blk = simple_strtoul(argv[1], NULL, 16);
+ cnt = simple_strtoul(argv[2], NULL, 16);
- mmc->has_init = 0;
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
- if (mmc_init(mmc))
- return CMD_RET_FAILURE;
- else
- return CMD_RET_SUCCESS;
- } else if (strncmp(argv[1], "part", 4) == 0) {
- block_dev_desc_t *mmc_dev;
- struct mmc *mmc;
+ printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
- if (argc != 2)
- return CMD_RET_USAGE;
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return CMD_RET_FAILURE;
+ }
+ n = mmc->block_dev.block_erase(curr_device, blk, cnt);
+ printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
- mmc = find_mmc_device(curr_device);
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return CMD_RET_FAILURE;
- }
- mmc_init(mmc);
- mmc_dev = mmc_get_dev(curr_device);
- if (mmc_dev != NULL &&
- mmc_dev->type != DEV_TYPE_UNKNOWN) {
- print_part(mmc_dev);
- return CMD_RET_SUCCESS;
- }
+ return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct mmc *mmc;
- puts("get mmc type error!\n");
+ mmc = init_mmc_device(curr_device, true);
+ if (!mmc)
return CMD_RET_FAILURE;
- } else if (strcmp(argv[1], "list") == 0) {
- if (argc != 2)
- return CMD_RET_USAGE;
- print_mmc_devices('\n');
+
+ return CMD_RET_SUCCESS;
+}
+static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ block_dev_desc_t *mmc_dev;
+ struct mmc *mmc;
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ mmc_dev = mmc_get_dev(curr_device);
+ if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
+ print_part(mmc_dev);
return CMD_RET_SUCCESS;
- } else if (strcmp(argv[1], "dev") == 0) {
- int dev, part = -1;
- struct mmc *mmc;
-
- if (argc == 2)
- dev = curr_device;
- else if (argc == 3)
- dev = simple_strtoul(argv[2], NULL, 10);
- else if (argc == 4) {
- dev = (int)simple_strtoul(argv[2], NULL, 10);
- part = (int)simple_strtoul(argv[3], NULL, 10);
- if (part > PART_ACCESS_MASK) {
- printf("#part_num shouldn't be larger"
- " than %d\n", PART_ACCESS_MASK);
- return CMD_RET_FAILURE;
- }
- } else
- return CMD_RET_USAGE;
+ }
- mmc = find_mmc_device(dev);
- if (!mmc) {
- printf("no mmc device at slot %x\n", dev);
+ puts("get mmc type error!\n");
+ return CMD_RET_FAILURE;
+}
+static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int dev, part = 0, ret;
+ struct mmc *mmc;
+
+ if (argc == 1) {
+ dev = curr_device;
+ } else if (argc == 2) {
+ dev = simple_strtoul(argv[1], NULL, 10);
+ } else if (argc == 3) {
+ dev = (int)simple_strtoul(argv[1], NULL, 10);
+ part = (int)simple_strtoul(argv[2], NULL, 10);
+ if (part > PART_ACCESS_MASK) {
+ printf("#part_num shouldn't be larger than %d\n",
+ PART_ACCESS_MASK);
return CMD_RET_FAILURE;
}
+ } else {
+ return CMD_RET_USAGE;
+ }
- mmc_init(mmc);
- if (part != -1) {
- int ret;
- if (mmc->part_config == MMCPART_NOAVAILABLE) {
- printf("Card doesn't support part_switch\n");
- return CMD_RET_FAILURE;
- }
+ mmc = init_mmc_device(dev, true);
+ if (!mmc)
+ return CMD_RET_FAILURE;
- if (part != mmc->part_num) {
- ret = mmc_switch_part(dev, part);
- if (!ret)
- mmc->part_num = part;
+ ret = mmc_select_hwpart(dev, part);
+ printf("switch to partitions #%d, %s\n",
+ part, (!ret) ? "OK" : "ERROR");
+ if (ret)
+ return 1;
- printf("switch to partions #%d, %s\n",
- part, (!ret) ? "OK" : "ERROR");
- }
- }
- curr_device = dev;
- if (mmc->part_config == MMCPART_NOAVAILABLE)
- printf("mmc%d is current device\n", curr_device);
- else
- printf("mmc%d(part %d) is current device\n",
- curr_device, mmc->part_num);
+ curr_device = dev;
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ printf("mmc%d is current device\n", curr_device);
+ else
+ printf("mmc%d(part %d) is current device\n",
+ curr_device, mmc->part_num);
- return CMD_RET_SUCCESS;
+ return CMD_RET_SUCCESS;
+}
+static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ print_mmc_devices('\n');
+ return CMD_RET_SUCCESS;
+}
#ifdef CONFIG_SUPPORT_EMMC_BOOT
- } else if ((strcmp(argv[1], "open") == 0) ||
- (strcmp(argv[1], "close") == 0)) {
- int dev;
- struct mmc *mmc;
- u8 part_num, access = 0;
-
- if (argc == 4) {
- dev = simple_strtoul(argv[2], NULL, 10);
- part_num = simple_strtoul(argv[3], NULL, 10);
- } else {
- return CMD_RET_USAGE;
- }
+static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u8 width, reset, mode;
- mmc = find_mmc_device(dev);
- if (!mmc) {
- printf("no mmc device at slot %x\n", dev);
- return CMD_RET_FAILURE;
- }
+ if (argc != 5)
+ return CMD_RET_USAGE;
+ dev = simple_strtoul(argv[1], NULL, 10);
+ width = simple_strtoul(argv[2], NULL, 10);
+ reset = simple_strtoul(argv[3], NULL, 10);
+ mode = simple_strtoul(argv[4], NULL, 10);
- if (IS_SD(mmc)) {
- printf("SD device cannot be opened/closed\n");
- return CMD_RET_FAILURE;
- }
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
- if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
- printf("Invalid boot partition number:\n");
- printf("Boot partition number cannot be <= 0\n");
- printf("EMMC44 supports only 2 boot partitions\n");
- return CMD_RET_FAILURE;
- }
+ if (IS_SD(mmc)) {
+ puts("BOOT_BUS_WIDTH only exists on eMMC\n");
+ return CMD_RET_FAILURE;
+ }
- if (strcmp(argv[1], "open") == 0)
- access = part_num; /* enable R/W access to boot part*/
- else
- access = 0; /* No access to boot partition */
+ /* acknowledge to be sent during boot operation */
+ return mmc_set_boot_bus_width(mmc, width, reset, mode);
+}
+static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u32 bootsize, rpmbsize;
- /* acknowledge to be sent during boot operation */
- return boot_part_access(mmc, 1, part_num, access);
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ dev = simple_strtoul(argv[1], NULL, 10);
+ bootsize = simple_strtoul(argv[2], NULL, 10);
+ rpmbsize = simple_strtoul(argv[3], NULL, 10);
- } else if (strcmp(argv[1], "bootpart") == 0) {
- int dev;
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
- if (argc != 5)
- return CMD_RET_USAGE;
+ if (IS_SD(mmc)) {
+ printf("It is not a EMMC device\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
+ printf("EMMC boot partition Size change Failed.\n");
+ return CMD_RET_FAILURE;
+ }
- dev = simple_strtoul(argv[2], NULL, 10);
+ printf("EMMC boot partition Size %d MB\n", bootsize);
+ printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+ return CMD_RET_SUCCESS;
+}
+static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u8 ack, part_num, access;
- u32 bootsize = simple_strtoul(argv[3], NULL, 10);
- u32 rpmbsize = simple_strtoul(argv[4], NULL, 10);
- struct mmc *mmc = find_mmc_device(dev);
- if (!mmc) {
- printf("no mmc device at slot %x\n", dev);
- return CMD_RET_FAILURE;
- }
+ if (argc != 5)
+ return CMD_RET_USAGE;
- if (IS_SD(mmc)) {
- printf("It is not a EMMC device\n");
- return CMD_RET_FAILURE;
- }
+ dev = simple_strtoul(argv[1], NULL, 10);
+ ack = simple_strtoul(argv[2], NULL, 10);
+ part_num = simple_strtoul(argv[3], NULL, 10);
+ access = simple_strtoul(argv[4], NULL, 10);
- if (0 == mmc_boot_partition_size_change(mmc,
- bootsize, rpmbsize)) {
- printf("EMMC boot partition Size %d MB\n", bootsize);
- printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
- return CMD_RET_SUCCESS;
- } else {
- printf("EMMC boot partition Size change Failed.\n");
- return CMD_RET_FAILURE;
- }
-#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (IS_SD(mmc)) {
+ puts("PARTITION_CONFIG only exists on eMMC\n");
+ return CMD_RET_FAILURE;
}
- state = MMC_INVALID;
- if (argc == 5 && strcmp(argv[1], "read") == 0)
- state = MMC_READ;
- else if (argc == 5 && strcmp(argv[1], "write") == 0)
- state = MMC_WRITE;
- else if (argc == 4 && strcmp(argv[1], "erase") == 0)
- state = MMC_ERASE;
-
- if (state != MMC_INVALID) {
- struct mmc *mmc = find_mmc_device(curr_device);
- int idx = 2;
- u32 blk, cnt, n;
- void *addr;
-
- if (state != MMC_ERASE) {
- addr = (void *)simple_strtoul(argv[idx], NULL, 16);
- ++idx;
- } else
- addr = NULL;
- blk = simple_strtoul(argv[idx], NULL, 16);
- cnt = simple_strtoul(argv[idx + 1], NULL, 16);
-
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return CMD_RET_FAILURE;
- }
- printf("\nMMC %s: dev # %d, block # %d, count %d ... ",
- argv[1], curr_device, blk, cnt);
+ /* acknowledge to be sent during boot operation */
+ return mmc_set_part_conf(mmc, ack, part_num, access);
+}
+static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u8 enable;
+
+ /*
+ * Set the RST_n_ENABLE bit of RST_n_FUNCTION
+ * The only valid values are 0x0, 0x1 and 0x2 and writing
+ * a value of 0x1 or 0x2 sets the value permanently.
+ */
+ if (argc != 3)
+ return CMD_RET_USAGE;
- mmc_init(mmc);
+ dev = simple_strtoul(argv[1], NULL, 10);
+ enable = simple_strtoul(argv[2], NULL, 10);
- if ((state == MMC_WRITE || state == MMC_ERASE)) {
- if (mmc_getwp(mmc) == 1) {
- printf("Error: card is write protected!\n");
- return CMD_RET_FAILURE;
- }
- }
+ if (enable > 2 || enable < 0) {
+ puts("Invalid RST_n_ENABLE value\n");
+ return CMD_RET_USAGE;
+ }
- switch (state) {
- case MMC_READ:
- n = mmc->block_dev.block_read(curr_device, blk,
- cnt, addr);
- /* flush cache after read */
- flush_cache((ulong)addr, cnt * 512); /* FIXME */
- break;
- case MMC_WRITE:
- n = mmc->block_dev.block_write(curr_device, blk,
- cnt, addr);
- break;
- case MMC_ERASE:
- n = mmc->block_dev.block_erase(curr_device, blk, cnt);
- break;
- default:
- BUG();
- }
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
- printf("%d blocks %s: %s\n",
- n, argv[1], (n == cnt) ? "OK" : "ERROR");
- return (n == cnt) ? 0 : 1;
+ if (IS_SD(mmc)) {
+ puts("RST_n_FUNCTION only exists on eMMC\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return mmc_set_rst_n_function(mmc, enable);
+}
+#endif
+static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct mmc *mmc;
+ u32 val;
+ int ret;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ val = simple_strtoul(argv[2], NULL, 16);
+
+ mmc = find_mmc_device(curr_device);
+ if (!mmc) {
+ printf("no mmc device at slot %x\n", curr_device);
+ return CMD_RET_FAILURE;
+ }
+ ret = mmc_set_dsr(mmc, val);
+ printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
+ if (!ret) {
+ mmc->has_init = 0;
+ if (mmc_init(mmc))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
}
+ return ret;
+}
+
+static cmd_tbl_t cmd_mmc[] = {
+ U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
+ U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
+ U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
+ U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
+ U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
+ U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
+ U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
+ U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
+ U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
+ U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
+#endif
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+ U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
+};
+
+static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ cmd_tbl_t *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
+
+ /* Drop the mmc command */
+ argc--;
+ argv++;
+
+ if (cp == NULL || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+ return CMD_RET_SUCCESS;
- return CMD_RET_USAGE;
+ if (curr_device < 0) {
+ if (get_mmc_num() > 0) {
+ curr_device = 0;
+ } else {
+ puts("No MMC device available\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ return cp->cmd(cmdtp, flag, argc, argv);
}
U_BOOT_CMD(
- mmc, 6, 1, do_mmcops,
+ mmc, 7, 1, do_mmcops,
"MMC sub system",
- "read addr blk# cnt\n"
+ "info - display info of the current MMC device\n"
+ "mmc read addr blk# cnt\n"
"mmc write addr blk# cnt\n"
"mmc erase blk# cnt\n"
"mmc rescan\n"
"mmc dev [dev] [part] - show or set current mmc device [partition]\n"
"mmc list - lists available devices\n"
#ifdef CONFIG_SUPPORT_EMMC_BOOT
- "mmc open <dev> <boot_partition>\n"
- " - Enable boot_part for booting and enable R/W access of boot_part\n"
- "mmc close <dev> <boot_partition>\n"
- " - Enable boot_part for booting and disable access to boot_part\n"
- "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
- " - change sizes of boot and RPMB partions of specified device\n"
+ "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
+ " - Set the BOOT_BUS_WIDTH field of the specified device\n"
+ "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
+ " - Change sizes of boot and RPMB partitions of specified device\n"
+ "mmc partconf dev boot_ack boot_partition partition_access\n"
+ " - Change the bits of the PARTITION_CONFIG field of the specified device\n"
+ "mmc rst-function dev value\n"
+ " - Change the RST_n_FUNCTION field of the specified device\n"
+ " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
#endif
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+ "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
+ "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
+ "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
+ "mmc rpmb counter - read the value of the write counter\n"
+#endif
+ "mmc setdsr <value> - set DSR register value\n"
);
+
+/* Old command kept for compatibility. Same as 'mmc info' */
+U_BOOT_CMD(
+ mmcinfo, 1, 0, do_mmcinfo,
+ "display MMC info",
+ "- display info of the current MMC device"
+);
+
#endif /* !CONFIG_GENERIC_MMC */
DECLARE_GLOBAL_DATA_PTR;
/* special size referring to all the remaining space in a partition */
-#define SIZE_REMAINING 0xFFFFFFFF
+#define SIZE_REMAINING (~0llu)
/* special offset value, it is used when not provided by user
*
* this value is used temporarily during parsing, later such offests
* are recalculated */
-#define OFFSET_NOT_SPECIFIED 0xFFFFFFFF
+#define OFFSET_NOT_SPECIFIED (~0llu)
/* minimum partition size */
#define MIN_PART_SIZE 4096
* @param retptr output pointer to next char after parse completes (output)
* @return resulting unsigned int
*/
-static unsigned long memsize_parse (const char *const ptr, const char **retptr)
+static u64 memsize_parse (const char *const ptr, const char **retptr)
{
- unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
+ u64 ret = simple_strtoull(ptr, (char **)retptr, 0);
switch (**retptr) {
case 'G':
* @param buf output buffer
* @param size size to be converted to string
*/
-static void memsize_format(char *buf, u32 size)
+static void memsize_format(char *buf, u64 size)
{
#define SIZE_GB ((u32)1024*1024*1024)
#define SIZE_MB ((u32)1024*1024)
#define SIZE_KB ((u32)1024)
if ((size % SIZE_GB) == 0)
- sprintf(buf, "%ug", size/SIZE_GB);
+ sprintf(buf, "%llug", size/SIZE_GB);
else if ((size % SIZE_MB) == 0)
- sprintf(buf, "%um", size/SIZE_MB);
+ sprintf(buf, "%llum", size/SIZE_MB);
else if (size % SIZE_KB == 0)
- sprintf(buf, "%uk", size/SIZE_KB);
+ sprintf(buf, "%lluk", size/SIZE_KB);
else
- sprintf(buf, "%u", size);
+ sprintf(buf, "%llu", size);
}
/**
printf("Device %s not found!\n", mtd_dev);
return 1;
}
+ put_mtd_device(*mtd);
return 0;
}
struct mtd_info *mtd = NULL;
int i, j;
ulong start;
+ u64 offset, size;
if (get_mtd_info(id->type, id->num, &mtd))
return 1;
* Only one eraseregion (NAND, OneNAND or uniform NOR),
* checking for alignment is easy here
*/
- if ((unsigned long)part->offset % mtd->erasesize) {
+ offset = part->offset;
+ if (do_div(offset, mtd->erasesize)) {
- printf("%s%d: partition (%s) start offset"
- "alignment incorrect\n",
+ printf("%s%d: partition (%s) start offset alignment incorrect\n",
MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
}
- if (part->size % mtd->erasesize) {
+ size = part->size;
+ if (do_div(size, mtd->erasesize)) {
printf("%s%d: partition (%s) size alignment incorrect\n",
MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
/**
- * Performs sanity check for supplied partition. Offset and size are verified
- * to be within valid range. Partition type is checked and either
- * parts_validate_nor() or parts_validate_nand() is called with the argument
- * of part.
+ * Performs sanity check for supplied partition. Offset and size are
+ * verified to be within valid range. Partition type is checked and
+ * part_validate_eraseblock() is called with the argument of part.
*
* @param id of the parent device
* @param part partition to validate
part->size = id->size - part->offset;
if (part->offset > id->size) {
- printf("%s: offset %08x beyond flash size %08x\n",
+ printf("%s: offset %08llx beyond flash size %08llx\n",
id->mtd_id, part->offset, id->size);
return 1;
}
}
/**
- * Delete selected partition from the partion list of the specified device.
+ * Delete selected partition from the partition list of the specified device.
*
* @param dev device to delete partition from
* @param part partition to delete
static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
{
struct part_info *part;
- unsigned long size;
- unsigned long offset;
+ u64 size;
+ u64 offset;
const char *name;
int name_len;
unsigned int mask_flags;
} else {
size = memsize_parse(p, &p);
if (size < MIN_PART_SIZE) {
- printf("partition size too small (%lx)\n", size);
+ printf("partition size too small (%llx)\n", size);
return 1;
}
}
part->auto_name = 0;
} else {
/* auto generated name in form of size@offset */
- sprintf(part->name, "0x%08lx@0x%08lx", size, offset);
+ sprintf(part->name, "0x%08llx@0x%08llx", size, offset);
part->auto_name = 1;
}
part->name[name_len - 1] = '\0';
INIT_LIST_HEAD(&part->link);
- debug("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n",
+ debug("+ partition: name %-22s size 0x%08llx offset 0x%08llx mask flags %d\n",
part->name, part->size,
part->offset, part->mask_flags);
* @param size a pointer to the size of the mtd device (output)
* @return 0 if device is valid, 1 otherwise
*/
-static int mtd_device_validate(u8 type, u8 num, u32 *size)
+static int mtd_device_validate(u8 type, u8 num, u64 *size)
{
struct mtd_info *mtd = NULL;
LIST_HEAD(tmp_list);
struct list_head *entry, *n;
u16 num_parts;
- u32 offset;
+ u64 offset;
int err = 1;
debug("===device_parse===\n");
debug("dev type = %d (%s), dev num = %d, mtd-id = %s\n",
id->type, MTD_DEV_TYPE(id->type),
id->num, id->mtd_id);
- debug("parsing partitions %.*s\n", (pend ? pend - p : strlen(p)), p);
+ debug("parsing partitions %.*s\n", (int)(pend ? pend - p : strlen(p)), p);
/* parse partitions */
list_for_each(entry, &mtdids) {
id = list_entry(entry, struct mtdids, link);
- debug("entry: '%s' (len = %d)\n",
+ debug("entry: '%s' (len = %zu)\n",
id->mtd_id, strlen(id->mtd_id));
if (mtd_id_len != strlen(id->mtd_id))
struct part_info *part, *prev_part;
char *p = buf;
char tmpbuf[32];
- u32 size, offset, len, part_cnt;
+ u64 size, offset;
+ u32 len, part_cnt;
u32 maxlen = buflen - 1;
debug("--- generate_mtdparts ---\n");
list_for_each(pentry, &dev->parts) {
part = list_entry(pentry, struct part_info, link);
- printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
+ printf("%2d: %-20s0x%08llx\t0x%08llx\t%d\n",
part_num, part->name, part->size,
part->offset, part->mask_flags);
#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
if (current_mtd_dev) {
part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
if (part) {
- printf("\nactive partition: %s%d,%d - (%s) 0x%08x @ 0x%08x\n",
+ printf("\nactive partition: %s%d,%d - (%s) 0x%08llx @ 0x%08llx\n",
MTD_DEV_TYPE(current_mtd_dev->id->type),
current_mtd_dev->id->num, current_mtd_partnum,
part->name, part->size, part->offset);
if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
- debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08x@0x%08x\n",
+ debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08llx@0x%08llx\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
part->name, part->size, part->offset);
struct list_head *entry, *n;
struct mtdids *id_tmp;
u8 type, num;
- u32 size;
+ u64 size;
int ret = 1;
debug("\n---parse_mtdids---\nmtdids = %s\n\n", ids);
id->mtd_id[mtd_id_len - 1] = '\0';
INIT_LIST_HEAD(&id->link);
- debug("+ id %s%d\t%16d bytes\t%s\n",
+ debug("+ id %s%d\t%16lld bytes\t%s\n",
MTD_DEV_TYPE(id->type), id->num,
id->size, id->mtd_id);
int i;
u_char *datbuf, *oobbuf, *p;
static loff_t last;
+ int ret = 0;
if (repeat)
off = last + nand->writesize;
last = off;
datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
- oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
- if (!datbuf || !oobbuf) {
+ if (!datbuf) {
puts("No memory for page buffer\n");
return 1;
}
+
+ oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
+ if (!oobbuf) {
+ puts("No memory for page buffer\n");
+ ret = 1;
+ goto free_dat;
+ }
off &= ~(nand->writesize - 1);
loff_t addr = (loff_t) off;
struct mtd_oob_ops ops;
i = mtd_read_oob(nand, addr, &ops);
if (i < 0) {
printf("Error (%d) reading page %08lx\n", i, off);
- free(datbuf);
- free(oobbuf);
- return 1;
+ ret = 1;
+ goto free_all;
}
printf("Page %08lx dump:\n", off);
- i = nand->writesize >> 4;
- p = datbuf;
- while (i--) {
- if (!only_oob)
+ if (!only_oob) {
+ i = nand->writesize >> 4;
+ p = datbuf;
+
+ while (i--) {
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x %02x %02x %02x %02x\n",
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;
+ p += 16;
+ }
}
+
puts("OOB:\n");
i = nand->oobsize >> 3;
p = oobbuf;
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
p += 8;
}
- free(datbuf);
+
+free_all:
free(oobbuf);
+free_dat:
+ free(datbuf);
- return 0;
+ return ret;
}
/* ------------------------------------------------------------------------- */
/* Only "dump" is repeatable. */
if (repeat && strcmp(cmd, "dump"))
- return 0;
+ return CMD_RET_FAILURE;
if (strcmp(cmd, "info") == 0) {
if (nand_info[i].name)
nand_print_and_set_info(i);
}
- return 0;
+ return CMD_RET_SUCCESS;
}
if (strcmp(cmd, "device") == 0) {
puts("no devices available\n");
else
nand_print_and_set_info(dev);
- return 0;
+ return CMD_RET_SUCCESS;
}
dev = (int)simple_strtoul(argv[2], NULL, 10);
set_dev(dev);
- return 0;
+ return CMD_RET_SUCCESS;
}
#ifdef CONFIG_ENV_OFFSET_OOB
/* this command operates only on the first nand device */
if (strcmp(cmd, "env.oob") == 0)
- return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
+ return do_nand_env_oob(cmdtp, argc - 1, argv + 1) ?
+ CMD_RET_FAILURE : CMD_RET_SUCCESS;;
#endif
/* The following commands operate on the current device, unless
if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[dev].name) {
puts("\nno devices available\n");
- return 1;
+ return CMD_RET_FAILURE;
}
nand = &nand_info[dev];
for (off = 0; off < nand->size; off += nand->erasesize)
if (nand_block_isbad(nand, off))
printf(" %08llx\n", (unsigned long long)off);
- return 0;
+ return CMD_RET_SUCCESS;
}
/*
/* skip first two or three arguments, look for offset and size */
if (arg_off_size(argc - o, argv + o, &dev, &off, &size,
&maxsize) != 0)
- return 1;
+ return CMD_RET_FAILURE;
nand = &nand_info[dev];
opts.spread = spread;
if (scrub) {
- if (!scrub_yes)
- puts(scrub_warn);
-
- if (scrub_yes)
+ if (scrub_yes) {
opts.scrub = 1;
- else if (getc() == 'y') {
- puts("y");
- if (getc() == '\r')
+ } else {
+ puts(scrub_warn);
+ if (confirm_yesno()) {
opts.scrub = 1;
- else {
+ } else {
puts("scrub aborted\n");
- return 1;
+ return CMD_RET_FAILURE;
}
- } else {
- puts("scrub aborted\n");
- return CMD_RET_FAILURE;
}
}
ret = nand_erase_opts(nand, &opts);
printf("%s\n", ret ? "ERROR" : "OK");
- return ret == 0 ? 0 : 1;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
if (strncmp(cmd, "dump", 4) == 0) {
off = (int)simple_strtoul(argv[2], NULL, 16);
ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
- return ret == 0 ? 1 : 0;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
printf("\nNAND %s: ", read ? "read" : "write");
- nand = &nand_info[dev];
-
s = strchr(cmd, '.');
if (s && !strcmp(s, ".raw")) {
if (arg_off(argv[3], &dev, &off, &size, &maxsize))
return 1;
+ nand = &nand_info[dev];
+
if (argc > 4 && !str2long(argv[4], &pagecount)) {
printf("'%s' is not a number\n", argv[4]);
return 1;
rwsize = size;
}
+ nand = &nand_info[dev];
+
if (!s || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
} else if (!strcmp(s, ".trimffs")) {
if (read) {
printf("Unknown nand command suffix '%s'\n", s);
- return 1;
+ return CMD_RET_FAILURE;
}
ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
maxsize, (u_char *)addr,
} else if (!strcmp(s, ".yaffs")) {
if (read) {
printf("Unknown nand command suffix '%s'.\n", s);
- return 1;
+ return CMD_RET_FAILURE;
}
ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
maxsize, (u_char *)addr,
ret = raw_access(nand, addr, off, pagecount, read);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
- return 1;
+ return CMD_RET_FAILURE;
}
printf(" %zu bytes %s: %s\n", rwsize,
read ? "read" : "written", ret ? "ERROR" : "OK");
- return ret == 0 ? 0 : 1;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
#ifdef CONFIG_CMD_NAND_TORTURE
--argc;
++argv;
}
- return ret;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
if (strcmp(cmd, "biterr") == 0) {
/* todo */
- return 1;
+ return CMD_RET_FAILURE;
}
#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
puts("NAND flash successfully locked\n");
} else {
puts("Error locking NAND flash\n");
- return 1;
+ return CMD_RET_FAILURE;
}
}
- return 0;
+ return CMD_RET_SUCCESS;
}
if (strncmp(cmd, "unlock", 5) == 0) {
if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
&maxsize) < 0)
- return 1;
+ return CMD_RET_FAILURE;
if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
puts("NAND flash successfully unlocked\n");
} else {
puts("Error unlocking NAND flash, "
"write and erase will probably fail\n");
- return 1;
+ return CMD_RET_FAILURE;
}
- return 0;
+ return CMD_RET_SUCCESS;
}
#endif
int r;
char *s;
size_t cnt;
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
image_header_t *hdr;
+#endif
#if defined(CONFIG_FIT)
const void *fit_hdr = NULL;
#endif
bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
switch (genimg_get_format ((void *)addr)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
hdr = (image_header_t *)addr;
cnt = image_get_image_size (hdr);
break;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
fit_hdr = (const void *)addr;
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Andreas Heppel <aheppel@sysgo.de>
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
env_t *env_ptr = &environment;
#elif defined(CONFIG_NAND_ENV_DST)
env_t *env_ptr = (env_t *)CONFIG_NAND_ENV_DST;
- #else /* ! ENV_IS_EMBEDDED */
- env_t *env_ptr;
#endif /* ENV_IS_EMBEDDED */
DECLARE_GLOBAL_DATA_PTR;
* The legacy NAND code saved the environment in the first NAND device i.e.,
* nand_dev_desc + 0. This is also the behaviour using the new NAND code.
*/
-int writeenv(size_t offset, u_char *buf)
+static int writeenv(size_t offset, u_char *buf)
{
size_t end = offset + CONFIG_ENV_RANGE;
size_t amount_saved = 0;
u_char *char_ptr;
blocksize = nand_info[0].erasesize;
- len = min(blocksize, CONFIG_ENV_SIZE);
+ len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
if (nand_block_isbad(&nand_info[0], offset)) {
return 0;
}
-#ifdef CONFIG_ENV_OFFSET_REDUND
-static unsigned char env_flags;
+struct env_location {
+ const char *name;
+ const nand_erase_options_t erase_opts;
+};
-int saveenv(void)
+static int erase_and_write_env(const struct env_location *location,
+ u_char *env_new)
{
- env_t env_new;
- ssize_t len;
- char *res;
- int ret = 0;
- nand_erase_options_t nand_erase_options;
-
- memset(&nand_erase_options, 0, sizeof(nand_erase_options));
- nand_erase_options.length = CONFIG_ENV_RANGE;
+ int ret = 0;
- if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
- return 1;
-
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
+ printf("Erasing %s...\n", location->name);
+ if (nand_erase_opts(&nand_info[0], &location->erase_opts))
return 1;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
- env_new.flags = ++env_flags; /* increase the serial */
-
- if (gd->env_valid == 1) {
- puts("Erasing redundant NAND...\n");
- nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
- if (nand_erase_opts(&nand_info[0], &nand_erase_options))
- return 1;
-
- puts("Writing to redundant NAND... ");
- ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *)&env_new);
- } else {
- puts("Erasing NAND...\n");
- nand_erase_options.offset = CONFIG_ENV_OFFSET;
- if (nand_erase_opts(&nand_info[0], &nand_erase_options))
- return 1;
-
- puts("Writing to NAND... ");
- ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new);
- }
- if (ret) {
- puts("FAILED!\n");
- return 1;
- }
-
- puts("done\n");
- gd->env_valid = gd->env_valid == 2 ? 1 : 2;
+ printf("Writing to %s... ", location->name);
+ ret = writeenv(location->erase_opts.offset, env_new);
+ puts(ret ? "FAILED!\n" : "OK\n");
return ret;
}
-#else /* ! CONFIG_ENV_OFFSET_REDUND */
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+static unsigned char env_flags;
+#endif
+
int saveenv(void)
{
int ret = 0;
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
- ssize_t len;
- char *res;
- nand_erase_options_t nand_erase_options;
+ int env_idx = 0;
+ static const struct env_location location[] = {
+ {
+ .name = "NAND",
+ .erase_opts = {
+ .length = CONFIG_ENV_RANGE,
+ .offset = CONFIG_ENV_OFFSET,
+ },
+ },
+#ifdef CONFIG_ENV_OFFSET_REDUND
+ {
+ .name = "redundant NAND",
+ .erase_opts = {
+ .length = CONFIG_ENV_RANGE,
+ .offset = CONFIG_ENV_OFFSET_REDUND,
+ },
+ },
+#endif
+ };
- memset(&nand_erase_options, 0, sizeof(nand_erase_options));
- nand_erase_options.length = CONFIG_ENV_RANGE;
- nand_erase_options.offset = CONFIG_ENV_OFFSET;
if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
return 1;
- res = (char *)&env_new->data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new->crc = crc32(0, env_new->data, ENV_SIZE);
+ ret = env_export(env_new);
+ if (ret)
+ return ret;
- puts("Erasing Nand...\n");
- if (nand_erase_opts(&nand_info[0], &nand_erase_options))
- return 1;
+#ifdef CONFIG_ENV_OFFSET_REDUND
+ env_new->flags = ++env_flags; /* increase the serial */
+ env_idx = (gd->env_valid == 1);
+#endif
- puts("Writing to Nand... ");
- if (writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new)) {
- puts("FAILED!\n");
- return 1;
+ ret = erase_and_write_env(&location[env_idx], (u_char *)env_new);
+#ifdef CONFIG_ENV_OFFSET_REDUND
+ if (!ret) {
+ /* preset other copy for next write */
+ gd->env_valid = gd->env_valid == 2 ? 1 : 2;
+ return ret;
}
- puts("done\n");
+ env_idx = (env_idx + 1) & 1;
+ ret = erase_and_write_env(&location[env_idx], (u_char *)env_new);
+ if (!ret)
+ printf("Warning: primary env write failed,"
+ " redundancy is lost!\n");
+#endif
+
return ret;
}
-#endif /* CONFIG_ENV_OFFSET_REDUND */
#endif /* CMD_SAVEENV */
-int readenv(size_t offset, u_char *buf)
+static int readenv(size_t offset, u_char *buf)
{
size_t end = offset + CONFIG_ENV_RANGE;
size_t amount_loaded = 0;
if (!blocksize)
return 1;
- len = min(blocksize, CONFIG_ENV_SIZE);
+ len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
while (amount_loaded < CONFIG_ENV_SIZE && offset < end) {
if (nand_block_isbad(&nand_info[0], offset)) {
gd->env_valid = 1;
}
+ #ifdef CONFIG_NAND_ENV_DST
free(env_ptr);
+ #endif
if (gd->env_valid == 1)
ep = tmp_env1;
*/
#include <common.h>
+#include <inttypes.h>
#include <stdio_dev.h>
#include <linux/ctype.h>
#include <linux/types.h>
#include <fdt_support.h>
#include <exports.h>
-/*
- * Global data (for the gd->bd)
+/**
+ * fdt_getprop_u32_default_node - Return a node's property or a default
+ *
+ * @fdt: ptr to device tree
+ * @off: offset of node
+ * @cell: cell offset in property
+ * @prop: property name
+ * @dflt: default value if the property isn't found
+ *
+ * Convenience function to return a node's property or a default value if
+ * the property doesn't exist.
*/
-DECLARE_GLOBAL_DATA_PTR;
+u32 fdt_getprop_u32_default_node(const void *fdt, int off, int cell,
+ const char *prop, const u32 dflt)
+{
+ const fdt32_t *val;
+ int len;
+
+ val = fdt_getprop(fdt, off, prop, &len);
+
+ /* Check if property exists */
+ if (!val)
+ return dflt;
+
+ /* Check if property is long enough */
+ if (len < ((cell + 1) * sizeof(uint32_t)))
+ return dflt;
+
+ return fdt32_to_cpu(*val);
+}
/**
* fdt_getprop_u32_default - Find a node and return it's property or a default
u32 fdt_getprop_u32_default(const void *fdt, const char *path,
const char *prop, const u32 dflt)
{
- const fdt32_t *val;
int off;
off = fdt_path_offset(fdt, path);
if (off < 0)
return dflt;
- val = fdt_getprop(fdt, off, prop, NULL);
- if (val)
- return fdt32_to_cpu(*val);
- else
- return dflt;
+ return fdt_getprop_u32_default_node(fdt, off, 0, prop, dflt);
}
/**
return fdt_setprop(fdt, nodeoff, prop, val, len);
}
-#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
+/**
+ * fdt_find_or_add_subnode() - find or possibly add a subnode of a given node
+ *
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node with a given name.
+ * If the subnode does not exist, it will be created.
+ */
+int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+ int offset;
+
+ offset = fdt_subnode_offset(fdt, parentoffset, name);
+
+ if (offset == -FDT_ERR_NOTFOUND)
+ offset = fdt_add_subnode(fdt, parentoffset, name);
+
+ if (offset < 0)
+ printf("%s: %s: %s\n", __func__, name, fdt_strerror(offset));
+
+ return offset;
+}
-#ifdef CONFIG_CONS_INDEX
+/* rename to CONFIG_OF_STDOUT_PATH ? */
+#if defined(OF_STDOUT_PATH)
+static int fdt_fixup_stdout(void *fdt, int chosenoff)
+{
+ return fdt_setprop(fdt, chosenoff, "linux,stdout-path",
+ OF_STDOUT_PATH, strlen(OF_STDOUT_PATH) + 1);
+}
+#elif defined(CONFIG_OF_STDOUT_VIA_ALIAS) && defined(CONFIG_CONS_INDEX)
static void fdt_fill_multisername(char *sername, size_t maxlen)
{
const char *outname = stdio_devices[stdout]->name;
if (strcmp(outname + 1, "serial") > 0)
strncpy(sername, outname + 1, maxlen);
}
-#endif
static int fdt_fixup_stdout(void *fdt, int chosenoff)
{
- int err = 0;
-#ifdef CONFIG_CONS_INDEX
- int node;
+ int err;
+ int aliasoff;
char sername[9] = { 0 };
- const char *path;
+ const void *path;
+ int len;
+ char tmp[256]; /* long enough */
fdt_fill_multisername(sername, sizeof(sername) - 1);
if (!sername[0])
sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1);
- err = node = fdt_path_offset(fdt, "/aliases");
- if (node >= 0) {
- int len;
- path = fdt_getprop(fdt, node, sername, &len);
- if (path) {
- char *p = malloc(len);
- err = -FDT_ERR_NOSPACE;
- if (p) {
- memcpy(p, path, len);
- err = fdt_setprop(fdt, chosenoff,
- "linux,stdout-path", p, len);
- free(p);
- }
- } else {
- err = len;
- }
+ aliasoff = fdt_path_offset(fdt, "/aliases");
+ if (aliasoff < 0) {
+ err = aliasoff;
+ goto error;
}
-#endif
+
+ path = fdt_getprop(fdt, aliasoff, sername, &len);
+ if (!path) {
+ err = len;
+ goto error;
+ }
+
+ /* fdt_setprop may break "path" so we copy it to tmp buffer */
+ memcpy(tmp, path, len);
+
+ err = fdt_setprop(fdt, chosenoff, "linux,stdout-path", tmp, len);
+error:
if (err < 0)
printf("WARNING: could not set linux,stdout-path %s.\n",
- fdt_strerror(err));
+ fdt_strerror(err));
return err;
}
+#else
+static int fdt_fixup_stdout(void *fdt, int chosenoff)
+{
+ return 0;
+}
#endif
-int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
+static inline int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name,
+ uint64_t val, int is_u64)
+{
+ if (is_u64)
+ return fdt_setprop_u64(fdt, nodeoffset, name, val);
+ else
+ return fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
+}
+
+
+int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
{
int nodeoffset;
int err, j, total;
- fdt32_t tmp;
- const char *path;
+ int is_u64;
uint64_t addr, size;
- /* Find the "chosen" node. */
- nodeoffset = fdt_path_offset (fdt, "/chosen");
+ /* just return if the size of initrd is zero */
+ if (initrd_start == initrd_end)
+ return 0;
- /* If there is no "chosen" node in the blob return */
- if (nodeoffset < 0) {
- printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset));
+ /* find or create "/chosen" node. */
+ nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+ if (nodeoffset < 0)
return nodeoffset;
- }
-
- /* just return if initrd_start/end aren't valid */
- if ((initrd_start == 0) || (initrd_end == 0))
- return 0;
total = fdt_num_mem_rsv(fdt);
return err;
}
- path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
- if ((path == NULL) || force) {
- tmp = cpu_to_fdt32(initrd_start);
- err = fdt_setprop(fdt, nodeoffset,
- "linux,initrd-start", &tmp, sizeof(tmp));
- if (err < 0) {
- printf("WARNING: "
- "could not set linux,initrd-start %s.\n",
- fdt_strerror(err));
- return err;
- }
- tmp = cpu_to_fdt32(initrd_end);
- err = fdt_setprop(fdt, nodeoffset,
- "linux,initrd-end", &tmp, sizeof(tmp));
- if (err < 0) {
- printf("WARNING: could not set linux,initrd-end %s.\n",
- fdt_strerror(err));
+ is_u64 = (fdt_address_cells(fdt, 0) == 2);
- return err;
- }
+ err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start",
+ (uint64_t)initrd_start, is_u64);
+
+ if (err < 0) {
+ printf("WARNING: could not set linux,initrd-start %s.\n",
+ fdt_strerror(err));
+ return err;
+ }
+
+ err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end",
+ (uint64_t)initrd_end, is_u64);
+
+ if (err < 0) {
+ printf("WARNING: could not set linux,initrd-end %s.\n",
+ fdt_strerror(err));
+
+ return err;
}
return 0;
}
-int fdt_chosen(void *fdt, int force)
+int fdt_chosen(void *fdt)
{
int nodeoffset;
int err;
char *str; /* used to set string properties */
- const char *path;
err = fdt_check_header(fdt);
if (err < 0) {
return err;
}
- /*
- * Find the "chosen" node.
- */
- nodeoffset = fdt_path_offset (fdt, "/chosen");
-
- /*
- * If there is no "chosen" node in the blob, create it.
- */
- if (nodeoffset < 0) {
- /*
- * Create a new node "/chosen" (offset 0 is root level)
- */
- nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
- if (nodeoffset < 0) {
- printf("WARNING: could not create /chosen %s.\n",
- fdt_strerror(nodeoffset));
- return nodeoffset;
- }
- }
+ /* find or create "/chosen" node. */
+ nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+ if (nodeoffset < 0)
+ return nodeoffset;
- /*
- * Create /chosen properites that don't exist in the fdt.
- * If the property exists, update it only if the "force" parameter
- * is true.
- */
str = getenv("bootargs");
- if (str != NULL) {
- path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL);
- if ((path == NULL) || force) {
- err = fdt_setprop(fdt, nodeoffset,
- "bootargs", str, strlen(str)+1);
- if (err < 0)
- printf("WARNING: could not set bootargs %s.\n",
- fdt_strerror(err));
+ if (str) {
+ err = fdt_setprop(fdt, nodeoffset, "bootargs", str,
+ strlen(str) + 1);
+ if (err < 0) {
+ printf("WARNING: could not set bootargs %s.\n",
+ fdt_strerror(err));
+ return err;
}
}
-#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
- path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
- if ((path == NULL) || force)
- err = fdt_fixup_stdout(fdt, nodeoffset);
-#endif
-
-#ifdef OF_STDOUT_PATH
- path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
- if ((path == NULL) || force) {
- err = fdt_setprop(fdt, nodeoffset,
- "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
- if (err < 0)
- printf("WARNING: could not set linux,stdout-path %s.\n",
- fdt_strerror(err));
- }
-#endif
-
- return err;
+ return fdt_fixup_stdout(fdt, nodeoffset);
}
void do_fixup_by_path(void *fdt, const char *path, const char *prop,
}
/*
- * Get cells len in bytes
- * if #NNNN-cells property is 2 then len is 8
- * otherwise len is 4
+ * fdt_pack_reg - pack address and size array into the "reg"-suitable stream
*/
-static int get_cells_len(void *blob, char *nr_cells_name)
+static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
+ int n)
{
- const fdt32_t *cell;
-
- cell = fdt_getprop(blob, 0, nr_cells_name, NULL);
- if (cell && fdt32_to_cpu(*cell) == 2)
- return 8;
+ int i;
+ int address_cells = fdt_address_cells(fdt, 0);
+ int size_cells = fdt_size_cells(fdt, 0);
+ char *p = buf;
- return 4;
-}
+ for (i = 0; i < n; i++) {
+ if (address_cells == 2)
+ *(fdt64_t *)p = cpu_to_fdt64(address[i]);
+ else
+ *(fdt32_t *)p = cpu_to_fdt32(address[i]);
+ p += 4 * address_cells;
-/*
- * Write a 4 or 8 byte big endian cell
- */
-static void write_cell(u8 *addr, u64 val, int size)
-{
- int shift = (size - 1) * 8;
- while (size-- > 0) {
- *addr++ = (val >> shift) & 0xff;
- shift -= 8;
+ if (size_cells == 2)
+ *(fdt64_t *)p = cpu_to_fdt64(size[i]);
+ else
+ *(fdt32_t *)p = cpu_to_fdt32(size[i]);
+ p += 4 * size_cells;
}
+
+ return p - (char *)buf;
}
#ifdef CONFIG_NR_DRAM_BANKS
int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{
int err, nodeoffset;
- int addr_cell_len, size_cell_len, len;
+ int len;
u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */
- int bank;
if (banks > MEMORY_BANKS_MAX) {
printf("%s: num banks %d exceeds hardcoded limit %d."
return err;
}
- /* update, or add and update /memory node */
- nodeoffset = fdt_path_offset(blob, "/memory");
- if (nodeoffset < 0) {
- nodeoffset = fdt_add_subnode(blob, 0, "memory");
- if (nodeoffset < 0)
- printf("WARNING: could not create /memory: %s.\n",
- fdt_strerror(nodeoffset));
- return nodeoffset;
- }
+ /* find or create "/memory" node. */
+ nodeoffset = fdt_find_or_add_subnode(blob, 0, "memory");
+ if (nodeoffset < 0)
+ return nodeoffset;
+
err = fdt_setprop(blob, nodeoffset, "device_type", "memory",
sizeof("memory"));
if (err < 0) {
return err;
}
- addr_cell_len = get_cells_len(blob, "#address-cells");
- size_cell_len = get_cells_len(blob, "#size-cells");
-
- for (bank = 0, len = 0; bank < banks; bank++) {
- write_cell(tmp + len, start[bank], addr_cell_len);
- len += addr_cell_len;
-
- write_cell(tmp + len, size[bank], size_cell_len);
- len += size_cell_len;
- }
+ len = fdt_pack_reg(blob, tmp, start, size, banks);
err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
if (err < 0) {
if (node < 0)
return;
+ if (!getenv("ethaddr")) {
+ if (getenv("usbethaddr")) {
+ strcpy(mac, "usbethaddr");
+ } else {
+ debug("No ethernet MAC Address defined\n");
+ return;
+ }
+ } else {
+ strcpy(mac, "ethaddr");
+ }
+
i = 0;
- strcpy(mac, "ethaddr");
while ((tmp = getenv(mac)) != NULL) {
sprintf(enet, "ethernet%d", i);
path = fdt_getprop(fdt, node, enet, NULL);
}
/* Resize the fdt to its actual size + a bit of padding */
-int fdt_resize(void *blob)
+int fdt_shrink_to_minimum(void *blob)
{
int i;
uint64_t addr, size;
ret = fdt_add_mem_rsv(blob, (uintptr_t)blob, actualsize);
if (ret < 0)
return ret;
-
+ if (getenv("fdtsize"))
+ setenv_hex("fdtsize", actualsize);
return actualsize;
}
part = list_entry(pentry, struct part_info, link);
- debug("%2d: %-20s0x%08x\t0x%08x\t%d\n",
+ debug("%2d: %-20s0x%08llx\t0x%08llx\t%d\n",
part_num, part->name, part->size,
part->offset, part->mask_flags);
- sprintf(buf, "partition@%x", part->offset);
+ sprintf(buf, "partition@%llx", part->offset);
add_sub:
ret = fdt_add_subnode(blob, parent_offset, buf);
if (ret == -FDT_ERR_NOSPACE) {
fdt_delprop(blob, off, alias);
}
-/* Helper to read a big number; size is in cells (not bytes) */
-static inline u64 of_read_number(const fdt32_t *cell, int size)
-{
- u64 r = 0;
- while (size--)
- r = (r << 32) | fdt32_to_cpu(*(cell++));
- return r;
-}
-
-#define PRu64 "%llx"
-
/* Max address size we deal with */
#define OF_MAX_ADDR_CELLS 4
#define OF_BAD_ADDR ((u64)-1)
};
/* Default translator (generic bus) */
-static void of_bus_default_count_cells(void *blob, int parentoffset,
+void of_bus_default_count_cells(void *blob, int parentoffset,
int *addrc, int *sizec)
{
const fdt32_t *prop;
- if (addrc) {
- prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
- if (prop)
- *addrc = be32_to_cpup(prop);
- else
- *addrc = 2;
- }
+ if (addrc)
+ *addrc = fdt_address_cells(blob, parentoffset);
if (sizec) {
prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
s = of_read_number(range + na + pna, ns);
da = of_read_number(addr, na);
- debug("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
- cp, s, da);
+ debug("OF: default map, cp=%" PRIu64 ", s=%" PRIu64
+ ", da=%" PRIu64 "\n", cp, s, da);
if (da < cp || da >= (cp + s))
return OF_BAD_ADDR;
finish:
of_dump_addr("OF: parent translation for:", addr, pna);
- debug("OF: with offset: "PRu64"\n", offset);
+ debug("OF: with offset: %" PRIu64 "\n", offset);
/* Translate it into parent bus space */
return pbus->translate(addr, offset, pna);
goto bail;
bus = &of_busses[0];
- /* Cound address cells & copy address locally */
+ /* Count address cells & copy address locally */
bus->count_cells(blob, parent, &na, &ns);
if (!OF_CHECK_COUNTS(na, ns)) {
printf("%s: Bad cell count for %s\n", __FUNCTION__,
*/
int fdt_alloc_phandle(void *blob)
{
- int offset, phandle = 0;
+ int offset;
+ uint32_t phandle = 0;
for (offset = fdt_next_node(blob, -1, NULL); offset >= 0;
offset = fdt_next_node(blob, offset, NULL)) {
dt_addr = fdt_translate_address(fdt, node, reg);
if (addr != dt_addr) {
- printf("Warning: U-Boot configured device %s at address %llx,\n"
- " but the device tree has it address %llx.\n",
- alias, addr, dt_addr);
+ printf("Warning: U-Boot configured device %s at address %"
+ PRIx64 ",\n but the device tree has it address %"
+ PRIx64 ".\n", alias, addr, dt_addr);
return 0;
}
u32 naddr;
const fdt32_t *prop;
- prop = fdt_getprop(fdt, node, "#address-cells", &size);
- if (prop && size == 4)
- naddr = be32_to_cpup(prop);
- else
- naddr = 2;
+ naddr = fdt_address_cells(fdt, node);
prop = fdt_getprop(fdt, node, "ranges", &size);
return prop ? fdt_translate_address(fdt, node, prop + naddr) : 0;
}
+
+/*
+ * Read a property of size <prop_len>. Currently only supports 1 or 2 cells.
+ */
+static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off,
+ uint64_t *val, int cells)
+{
+ const fdt32_t *prop32 = &prop[cell_off];
+ const fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off];
+
+ if ((cell_off + cells) > prop_len)
+ return -FDT_ERR_NOSPACE;
+
+ switch (cells) {
+ case 1:
+ *val = fdt32_to_cpu(*prop32);
+ break;
+ case 2:
+ *val = fdt64_to_cpu(*prop64);
+ break;
+ default:
+ return -FDT_ERR_NOSPACE;
+ }
+
+ return 0;
+}
+
+/**
+ * fdt_read_range - Read a node's n'th range property
+ *
+ * @fdt: ptr to device tree
+ * @node: offset of node
+ * @n: range index
+ * @child_addr: pointer to storage for the "child address" field
+ * @addr: pointer to storage for the CPU view translated physical start
+ * @len: pointer to storage for the range length
+ *
+ * Convenience function that reads and interprets a specific range out of
+ * a number of the "ranges" property array.
+ */
+int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr,
+ uint64_t *addr, uint64_t *len)
+{
+ int pnode = fdt_parent_offset(fdt, node);
+ const fdt32_t *ranges;
+ int pacells;
+ int acells;
+ int scells;
+ int ranges_len;
+ int cell = 0;
+ int r = 0;
+
+ /*
+ * The "ranges" property is an array of
+ * { <child address> <parent address> <size in child address space> }
+ *
+ * All 3 elements can span a diffent number of cells. Fetch their size.
+ */
+ pacells = fdt_getprop_u32_default_node(fdt, pnode, 0, "#address-cells", 1);
+ acells = fdt_getprop_u32_default_node(fdt, node, 0, "#address-cells", 1);
+ scells = fdt_getprop_u32_default_node(fdt, node, 0, "#size-cells", 1);
+
+ /* Now try to get the ranges property */
+ ranges = fdt_getprop(fdt, node, "ranges", &ranges_len);
+ if (!ranges)
+ return -FDT_ERR_NOTFOUND;
+ ranges_len /= sizeof(uint32_t);
+
+ /* Jump to the n'th entry */
+ cell = n * (pacells + acells + scells);
+
+ /* Read <child address> */
+ if (child_addr) {
+ r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
+ acells);
+ if (r)
+ return r;
+ }
+ cell += acells;
+
+ /* Read <parent address> */
+ if (addr)
+ *addr = fdt_translate_address(fdt, node, ranges + cell);
+ cell += pacells;
+
+ /* Read <size in child address space> */
+ if (len) {
+ r = fdt_read_prop(ranges, ranges_len, cell, len, scells);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+/**
+ * fdt_setup_simplefb_node - Fill and enable a simplefb node
+ *
+ * @fdt: ptr to device tree
+ * @node: offset of the simplefb node
+ * @base_address: framebuffer base address
+ * @width: width in pixels
+ * @height: height in pixels
+ * @stride: bytes per line
+ * @format: pixel format string
+ *
+ * Convenience function to fill and enable a simplefb node.
+ */
+int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width,
+ u32 height, u32 stride, const char *format)
+{
+ char name[32];
+ fdt32_t cells[4];
+ int i, addrc, sizec, ret;
+
+ of_bus_default_count_cells(fdt, fdt_parent_offset(fdt, node),
+ &addrc, &sizec);
+ i = 0;
+ if (addrc == 2)
+ cells[i++] = cpu_to_fdt32(base_address >> 32);
+ cells[i++] = cpu_to_fdt32(base_address);
+ if (sizec == 2)
+ cells[i++] = 0;
+ cells[i++] = cpu_to_fdt32(height * stride);
+
+ ret = fdt_setprop(fdt, node, "reg", cells, sizeof(cells[0]) * i);
+ if (ret < 0)
+ return ret;
+
+ snprintf(name, sizeof(name), "framebuffer@%llx", base_address);
+ ret = fdt_set_name(fdt, node, name);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_u32(fdt, node, "width", width);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_u32(fdt, node, "height", height);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_u32(fdt, node, "stride", stride);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_string(fdt, node, "format", format);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_string(fdt, node, "status", "okay");
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
* (C) Copyright 2001-2002
* Wolfgang Denk, DENX Software Engineering -- wd@denx.de
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
/************************************************************************/
#endif
#include <lcd.h>
#include <watchdog.h>
-
+#include <asm/unaligned.h>
#include <splash.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <fdt_support.h>
#if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
defined(CONFIG_CPU_MONAHANS)
-#define CONFIG_CPU_PXA
#include <asm/byteorder.h>
#endif
/* ** FONT DATA */
/************************************************************************/
#include <video_font.h> /* Get font data, width and height */
-#include <video_font_data.h>
/************************************************************************/
/* ** LOGO DATA */
#ifdef CONFIG_LCD_LOGO
# include <bmp_logo.h> /* Get logo data, width and height */
# include <bmp_logo_data.h>
- # if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16)
+ # if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP < LCD_COLOR16)
# error Default Color Map overlaps with Logo Color Map
# endif
#endif
+#ifdef CONFIG_SANDBOX
+#include <asm/sdl.h>
+#endif
+
#ifndef CONFIG_LCD_ALIGNMENT
#define CONFIG_LCD_ALIGNMENT PAGE_SIZE
#endif
#if LCD_BPP == LCD_MONOCHROME
# define COLOR_MASK(c) ((c) | (c) << 1 | (c) << 2 | (c) << 3 | \
(c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
-#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || (LCD_BPP == LCD_COLOR24)
+#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || \
+ (LCD_BPP == LCD_COLOR32)
# define COLOR_MASK(c) (c)
#else
# error Unsupported LCD BPP.
DECLARE_GLOBAL_DATA_PTR;
static void lcd_drawchars(ushort x, ushort y, uchar *str, int count);
-static inline void lcd_puts_xy(ushort x, ushort y, uchar *s);
static inline void lcd_putc_xy(ushort x, ushort y, uchar c);
static int lcd_init(void *lcdbase);
static void *lcd_logo(void);
-static int lcd_getbgcolor(void);
static void lcd_setfgcolor(int color);
static void lcd_setbgcolor(int color);
if (lcd_flush_dcache)
flush_dcache_range((u32)lcd_base,
(u32)(lcd_base + lcd_get_size(&line_length)));
+#elif defined(CONFIG_SANDBOX) && defined(CONFIG_VIDEO_SANDBOX_SDL)
+ static ulong last_sync;
+
+ if (get_timer(last_sync) > 10) {
+ sandbox_sdl_sync(lcd_base);
+ last_sync = get_timer(0);
+ }
#endif
}
CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
/* Clear the last rows */
+#if (LCD_BPP != LCD_COLOR32)
memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
COLOR_MASK(lcd_color_bg),
CONSOLE_ROW_SIZE * rows);
-
+#else
+ u32 *ppix = lcd_console_address +
+ CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows;
+ u32 i;
+ for (i = 0;
+ i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix);
+ i++) {
+ *ppix++ = COLOR_MASK(lcd_color_bg);
+ }
+#endif
lcd_sync();
console_row -= rows;
}
/*----------------------------------------------------------------------*/
+static void lcd_stub_putc(struct stdio_dev *dev, const char c)
+{
+ lcd_putc(c);
+}
+
void lcd_putc(const char c)
{
if (!lcd_is_enabled) {
/*----------------------------------------------------------------------*/
+static void lcd_stub_puts(struct stdio_dev *dev, const char *s)
+{
+ lcd_puts(s);
+}
+
void lcd_puts(const char *s)
{
if (!lcd_is_enabled) {
static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
{
- uchar *dest;
+ void *dest;
ushort row;
#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
#endif
#if LCD_BPP == LCD_MONOCHROME
-- ushort off = x * (1 << LCD_BPP) % 8;
++ ushort off = x * NBITS(LCD_BPP) % 8;
#endif
- dest = (uchar *)(lcd_base + y * lcd_line_length + x * NBITS(LCD_BPP)/8);
- dest = lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8;
++ dest = lcd_base + y * lcd_line_length + x * NBITS(LCD_BPP) / 8;
for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
uchar *s = str;
int i;
-#if LCD_BPP == LCD_COLOR24
- ulong *d = dest;
-#elif LCD_BPP == LCD_COLOR16
- ushort *d = dest;
+#if LCD_BPP == LCD_COLOR16
+ ushort *d = (ushort *)dest;
+#elif LCD_BPP == LCD_COLOR32
+ u32 *d = (u32 *)dest;
#else
uchar *d = dest;
#endif
*d++ = rest | (sym >> off);
rest = sym << (8-off);
- #elif LCD_BPP == LCD_COLOR8
- for (c = 0; c < 8; ++c) {
- *d++ = (bits & 0x80) ?
- lcd_color_fg : lcd_color_bg;
- bits <<= 1;
- }
- #elif LCD_BPP == LCD_COLOR16
- for (c = 0; c < 8; ++c) {
- *d++ = (bits & 0x80) ?
- lcd_color_fg : lcd_color_bg;
- bits <<= 1;
- }
- #elif LCD_BPP == LCD_COLOR32
+ #else
for (c = 0; c < 8; ++c) {
*d++ = (bits & 0x80) ?
lcd_color_fg : lcd_color_bg;
}
}
-/*----------------------------------------------------------------------*/
-
-static inline void lcd_puts_xy(ushort x, ushort y, uchar *s)
-{
- lcd_drawchars(x, y, s, strlen((char *)s));
-}
-
-/*----------------------------------------------------------------------*/
-
static inline void lcd_putc_xy(ushort x, ushort y, uchar c)
{
lcd_drawchars(x, y, &c, 1);
CONSOLE_COLOR_BLUE, CONSOLE_COLOR_MAGENTA, CONSOLE_COLOR_CYAN,
};
-#elif LCD_BPP == LCD_COLOR24
+ #if LCD_BPP == LCD_COLOR8
+ typedef uchar pix_t;
+ #elif LCD_BPP == LCD_COLOR16
+ typedef ushort pix_t;
++#elif LCD_BPP == LCD_COLOR32
+ typedef ulong pix_t;
+ #else
+ #error Unsupported pixelformat
+ #endif
+
static void test_pattern(void)
{
ushort v_max = panel_info.vl_row;
ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT;
ushort h_step = (h_max + N_BLK_HOR - 1) / N_BLK_HOR;
ushort v, h;
- uchar *pix = (uchar *)lcd_base;
+ pix_t *pix = lcd_base;
printf("[LCD] Test Pattern: %d x %d [%d x %d]\n",
h_max, v_max, h_step, v_step);
/************************************************************************/
/* ** GENERIC Initialization Routines */
/************************************************************************/
-
-int lcd_get_size(int *line_length)
+/*
+ * With most lcd drivers the line length is set up
+ * by calculating it from panel_info parameters. Some
+ * drivers need to calculate the line length differently,
+ * so make the function weak to allow overriding it.
+ */
+__weak int lcd_get_size(int *line_length)
{
*line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
return *line_length * panel_info.vl_row;
struct stdio_dev lcddev;
int rc;
- lcd_base = (void *)gd->fb_base;
+ lcd_base = map_sysmem(gd->fb_base, 0);
lcd_init(lcd_base); /* LCD initialization */
strcpy(lcddev.name, "lcd");
lcddev.ext = 0; /* No extensions */
lcddev.flags = DEV_FLAGS_OUTPUT; /* Output only */
- lcddev.putc = lcd_putc; /* 'putc' function */
- lcddev.puts = lcd_puts; /* 'puts' function */
+ lcddev.putc = lcd_stub_putc; /* 'putc' function */
+ lcddev.puts = lcd_stub_puts; /* 'puts' function */
rc = stdio_register(&lcddev);
test_pattern();
#else
/* set framebuffer to background color */
+#if (LCD_BPP != LCD_COLOR32)
memset((char *)lcd_base,
- COLOR_MASK(lcd_getbgcolor()),
+ COLOR_MASK(lcd_color_bg),
lcd_line_length * panel_info.vl_row);
+#else
+ u32 *ppix = lcd_base;
+ u32 i;
+ for (i = 0;
+ i < (lcd_line_length * panel_info.vl_row)/NBYTES(panel_info.vl_bpix);
+ i++) {
+ *ppix++ = COLOR_MASK(lcd_color_bg);
+ }
+#endif
#endif
/* Paint the logo and retrieve LCD base address */
- debug("[LCD] Drawing the logo...\n");
+ debug("[LCD] Drawing the logo @ %p...\n", lcd_base);
lcd_console_address = lcd_logo();
console_col = 0;
static int lcd_init(void *lcdbase)
{
/* Initialize the lcd controller */
- debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
+ debug("[LCD] Initializing %ux%ux%u LCD framebuffer at %p\n",
+ panel_info.vl_col, panel_info.vl_row, NBITS(panel_info.vl_bpix),
+ lcdbase);
lcd_ctrl_init(lcdbase);
/*
- * lcd_ctrl_init() of some drivers (i.e. bcm2835 on rpi_b) ignores
+ * lcd_ctrl_init() of some drivers (i.e. bcm2835 on rpi) ignores
* the 'lcdbase' argument and uses custom lcd base address
* by setting up gd->fb_base. Check for this condition and fixup
* 'lcd_base' address.
*/
- if ((unsigned long)lcdbase != gd->fb_base)
- lcd_base = (void *)gd->fb_base;
+ if (map_to_sysmem(lcdbase) != gd->fb_base)
+ lcd_base = map_sysmem(gd->fb_base, 0);
debug("[LCD] Using LCD frambuffer at %p\n", lcd_base);
lcd_get_size(&lcd_line_length);
- lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
lcd_is_enabled = 1;
lcd_clear();
lcd_enable();
lcd_color_bg = color;
}
-/*----------------------------------------------------------------------*/
-
-int lcd_getfgcolor(void)
-{
- return lcd_color_fg;
-}
-
-/*----------------------------------------------------------------------*/
-
-static inline int lcd_getbgcolor(void)
-{
- return lcd_color_bg;
-}
-
/************************************************************************/
/* ** Chipset depending Bitmap / Logo stuff... */
/************************************************************************/
struct pxafb_info *fbi = &panel_info.pxa;
return (ushort *)fbi->palette;
#elif defined(CONFIG_MPC823)
- immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
cpm8xx_t *cp = &(immr->im_cpm);
return (ushort *)&(cp->lcd_cmap[255 * sizeof(ushort)]);
#elif defined(CONFIG_ATMEL_LCD)
uchar *fb;
ushort *fb16;
#if defined(CONFIG_MPC823)
- immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
cpm8xx_t *cp = &(immr->im_cpm);
#endif
unsigned bpix = NBITS(panel_info.vl_bpix);
bmap += BMP_LOGO_WIDTH;
fb += panel_info.vl_col;
}
- }
- else { /* true color mode */
+ } else if (NBITS(panel_info.vl_bpix) == 16) {
u16 col16;
fb16 = (ushort *)fb;
for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {
bmap += BMP_LOGO_WIDTH;
fb16 += panel_info.vl_col;
}
+ } else { /* true color mode */
+ u16 col16;
+ u32 *fb32 = lcd_base + y * lcd_line_length + x;
+
+ for (i = 0; i < BMP_LOGO_HEIGHT; i++) {
+ for (j = 0; j < BMP_LOGO_WIDTH; j++) {
+ col16 = bmp_logo_palette[bmap[j] - 16];
+ fb32[j] =
+ ((col16 & 0x000F) << 4) |
+ ((col16 & 0x00F0) << 8) |
+ ((col16 & 0x0F00) << 12);
+ }
+ bmap += BMP_LOGO_WIDTH;
+ fb32 += panel_info.vl_col;
+ }
}
WATCHDOG_RESET();
else
return;
- *axis = max(0, axis_alignment);
+ *axis = max(0, (int)axis_alignment);
}
#endif
int x, y;
int decode = 1;
- width = le32_to_cpu(bmp->header.width);
- height = le32_to_cpu(bmp->header.height);
- bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset);
+ width = get_unaligned_le32(&bmp->header.width);
+ height = get_unaligned_le32(&bmp->header.height);
+ bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
x = 0;
y = height - 1;
}
#endif
-#if defined(CONFIG_MPC823) || defined(CONFIG_MCC200)
+#if defined(CONFIG_MPC823)
#define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)
#else
#define FB_PUT_BYTE(fb, from) *(fb)++ = *(from)++
#endif
#endif /* CONFIG_BMP_16BPP */
+ static inline bmp_color_table_entry_t *get_color_table(bmp_image_t *bmp)
+ {
+ bmp_header_t *bh = &bmp->header;
+ return (void *)bmp + offsetof(bmp_header_t, size) + bh->size;
+ }
+
int lcd_display_bitmap(ulong bmp_image, int x, int y)
{
-#if !defined(CONFIG_MCC200)
ushort *cmap = NULL;
-#endif
ushort *cmap_base = NULL;
ushort i, j;
uchar *fb;
- bmp_image_t *bmp=(bmp_image_t *)bmp_image;
+ bmp_image_t *bmp = (bmp_image_t *)map_sysmem(bmp_image, 0);
uchar *bmap;
ushort padded_width;
- unsigned long width, height, byte_width;
+ unsigned long width, height;
unsigned long pwidth = panel_info.vl_col;
- unsigned colors, bpix, bmp_bpix;
+ unsigned long long colors;
+ unsigned bpix, bmp_bpix;
+ bmp_color_table_entry_t *cte;
if (!bmp || !(bmp->header.signature[0] == 'B' &&
bmp->header.signature[1] == 'M')) {
return 1;
}
- width = le32_to_cpu(bmp->header.width);
- height = le32_to_cpu(bmp->header.height);
- bmp_bpix = le16_to_cpu(bmp->header.bit_count);
- colors = 1ULL << bmp_bpix;
+ width = get_unaligned_le32(&bmp->header.width);
+ height = get_unaligned_le32(&bmp->header.height);
+ bmp_bpix = get_unaligned_le16(&bmp->header.bit_count);
+
+ colors = 1 << bmp_bpix;
bpix = NBITS(panel_info.vl_bpix);
return 1;
}
- /* We support displaying 8bpp BMPs on 16bpp or 32bpp LCDs */
- if (bpix != bmp_bpix && (bmp_bpix != 8 || (bpix != 16 && bpix != 32))) {
+ /*
+ * We support displaying 8bpp BMPs on 16bpp LCDs
+ * and displaying 24bpp BMPs on 32bpp LCDs
+ * */
+ if (bpix != bmp_bpix &&
+ !(bmp_bpix == 8 && bpix == 16) &&
+ !(bmp_bpix == 24 && bpix == 32)) {
printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
- bpix,
- le16_to_cpu(bmp->header.bit_count));
-
+ bpix, get_unaligned_le16(&bmp->header.bit_count));
return 1;
}
- debug("Display-bmp: %d x %d with %d colors\n",
- (int)width, (int)height, (int)colors);
+ debug("Display-bmp: %lu x %lu with %llu colors\n",
+ width, height, colors);
-#if !defined(CONFIG_MCC200)
- /* MCC200 LCD doesn't need CMAP, supports 1bpp b&w only */
+ cte = get_color_table(bmp);
if (bmp_bpix == 8) {
cmap = configuration_get_cmap();
cmap_base = cmap;
/* Set color map */
for (i = 0; i < colors; ++i) {
- bmp_color_table_entry_t cte = bmp->color_table[i];
#if !defined(CONFIG_ATMEL_LCD)
ushort colreg =
- ( ((cte.red) << 8) & 0xf800) |
- ( ((cte.green) << 3) & 0x07e0) |
- ( ((cte.blue) >> 3) & 0x001f) ;
+ ( ((cte[i].red) << 8) & 0xf800) |
+ ( ((cte[i].green) << 3) & 0x07e0) |
+ ( ((cte[i].blue) >> 3) & 0x001f) ;
#ifdef CONFIG_SYS_INVERT_COLORS
*cmap = 0xffff - colreg;
#else
cmap++;
#endif
#else /* CONFIG_ATMEL_LCD */
- lcd_setcolreg(i, cte.red, cte.green, cte.blue);
+ lcd_setcolreg(i, cte[i].red, cte[i].green, cte[i].blue);
#endif
}
}
-#endif
-
- /*
- * BMP format for Monochrome assumes that the state of a
- * pixel is described on a per Bit basis, not per Byte.
- * So, in case of Monochrome BMP we should align widths
- * on a byte boundary and convert them from Bit to Byte
- * units.
- * Probably, PXA250 and MPC823 process 1bpp BMP images in
- * their own ways, so make the converting to be MCC200
- * specific.
- */
-#if defined(CONFIG_MCC200)
- if (bpix == 1) {
- width = ALIGN(width, 8) >> 3;
- x = ALIGN(x, 8) >> 3;
- pwidth= ALIGN(pwidth, 8) >> 3;
- }
-#endif
- padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width);
+ padded_width = ALIGN(width, 4);
#ifdef CONFIG_SPLASH_SCREEN_ALIGN
splash_align_axis(&x, pwidth, width);
splash_align_axis(&y, panel_info.vl_row, height);
#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
- bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset);
++ bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
if ((x + width) > pwidth)
width = pwidth - x;
- if ((y + height) > panel_info.vl_row)
+ if ((y + height) > panel_info.vl_row) {
height = panel_info.vl_row - y;
+ bmap += (panel_info.vl_row - y) * padded_width;
+ }
- bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
fb = (uchar *)(lcd_base +
(y + height - 1) * lcd_line_length + x * bpix / 8);
switch (bmp_bpix) {
case 1: /* pass through */
- case 8:
+ case 8: {
#ifdef CONFIG_LCD_BMP_RLE8
- if (le32_to_cpu(bmp->header.compression) == BMP_BI_RLE8) {
+ u32 compression = get_unaligned_le32(&bmp->header.compression);
+ if (compression == BMP_BI_RLE8) {
if (bpix != 16) {
/* TODO implement render code for bpix != 16 */
printf("Error: only support 16 bpix");
}
#endif
- if (bpix != 16)
- byte_width = width;
- else
- byte_width = width * 2;
-
for (i = 0; i < height; ++i) {
WATCHDOG_RESET();
for (j = 0; j < width; j++) {
- if (bpix != 16) {
- FB_PUT_BYTE(fb, bmap);
- } else {
+ if (bpix == 32) {
+ int i = *bmap++;
+
+ fb[3] = 0; /* T */
+ fb[0] = cte[i].blue;
+ fb[1] = cte[i].green;
+ fb[2] = cte[i].red;
+ fb += sizeof(uint32_t) / sizeof(*fb);
+ } else if (bpix == 16) {
*(uint16_t *)fb = cmap_base[*(bmap++)];
fb += sizeof(uint16_t) / sizeof(*fb);
+ } else {
+ FB_PUT_BYTE(fb, bmap);
}
}
- bmap += (padded_width - width);
- fb -= byte_width + lcd_line_length;
+ if (bpix > 8) {
+ bmap += padded_width - width;
+ fb -= width * bpix / 8 + lcd_line_length;
+ } else {
+ bmap += padded_width;
+ fb -= lcd_line_length;
+ }
}
break;
-
+ }
#if defined(CONFIG_BMP_16BPP)
case 16:
for (i = 0; i < height; ++i) {
}
break;
#endif /* CONFIG_BMP_16BPP */
- #endif /* CONFIG_BMP_24BMP */
+#if defined(CONFIG_BMP_24BMP)
+ case 24:
+ for (i = 0; i < height; ++i) {
+ for (j = 0; j < width; j++) {
+ *(fb++) = *(bmap++);
+ *(fb++) = *(bmap++);
+ *(fb++) = *(bmap++);
+ *(fb++) = 0;
+ }
+ fb -= lcd_line_length + width * (bpix / 8);
+ }
+ break;
++#endif /* CONFIG_BMP_24BPP */
+#if defined(CONFIG_BMP_32BPP)
case 32:
for (i = 0; i < height; ++i) {
+ WATCHDOG_RESET();
for (j = 0; j < width; j++) {
- *(fb++) = *(bmap++);
- *(fb++) = *(bmap++);
- *(fb++) = *(bmap++);
- *(fb++) = *(bmap++);
+ fb[3] = *bmap++; /* T */
+ fb[0] = *bmap++; /* B */
+ fb[1] = *bmap++; /* G */
+ fb[2] = *bmap++; /* R */
+ fb += 4;
}
+ bmap += (padded_width - width) * 4;
fb -= lcd_line_length + width * (bpix / 8);
}
break;
- default:
- break;
+#endif /* CONFIG_BMP_32BPP */
};
- lcd_sync();
return 0;
}
#endif
if (do_splash && (s = getenv("splashimage")) != NULL) {
int x = 0, y = 0;
+ char *end;
+
do_splash = 0;
if (splash_screen_prepare())
return (void *)lcd_base;
- addr = simple_strtoul (s, NULL, 16);
+ addr = simple_strtoul (s, &end, 16);
+ if (addr == 0 || *end != '\0')
+ return lcd_base;
splash_get_pos(&x, &y);
#endif /* CONFIG_LCD_INFO */
#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
- return (void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length);
+ return lcd_base + BMP_LOGO_HEIGHT * lcd_line_length;
#else
- return (void *)lcd_base;
- #endif /* CONFIG_LCD_LOGO && !defined(CONFIG_LCD_INFO_BELOW_LOGO) */
+ return lcd_base;
+ #endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */
}
#ifdef CONFIG_SPLASHIMAGE_GUARD
void lcd_position_cursor(unsigned col, unsigned row)
{
- console_col = min(col, CONSOLE_COLS - 1);
- console_row = min(row, CONSOLE_ROWS - 1);
+ console_col = min_t(short, col, CONSOLE_COLS - 1);
+ console_row = min_t(short, row, CONSOLE_ROWS - 1);
}
int lcd_get_pixel_width(void)
#if defined(CONFIG_LCD_DT_SIMPLEFB)
static int lcd_dt_simplefb_configure_node(void *blob, int off)
{
- u32 stride;
- fdt32_t cells[2];
- int ret;
- static const char format[] =
#if LCD_BPP == LCD_COLOR16
- "r5g6b5";
+ return fdt_setup_simplefb_node(blob, off, gd->fb_base,
+ panel_info.vl_col, panel_info.vl_row,
+ panel_info.vl_col * 2, "r5g6b5");
#else
- "";
+ return -1;
#endif
-
- if (!format[0])
- return -1;
-
- stride = panel_info.vl_col * 2;
-
- cells[0] = cpu_to_fdt32(gd->fb_base);
- cells[1] = cpu_to_fdt32(stride * panel_info.vl_row);
- ret = fdt_setprop(blob, off, "reg", cells, sizeof(cells[0]) * 2);
- if (ret < 0)
- return -1;
-
- cells[0] = cpu_to_fdt32(panel_info.vl_col);
- ret = fdt_setprop(blob, off, "width", cells, sizeof(cells[0]));
- if (ret < 0)
- return -1;
-
- cells[0] = cpu_to_fdt32(panel_info.vl_row);
- ret = fdt_setprop(blob, off, "height", cells, sizeof(cells[0]));
- if (ret < 0)
- return -1;
-
- cells[0] = cpu_to_fdt32(stride);
- ret = fdt_setprop(blob, off, "stride", cells, sizeof(cells[0]));
- if (ret < 0)
- return -1;
-
- ret = fdt_setprop(blob, off, "format", format, strlen(format) + 1);
- if (ret < 0)
- return -1;
-
- ret = fdt_delprop(blob, off, "status");
- if (ret < 0)
- return -1;
-
- return 0;
}
int lcd_dt_simplefb_add_node(void *blob)
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include <dm.h>
#include <spl.h>
#include <asm/u-boot.h>
#include <nand.h>
#include <i2c.h>
#include <image.h>
#include <malloc.h>
+#include <dm/root.h>
#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE
#endif
#ifndef CONFIG_SYS_MONITOR_LEN
+/* Unknown U-Boot size, let's assume it will not be more than 200 KB */
#define CONFIG_SYS_MONITOR_LEN (200 * 1024)
#endif
/* Nothing to do! */
}
+void spl_set_header_raw_uboot(void)
+{
+ spl_image.size = CONFIG_SYS_MONITOR_LEN;
+ spl_image.entry_point = CONFIG_SYS_UBOOT_START;
+ spl_image.load_addr = CONFIG_SYS_TEXT_BASE;
+ spl_image.os = IH_OS_U_BOOT;
+ spl_image.name = "U-Boot";
+}
+
void spl_parse_image_header(const struct image_header *header)
{
u32 header_size = sizeof(struct image_header);
}
spl_image.os = image_get_os(header);
spl_image.name = image_get_name(header);
- debug("spl: payload image: %s load addr: 0x%x size: %d\n",
- spl_image.name, spl_image.load_addr, spl_image.size);
+ debug("spl: payload image: %.*s load addr: 0x%x size: %d\n",
+ (int)sizeof(spl_image.name), spl_image.name,
+ spl_image.load_addr, spl_image.size);
} else {
/* Signature not found - assume u-boot.bin */
debug("mkimage signature not found - ih_magic = %x\n",
header->ih_magic);
- /* Let's assume U-Boot will not be more than 200 KB */
- spl_image.size = CONFIG_SYS_MONITOR_LEN;
- spl_image.entry_point = CONFIG_SYS_UBOOT_START;
- spl_image.load_addr = CONFIG_SYS_TEXT_BASE;
- spl_image.os = IH_OS_U_BOOT;
- spl_image.name = "U-Boot";
+ spl_set_header_raw_uboot();
}
}
u32 boot_device;
debug(">>spl:board_init_r()\n");
-#ifdef CONFIG_SYS_SPL_MALLOC_START
+#if defined(CONFIG_SYS_SPL_MALLOC_START)
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
CONFIG_SYS_SPL_MALLOC_SIZE);
+ gd->flags |= GD_FLG_FULL_MALLOC_INIT;
+#elif defined(CONFIG_SYS_MALLOC_F_LEN)
+ gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
+ gd->malloc_ptr = 0;
+#endif
+#ifdef CONFIG_SPL_DM
+ dm_init_and_scan(true);
#endif
#ifndef CONFIG_PPC
#endif
#ifdef CONFIG_SPL_NAND_SUPPORT
case BOOT_DEVICE_NAND:
- spl_nand_load_image();
- break;
+ if (spl_nand_load_image() == 0)
+ break;
+ /* fallthru in case of failure to activate ymodem download */
#endif
#ifdef CONFIG_SPL_ONENAND_SUPPORT
case BOOT_DEVICE_ONENAND:
case BOOT_DEVICE_USBETH:
spl_net_load_image("usb_ether");
break;
+#endif
+#ifdef CONFIG_SPL_USB_SUPPORT
+ case BOOT_DEVICE_USB:
+ spl_usb_load_image();
+ break;
+#endif
+#ifdef CONFIG_SPL_SATA_SUPPORT
+ case BOOT_DEVICE_SATA:
+ spl_sata_load_image();
+ break;
#endif
default:
- printf("SPL: Unsupported Boot Device\n");
+#if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+ printf("SPL: Unsupported Boot Device %d\n", boot_device);
+#endif
hang();
}
default:
debug("Unsupported OS image.. Jumping nevertheless..\n");
}
+#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE)
+ debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr,
+ gd->malloc_ptr / 1024);
+#endif
+
jump_to_image_no_args(&spl_image);
}
#include <asm/io.h>
#include <nand.h>
- void spl_nand_load_image(void)
+#if defined(CONFIG_SPL_NAND_RAW_ONLY)
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
++int spl_nand_load_image(void)
+{
++ int ret;
++
+ nand_init();
+
- spl_set_header_raw_uboot();
++ ret = nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+ CONFIG_SYS_NAND_U_BOOT_SIZE,
+ (void *)CONFIG_SYS_NAND_U_BOOT_DST);
- void spl_nand_load_image(void)
+ nand_deselect();
++ if (ret)
++ return ret;
++
++ spl_set_header_raw_uboot();
++ return 0;
+}
+#else
+ int spl_nand_load_image(void)
{
+ int ret;
struct image_header *header;
int *src __attribute__((unused));
int *dst __attribute__((unused));
nand_init();
/*use CONFIG_SYS_TEXT_BASE as temporary storage area */
- header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
+ header = (struct image_header *)CONFIG_SYS_TEXT_BASE;
#ifdef CONFIG_SPL_OS_BOOT
if (!spl_start_uboot()) {
/*
/* load linux */
nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
- CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+ sizeof(*header), (void *)header);
spl_parse_image_header(header);
if (header->ih_os == IH_OS_LINUX) {
/* happy - was a linux */
nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
spl_image.size, (void *)spl_image.load_addr);
nand_deselect();
- return;
+ return 0;
} else {
- puts("The Expected Linux image was not "
- "found. Please check your NAND "
+ printf("The Expected Linux image was not"
+ "found. Please check your NAND"
"configuration.\n");
- puts("Trying to start u-boot now...\n");
+ printf("Trying to start u-boot now...\n");
}
}
#endif
#ifdef CONFIG_NAND_ENV_DST
nand_spl_load_image(CONFIG_ENV_OFFSET,
- CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+ sizeof(*header), (void *)header);
spl_parse_image_header(header);
nand_spl_load_image(CONFIG_ENV_OFFSET, spl_image.size,
(void *)spl_image.load_addr);
#ifdef CONFIG_ENV_OFFSET_REDUND
nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND,
- CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+ sizeof(*header), (void *)header);
spl_parse_image_header(header);
nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, spl_image.size,
(void *)spl_image.load_addr);
#endif
#endif
/* Load u-boot */
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
- sizeof(*header), (void *)header);
- spl_parse_image_header(header);
- nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
- spl_image.size, (void *)spl_image.load_addr);
+ ret = nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+ CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+ if (ret == 0) {
+ spl_parse_image_header(header);
+ ret = nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+ spl_image.size, (void *)spl_image.load_addr);
+ }
nand_deselect();
+ return ret;
}
+#endif
#define BSP 0x08
#define NAK 0x15
#define CAN 0x18
- #define EOF 0x1A /* ^Z for DOS officionados */
+ #define EOF 0x1A /* ^Z for DOS aficionados */
#define USE_YMODEM_LENGTH
static int
zm_dprintf (char *fmt, ...)
{
- int cur_console;
+ int cur_console __attribute__((unused));
va_list args;
va_start (args, fmt);
#ifdef REDBOOT
CYGACC_CALL_IF_SET_CONSOLE_COMM (cur_console);
#endif
+ return 0;
}
- static void
+ static inline void
zm_flush (void)
{
}
return len;
}
- static void
+ static inline void
zm_flush (void)
{
#ifdef REDBOOT
static unsigned char zm_buf[2048];
static unsigned char *zm_bp;
- static void
+ static inline void
zm_new (void)
{
zm_bp = zm_buf;
}
- static void
+ static inline void
zm_save (unsigned char c)
{
*zm_bp++ = c;
}
- static void
+ static inline void
zm_dump (int line)
{
zm_dprintf ("Packet at line: %d\n", line);
* If we don't eat it now, RedBoot will think the user typed it.
*/
ZM_DEBUG (zm_dprintf ("Trailing gunk:\n"));
- while ((c = (*getc) ()) > -1);
+ while ((c = (*getc) ()) > -1)
+ ;
ZM_DEBUG (zm_dprintf ("\n"));
/*
* Make a small delay to give terminal programs like minicom
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28,SDRAM_SIZE=SZ_128M
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28,SDRAM_SIZE=SZ_128M,ENV_IS_NOWHERE
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28,SDRAM_SIZE=SZ_256M
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28,SDRAM_SIZE=SZ_256M,ENV_IS_NOWHERE
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28,SDRAM_SIZE=SZ_128M,SYS_NAND_BLOCKS=2048
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28,SDRAM_SIZE=SZ_128M,SYS_NAND_BLOCKS=2048,ENV_IS_NOWHERE
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28_S,SDRAM_SIZE=SZ_64M
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX28_S,SDRAM_SIZE=SZ_64M,ENV_IS_NOWHERE
++CONFIG_ARM=y
++CONFIG_TARGET_TX28=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_MPU_CLK=720,SYS_DDR_CLK=400
++CONFIG_ARM=y
++CONFIG_TARGET_TX48=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_CPU_CLK=800,NR_DRAM_BANKS=1
++CONFIG_ARM=y
++CONFIG_TARGET_TX51=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_CPU_CLK=800,NR_DRAM_BANKS=2
++CONFIG_ARM=y
++CONFIG_TARGET_TX51=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=NR_DRAM_BANKS=2,SYS_SDRAM_SIZE=SZ_2G
++CONFIG_ARM=y
++CONFIG_TARGET_TX53=y
++CONFIG_TARGET_TX53_1232=y
++CONFIG_TX53_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_ENV_IS_IN_NAND=y
++CONFIG_FEC_MXC_PHYADDR=0
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=NR_DRAM_BANKS=1
++CONFIG_ARM=y
++CONFIG_TARGET_TX53=y
++CONFIG_TARGET_TX53_X030=y
++CONFIG_TX53_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_CMD_I2C=y
++CONFIG_ENV_IS_IN_NAND=y
++CONFIG_FEC_MXC_PHYADDR=0
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=NR_DRAM_BANKS=1,SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_TARGET_TX53=y
++CONFIG_TARGET_TX53_X130=y
++CONFIG_TX53_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_ENV_IS_IN_NAND=y
++CONFIG_FEC_MXC_PHYADDR=0
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=NR_DRAM_BANKS=2,SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_TARGET_TX53=y
++CONFIG_TARGET_TX53_X131=y
++CONFIG_TX53_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_ENV_IS_IN_NAND=y
++CONFIG_FEC_MXC_PHYADDR=0
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX6_REV=0x2
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_1020=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX6_REV=0x2
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_1020=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=TX6_REV=0x2
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_1020=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_10X0=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_10X0=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_10X0=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_11X0=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_11X0=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_MX6Q=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6Q_11X0=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=16
++CONFIG_ARM=y
++CONFIG_MX6S=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6S_8034=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=16
++CONFIG_ARM=y
++CONFIG_MX6S=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6S_8034=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=16
++CONFIG_ARM=y
++CONFIG_MX6S=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6S_8034=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=MMC_BOOT_SIZE=1024,SYS_SDRAM_BUS_WIDTH=32
++CONFIG_ARM=y
++CONFIG_MX6S=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6S_8035=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=MMC_BOOT_SIZE=1024,SYS_SDRAM_BUS_WIDTH=32
++CONFIG_ARM=y
++CONFIG_MX6S=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6S_8035=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=MMC_BOOT_SIZE=1024,SYS_SDRAM_BUS_WIDTH=32
++CONFIG_ARM=y
++CONFIG_MX6S=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6S_8035=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=32
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8011=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=32
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8011=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=32
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8011=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_NAND_BLOCKS=2048
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8012=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_NAND_BLOCKS=2048
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8012=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_NAND_BLOCKS=2048
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8012=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=MMC_BOOT_SIZE=1024
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8033=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=MMC_BOOT_SIZE=1024
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8033=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=MMC_BOOT_SIZE=1024
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_8033=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_80X0=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_80X0=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_80X0=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=32,SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_81X0=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=32,SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_81X0=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_SYS_EXTRA_OPTIONS=SYS_SDRAM_BUS_WIDTH=32,SYS_LVDS_IF
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_81X0=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_81X0=y
++CONFIG_TX6_UBOOT=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_81X0=y
++CONFIG_TX6_UBOOT_MFG=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
--- /dev/null
--- /dev/null
++CONFIG_ARM=y
++CONFIG_MX6DL=y
++CONFIG_TARGET_TX6=y
++CONFIG_TARGET_TX6U_81X0=y
++CONFIG_TX6_UBOOT_NOENV=y
++CONFIG_CMD_MII=y
++CONFIG_CMD_DHCP=y
++CONFIG_CMD_PING=y
++CONFIG_BOOTP_SUBNETMASK=y
++CONFIG_BOOTP_GATEWAY=y
++CONFIG_BOOTP_DNS=y
++CONFIG_MMC=y
++CONFIG_FSL_ESDHC=y
++CONFIG_FSL_USDHC=y
++CONFIG_LCD=y
++CONFIG_NET=y
++CONFIG_NETDEVICES=y
++CONFIG_FEC_MXC=y
++CONFIG_IMX_WATCHDOG=y
++CONFIG_CMD_I2C=y
++CONFIG_NAND=y
++CONFIG_NAND_MXS=y
struct block_drvr {
char *name;
block_dev_desc_t* (*get_dev)(int dev);
+ int (*select_hwpart)(int dev_num, int hwpart);
};
static const struct block_drvr block_drvr[] = {
#if defined(CONFIG_CMD_IDE)
{ .name = "ide", .get_dev = ide_get_dev, },
#endif
+ #if defined(CONFIG_CMD_PATA)
+ { .name = "pata", .get_dev = pata_get_dev, },
+ #endif
#if defined(CONFIG_CMD_SATA)
{.name = "sata", .get_dev = sata_get_dev, },
#endif
{ .name = "usb", .get_dev = usb_stor_get_dev, },
#endif
#if defined(CONFIG_MMC)
- { .name = "mmc", .get_dev = mmc_get_dev, },
+ {
+ .name = "mmc",
+ .get_dev = mmc_get_dev,
+ .select_hwpart = mmc_select_hwpart,
+ },
#endif
#if defined(CONFIG_SYSTEMACE)
{ .name = "ace", .get_dev = systemace_get_dev, },
+#endif
+#if defined(CONFIG_SANDBOX)
+ { .name = "host", .get_dev = host_get_dev, },
#endif
{ },
};
DECLARE_GLOBAL_DATA_PTR;
#ifdef HAVE_BLOCK_DEVICE
-block_dev_desc_t *get_dev(const char *ifname, int dev)
+static block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
{
const struct block_drvr *drvr = block_drvr;
block_dev_desc_t* (*reloc_get_dev)(int dev);
+ int (*select_hwpart)(int dev_num, int hwpart);
char *name;
+ int ret;
if (!ifname)
return NULL;
while (drvr->name) {
name = drvr->name;
reloc_get_dev = drvr->get_dev;
+ select_hwpart = drvr->select_hwpart;
#ifdef CONFIG_NEEDS_MANUAL_RELOC
name += gd->reloc_off;
reloc_get_dev += gd->reloc_off;
+ if (select_hwpart)
+ select_hwpart += gd->reloc_off;
#endif
- if (strncmp(ifname, name, strlen(name)) == 0)
- return reloc_get_dev(dev);
+ if (strncmp(ifname, name, strlen(name)) == 0) {
+ block_dev_desc_t *dev_desc = reloc_get_dev(dev);
+ if (!dev_desc)
+ return NULL;
+ if (hwpart == 0 && !select_hwpart)
+ return dev_desc;
+ if (!select_hwpart)
+ return NULL;
+ ret = select_hwpart(dev_desc->dev, hwpart);
+ if (ret < 0)
+ return NULL;
+ return dev_desc;
+ }
drvr++;
}
return NULL;
}
+
+block_dev_desc_t *get_dev(const char *ifname, int dev)
+{
+ return get_dev_hwpart(ifname, dev, 0);
+}
#else
+block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
+{
+ return NULL;
+}
+
block_dev_desc_t *get_dev(const char *ifname, int dev)
{
return NULL;
* Overflowless variant of (block_count * mul_by / div_by)
* when div_by > mul_by
*/
-static lba512_t lba512_muldiv (lba512_t block_count, lba512_t mul_by, lba512_t div_by)
+static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by)
{
lba512_t bc_quot, bc_rem;
lba512 = (lba * (dev_desc->blksz/512));
/* round to 1 digit */
- mb = lba512_muldiv(lba512, 10, 2048); /* 2048 = (1024 * 1024) / 512 MB */
+ /* 2048 = (1024 * 1024) / 512 MB */
+ mb = lba512_muldiv(lba512, 10, 2048);
mb_quot = mb / 10;
mb_rem = mb - (10 * mb_quot);
#ifdef HAVE_BLOCK_DEVICE
-void init_part (block_dev_desc_t * dev_desc)
+void init_part(block_dev_desc_t *dev_desc)
{
#ifdef CONFIG_ISO_PARTITION
if (test_part_iso(dev_desc) == 0) {
defined(CONFIG_AMIGA_PARTITION) || \
defined(CONFIG_EFI_PARTITION)
-static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
+static void print_part_header(const char *type, block_dev_desc_t *dev_desc)
{
puts ("\nPartition Map for ");
switch (dev_desc->if_type) {
case IF_TYPE_MMC:
puts ("MMC");
break;
+ case IF_TYPE_HOST:
+ puts("HOST");
+ break;
default:
puts ("UNKNOWN");
break;
#endif /* any CONFIG_..._PARTITION */
-void print_part (block_dev_desc_t * dev_desc)
+void print_part(block_dev_desc_t * dev_desc)
{
switch (dev_desc->part_type) {
#endif /* HAVE_BLOCK_DEVICE */
-int get_partition_info(block_dev_desc_t *dev_desc, int part
- , disk_partition_t *info)
+int get_partition_info(block_dev_desc_t *dev_desc, int part,
+ disk_partition_t *info)
{
#ifdef HAVE_BLOCK_DEVICE
return -1;
}
-int get_device(const char *ifname, const char *dev_str,
+int get_device(const char *ifname, const char *dev_hwpart_str,
block_dev_desc_t **dev_desc)
{
char *ep;
- int dev;
+ char *dup_str = NULL;
+ const char *dev_str, *hwpart_str;
+ int dev, hwpart;
+
+ hwpart_str = strchr(dev_hwpart_str, '.');
+ if (hwpart_str) {
+ dup_str = strdup(dev_hwpart_str);
+ dup_str[hwpart_str - dev_hwpart_str] = 0;
+ dev_str = dup_str;
+ hwpart_str++;
+ } else {
+ dev_str = dev_hwpart_str;
+ hwpart = 0;
+ }
dev = simple_strtoul(dev_str, &ep, 16);
if (*ep) {
printf("** Bad device specification %s %s **\n",
ifname, dev_str);
- return -1;
+ dev = -1;
+ goto cleanup;
+ }
+
+ if (hwpart_str) {
+ hwpart = simple_strtoul(hwpart_str, &ep, 16);
+ if (*ep) {
+ printf("** Bad HW partition specification %s %s **\n",
+ ifname, hwpart_str);
+ dev = -1;
+ goto cleanup;
+ }
}
- *dev_desc = get_dev(ifname, dev);
+ *dev_desc = get_dev_hwpart(ifname, dev, hwpart);
if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
- printf("** Bad device %s %s **\n", ifname, dev_str);
- return -1;
+ printf("** Bad device %s %s **\n", ifname, dev_hwpart_str);
+ dev = -1;
+ goto cleanup;
}
+cleanup:
+ free(dup_str);
return dev;
}
disk_partition_t tmpinfo;
/*
- * For now, we have a special case for sandbox, since there is no
- * real block device support.
+ * Special-case a pseudo block device "hostfs", to allow access to the
+ * host's own filesystem.
*/
- if (0 == strcmp(ifname, "host")) {
+ if (0 == strcmp(ifname, "hostfs")) {
*dev_desc = NULL;
- info->start = info->size = info->blksz = 0;
+ info->start = 0;
+ info->size = 0;
+ info->blksz = 0;
info->bootable = 0;
strcpy((char *)info->type, BOOT_PART_TYPE);
strcpy((char *)info->name, "Sandbox host");
--- /dev/null
++config APBH_DMA
++ bool "Freescale MXS and i.MX6 APBH DMA support"
++ default y
++ depends on MX28 || MX6
++
++config APBH_DMA_BURST
++ bool "Enable DMA burst mode"
++ default y
++ depends on APBH_DMA
++
++config APBH_DMA_BURST8
++ bool "Use 8-beat DMA bursts"
++ default y
++ depends on APBH_DMA_BURST
#include <asm/imx-common/regs-apbh.h>
static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS];
+ static struct mxs_apbh_regs *apbh_regs = (struct mxs_apbh_regs *)MXS_APBH_BASE;
/*
* Test is the DMA channel is valid channel
{
struct mxs_dma_chan *pchan;
- if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS)) {
+ printf("Invalid DMA channel %d\n", channel);
return -EINVAL;
+ }
pchan = mxs_dma_channels + channel;
- if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED)) {
+ printf("DMA channel %d not allocated\n", channel);
return -EINVAL;
+ }
return 0;
}
*/
static int mxs_dma_read_semaphore(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
uint32_t tmp;
int ret;
}
#ifndef CONFIG_SYS_DCACHE_OFF
- void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
+ static void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
{
uint32_t addr;
uint32_t size;
flush_dcache_range(addr, addr + size);
}
#else
- inline void mxs_dma_flush_desc(struct mxs_dma_desc *desc) {}
+ static inline void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
+ {
+ }
#endif
/*
*/
static int mxs_dma_enable(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
unsigned int sem;
struct mxs_dma_chan *pchan;
struct mxs_dma_desc *pdesc;
pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
if (pdesc == NULL)
- return -EFAULT;
+ return -EINVAL;
if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
if (!(pdesc->cmd.data & MXS_DMA_DESC_CHAIN))
} else {
pchan->active_num += pchan->pending_num;
pchan->pending_num = 0;
+ writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+ &apbh_regs->hw_apbh_ctrl0_clr);
writel(mxs_dma_cmd_address(pdesc),
&apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar);
writel(pchan->active_num,
&apbh_regs->ch[channel].hw_apbh_ch_sema);
- writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
- &apbh_regs->hw_apbh_ctrl0_clr);
}
pchan->flags |= MXS_DMA_FLAGS_BUSY;
static int mxs_dma_disable(int channel)
{
struct mxs_dma_chan *pchan;
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
pchan = mxs_dma_channels + channel;
- if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
+ if ((pchan->flags & MXS_DMA_FLAGS_BUSY)) {
+ printf("%s: DMA channel %d busy\n", __func__, channel);
return -EINVAL;
-
+ }
writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
&apbh_regs->hw_apbh_ctrl0_set);
-
- pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
pchan->active_num = 0;
pchan->pending_num = 0;
list_splice_init(&pchan->active, &pchan->done);
*/
static int mxs_dma_reset(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
#if defined(CONFIG_MX23)
- uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
+ uint32_t *setreg = &apbh_regs->hw_apbh_ctrl0_set;
uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6))
- uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
+ uint32_t *setreg = &apbh_regs->hw_apbh_channel_ctrl_set;
uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
#endif
*/
static int mxs_dma_enable_irq(int channel, int enable)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
*/
static int mxs_dma_ack_irq(int channel)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(channel);
pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
pchan->active_num = 0;
pchan->pending_num = 0;
+ pchan->timeout = 10000000;
INIT_LIST_HEAD(&pchan->active);
INIT_LIST_HEAD(&pchan->done);
return 0;
}
+ /*
+ * Set the timeout for any DMA operation started with mxs_dma_go()
+ * The timeout value given is in milliseconds
+ */
+ int mxs_dma_set_timeout(int channel, unsigned long timeout)
+ {
+ int ret;
+ struct mxs_dma_chan *pchan;
+
+ ret = mxs_dma_validate_chan(channel);
+ if (ret)
+ return ret;
+
+ pchan = &mxs_dma_channels[channel];
+
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+ return -EBUSY;
+
+ if (timeout > ~0UL / 1000)
+ return -EINVAL;
+
+ pchan->timeout = timeout;
+ return 0;
+ }
+
+ unsigned long mxs_dma_get_timeout(int channel)
+ {
+ int ret;
+ struct mxs_dma_chan *pchan;
+
+ ret = mxs_dma_validate_chan(channel);
+ if (ret)
+ return 0;
+
+ pchan = &mxs_dma_channels[channel];
+ return pchan->timeout;
+ }
+
/*
* Allocate DMA descriptor
*/
*/
static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
int ret;
ret = mxs_dma_validate_chan(chan);
*/
int mxs_dma_go(int chan)
{
- uint32_t timeout = 10000000;
int ret;
-
+ struct mxs_dma_chan *pchan;
LIST_HEAD(tmp_desc_list);
+ ret = mxs_dma_validate_chan(chan);
+ if (ret)
+ return ret;
+
+ pchan = &mxs_dma_channels[chan];
+
mxs_dma_enable_irq(chan, 1);
- mxs_dma_enable(chan);
+ ret = mxs_dma_enable(chan);
+ if (ret) {
+ mxs_dma_enable_irq(chan, 0);
+ return ret;
+ }
/* Wait for DMA to finish. */
- ret = mxs_dma_wait_complete(timeout, chan);
+ ret = mxs_dma_wait_complete(pchan->timeout * 1000, chan);
/* Clear out the descriptors we just ran. */
mxs_dma_finish(chan, &tmp_desc_list);
return ret;
}
+/*
+ * Execute a continuously running circular DMA descriptor.
+ * NOTE: This is not intended for general use, but rather
+ * for the LCD driver in Smart-LCD mode. It allows
+ * continuous triggering of the RUN bit there.
+ */
+void mxs_dma_circ_start(int chan, struct mxs_dma_desc *pdesc)
+{
+ struct mxs_apbh_regs *apbh_regs =
+ (struct mxs_apbh_regs *)MXS_APBH_BASE;
+
+ mxs_dma_flush_desc(pdesc);
+
+ mxs_dma_enable_irq(chan, 1);
+
+ writel(mxs_dma_cmd_address(pdesc),
+ &apbh_regs->ch[chan].hw_apbh_ch_nxtcmdar);
+ writel(1, &apbh_regs->ch[chan].hw_apbh_ch_sema);
+ writel(1 << (chan + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+ &apbh_regs->hw_apbh_ctrl0_clr);
+}
+
/*
* Initialize the DMA hardware
*/
void mxs_dma_init(void)
{
- struct mxs_apbh_regs *apbh_regs =
- (struct mxs_apbh_regs *)MXS_APBH_BASE;
-
mxs_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
#ifdef CONFIG_APBH_DMA_BURST8
# SPDX-License-Identifier: GPL-2.0+
#
-include $(TOPDIR)/config.mk
-
-LIB := $(obj)libgpio.o
-
-COBJS-y += gpiolib.o
-
-COBJS-$(CONFIG_AM33XX_GPIO) += am33xx_gpio.o
-COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o
-COBJS-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
-COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
-COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o
-COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o
-COBJS-$(CONFIG_MXC_GPIO) += mxc_gpio.o
-COBJS-$(CONFIG_MXS_GPIO) += mxs_gpio.o
-COBJS-$(CONFIG_PCA953X) += pca953x.o
-COBJS-$(CONFIG_PCA9698) += pca9698.o
-COBJS-$(CONFIG_S5P) += s5p_gpio.o
-COBJS-$(CONFIG_SANDBOX_GPIO) += sandbox.o
-COBJS-$(CONFIG_SPEAR_GPIO) += spear_gpio.o
-COBJS-$(CONFIG_TEGRA_GPIO) += tegra_gpio.o
-COBJS-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o
-COBJS-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o
-COBJS-$(CONFIG_ALTERA_PIO) += altera_pio.o
-COBJS-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o
-COBJS-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
-COBJS-$(CONFIG_OMAP_GPIO) += omap_gpio.o
-COBJS-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
-COBJS-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o
-COBJS-$(CONFIG_S3C2440_GPIO) += s3c2440_gpio.o
-COBJS-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o
-COBJS-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
-
-COBJS := $(COBJS-y)
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(call cmd_link_o_target, $(OBJS))
-
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-########################################################################
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_DM_GPIO) += gpio-uclass.o
+endif
+
- obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
++obj-$(CONFIG_AM33XX_GPIO) += am33xx_gpio.o
++obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
+obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
+obj-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
- obj-$(CONFIG_KONA_GPIO) += kona_gpio.o
++obj-$(CONFIG_KONA_GPIO) += kona_gpio.o
+obj-$(CONFIG_MARVELL_GPIO) += mvgpio.o
+obj-$(CONFIG_MARVELL_MFP) += mvmfp.o
- obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o
- obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o
++obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o
++obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o
+obj-$(CONFIG_PCA953X) += pca953x.o
+obj-$(CONFIG_PCA9698) += pca9698.o
+obj-$(CONFIG_S5P) += s5p_gpio.o
+obj-$(CONFIG_SANDBOX_GPIO) += sandbox.o
+obj-$(CONFIG_SPEAR_GPIO) += spear_gpio.o
+obj-$(CONFIG_TEGRA_GPIO) += tegra_gpio.o
+obj-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o
+obj-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o
+obj-$(CONFIG_ALTERA_PIO) += altera_pio.o
+obj-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o
+obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
- obj-$(CONFIG_OMAP_GPIO) += omap_gpio.o
++obj-$(CONFIG_OMAP_GPIO) += omap_gpio.o
+obj-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
+obj-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o
+obj-$(CONFIG_S3C2440_GPIO) += s3c2440_gpio.o
+obj-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o
- obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
++obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
+obj-$(CONFIG_TCA642X) += tca642x.o
+oby-$(CONFIG_SX151X) += sx151x.o
+obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o
--- /dev/null
-#include <asm/sizes.h>
+ /*
+ * Copyright (C) 2012 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 <errno.h>
+ #include <asm/io.h>
+ #include <asm/bitops.h>
++#include <linux/sizes.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/gpio.h>
+
+ struct gpio_regs {
+ unsigned int res1[0x134 / 4];
+ unsigned int oe; /* 0x134 */
+ unsigned int datain; /* 0x138 */
+ unsigned int res2[0x54 / 4];
+ unsigned int cleardataout; /* 0x190 */
+ unsigned int setdataout; /* 0x194 */
+ };
+
+ static const struct gpio_regs *gpio_base[] = {
+ (struct gpio_regs *)AM33XX_GPIO0_BASE,
+ (struct gpio_regs *)AM33XX_GPIO1_BASE,
+ (struct gpio_regs *)AM33XX_GPIO2_BASE,
+ (struct gpio_regs *)AM33XX_GPIO3_BASE,
+ };
+
+ static unsigned long gpio_map[ARRAY_SIZE(gpio_base)] __attribute__((section("data")));
+
+ #define MAX_GPIO (ARRAY_SIZE(gpio_base) * 32)
+
+ int gpio_request(unsigned gpio, const char *name)
+ {
+ if (gpio >= MAX_GPIO) {
+ printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
+ gpio / 32, gpio % 32);
+ return -EINVAL;
+ }
+ if (test_and_set_bit(gpio, gpio_map))
+ return -EBUSY;
+ return 0;
+ }
+
+ int gpio_free(unsigned gpio)
+ {
+ if (gpio >= MAX_GPIO) {
+ printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
+ gpio / 32, gpio % 32);
+ return -EINVAL;
+ }
+ if (test_bit(gpio, gpio_map))
+ __clear_bit(gpio, gpio_map);
+ else
+ printf("ERROR: trying to free unclaimed GPIO %u\n", gpio);
+
+ return 0;
+ }
+
+ int gpio_set_value(unsigned gpio, int val)
+ {
+ int bank = gpio / 32;
+ int mask = 1 << (gpio % 32);
+
+ if (bank >= ARRAY_SIZE(gpio_base)) {
+ printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
+ gpio / 32, gpio % 32);
+ return -EINVAL;
+ }
+ if (val)
+ writel(mask, &gpio_base[bank]->setdataout);
+ else
+ writel(mask, &gpio_base[bank]->cleardataout);
+ return 0;
+ }
+
+ int gpio_get_value(unsigned gpio)
+ {
+ int bank = gpio / 32;
+ int mask = 1 << (gpio % 32);
+
+ if (bank >= ARRAY_SIZE(gpio_base)) {
+ printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
+ gpio / 32, gpio % 32);
+ return -EINVAL;
+ }
+ return (readl(&gpio_base[bank]->datain) & mask) != 0;
+ }
+
+ int gpio_direction_input(unsigned gpio)
+ {
+ int bank = gpio / 32;
+ int mask = 1 << (gpio % 32);
+
+ if (bank >= ARRAY_SIZE(gpio_base)) {
+ printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
+ gpio / 32, gpio % 32);
+ return -EINVAL;
+ }
+ writel(readl(&gpio_base[bank]->oe) | mask, &gpio_base[bank]->oe);
+ return 0;
+ }
+
+ int gpio_direction_output(unsigned gpio, int val)
+ {
+ int bank = gpio / 32;
+ int mask = 1 << (gpio % 32);
+
+ if (bank >= ARRAY_SIZE(gpio_base)) {
+ printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
+ gpio / 32, gpio % 32);
+ return -EINVAL;
+ }
+ gpio_set_value(gpio, val);
+ writel(readl(&gpio_base[bank]->oe) & ~mask, &gpio_base[bank]->oe);
+ return 0;
+ }
--- /dev/null
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/gpio.h>
+#include <linux/ctype.h>
+
+/**
+ * gpio_to_device() - Convert global GPIO number to device, number
+ * gpio: The numeric representation of the GPIO
+ *
+ * Convert the GPIO number to an entry in the list of GPIOs
+ * or GPIO blocks registered with the GPIO controller. Returns
+ * entry on success, NULL on error.
+ */
+static int gpio_to_device(unsigned int gpio, struct udevice **devp,
+ unsigned int *offset)
+{
+ struct gpio_dev_priv *uc_priv;
+ struct udevice *dev;
+ int ret;
+
+ for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ uc_priv = dev->uclass_priv;
+ if (gpio >= uc_priv->gpio_base &&
+ gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
+ *devp = dev;
+ *offset = gpio - uc_priv->gpio_base;
+ return 0;
+ }
+ }
+
+ /* No such GPIO */
+ return ret ? ret : -EINVAL;
+}
+
+int gpio_lookup_name(const char *name, struct udevice **devp,
+ unsigned int *offsetp, unsigned int *gpiop)
+{
+ struct gpio_dev_priv *uc_priv = NULL;
+ struct udevice *dev;
+ ulong offset;
+ int numeric;
+ int ret;
+
+ if (devp)
+ *devp = NULL;
+ numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
+ for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ int len;
+
+ uc_priv = dev->uclass_priv;
+ if (numeric != -1) {
+ offset = numeric - uc_priv->gpio_base;
+ /* Allow GPIOs to be numbered from 0 */
+ if (offset >= 0 && offset < uc_priv->gpio_count)
+ break;
+ }
+
+ len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
+
+ if (!strncasecmp(name, uc_priv->bank_name, len)) {
+ if (!strict_strtoul(name + len, 10, &offset))
+ break;
+ }
+ }
+
+ if (!dev)
+ return ret ? ret : -EINVAL;
+
+ if (devp)
+ *devp = dev;
+ if (offsetp)
+ *offsetp = offset;
+ if (gpiop)
+ *gpiop = uc_priv->gpio_base + offset;
+
+ return 0;
+}
+
+/**
+ * gpio_request() - [COMPAT] Request GPIO
+ * gpio: GPIO number
+ * label: Name for the requested GPIO
+ *
+ * The label is copied and allocated so the caller does not need to keep
+ * the pointer around.
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_request(unsigned gpio, const char *label)
+{
+ struct gpio_dev_priv *uc_priv;
+ unsigned int offset;
+ struct udevice *dev;
+ char *str;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ uc_priv = dev->uclass_priv;
+ if (uc_priv->name[offset])
+ return -EBUSY;
+ str = strdup(label);
+ if (!str)
+ return -ENOMEM;
+ if (gpio_get_ops(dev)->request) {
+ ret = gpio_get_ops(dev)->request(dev, offset, label);
+ if (ret) {
+ free(str);
+ return ret;
+ }
+ }
+ uc_priv->name[offset] = str;
+
+ return 0;
+}
+
+/**
+ * gpio_requestf() - [COMPAT] Request GPIO
+ * @gpio: GPIO number
+ * @fmt: Format string for the requested GPIO
+ * @...: Arguments for the printf() format string
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_requestf(unsigned gpio, const char *fmt, ...)
+{
+ va_list args;
+ char buf[40];
+
+ va_start(args, fmt);
+ vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ return gpio_request(gpio, buf);
+}
+
++int gpio_request_one(unsigned int gpio, enum gpio_flags flags,
++ const char *label)
++{
++ int ret;
++
++ ret = gpio_request(gpio, label);
++ if (ret)
++ return ret;
++
++ if (flags == GPIOFLAG_INPUT)
++ gpio_direction_input(gpio);
++ else if (flags == GPIOFLAG_OUTPUT_INIT_LOW)
++ gpio_direction_output(gpio, 0);
++ else if (flags == GPIOFLAG_OUTPUT_INIT_HIGH)
++ gpio_direction_output(gpio, 1);
++
++ return ret;
++}
++
++int gpio_request_array(const struct gpio *gpios, int count)
++{
++ int ret;
++ int i;
++
++ for (i = 0; i < count; i++) {
++ ret = gpio_request_one(gpios[i].gpio, gpios[i].flags,
++ gpios[i].label);
++ if (ret) {
++ printf("Failed to request GPIO%d (%u of %u): %d\n",
++ gpios[i].gpio, i, count, ret);
++ goto error;
++ }
++ }
++ return 0;
++
++error:
++ while (--i >= 0)
++ gpio_free(gpios[i].gpio);
++
++ return ret;
++}
++
+/**
+ * gpio_free() - [COMPAT] Relinquish GPIO
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_free(unsigned gpio)
+{
+ struct gpio_dev_priv *uc_priv;
+ unsigned int offset;
+ struct udevice *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ uc_priv = dev->uclass_priv;
+ if (!uc_priv->name[offset])
+ return -ENXIO;
+ if (gpio_get_ops(dev)->free) {
+ ret = gpio_get_ops(dev)->free(dev, offset);
+ if (ret)
+ return ret;
+ }
+
+ free(uc_priv->name[offset]);
+ uc_priv->name[offset] = NULL;
+
+ return 0;
+}
+
++int gpio_free_array(const struct gpio *gpios, int count)
++{
++ int ret = 0;
++ int i;
++
++ for (i = 0; i < count; i++)
++ ret |= gpio_free(gpios[i].gpio);
++
++ return ret;
++}
++
+static int check_reserved(struct udevice *dev, unsigned offset,
+ const char *func)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ if (!uc_priv->name[offset]) {
+ printf("%s: %s: error: gpio %s%d not reserved\n",
+ dev->name, func,
+ uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/**
+ * gpio_direction_input() - [COMPAT] Set GPIO direction to input
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_direction_input(unsigned gpio)
+{
+ unsigned int offset;
+ struct udevice *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+ ret = check_reserved(dev, offset, "dir_input");
+
+ return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
+}
+
+/**
+ * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
+ * gpio: GPIO number
+ * value: Logical value to be set on the GPIO pin
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_direction_output(unsigned gpio, int value)
+{
+ unsigned int offset;
+ struct udevice *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+ ret = check_reserved(dev, offset, "dir_output");
+
+ return ret ? ret :
+ gpio_get_ops(dev)->direction_output(dev, offset, value);
+}
+
+/**
+ * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns the value of the GPIO pin, or negative value
+ * on error.
+ */
+int gpio_get_value(unsigned gpio)
+{
+ unsigned int offset;
+ struct udevice *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+ ret = check_reserved(dev, offset, "get_value");
+
+ return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
+}
+
+/**
+ * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
+ * gpio: GPIO number
+ * value: Logical value to be set on the GPIO pin.
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_set_value(unsigned gpio, int value)
+{
+ unsigned int offset;
+ struct udevice *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+ ret = check_reserved(dev, offset, "set_value");
+
+ return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
+}
+
+const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
+{
+ struct gpio_dev_priv *priv;
+
+ /* Must be called on an active device */
+ priv = dev->uclass_priv;
+ assert(priv);
+
+ *bit_count = priv->gpio_count;
+ return priv->bank_name;
+}
+
+static const char * const gpio_function[GPIOF_COUNT] = {
+ "input",
+ "output",
+ "unused",
+ "unknown",
+ "func",
+};
+
+int get_function(struct udevice *dev, int offset, bool skip_unused,
+ const char **namep)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
+
+ BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+ if (!device_active(dev))
+ return -ENODEV;
+ if (offset < 0 || offset >= uc_priv->gpio_count)
+ return -EINVAL;
+ if (namep)
+ *namep = uc_priv->name[offset];
+ if (skip_unused && !uc_priv->name[offset])
+ return GPIOF_UNUSED;
+ if (ops->get_function) {
+ int ret;
+
+ ret = ops->get_function(dev, offset);
+ if (ret < 0)
+ return ret;
+ if (ret >= ARRAY_SIZE(gpio_function))
+ return -ENODATA;
+ return ret;
+ }
+
+ return GPIOF_UNKNOWN;
+}
+
+int gpio_get_function(struct udevice *dev, int offset, const char **namep)
+{
+ return get_function(dev, offset, true, namep);
+}
+
+int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
+{
+ return get_function(dev, offset, false, namep);
+}
+
+int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
+{
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
+ struct gpio_dev_priv *priv;
+ char *str = buf;
+ int func;
+ int ret;
+ int len;
+
+ BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+
+ *buf = 0;
+ priv = dev->uclass_priv;
+ ret = gpio_get_raw_function(dev, offset, NULL);
+ if (ret < 0)
+ return ret;
+ func = ret;
+ len = snprintf(str, buffsize, "%s%d: %s",
+ priv->bank_name ? priv->bank_name : "",
+ offset, gpio_function[func]);
+ if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
+ func == GPIOF_UNUSED) {
+ const char *label;
+ bool used;
+
+ ret = ops->get_value(dev, offset);
+ if (ret < 0)
+ return ret;
+ used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
+ snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
+ ret,
+ used ? 'x' : ' ',
+ used ? " " : "",
+ label ? label : "");
+ }
+
+ return 0;
+}
+
+/*
+ * get a number comprised of multiple GPIO values. gpio_num_array points to
+ * the array of gpio pin numbers to scan, terminated by -1.
+ */
+unsigned gpio_get_values_as_int(const int *gpio_num_array)
+{
+ int gpio;
+ unsigned bitmask = 1;
+ unsigned vector = 0;
+
+ while (bitmask &&
+ ((gpio = *gpio_num_array++) != -1)) {
+ if (gpio_get_value(gpio))
+ vector |= bitmask;
+ bitmask <<= 1;
+ }
+ return vector;
+}
+
+/* We need to renumber the GPIOs when any driver is probed/removed */
+static int gpio_renumber(struct udevice *removed_dev)
+{
+ struct gpio_dev_priv *uc_priv;
+ struct udevice *dev;
+ struct uclass *uc;
+ unsigned base;
+ int ret;
+
+ ret = uclass_get(UCLASS_GPIO, &uc);
+ if (ret)
+ return ret;
+
+ /* Ensure that we have a base for each bank */
+ base = 0;
+ uclass_foreach_dev(dev, uc) {
+ if (device_active(dev) && dev != removed_dev) {
+ uc_priv = dev->uclass_priv;
+ uc_priv->gpio_base = base;
+ base += uc_priv->gpio_count;
+ }
+ }
+
+ return 0;
+}
+
+static int gpio_post_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
+ if (!uc_priv->name)
+ return -ENOMEM;
+
+ return gpio_renumber(NULL);
+}
+
+static int gpio_pre_remove(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ int i;
+
+ for (i = 0; i < uc_priv->gpio_count; i++) {
+ if (uc_priv->name[i])
+ free(uc_priv->name[i]);
+ }
+ free(uc_priv->name);
+
+ return gpio_renumber(dev);
+}
+
+UCLASS_DRIVER(gpio) = {
+ .id = UCLASS_GPIO,
+ .name = "gpio",
+ .post_probe = gpio_post_probe,
+ .pre_remove = gpio_pre_remove,
+ .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
+};
--- /dev/null
- if (flags == GPIOF_INPUT)
+ #include <common.h>
+ #include <asm-generic/gpio.h>
+
+ int gpio_request_one(unsigned int gpio, enum gpio_flags flags,
+ const char *label)
+ {
+ int ret;
+
+ ret = gpio_request(gpio, label);
+ if (ret)
+ return ret;
+
- else if (flags == GPIOF_OUTPUT_INIT_LOW)
++ if (flags == GPIOFLAG_INPUT)
+ gpio_direction_input(gpio);
- else if (flags == GPIOF_OUTPUT_INIT_HIGH)
++ else if (flags == GPIOFLAG_OUTPUT_INIT_LOW)
+ gpio_direction_output(gpio, 0);
++ else if (flags == GPIOFLAG_OUTPUT_INIT_HIGH)
+ gpio_direction_output(gpio, 1);
+
+ return ret;
+ }
+
+ int gpio_request_array(const struct gpio *gpios, int count)
+ {
+ int ret;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ ret = gpio_request_one(gpios[i].gpio, gpios[i].flags,
+ gpios[i].label);
+ if (ret) {
+ printf("Failed to request GPIO%d (%u of %u): %d\n",
+ gpios[i].gpio, i, count, ret);
+ goto error;
+ }
+ }
+ return 0;
+
+ error:
+ while (--i >= 0)
+ gpio_free(gpios[i].gpio);
+
+ return ret;
+ }
+
+ int gpio_free_array(const struct gpio *gpios, int count)
+ {
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < count; i++)
+ ret |= gpio_free(gpios[i].gpio);
+
+ return ret;
+ }
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <malloc.h>
#include <asm/arch/imx-regs.h>
#include <asm/gpio.h>
#include <asm/io.h>
-#include <errno.h>
enum mxc_gpio_direction {
MXC_GPIO_DIRECTION_IN,
MXC_GPIO_DIRECTION_OUT,
};
- #define GPIO_TO_PORT(n) (n / 32)
+#define GPIO_PER_BANK 32
+
+struct mxc_gpio_plat {
+ struct gpio_regs *regs;
+};
+
+struct mxc_bank_info {
+ struct gpio_regs *regs;
+};
+
+#ifndef CONFIG_DM_GPIO
+ #define GPIO_TO_PORT(n) ((n) / 32)
/* GPIO port description */
static unsigned long gpio_ports[] = {
struct gpio_regs *regs;
u32 l;
- if (port >= ARRAY_SIZE(gpio_ports))
+ if (port >= ARRAY_SIZE(gpio_ports)) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
return -1;
+ }
gpio &= 0x1f;
struct gpio_regs *regs;
u32 l;
- if (port >= ARRAY_SIZE(gpio_ports))
+ if (port >= ARRAY_SIZE(gpio_ports)) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
return -1;
+ }
gpio &= 0x1f;
struct gpio_regs *regs;
u32 val;
- if (port >= ARRAY_SIZE(gpio_ports))
+ if (port >= ARRAY_SIZE(gpio_ports)) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
return -1;
+ }
gpio &= 0x1f;
regs = (struct gpio_regs *)gpio_ports[port];
- val = (readl(®s->gpio_psr) >> gpio) & 0x01;
-
+ if (readl(®s->gpio_dir) & (1 << gpio)) {
+ printf("WARNING: Reading status of output GPIO_%d_%d\n",
+ port - GPIO_TO_PORT(0), gpio);
+ val = (readl(®s->gpio_dr) >> gpio) & 0x01;
+ } else {
+ val = (readl(®s->gpio_psr) >> gpio) & 0x01;
+ }
return val;
}
int gpio_request(unsigned gpio, const char *label)
{
unsigned int port = GPIO_TO_PORT(gpio);
- if (port >= ARRAY_SIZE(gpio_ports))
+ if (port >= ARRAY_SIZE(gpio_ports)) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
return -1;
+ }
return 0;
}
int gpio_free(unsigned gpio)
{
+ unsigned int port = GPIO_TO_PORT(gpio);
+ if (port >= ARRAY_SIZE(gpio_ports)) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
+ return -1;
+ }
return 0;
}
return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
}
+#endif
+
+#ifdef CONFIG_DM_GPIO
+static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
+{
+ u32 val;
+
+ val = readl(®s->gpio_dir);
+
+ return val & (1 << offset) ? 1 : 0;
+}
+
+static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
+ enum mxc_gpio_direction direction)
+{
+ u32 l;
+
+ l = readl(®s->gpio_dir);
+
+ switch (direction) {
+ case MXC_GPIO_DIRECTION_OUT:
+ l |= 1 << offset;
+ break;
+ case MXC_GPIO_DIRECTION_IN:
+ l &= ~(1 << offset);
+ }
+ writel(l, ®s->gpio_dir);
+}
+
+static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
+ int value)
+{
+ u32 l;
+
+ l = readl(®s->gpio_dr);
+ if (value)
+ l |= 1 << offset;
+ else
+ l &= ~(1 << offset);
+ writel(l, ®s->gpio_dr);
+}
+
+static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
+{
+ return (readl(®s->gpio_psr) >> offset) & 0x01;
+}
+
+/* set GPIO pin 'gpio' as an input */
+static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+ struct mxc_bank_info *bank = dev_get_priv(dev);
+
+ /* Configure GPIO direction as input. */
+ mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct mxc_bank_info *bank = dev_get_priv(dev);
+
+ /* Configure GPIO output value. */
+ mxc_gpio_bank_set_value(bank->regs, offset, value);
+
+ /* Configure GPIO direction as output. */
+ mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
+
+ return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+ struct mxc_bank_info *bank = dev_get_priv(dev);
+
+ return mxc_gpio_bank_get_value(bank->regs, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct mxc_bank_info *bank = dev_get_priv(dev);
+
+ mxc_gpio_bank_set_value(bank->regs, offset, value);
+
+ return 0;
+}
+
+static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct mxc_bank_info *bank = dev_get_priv(dev);
+
+ /* GPIOF_FUNC is not implemented yet */
+ if (mxc_gpio_is_output(bank->regs, offset))
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_mxc_ops = {
+ .direction_input = mxc_gpio_direction_input,
+ .direction_output = mxc_gpio_direction_output,
+ .get_value = mxc_gpio_get_value,
+ .set_value = mxc_gpio_set_value,
+ .get_function = mxc_gpio_get_function,
+};
+
+static const struct mxc_gpio_plat mxc_plat[] = {
+ { (struct gpio_regs *)GPIO1_BASE_ADDR },
+ { (struct gpio_regs *)GPIO2_BASE_ADDR },
+ { (struct gpio_regs *)GPIO3_BASE_ADDR },
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+ defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { (struct gpio_regs *)GPIO4_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { (struct gpio_regs *)GPIO5_BASE_ADDR },
+ { (struct gpio_regs *)GPIO6_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { (struct gpio_regs *)GPIO7_BASE_ADDR },
+#endif
+};
+
+static int mxc_gpio_probe(struct udevice *dev)
+{
+ struct mxc_bank_info *bank = dev_get_priv(dev);
+ struct mxc_gpio_plat *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ int banknum;
+ char name[18], *str;
+
+ banknum = plat - mxc_plat;
+ sprintf(name, "GPIO%d_", banknum + 1);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+ uc_priv->bank_name = str;
+ uc_priv->gpio_count = GPIO_PER_BANK;
+ bank->regs = plat->regs;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(gpio_mxc) = {
+ .name = "gpio_mxc",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_mxc_ops,
+ .probe = mxc_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
+};
+
+U_BOOT_DEVICES(mxc_gpios) = {
+ { "gpio_mxc", &mxc_plat[0] },
+ { "gpio_mxc", &mxc_plat[1] },
+ { "gpio_mxc", &mxc_plat[2] },
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+ defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { "gpio_mxc", &mxc_plat[3] },
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { "gpio_mxc", &mxc_plat[4] },
+ { "gpio_mxc", &mxc_plat[5] },
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { "gpio_mxc", &mxc_plat[6] },
+#endif
+};
+#endif
--- /dev/null
++menuconfig SYS_I2C
++ bool "I2C device support"
++
++if SYS_I2C
++
++config HARD_I2C
++ bool
++
++config SYS_I2C_MXC
++ bool "Freescale i.MX I2C controller"
++ select HARD_I2C
++ select I2C_QUIRK_REG if FSL_LSCH3 || LS102XA
++
++endif
#ifndef CONFIG_MPC512X
#include <asm/arch/imx-regs.h>
#endif
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
+#include <asm/arch/clock.h>
+#endif
/* FSL IIM-specific constants */
#define STAT_BUSY 0x80
u32 sdat;
u32 prev;
u32 srev;
- u32 prg_p;
+ u32 preg_p;
u32 scs[0x1f5];
struct {
u32 word[0x100];
} bank[8];
};
+#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53)
+#define enable_efuse_prog_supply(enable)
+#endif
+
static int prepare_access(struct fsl_iim **regs, u32 bank, u32 word, int assert,
const char *caller)
{
iim_write32(®s->ua, bank << 3 | word >> 5);
iim_write32(®s->la, (word << 3 | bit) & 0xff);
if (fctl == FCTL_PRG)
- iim_write32(®s->prg_p, 0xaa);
+ iim_write32(®s->preg_p, 0xaa);
iim_setbits32(®s->fctl, fctl);
while (iim_read32(®s->stat) & STAT_BUSY)
udelay(20);
clear_status(regs);
direct_access(regs, bank, word, bit, FCTL_PRG, &stat, &err);
- iim_write32(®s->prg_p, 0x00);
+ iim_write32(®s->preg_p, 0x00);
if (err & ERR_PRGE) {
puts("fsl_iim fuse_prog(): Program error\n");
if (ret)
return ret;
+ enable_efuse_prog_supply(1);
for (bit = 0; val; bit++, val >>= 1)
if (val & 0x01) {
ret = prog_bit(regs, bank, word, bit);
- if (ret)
+ if (ret) {
+ enable_efuse_prog_supply(0);
return ret;
+ }
}
+ enable_efuse_prog_supply(0);
return 0;
}
--- /dev/null
++menuconfig MMC
++ bool "MMC/SD device support"
++ select CMD_MMC
++
++if MMC
++
++config GENERIC_MMC
++ bool
++
++config FSL_ESDHC
++ bool "Freescale ESDHC controller"
++ select GENERIC_MMC
++
++config FSL_USDHC
++ bool "Support USDHC"
++ depends on MX6Q
++ depends on FSL_ESDHC
++
++config SUPPORT_EMMC_BOOT
++ bool "Support boot from eMMC"
++ depends on MMC
++
++endif
DECLARE_GLOBAL_DATA_PTR;
+#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
+ IRQSTATEN_CINT | \
+ IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
+ IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
+ IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
+ IRQSTATEN_DINT)
+
struct fsl_esdhc {
- uint dsaddr;
- uint blkattr;
- uint cmdarg;
- uint xfertyp;
- uint cmdrsp0;
- uint cmdrsp1;
- uint cmdrsp2;
- uint cmdrsp3;
- uint datport;
- uint prsstat;
- uint proctl;
- uint sysctl;
- uint irqstat;
- uint irqstaten;
- uint irqsigen;
- uint autoc12err;
- uint hostcapblt;
- uint wml;
- uint mixctrl;
- char reserved1[4];
- uint fevt;
- char reserved2[168];
- uint hostver;
- char reserved3[780];
- uint scr;
+ uint dsaddr; /* SDMA system address register */
+ uint blkattr; /* Block attributes register */
+ uint cmdarg; /* Command argument register */
+ uint xfertyp; /* Transfer type register */
+ uint cmdrsp0; /* Command response 0 register */
+ uint cmdrsp1; /* Command response 1 register */
+ uint cmdrsp2; /* Command response 2 register */
+ uint cmdrsp3; /* Command response 3 register */
+ uint datport; /* Buffer data port register */
+ uint prsstat; /* Present state register */
+ uint proctl; /* Protocol control register */
+ uint sysctl; /* System Control Register */
+ uint irqstat; /* Interrupt status register */
+ uint irqstaten; /* Interrupt status enable register */
+ uint irqsigen; /* Interrupt signal enable register */
+ uint autoc12err; /* Auto CMD error status register */
+ uint hostcapblt; /* Host controller capabilities register */
+ uint wml; /* Watermark level register */
+ uint mixctrl; /* For USDHC */
+ char reserved1[4]; /* reserved */
+ uint fevt; /* Force event register */
+ uint admaes; /* ADMA error status register */
+ uint adsaddr; /* ADMA system address register */
+ char reserved2[160]; /* reserved */
+ uint hostver; /* Host controller version register */
+ char reserved3[4]; /* reserved */
+ uint dmaerraddr; /* DMA error address register */
+ char reserved4[4]; /* reserved */
+ uint dmaerrattr; /* DMA error attribute register */
+ char reserved5[4]; /* reserved */
+ uint hostcapblt2; /* Host controller capabilities register 2 */
+ char reserved6[8]; /* reserved */
+ uint tcr; /* Tuning control register */
+ char reserved7[28]; /* reserved */
+ uint sddirctl; /* SD direction control register */
+ char reserved8[712]; /* reserved */
+ uint scr; /* eSDHC control register */
};
/* Return the XFERTYP flags for a given command and data packet */
else if (cmd->resp_type & MMC_RSP_PRESENT)
xfertyp |= XFERTYP_RSPTYP_48;
-#if defined(CONFIG_MX53) || defined(CONFIG_T4240QDS)
+#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || defined(CONFIG_LS102XA)
if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
xfertyp |= XFERTYP_CMDTYP_ABORT;
#endif
esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
{
struct fsl_esdhc_cfg *cfg = mmc->priv;
- struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+ struct fsl_esdhc *regs = cfg->esdhc_base;
uint blocks;
char *buffer;
uint databuf;
uint size;
- uint irqstat;
uint timeout;
+ int wml = esdhc_read32(®s->wml);
if (data->flags & MMC_DATA_READ) {
+ wml &= WML_RD_WML_MASK;
blocks = data->blocks;
buffer = data->dest;
while (blocks) {
timeout = PIO_TIMEOUT;
size = data->blocksize;
- irqstat = esdhc_read32(®s->irqstat);
- while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN)
- && --timeout);
- if (timeout <= 0) {
- printf("\nData Read Failed in PIO Mode.");
- return;
- }
- while (size && (!(irqstat & IRQSTAT_TC))) {
- udelay(100); /* Wait before last byte transfer complete */
- irqstat = esdhc_read32(®s->irqstat);
- databuf = in_le32(®s->datport);
- *((uint *)buffer) = databuf;
- buffer += 4;
- size -= 4;
+ while (size &&
+ !(esdhc_read32(®s->irqstat) & IRQSTAT_TC)) {
+ int i;
+ u32 prsstat;
+
+ while (!((prsstat = esdhc_read32(®s->prsstat)) &
+ PRSSTAT_BREN) && --timeout)
+ /* NOP */;
+ if (!(prsstat & PRSSTAT_BREN)) {
+ printf("%s: Data Read Failed in PIO Mode\n",
+ __func__);
+ return;
+ }
+ for (i = 0; i < wml && size; i++) {
+ databuf = in_le32(®s->datport);
+ memcpy(buffer, &databuf, sizeof(databuf));
+ buffer += 4;
+ size -= 4;
+ }
}
blocks--;
}
} else {
+ wml = (wml & WML_WR_WML_MASK) >> 16;
blocks = data->blocks;
- buffer = (char *)data->src;
+ buffer = (char *)data->src; /* cast away 'const' */
while (blocks) {
timeout = PIO_TIMEOUT;
size = data->blocksize;
- irqstat = esdhc_read32(®s->irqstat);
- while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN)
- && --timeout);
- if (timeout <= 0) {
- printf("\nData Write Failed in PIO Mode.");
- return;
- }
- while (size && (!(irqstat & IRQSTAT_TC))) {
- udelay(100); /* Wait before last byte transfer complete */
- databuf = *((uint *)buffer);
- buffer += 4;
- size -= 4;
- irqstat = esdhc_read32(®s->irqstat);
- out_le32(®s->datport, databuf);
+ while (size &&
+ !(esdhc_read32(®s->irqstat) & IRQSTAT_TC)) {
+ int i;
+ u32 prsstat;
+
+ while (!((prsstat = esdhc_read32(®s->prsstat)) &
+ PRSSTAT_BWEN) && --timeout)
+ /* NOP */;
+ if (!(prsstat & PRSSTAT_BWEN)) {
+ printf("%s: Data Write Failed in PIO Mode\n",
+ __func__);
+ return;
+ }
+ for (i = 0; i < wml && size; i++) {
+ memcpy(&databuf, buffer, sizeof(databuf));
+ out_le32(®s->datport, databuf);
+ buffer += 4;
+ size -= 4;
+ }
}
blocks--;
}
{
int timeout;
struct fsl_esdhc_cfg *cfg = mmc->priv;
- struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
-
+ struct fsl_esdhc *regs = cfg->esdhc_base;
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
uint wml_value;
- wml_value = data->blocksize/4;
+ wml_value = data->blocksize / 4;
if (data->flags & MMC_DATA_READ) {
if (wml_value > WML_RD_WML_MAX)
wml_value = WML_RD_WML_MAX_VAL;
esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value);
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
esdhc_write32(®s->dsaddr, (u32)data->dest);
+#endif
} else {
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+ flush_dcache_range((ulong)data->src,
+ (ulong)data->src+data->blocks
+ *data->blocksize);
+#endif
if (wml_value > WML_WR_WML_MAX)
wml_value = WML_WR_WML_MAX_VAL;
if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
- printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
- return TIMEOUT;
+ printf("The SD card is locked. Can not write to a locked card.\n");
+ return UNUSABLE_ERR;
}
+ flush_dcache_range((unsigned long)data->src,
+ (unsigned long)data->src + data->blocks * data->blocksize);
esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK,
wml_value << 16);
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
esdhc_write32(®s->dsaddr, (u32)data->src);
+#endif
}
-#else /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
- if (!(data->flags & MMC_DATA_READ)) {
- if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
- printf("The SD card is locked. Can not write to a locked card.\n");
- return UNUSABLE_ERR;
- }
- esdhc_write32(®s->dsaddr, (u32)data->src);
- } else {
- esdhc_write32(®s->dsaddr, (u32)data->dest);
- }
-#endif /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
- esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize);
+ esdhc_write32(®s->blkattr, (data->blocks << 16) | data->blocksize);
/* Calculate the timeout period for data transactions */
/*
* 2)Timeout period should be minimum 0.250sec as per SD Card spec
* So, Number of SD Clock cycles for 0.25sec should be minimum
* (SD Clock/sec * 0.25 sec) SD Clock cycles
- * = (mmc->tran_speed * 1/4) SD Clock cycles
+ * = (mmc->clock * 1/4) SD Clock cycles
* As 1) >= 2)
- * => (2^(timeout+13)) >= mmc->tran_speed * 1/4
+ * => (2^(timeout+13)) >= mmc->clock * 1/4
* Taking log2 both the sides
- * => timeout + 13 >= log2(mmc->tran_speed/4)
+ * => timeout + 13 >= log2(mmc->clock/4)
* Rounding up to next power of 2
- * => timeout + 13 = log2(mmc->tran_speed/4) + 1
- * => timeout + 13 = fls(mmc->tran_speed/4)
+ * => timeout + 13 = log2(mmc->clock/4) + 1
+ * => timeout + 13 = fls(mmc->clock/4)
*/
- timeout = fls(mmc->tran_speed / 4);
+ timeout = fls(mmc->clock/4);
timeout -= 13;
if (timeout > 14)
timeout = 14;
-
- if (timeout < 0)
+ else if (timeout < 0)
timeout = 0;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
if ((timeout == 4) || (timeout == 8) || (timeout == 12))
timeout++;
#endif
+
+#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
+ timeout = 0xE;
+#endif
esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
return 0;
}
-static inline void check_and_invalidate_dcache_range(struct mmc_cmd *cmd,
- struct mmc_data *data)
-{
- unsigned long start = (unsigned long)data->dest;
- size_t start_ofs = start & (ARCH_DMA_MINALIGN - 1);
- unsigned long size = data->blocks * data->blocksize;
- unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
-
- start -= start_ofs;
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+static void check_and_invalidate_dcache_range
+ (struct mmc_cmd *cmd,
+ struct mmc_data *data) {
+ unsigned start = (unsigned)data->dest ;
+ unsigned size = roundup(ARCH_DMA_MINALIGN,
+ data->blocks*data->blocksize);
+ unsigned end = start+size ;
invalidate_dcache_range(start, end);
}
+#endif
/*
* Sends a command out on the bus. Takes the mmc pointer,
static int
esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
+ int err = 0;
uint xfertyp;
uint irqstat;
struct fsl_esdhc_cfg *cfg = mmc->priv;
- volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+ volatile struct fsl_esdhc *regs = cfg->esdhc_base;
+ unsigned long start;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
return 0;
#endif
-
esdhc_write32(®s->irqstat, -1);
sync();
+ start = get_timer_masked();
/* Wait for the bus to be idle */
while ((esdhc_read32(®s->prsstat) & PRSSTAT_CICHB) ||
- (esdhc_read32(®s->prsstat) & PRSSTAT_CIDHB))
- ;
+ (esdhc_read32(®s->prsstat) & PRSSTAT_CIDHB)) {
+ if (get_timer(start) > CONFIG_SYS_HZ) {
+ printf("%s: Timeout waiting for bus idle\n", __func__);
+ return TIMEOUT;
+ }
+ }
- while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA)
- ;
+ start = get_timer_masked();
+ while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA) {
+ if (get_timer(start) > CONFIG_SYS_HZ)
+ return TIMEOUT;
+ }
/* Wait at least 8 SD clock cycles before the next command */
/*
/* Set up for a data transfer if we have one */
if (data) {
- int err;
-
err = esdhc_setup_data(mmc, data);
- if(err)
+ if (err)
return err;
}
esdhc_write32(®s->cmdarg, cmd->cmdarg);
#if defined(CONFIG_FSL_USDHC)
esdhc_write32(®s->mixctrl,
- (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F));
+ (esdhc_read32(®s->mixctrl) & ~0x7f) | (xfertyp & 0x7F));
esdhc_write32(®s->xfertyp, xfertyp & 0xFFFF0000);
#else
esdhc_write32(®s->xfertyp, xfertyp);
#endif
+ /* Mask all irqs */
+ esdhc_write32(®s->irqsigen, 0);
+
+ start = get_timer_masked();
/* Wait for the command to complete */
- while (!(esdhc_read32(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))
- ;
+ while (!(esdhc_read32(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE))) {
+ if (get_timer(start) > CONFIG_SYS_HZ) {
+ printf("%s: Timeout waiting for cmd completion\n", __func__);
+ return TIMEOUT;
+ }
+ }
+
+ if (data && (data->flags & MMC_DATA_READ))
+ check_and_invalidate_dcache_range(cmd, data);
irqstat = esdhc_read32(®s->irqstat);
- /* Reset CMD and DATA portions on error */
- if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) {
- esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) |
- SYSCTL_RSTC);
- start = get_timer_masked();
- while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) {
- if (get_timer(start) > CONFIG_SYS_HZ)
- return TIMEOUT;
- }
-
- if (data) {
- esdhc_write32(®s->sysctl,
- esdhc_read32(®s->sysctl) |
- SYSCTL_RSTD);
- start = get_timer_masked();
- while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) {
- if (get_timer(start) > CONFIG_SYS_HZ)
- return TIMEOUT;
- }
- }
+ if (irqstat & CMD_ERR) {
+ err = COMM_ERR;
+ goto out;
}
- if (irqstat & CMD_ERR)
- return COMM_ERR;
-
- if (irqstat & IRQSTAT_CTOE)
- return TIMEOUT;
+ if (irqstat & IRQSTAT_CTOE) {
+ err = TIMEOUT;
+ goto out;
+ }
/* Workaround for ESDHC errata ENGcm03648 */
if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
if (timeout <= 0) {
printf("Timeout waiting for DAT0 to go high!\n");
- return TIMEOUT;
+ err = TIMEOUT;
+ goto out;
}
}
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
esdhc_pio_read_write(mmc, data);
#else
- unsigned long start = get_timer_masked();
- unsigned long data_timeout = data->blocks *
- data->blocksize * 100 / mmc->bus_width /
- (mmc->tran_speed / CONFIG_SYS_HZ) + CONFIG_SYS_HZ;
-
do {
irqstat = esdhc_read32(®s->irqstat);
if (irqstat & IRQSTAT_DTOE) {
- printf("MMC/SD data %s timeout\n",
- data->flags & MMC_DATA_READ ?
- "read" : "write");
- return TIMEOUT;
+ err = TIMEOUT;
+ goto out;
}
if (irqstat & DATA_ERR) {
- printf("MMC/SD data error\n");
- return COMM_ERR;
- }
-
- if (get_timer(start) > data_timeout) {
- printf("MMC/SD timeout waiting for %s xfer completion\n",
- data->flags & MMC_DATA_READ ?
- "read" : "write");
- return TIMEOUT;
+ err = COMM_ERR;
+ goto out;
}
- } while (!(irqstat & IRQSTAT_TC) &&
- (esdhc_read32(®s->prsstat) & PRSSTAT_DLA));
+ } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
- check_and_invalidate_dcache_range(cmd, data);
+ if (data->flags & MMC_DATA_READ)
+ check_and_invalidate_dcache_range(cmd, data);
#endif
}
- esdhc_write32(®s->irqstat, -1);
+out:
+ /* Reset CMD and DATA portions on error */
+ if (err) {
+ esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) |
+ SYSCTL_RSTC);
+ while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC)
+ ;
+
+ if (data) {
+ esdhc_write32(®s->sysctl,
+ esdhc_read32(®s->sysctl) |
+ SYSCTL_RSTD);
+ while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD))
+ ;
+ }
+ }
+
+ esdhc_write32(®s->irqstat, irqstat);
- return 0;
+ return err;
}
static void set_sysctl(struct mmc *mmc, uint clock)
{
int div, pre_div;
struct fsl_esdhc_cfg *cfg = mmc->priv;
- volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+ volatile struct fsl_esdhc *regs = cfg->esdhc_base;
int sdhc_clk = cfg->sdhc_clk;
uint clk;
- if (clock < mmc->f_min)
- clock = mmc->f_min;
+ if (clock < mmc->cfg->f_min)
+ clock = mmc->cfg->f_min;
if (sdhc_clk / 16 > clock) {
for (pre_div = 2; pre_div < 256; pre_div *= 2)
static void esdhc_set_ios(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = mmc->priv;
- struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+ struct fsl_esdhc *regs = cfg->esdhc_base;
/* Set the clock speed */
set_sysctl(mmc, mmc->clock);
static int esdhc_init(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = mmc->priv;
- struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+ struct fsl_esdhc *regs = cfg->esdhc_base;
int timeout = 1000;
/* Reset the entire host controller */
static int esdhc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = mmc->priv;
- struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+ struct fsl_esdhc *regs = cfg->esdhc_base;
int timeout = 1000;
+#ifdef CONFIG_ESDHC_DETECT_QUIRK
+ if (CONFIG_ESDHC_DETECT_QUIRK)
+ return 1;
+#endif
while (!(esdhc_read32(®s->prsstat) & PRSSTAT_CINS) && --timeout)
udelay(1000);
printf("MMC/SD: Reset never completed.\n");
}
+static const struct mmc_ops esdhc_ops = {
+ .send_cmd = esdhc_send_cmd,
+ .set_ios = esdhc_set_ios,
+ .init = esdhc_init,
+ .getcd = esdhc_getcd,
+};
+
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
struct fsl_esdhc *regs;
u32 caps, voltage_caps;
if (!cfg)
- return -1;
+ return -EINVAL;
- mmc = kzalloc(sizeof(struct mmc), GFP_KERNEL);
- if (!mmc)
- return -ENOMEM;
-
- sprintf(mmc->name, "FSL_SDHC");
- regs = cfg->esdhc_base;
+ regs = (struct fsl_esdhc *)cfg->esdhc_base;
/* First reset the eSDHC controller */
esdhc_reset(regs);
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
| SYSCTL_IPGEN | SYSCTL_CKEN);
- mmc->priv = cfg;
- mmc->send_cmd = esdhc_send_cmd;
- mmc->set_ios = esdhc_set_ios;
- mmc->init = esdhc_init;
- mmc->getcd = esdhc_getcd;
- mmc->getwp = NULL;
+ writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten);
+ memset(&cfg->cfg, 0, sizeof(cfg->cfg));
voltage_caps = 0;
- caps = regs->hostcapblt;
+ caps = esdhc_read32(®s->hostcapblt);
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
caps = caps & ~(ESDHC_HOSTCAPBLT_SRS |
ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30);
#endif
+
+/* T4240 host controller capabilities register should have VS33 bit */
+#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
+ caps = caps | ESDHC_HOSTCAPBLT_VS33;
+#endif
+
if (caps & ESDHC_HOSTCAPBLT_VS18)
voltage_caps |= MMC_VDD_165_195;
if (caps & ESDHC_HOSTCAPBLT_VS30)
if (caps & ESDHC_HOSTCAPBLT_VS33)
voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
+ cfg->cfg.name = "FSL_SDHC";
+ cfg->cfg.ops = &esdhc_ops;
#ifdef CONFIG_SYS_SD_VOLTAGE
- mmc->voltages = CONFIG_SYS_SD_VOLTAGE;
+ cfg->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
#else
- mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+ cfg->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
#endif
- if ((mmc->voltages & voltage_caps) == 0) {
+ if ((cfg->cfg.voltages & voltage_caps) == 0) {
printf("voltage not supported by controller\n");
- return -1;
+ return -EINVAL;
}
- mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
+ cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
if (cfg->max_bus_width > 0) {
if (cfg->max_bus_width < 8)
- mmc->host_caps &= ~MMC_MODE_8BIT;
+ cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
if (cfg->max_bus_width < 4)
- mmc->host_caps &= ~MMC_MODE_4BIT;
+ cfg->cfg.host_caps &= ~MMC_MODE_4BIT;
}
if (caps & ESDHC_HOSTCAPBLT_HSS)
- mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+ cfg->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
+ if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
+ cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
+#endif
+
+ cfg->cfg.f_min = 400000;
+ cfg->cfg.f_max = min(cfg->sdhc_clk, (u32)52000000);
- mmc->f_min = 400000;
- mmc->f_max = MIN(cfg->sdhc_clk, 52000000);
+ cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
- mmc->b_max = 0;
- mmc_register(mmc);
+ mmc = mmc_create(&cfg->cfg, cfg);
+ if (mmc == NULL)
+ return -1;
return 0;
}
{
struct fsl_esdhc_cfg *cfg;
- cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1);
- cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
+ cfg = kzalloc(sizeof(struct fsl_esdhc_cfg), GFP_KERNEL);
+ if (!cfg)
+ return -ENOMEM;
+ cfg->esdhc_base = (void __iomem *)CONFIG_SYS_FSL_ESDHC_ADDR;
cfg->sdhc_clk = gd->arch.sdhc_clk;
return fsl_esdhc_initialize(bis, cfg);
}
#include <config.h>
#include <common.h>
#include <command.h>
+#include <errno.h>
#include <mmc.h>
#include <part.h>
#include <malloc.h>
#include <linux/list.h>
#include <div64.h>
-
-/* Set block count limit because of 16 bit register limit on some hardware*/
-#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
-#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
-#endif
+#include "mmc_private.h"
static struct list_head mmc_devices;
static int cur_dev_num = -1;
-int __weak board_mmc_getwp(struct mmc *mmc)
+__weak int board_mmc_getwp(struct mmc *mmc)
{
return -1;
}
wp = board_mmc_getwp(mmc);
if (wp < 0) {
- if (mmc->getwp)
- wp = mmc->getwp(mmc);
+ if (mmc->cfg->ops->getwp)
+ wp = mmc->cfg->ops->getwp(mmc);
else
wp = 0;
}
return wp;
}
-int __board_mmc_getcd(struct mmc *mmc) {
+__weak int board_mmc_getcd(struct mmc *mmc)
+{
return -1;
}
-int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
- alias("__board_mmc_getcd")));
-
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
- struct mmc_data backup;
int ret;
- memset(&backup, 0, sizeof(backup));
-
#ifdef CONFIG_MMC_TRACE
int i;
u8 *ptr;
printf("CMD_SEND:%d\n", cmd->cmdidx);
printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
- ret = mmc->send_cmd(mmc, cmd, data);
+ ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
switch (cmd->resp_type) {
case MMC_RSP_NONE:
printf("\t\tMMC_RSP_NONE\n");
break;
}
#else
- ret = mmc->send_cmd(mmc, cmd, data);
+ ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
#endif
return ret;
}
-static int mmc_send_status(struct mmc *mmc, int timeout)
+int mmc_send_status(struct mmc *mmc, int timeout)
{
struct mmc_cmd cmd;
int err, retries = 5;
MMC_STATE_PRG)
break;
else if (cmd.response[0] & MMC_STATUS_MASK) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Status Error: 0x%08X\n",
cmd.response[0]);
+#endif
return COMM_ERR;
}
} else if (--retries < 0)
printf("CURR STATE:%d\n", status);
#endif
if (timeout <= 0) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Timeout waiting card ready\n");
+#endif
return TIMEOUT;
}
+ if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR)
+ return SWITCH_ERR;
return 0;
}
-static int mmc_set_blocklen(struct mmc *mmc, int len)
+int mmc_set_blocklen(struct mmc *mmc, int len)
{
struct mmc_cmd cmd;
+ if (mmc->ddr_mode)
+ return 0;
+
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = len;
return m;
}
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC Device %d not found\n", dev_num);
+#endif
return NULL;
}
-static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
-{
- struct mmc_cmd cmd;
- ulong end;
- int err, start_cmd, end_cmd;
-
- if (mmc->high_capacity)
- end = start + blkcnt - 1;
- else {
- end = (start + blkcnt - 1) * mmc->write_bl_len;
- start *= mmc->write_bl_len;
- }
-
- if (IS_SD(mmc)) {
- start_cmd = SD_CMD_ERASE_WR_BLK_START;
- end_cmd = SD_CMD_ERASE_WR_BLK_END;
- } else {
- start_cmd = MMC_CMD_ERASE_GROUP_START;
- end_cmd = MMC_CMD_ERASE_GROUP_END;
- }
-
- cmd.cmdidx = start_cmd;
- cmd.cmdarg = start;
- cmd.resp_type = MMC_RSP_R1;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err)
- goto err_out;
-
- cmd.cmdidx = end_cmd;
- cmd.cmdarg = end;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err)
- goto err_out;
-
- cmd.cmdidx = MMC_CMD_ERASE;
- cmd.cmdarg = SECURE_ERASE;
- cmd.resp_type = MMC_RSP_R1b;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err)
- goto err_out;
-
- return 0;
-
-err_out:
- puts("mmc erase failed\n");
- return err;
-}
-
-static unsigned long
-mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
-{
- int err = 0;
- struct mmc *mmc = find_mmc_device(dev_num);
- lbaint_t blk = 0, blk_r = 0;
- int timeout = 1000;
-
- if (!mmc)
- return -1;
-
- if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
- printf("\n\nCaution! Your devices Erase group is 0x%x\n"
- "The erase range would be change to "
- "0x" LBAF "~0x" LBAF "\n\n",
- mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
- ((start + blkcnt + mmc->erase_grp_size)
- & ~(mmc->erase_grp_size - 1)) - 1);
-
- while (blk < blkcnt) {
- blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
- mmc->erase_grp_size : (blkcnt - blk);
- err = mmc_erase_t(mmc, start + blk, blk_r);
- if (err)
- break;
-
- blk += blk_r;
-
- /* Waiting for the ready status */
- if (mmc_send_status(mmc, timeout))
- return 0;
- }
-
- return blk;
-}
-
-static ulong
-mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
-{
- struct mmc_cmd cmd;
- struct mmc_data data;
- int timeout = 1000;
-
- if ((start + blkcnt) > mmc->block_dev.lba) {
- printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
- start + blkcnt, mmc->block_dev.lba);
- return 0;
- }
-
- if (blkcnt == 0)
- return 0;
- else if (blkcnt == 1)
- cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
- else
- cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
-
- if (mmc->high_capacity)
- cmd.cmdarg = start;
- else
- cmd.cmdarg = start * mmc->write_bl_len;
-
- cmd.resp_type = MMC_RSP_R1;
-
- data.src = src;
- data.blocks = blkcnt;
- data.blocksize = mmc->write_bl_len;
- data.flags = MMC_DATA_WRITE;
-
- if (mmc_send_cmd(mmc, &cmd, &data)) {
- printf("mmc write failed\n");
- return 0;
- }
-
- /* SPI multiblock writes terminate using a special
- * token, not a STOP_TRANSMISSION request.
- */
- if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
- cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
- cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1b;
- if (mmc_send_cmd(mmc, &cmd, NULL)) {
- printf("mmc fail to send stop cmd\n");
- return 0;
- }
- }
-
- /* Waiting for the ready status */
- if (mmc_send_status(mmc, timeout))
- return 0;
-
- return blkcnt;
-}
-
-static ulong
-mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
-{
- lbaint_t cur, blocks_todo = blkcnt;
-
- struct mmc *mmc = find_mmc_device(dev_num);
- if (!mmc)
- return 0;
-
- if (mmc_set_blocklen(mmc, mmc->write_bl_len))
- return 0;
-
- do {
- cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
- if(mmc_write_blocks(mmc, start, cur, src) != cur)
- return 0;
- blocks_todo -= cur;
- start += cur;
- src += cur * mmc->write_bl_len;
- } while (blocks_todo > 0);
-
- return blkcnt;
-}
-
static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
lbaint_t blkcnt)
{
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
if (mmc_send_cmd(mmc, &cmd, NULL)) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("mmc fail to send stop cmd\n");
+#endif
return 0;
}
}
return 0;
if ((start + blkcnt) > mmc->block_dev.lba) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
start + blkcnt, mmc->block_dev.lba);
+#endif
return 0;
}
return 0;
do {
- cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
+ cur = (blocks_todo > mmc->cfg->b_max) ?
+ mmc->cfg->b_max : blocks_todo;
if(mmc_read_blocks(mmc, dst, start, cur) != cur)
return 0;
blocks_todo -= cur;
* specified.
*/
cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
- (mmc->voltages & 0xff8000);
+ (mmc->cfg->voltages & 0xff8000);
if (mmc->version == SD_VERSION_2)
cmd.cmdarg |= OCR_HCS;
udelay(1000);
} while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);
-
- if (timeout <= 0)
+ if (!(cmd.response[0] & OCR_BUSY))
return UNUSABLE_ERR;
if (mmc->version != SD_VERSION_2)
cmd->cmdarg = 0;
if (use_arg && !mmc_host_is_spi(mmc)) {
cmd->cmdarg =
- (mmc->voltages &
+ (mmc->cfg->voltages &
(mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
(mmc->op_cond_response & OCR_ACCESS_MODE);
- if (mmc->host_caps & MMC_MODE_HC)
+ if (mmc->cfg->host_caps & MMC_MODE_HC)
cmd->cmdarg |= OCR_HCS;
}
err = mmc_send_cmd(mmc, cmd, NULL);
return 0;
}
-int mmc_send_op_cond(struct mmc *mmc)
+static int mmc_send_op_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
int err, i;
/* Some cards seem to need this */
mmc_go_idle(mmc);
- /* Asking to the card its capabilities */
+ /* Asking to the card its capabilities */
mmc->op_cond_pending = 1;
for (i = 0; i < 2; i++) {
err = mmc_send_op_cond_iter(mmc, &cmd, i != 0);
return IN_PROGRESS;
}
-int mmc_complete_op_cond(struct mmc *mmc)
+static int mmc_complete_op_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
int timeout = 1000;
if (err)
return err;
if (get_timer(start) > timeout)
- return UNUSABLE_ERR;
+ break;
udelay(100);
} while (!(mmc->op_cond_response & OCR_BUSY));
+ if (!(mmc->op_cond_response & OCR_BUSY)) {
+ debug("%s: timeout\n", __func__);
+ return UNUSABLE_ERR;
+ }
if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
mmc->ocr = cmd.response[0];
mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
- mmc->rca = 0;
+ mmc->rca = 1;
return 0;
}
char cardtype;
int err;
- mmc->card_caps = 0;
+ mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
if (mmc_host_is_spi(mmc))
return 0;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
if (err)
- return err;
+ return err == SWITCH_ERR ? 0 : err;
/* Now check to see that it worked */
err = mmc_send_ext_csd(mmc, ext_csd);
return 0;
/* High Speed is set, there are two types: 52MHz and 26MHz */
- if (cardtype & MMC_HS_52MHZ)
+ if (cardtype & EXT_CSD_CARD_TYPE_52) {
+ if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
+ mmc->card_caps |= MMC_MODE_DDR_52MHz;
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
- else
+ } else {
mmc->card_caps |= MMC_MODE_HS;
+ }
return 0;
}
return 0;
}
+int mmc_select_hwpart(int dev_num, int hwpart)
+{
+ struct mmc *mmc = find_mmc_device(dev_num);
+ int ret;
+
+ if (!mmc)
+ return -ENODEV;
+
+ if (mmc->part_num == hwpart)
+ return 0;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE) {
+ printf("Card doesn't support part_switch\n");
+ return -EMEDIUMTYPE;
+ }
+
+ ret = mmc_switch_part(dev_num, hwpart);
+ if (ret)
+ return ret;
+
+ mmc->part_num = hwpart;
+
+ return 0;
+}
+
+
int mmc_switch_part(int dev_num, unsigned int part_num)
{
struct mmc *mmc = find_mmc_device(dev_num);
ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
(mmc->part_config & ~PART_ACCESS_MASK)
| (part_num & PART_ACCESS_MASK));
- if (ret)
- return ret;
- return mmc_set_capacity(mmc, part_num);
+ /*
+ * Set the capacity if the switch succeeded or was intended
+ * to return to representing the raw device.
+ */
+ if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0)))
+ ret = mmc_set_capacity(mmc, part_num);
+
+ return ret;
}
int mmc_getcd(struct mmc *mmc)
cd = board_mmc_getcd(mmc);
if (cd < 0) {
- if (mmc->getcd)
- cd = mmc->getcd(mmc);
+ if (mmc->cfg->ops->getcd)
+ cd = mmc->cfg->ops->getcd(mmc);
else
cd = 1;
}
* This can avoid furthur problem when the card runs in different
* mode between the host.
*/
- if (!((mmc->host_caps & MMC_MODE_HS_52MHz) &&
- (mmc->host_caps & MMC_MODE_HS)))
+ if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) &&
+ (mmc->cfg->host_caps & MMC_MODE_HS)))
return 0;
err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
static void mmc_set_ios(struct mmc *mmc)
{
- mmc->set_ios(mmc);
+ if (mmc->cfg->ops->set_ios)
+ mmc->cfg->ops->set_ios(mmc);
}
void mmc_set_clock(struct mmc *mmc, uint clock)
{
- if (clock > mmc->f_max)
- clock = mmc->f_max;
+ if (clock > mmc->cfg->f_max)
+ clock = mmc->cfg->f_max;
- if (clock < mmc->f_min)
- clock = mmc->f_min;
+ if (clock < mmc->cfg->f_min)
+ clock = mmc->cfg->f_min;
mmc->clock = clock;
mmc->tran_speed = freq * mult;
+ mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
if (IS_SD(mmc))
if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
+ if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
+ cmd.cmdidx = MMC_CMD_SET_DSR;
+ cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
+ cmd.resp_type = MMC_RSP_NONE;
+ if (mmc_send_cmd(mmc, &cmd, NULL))
+ printf("MMC: SET_DSR failed\n");
+ }
+
/* Select the card, and put it into Transfer Mode */
if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
cmd.cmdidx = MMC_CMD_SELECT_CARD;
case 6:
mmc->version = MMC_VERSION_4_5;
break;
+ case 7:
+ mmc->version = MMC_VERSION_5_0;
+ break;
}
/*
- * Check whether GROUP_DEF is set, if yes, read out
- * group size from ext_csd directly, or calculate
- * the group size from the csd value.
+ * Host needs to enable ERASE_GRP_DEF bit if device is
+ * partitioned. This bit will be lost every time after a reset
+ * or power off. This will affect erase size.
*/
- if (ext_csd[EXT_CSD_ERASE_GROUP_DEF]) {
+ if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
+ (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB)) {
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_ERASE_GROUP_DEF, 1);
+
+ if (err)
+ return err;
+ else
+ ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
+
+ /* Read out group size from ext_csd */
mmc->erase_grp_size =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
MMC_MAX_BLOCK_LEN * 1024;
+ /*
+ * if high capacity and partition setting completed
+ * SEC_COUNT is valid even if it is smaller than 2 GiB
+ * JEDEC Standard JESD84-B45, 6.2.4
+ */
+ if (mmc->high_capacity &&
+ (ext_csd[EXT_CSD_PARTITION_SETTING] &
+ EXT_CSD_PARTITION_SETTING_COMPLETED)) {
+ capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
+ (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
+ (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
+ (ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
+ capacity *= MMC_MAX_BLOCK_LEN;
+ mmc->capacity_user = capacity;
+ }
} else {
+ /* Calculate the group size from the csd value. */
int erase_gsz, erase_gmul;
erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
return err;
/* Restrict card's capabilities by what the host can do */
- mmc->card_caps &= mmc->host_caps;
+ mmc->card_caps &= mmc->cfg->host_caps;
if (IS_SD(mmc)) {
if (mmc->card_caps & MMC_MODE_4BIT) {
/* An array of possible bus widths in order of preference */
static unsigned ext_csd_bits[] = {
+ EXT_CSD_DDR_BUS_WIDTH_8,
+ EXT_CSD_DDR_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8,
EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_1,
/* An array to map CSD bus widths to host cap bits */
static unsigned ext_to_hostcaps[] = {
+ [EXT_CSD_DDR_BUS_WIDTH_4] =
+ MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
+ [EXT_CSD_DDR_BUS_WIDTH_8] =
+ MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
};
/* An array to map chosen bus width to an integer */
static unsigned widths[] = {
- 8, 4, 1,
+ 8, 4, 8, 4, 1,
};
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
unsigned int extw = ext_csd_bits[idx];
+ unsigned int caps = ext_to_hostcaps[extw];
/*
- * Check to make sure the controller supports
- * this bus width, if it's more than 1
+ * Check to make sure the card and controller support
+ * these capabilities
*/
- if (extw != EXT_CSD_BUS_WIDTH_1 &&
- !(mmc->host_caps & ext_to_hostcaps[extw]))
+ if ((mmc->card_caps & caps) != caps)
continue;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
if (err)
continue;
+ mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
mmc_set_bus_width(mmc, widths[idx]);
err = mmc_send_ext_csd(mmc, test_csd);
- if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
- == test_csd[EXT_CSD_PARTITIONING_SUPPORT]
- && ext_csd[EXT_CSD_ERASE_GROUP_DEF] \
- == test_csd[EXT_CSD_ERASE_GROUP_DEF] \
- && ext_csd[EXT_CSD_REV] \
- == test_csd[EXT_CSD_REV]
- && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \
- == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
- && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
- &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
-
- mmc->card_caps |= ext_to_hostcaps[extw];
+
+ if (err)
+ continue;
+
+ /* Only compare read only fields */
+ if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
+ == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
+ ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
+ == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
+ ext_csd[EXT_CSD_REV]
+ == test_csd[EXT_CSD_REV] &&
+ ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
+ == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
+ memcmp(&ext_csd[EXT_CSD_SEC_CNT],
+ &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
break;
- }
+ else
+ err = SWITCH_ERR;
}
+ if (err)
+ return err;
+
if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz)
mmc->tran_speed = 52000000;
mmc_set_clock(mmc, mmc->tran_speed);
+ /* Fix the block length for DDR mode */
+ if (mmc->ddr_mode) {
+ mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
+ mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
+ }
+
/* fill in device description */
mmc->block_dev.lun = 0;
mmc->block_dev.type = 0;
mmc->block_dev.blksz = mmc->read_bl_len;
mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
(mmc->cid[3] >> 16) & 0xffff);
(mmc->cid[2] >> 24) & 0xff);
sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
(mmc->cid[2] >> 16) & 0xf);
+#else
+ mmc->block_dev.vendor[0] = 0;
+ mmc->block_dev.product[0] = 0;
+ mmc->block_dev.revision[0] = 0;
+#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
init_part(&mmc->block_dev);
#endif
cmd.cmdidx = SD_CMD_SEND_IF_COND;
/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
- cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
+ cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
cmd.resp_type = MMC_RSP_R7;
err = mmc_send_cmd(mmc, &cmd, NULL);
return 0;
}
-int mmc_register(struct mmc *mmc)
+/* not used any more */
+int __deprecated mmc_register(struct mmc *mmc)
+{
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+ printf("%s is deprecated! use mmc_create() instead.\n", __func__);
+#endif
+ return -1;
+}
+
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
{
+ struct mmc *mmc;
+
+ /* quick validation */
+ if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
+ cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
+ return NULL;
+
+ mmc = calloc(1, sizeof(*mmc));
+ if (mmc == NULL)
+ return NULL;
+
+ mmc->cfg = cfg;
+ mmc->priv = priv;
+
+ /* the following chunk was mmc_register() */
+
+ /* Setup dsr related values */
+ mmc->dsr_imp = 0;
+ mmc->dsr = 0xffffffff;
/* Setup the universal parts of the block interface just once */
mmc->block_dev.if_type = IF_TYPE_MMC;
mmc->block_dev.dev = cur_dev_num++;
mmc->block_dev.block_read = mmc_bread;
mmc->block_dev.block_write = mmc_bwrite;
mmc->block_dev.block_erase = mmc_berase;
- if (!mmc->b_max)
- mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
- INIT_LIST_HEAD (&mmc->link);
+ /* setup initial part type */
+ mmc->block_dev.part_type = mmc->cfg->part_type;
- list_add_tail (&mmc->link, &mmc_devices);
+ INIT_LIST_HEAD(&mmc->link);
- return 0;
+ list_add_tail(&mmc->link, &mmc_devices);
+
+ return mmc;
+}
+
+void mmc_destroy(struct mmc *mmc)
+{
+ /* only freeing memory for now */
+ free(mmc);
}
#ifdef CONFIG_PARTITIONS
}
#endif
+/* board-specific MMC power initializations. */
+__weak void board_mmc_power_init(void)
+{
+}
+
int mmc_start_init(struct mmc *mmc)
{
int err;
- if (mmc_getcd(mmc) == 0) {
+ /* we pretend there's no card when init is NULL */
+ if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) {
mmc->has_init = 0;
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: no card present\n");
+#endif
return NO_CARD_ERR;
}
if (mmc->has_init)
return 0;
- err = mmc->init(mmc);
+ board_mmc_power_init();
+
+ /* made sure it's not NULL earlier */
+ err = mmc->cfg->ops->init(mmc);
if (err)
return err;
+ mmc->ddr_mode = 0;
mmc_set_bus_width(mmc, 1);
mmc_set_clock(mmc, 1);
err = mmc_send_op_cond(mmc);
if (err && err != IN_PROGRESS) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Card did not respond to voltage select!\n");
+#endif
return UNUSABLE_ERR;
}
}
int mmc_init(struct mmc *mmc)
{
int err = IN_PROGRESS;
- unsigned start = get_timer(0);
+ unsigned start;
if (mmc->has_init)
return 0;
+
+ start = get_timer(0);
+
if (!mmc->init_in_progress)
err = mmc_start_init(mmc);
return err;
}
-/*
- * CPU and board-specific MMC initializations. Aliased function
- * signals caller to move on
- */
-static int __def_mmc_init(bd_t *bis)
+int mmc_set_dsr(struct mmc *mmc, u16 val)
+{
+ mmc->dsr = val;
+ return 0;
+}
+
+/* CPU-specific MMC initializations */
+__weak int cpu_mmc_init(bd_t *bis)
+{
+ return -1;
+}
+
+/* board-specific MMC initializations. */
+__weak int board_mmc_init(bd_t *bis)
{
return -1;
}
-int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
-int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
void print_mmc_devices(char separator)
{
list_for_each(entry, &mmc_devices) {
m = list_entry(entry, struct mmc, link);
- printf("%s: %d", m->name, m->block_dev.dev);
+ printf("%s: %d", m->cfg->name, m->block_dev.dev);
- if (entry->next != &mmc_devices)
- printf("%c ", separator);
+ if (entry->next != &mmc_devices) {
+ printf("%c", separator);
+ if (separator != '\n')
+ puts (" ");
+ }
}
printf("\n");
}
+#else
+void print_mmc_devices(char separator) { }
+#endif
+
int get_mmc_num(void)
{
return cur_dev_num;
if (board_mmc_init(bis) < 0)
cpu_mmc_init(bis);
+#ifndef CONFIG_SPL_BUILD
print_mmc_devices(',');
+#endif
do_preinit();
return 0;
}
/*
- * This function shall form and send the commands to open / close the
- * boot partition specified by user.
- *
- * Input Parameters:
- * ack: 0x0 - No boot acknowledge sent (default)
- * 0x1 - Boot acknowledge sent during boot operation
- * part_num: User selects boot data that will be sent to master
- * 0x0 - Device not boot enabled (default)
- * 0x1 - Boot partition 1 enabled for boot
- * 0x2 - Boot partition 2 enabled for boot
- * access: User selects partitions to access
- * 0x0 : No access to boot partition (default)
- * 0x1 : R/W boot partition 1
- * 0x2 : R/W boot partition 2
- * 0x3 : R/W Replay Protected Memory Block (RPMB)
+ * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
+ * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
+ * and BOOT_MODE.
*
* Returns 0 on success.
*/
-int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
{
int err;
- struct mmc_cmd cmd;
- /* Boot ack enable, boot partition enable , boot partition access */
- cmd.cmdidx = MMC_CMD_SWITCH;
- cmd.resp_type = MMC_RSP_R1b;
-
- cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
- (EXT_CSD_PART_CONF << 16) |
- ((EXT_CSD_BOOT_ACK(ack) |
- EXT_CSD_BOOT_PART_NUM(part_num) |
- EXT_CSD_PARTITION_ACCESS(access)) << 8);
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
+ EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
+ EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
+ EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- if (access) {
- debug("mmc boot partition#%d open fail:Error1 = %d\n",
- part_num, err);
- } else {
- debug("mmc boot partition#%d close fail:Error = %d\n",
- part_num, err);
- }
+ if (err)
return err;
- }
+ return 0;
+}
- if (access) {
- /* 4bit transfer mode at booting time. */
- cmd.cmdidx = MMC_CMD_SWITCH;
- cmd.resp_type = MMC_RSP_R1b;
+/*
+ * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
+ * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
+ * PARTITION_ACCESS.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+ int err;
- cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
- (EXT_CSD_BOOT_BUS_WIDTH << 16) |
- ((1 << 0) << 8);
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+ EXT_CSD_BOOT_ACK(ack) |
+ EXT_CSD_BOOT_PART_NUM(part_num) |
+ EXT_CSD_PARTITION_ACCESS(access));
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc boot partition#%d open fail:Error2 = %d\n",
- part_num, err);
- return err;
- }
- }
+ if (err)
+ return err;
return 0;
}
+
+/*
+ * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
+ * for enable. Note that this is a write-once field for non-zero values.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
+{
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
+ enable);
+}
#endif
int (*mmc_is_wp)(int);
int (*mmc_cd)(int);
struct mxs_dma_desc *desc;
+ struct mmc_config cfg; /* mmc configuration */
};
#define MXSMMC_MAX_TIMEOUT 10000
return timeout ? 0 : COMM_ERR;
}
- static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
+ static int mxsmmc_send_cmd_dma(struct mmc *mmc, struct mxsmmc_priv *priv,
+ struct mmc_data *data)
{
uint32_t data_count = data->blocksize * data->blocks;
int dmach;
void *addr;
unsigned int flags;
struct bounce_buffer bbstate;
+ unsigned long xfer_rate = (mmc->clock ?: 400000) * mmc->bus_width;
+ unsigned long dma_timeout = data_count * 8 /
+ DIV_ROUND_UP(xfer_rate, 1000);
memset(desc, 0, sizeof(struct mxs_dma_desc));
desc->address = (dma_addr_t)desc;
dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id;
mxs_dma_desc_append(dmach, priv->desc);
+ /* set DMA timeout adding 250ms for min timeout according to SD spec. */
+ mxs_dma_set_timeout(dmach, dma_timeout + 250);
if (mxs_dma_go(dmach)) {
bounce_buffer_stop(&bbstate);
return COMM_ERR;
static int
mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
- struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+ struct mxsmmc_priv *priv = mmc->priv;
struct mxs_ssp_regs *ssp_regs = priv->regs;
uint32_t reg;
int timeout;
uint32_t ctrl0;
+ const uint32_t busy_stat = SSP_STATUS_BUSY | SSP_STATUS_DATA_BUSY |
+ SSP_STATUS_CMD_BUSY;
int ret;
debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx);
/* Check bus busy */
timeout = MXSMMC_MAX_TIMEOUT;
- while (--timeout) {
- udelay(1000);
- reg = readl(&ssp_regs->hw_ssp_status);
- if (!(reg &
- (SSP_STATUS_BUSY | SSP_STATUS_DATA_BUSY |
- SSP_STATUS_CMD_BUSY))) {
+ while ((reg = readl(&ssp_regs->hw_ssp_status)) & busy_stat) {
+ if (timeout-- <= 0)
break;
- }
+ udelay(1000);
}
-
- if (!timeout) {
+ if (reg & busy_stat && readl(&ssp_regs->hw_ssp_status) & busy_stat) {
printf("MMC%d: Bus busy timeout!\n", mmc->block_dev.dev);
return TIMEOUT;
}
if (!(reg & SSP_STATUS_CMD_BUSY))
break;
}
-
- if (!timeout) {
+ if ((reg & SSP_STATUS_CMD_BUSY) &&
+ (readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CMD_BUSY)) {
printf("MMC%d: Command %d busy\n",
mmc->block_dev.dev, cmd->cmdidx);
return TIMEOUT;
if (data->blocksize * data->blocks < MXSMMC_SMALL_TRANSFER) {
ret = mxsmmc_send_cmd_pio(priv, data);
if (ret) {
- printf("MMC%d: Data timeout with command %d "
- "(status 0x%08x)!\n",
+ printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n",
mmc->block_dev.dev, cmd->cmdidx, reg);
return ret;
}
} else {
- ret = mxsmmc_send_cmd_dma(priv, data);
+ ret = mxsmmc_send_cmd_dma(mmc, priv, data);
if (ret) {
printf("MMC%d: DMA transfer failed\n",
mmc->block_dev.dev);
static void mxsmmc_set_ios(struct mmc *mmc)
{
- struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+ struct mxsmmc_priv *priv = mmc->priv;
struct mxs_ssp_regs *ssp_regs = priv->regs;
/* Set the clock speed */
static int mxsmmc_init(struct mmc *mmc)
{
- struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+ struct mxsmmc_priv *priv = mmc->priv;
struct mxs_ssp_regs *ssp_regs = priv->regs;
/* Reset SSP */
return 0;
}
+static const struct mmc_ops mxsmmc_ops = {
+ .send_cmd = mxsmmc_send_cmd,
+ .set_ios = mxsmmc_set_ios,
+ .init = mxsmmc_init,
+};
+
int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
{
-- struct mmc *mmc = NULL;
-- struct mxsmmc_priv *priv = NULL;
++ struct mmc *mmc;
++ struct mxsmmc_priv *priv;
int ret;
const unsigned int mxsmmc_clk_id = mxs_ssp_clock_by_bus(id);
if (!mxs_ssp_bus_id_valid(id))
return -ENODEV;
- priv = malloc(sizeof(struct mxsmmc_priv));
- mmc = calloc(sizeof(struct mmc), 1);
- if (!mmc)
- return -ENOMEM;
-
+ priv = calloc(sizeof(struct mxsmmc_priv), 1);
- if (!priv) {
- free(mmc);
+ if (!priv)
return -ENOMEM;
- }
priv->desc = mxs_dma_desc_alloc();
if (!priv->desc) {
-- free(priv);
- free(mmc);
-- return -ENOMEM;
++ ret = -ENOMEM;
++ goto free_priv;
}
ret = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + id);
if (ret)
-- return ret;
++ goto free_priv;
priv->mmc_is_wp = wp;
priv->mmc_cd = cd;
priv->id = id;
priv->regs = mxs_ssp_regs_by_bus(id);
- sprintf(mmc->name, "MXS MMC");
- mmc->send_cmd = mxsmmc_send_cmd;
- mmc->set_ios = mxsmmc_set_ios;
- mmc->init = mxsmmc_init;
- mmc->getcd = NULL;
- mmc->getwp = NULL;
- mmc->priv = priv;
+ priv->cfg.name = "MXS MMC";
+ priv->cfg.ops = &mxsmmc_ops;
- mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+ priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
- MMC_MODE_HS_52MHz | MMC_MODE_HS;
+ priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
+ MMC_MODE_HS_52MHz | MMC_MODE_HS |
+ MMC_MODE_HC;
/*
* SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
* CLOCK_DIVIDE has to be an even value from 2 to 254, and
* CLOCK_RATE could be any integer from 0 to 255.
*/
- mmc->f_min = 400000;
- mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
- mmc->b_max = 0x20;
-
- mmc_register(mmc);
+ priv->cfg.f_min = 400000;
+ priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
+ priv->cfg.b_max = 0x20;
+
+ mmc = mmc_create(&priv->cfg, priv);
+ if (mmc == NULL) {
- mxs_dma_desc_free(priv->desc);
- free(priv);
- return -ENOMEM;
++ ret = -ENOMEM;
++ goto free_dma;
+ }
return 0;
++
++free_dma:
++ mxs_dma_desc_free(priv->desc);
++free_priv:
++ free(priv);
++ return ret;
}
#include <config.h>
#include <common.h>
+#include <malloc.h>
#include <mmc.h>
#include <part.h>
#include <i2c.h>
#include <asm/arch/mmc_host_def.h>
#include <asm/arch/sys_proto.h>
+/* simplify defines to OMAP_HSMMC_USE_GPIO */
+#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
+ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
+#define OMAP_HSMMC_USE_GPIO
+#else
+#undef OMAP_HSMMC_USE_GPIO
+#endif
+
/* common definitions for all OMAPs */
#define SYSCTL_SRC (1 << 25)
#define SYSCTL_SRD (1 << 26)
struct omap_hsmmc_data {
struct hsmmc *base_addr;
+ struct mmc_config cfg;
+#ifdef OMAP_HSMMC_USE_GPIO
int cd_gpio;
int wp_gpio;
+#endif
};
/* If we fail after 1 second wait, something is really bad */
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int siz);
-static struct mmc hsmmc_dev[3];
-static struct omap_hsmmc_data hsmmc_dev_data[3];
-#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
- (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
+#ifdef OMAP_HSMMC_USE_GPIO
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
{
- if (!gpio_is_valid(gpio))
- return -1;
+ int ret;
- if (gpio_request(gpio, label) < 0)
+#ifndef CONFIG_DM_GPIO
+ if (!gpio_is_valid(gpio))
return -1;
+#endif
+ ret = gpio_request(gpio, label);
+ if (ret)
+ return ret;
- if (gpio_direction_input(gpio) < 0)
- return -1;
+ ret = gpio_direction_input(gpio);
+ if (ret)
+ return ret;
return gpio;
}
-
-static int omap_mmc_getcd(struct mmc *mmc)
-{
- int cd_gpio = ((struct omap_hsmmc_data *)mmc->priv)->cd_gpio;
- return gpio_get_value(cd_gpio);
-}
-
-static int omap_mmc_getwp(struct mmc *mmc)
-{
- int wp_gpio = ((struct omap_hsmmc_data *)mmc->priv)->wp_gpio;
- return gpio_get_value(wp_gpio);
-}
-#else
-static inline int omap_mmc_setup_gpio_in(int gpio, const char *label)
-{
- return -1;
-}
-
-#define omap_mmc_getcd NULL
-#define omap_mmc_getwp NULL
#endif
#if defined(CONFIG_OMAP44XX) && defined(CONFIG_TWL6030_POWER)
}
#endif
- static unsigned char mmc_board_init(struct mmc *mmc)
+ static void mmc_board_init(struct mmc *mmc)
{
#if defined(CONFIG_OMAP34XX)
t2_t *t2_base = (t2_t *)T2_BASE;
pbias_lite = readl(&t2_base->pbias_lite);
pbias_lite &= ~(PBIASLITEPWRDNZ1 | PBIASLITEPWRDNZ0);
writel(pbias_lite, &t2_base->pbias_lite);
-#endif
-#if defined(CONFIG_TWL4030_POWER)
- twl4030_power_mmc_init();
- mdelay(100); /* ramp-up delay from Linux code */
-#endif
-#if defined(CONFIG_OMAP34XX)
+
writel(pbias_lite | PBIASLITEPWRDNZ1 |
PBIASSPEEDCTRL0 | PBIASLITEPWRDNZ0,
&t2_base->pbias_lite);
&t2_base->devconf1);
/* Change from default of 52MHz to 26MHz if necessary */
- if (!(mmc->host_caps & MMC_MODE_HS_52MHz))
+ if (!(mmc->cfg->host_caps & MMC_MODE_HS_52MHz))
writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL,
&t2_base->ctl_prog_io1);
if (mmc->block_dev.dev == 0)
omap5_pbias_config(mmc);
#endif
-
- return 0;
}
void mmc_init_stream(struct hsmmc *mmc_base)
writel(MMC_CMD0, &mmc_base->cmd);
start = get_timer(0);
while (!(readl(&mmc_base->stat) & CC_MASK)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for cc!\n", __func__);
- return;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if (!(readl(&mmc_base->stat) & CC_MASK)) {
+ printf("%s: timeout waiting for cc!\n", __func__);
+ return;
}
- writel(CC_MASK, &mmc_base->stat)
- ;
- writel(MMC_CMD0, &mmc_base->cmd)
- ;
+
+ writel(CC_MASK, &mmc_base->stat);
+ writel(MMC_CMD0, &mmc_base->cmd);
+
start = get_timer(0);
while (!(readl(&mmc_base->stat) & CC_MASK)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for cc2!\n", __func__);
- return;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if (!(readl(&mmc_base->stat) & CC_MASK)) {
+ printf("%s: timeout waiting for cc2!\n", __func__);
+ return;
}
writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con);
}
-static int mmc_init_setup(struct mmc *mmc)
+
+static int omap_hsmmc_init_setup(struct mmc *mmc)
{
- struct hsmmc *mmc_base;
+ struct omap_hsmmc_data *priv_data = mmc->priv;
+ struct hsmmc *mmc_base = priv_data->base_addr;
unsigned int reg_val;
unsigned int dsor;
ulong start;
- mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
mmc_board_init(mmc);
writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
&mmc_base->sysconfig);
start = get_timer(0);
while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for cc2!\n", __func__);
- return TIMEOUT;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) {
+ printf("%s: timeout %08x waiting for softreset done!\n", __func__,
+ readl(&mmc_base->sysstatus));
+ return TIMEOUT;
}
writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl);
start = get_timer(0);
- while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for softresetall!\n",
- __func__);
- return TIMEOUT;
- }
+ while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0) {
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0) {
+ printf("%s: timeout waiting for softresetall!\n", __func__);
+ return TIMEOUT;
}
writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP,
(dsor << CLKD_OFFSET) | ICE_OSCILLATE);
start = get_timer(0);
while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for ics!\n", __func__);
- return TIMEOUT;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
+ printf("%s: timeout waiting for ics!\n", __func__);
+ return TIMEOUT;
}
writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
mmc_reg_out(&mmc_base->sysctl, bit, bit);
+ /*
+ * CMD(DAT) lines reset procedures are slightly different
+ * for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx).
+ * According to OMAP3 TRM:
+ * Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it
+ * returns to 0x0.
+ * According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset
+ * procedure steps must be as follows:
+ * 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in
+ * MMCHS_SYSCTL register (SD_SYSCTL for AM335x).
+ * 2. Poll the SRC(SRD) bit until it is set to 0x1.
+ * 3. Wait until the SRC (SRD) bit returns to 0x0
+ * (reset procedure is completed).
+ */
+#if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
+ defined(CONFIG_AM33XX)
+ if (!(readl(&mmc_base->sysctl) & bit)) {
+ start = get_timer(0);
+ while (!(readl(&mmc_base->sysctl) & bit)) {
+ if (get_timer(0) - start > MAX_RETRY_MS)
+ return;
+ }
+ }
+#endif
start = get_timer(0);
while ((readl(&mmc_base->sysctl) & bit) != 0) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for sysctl %x to clear\n",
- __func__, bit);
- return;
- }
+ if (get_timer(0) - start > MAX_RETRY_MS)
+ break;
+ }
+ if ((readl(&mmc_base->sysctl) & bit) != 0) {
+ printf("%s: timedout waiting for sysctl %x to clear\n", __func__, bit);
+ return;
}
}
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
- struct hsmmc *mmc_base;
+ struct omap_hsmmc_data *priv_data = mmc->priv;
+ struct hsmmc *mmc_base = priv_data->base_addr;
unsigned int flags, mmc_stat;
ulong start;
- mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
start = get_timer(0);
while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting on cmd inhibit to clear\n",
- __func__);
- return TIMEOUT;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
+ printf("%s: timeout waiting on cmd inhibit to clear\n", __func__);
+ return TIMEOUT;
}
writel(0xFFFFFFFF, &mmc_base->stat);
start = get_timer(0);
while (readl(&mmc_base->stat)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for STAT (%x) to clear\n",
- __func__, readl(&mmc_base->stat));
- return TIMEOUT;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if (readl(&mmc_base->stat)) {
+ printf("%s: timeout waiting for stat!\n", __func__);
+ return TIMEOUT;
}
/*
* CMDREG
}
writel(cmd->cmdarg, &mmc_base->arg);
+ udelay(20); /* To fix "No status update" error on eMMC */
writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
start = get_timer(0);
- do {
- mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s : timeout: No status update\n", __func__);
- return TIMEOUT;
- }
- } while (!mmc_stat);
+ while (!(mmc_stat = readl(&mmc_base->stat))) {
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if (!mmc_stat) {
+ printf("%s : timeout: No status update\n", __func__);
+ return TIMEOUT;
+ }
if ((mmc_stat & IE_CTO) != 0) {
mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
while (size) {
ulong start = get_timer(0);
- do {
- mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for status!\n",
- __func__);
- return TIMEOUT;
- }
- } while (mmc_stat == 0);
+
+ while (!(mmc_stat = readl(&mmc_base->stat))) {
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if (!mmc_stat) {
+ printf("%s: timeout waiting for status!\n", __func__);
+ return TIMEOUT;
+ }
if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0)
mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
unsigned int count;
/*
- * Start Polled Read
+ * Start Polled Write
*/
count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size;
count /= 4;
while (size) {
ulong start = get_timer(0);
- do {
- mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for status!\n",
- __func__);
- return TIMEOUT;
- }
- } while (mmc_stat == 0);
+
+ while (!(mmc_stat = readl(&mmc_base->stat))) {
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if (!mmc_stat) {
+ printf("%s: timeout waiting for status!\n", __func__);
+ return TIMEOUT;
+ }
if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0)
mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
return 0;
}
-static void mmc_set_ios(struct mmc *mmc)
+static void omap_hsmmc_set_ios(struct mmc *mmc)
{
- struct hsmmc *mmc_base;
+ struct omap_hsmmc_data *priv_data = mmc->priv;
+ struct hsmmc *mmc_base = priv_data->base_addr;
unsigned int dsor = 0;
ulong start;
- mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
/* configue bus width */
switch (mmc->bus_width) {
case 8:
start = get_timer(0);
while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for ics!\n", __func__);
- return;
- }
+ if (get_timer(start) > MAX_RETRY_MS)
+ break;
+ }
+ if ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
+ printf("%s: timeout waiting for ics!\n", __func__);
+ return;
}
writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
}
+#ifdef OMAP_HSMMC_USE_GPIO
+static int omap_hsmmc_getcd(struct mmc *mmc)
+{
+ struct omap_hsmmc_data *priv_data = mmc->priv;
+ int cd_gpio;
+
+ /* if no CD return as 1 */
+ cd_gpio = priv_data->cd_gpio;
+ if (cd_gpio < 0)
+ return 1;
+
+ /* NOTE: assumes card detect signal is active-low */
+ return !gpio_get_value(cd_gpio);
+}
+
+static int omap_hsmmc_getwp(struct mmc *mmc)
+{
+ struct omap_hsmmc_data *priv_data = mmc->priv;
+ int wp_gpio;
+
+ /* if no WP return as 0 */
+ wp_gpio = priv_data->wp_gpio;
+ if (wp_gpio < 0)
+ return 0;
+
+ /* NOTE: assumes write protect signal is active-high */
+ return gpio_get_value(wp_gpio);
+}
+#endif
+
+static const struct mmc_ops omap_hsmmc_ops = {
+ .send_cmd = omap_hsmmc_send_cmd,
+ .set_ios = omap_hsmmc_set_ios,
+ .init = omap_hsmmc_init_setup,
+#ifdef OMAP_HSMMC_USE_GPIO
+ .getcd = omap_hsmmc_getcd,
+ .getwp = omap_hsmmc_getwp,
+#endif
+};
+
int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
int wp_gpio)
{
++ int ret;
struct mmc *mmc;
struct omap_hsmmc_data *priv_data;
- unsigned long base_addr;
+ struct mmc_config *cfg;
+ uint host_caps_val;
+
- priv_data = malloc(sizeof(*priv_data));
++ priv_data = calloc(sizeof(*priv_data), 1);
+ if (priv_data == NULL)
- return -1;
++ return -ENOMEM;
+
+ host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
+ MMC_MODE_HC;
switch (dev_index) {
case 0:
- priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
+ base_addr = OMAP_HSMMC1_BASE;
break;
#ifdef OMAP_HSMMC2_BASE
case 1:
- base_addr = OMAP_HSMMC2_BASE;
+ priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
+#if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
+ defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)) && \
+ defined(CONFIG_HSMMC2_8BIT)
+ /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */
+ host_caps_val |= MMC_MODE_8BIT;
+#endif
break;
#endif
#ifdef OMAP_HSMMC3_BASE
case 2:
- base_addr = OMAP_HSMMC3_BASE;
+ priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
+#if (defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)) && defined(CONFIG_HSMMC3_8BIT)
+ /* Enable 8-bit interface for eMMC on DRA7XX */
+ host_caps_val |= MMC_MODE_8BIT;
+#endif
break;
#endif
default:
- priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
- return 1;
+ printf("Invalid MMC device index: %d\n", dev_index);
- return 1;
++ ret = 1;
++ goto out;
}
-
- mmc = &hsmmc_dev[dev_index];
- priv_data = &hsmmc_dev_data[dev_index];
- priv_data->base_addr = (void *)base_addr;
-
- sprintf(mmc->name, "OMAP SD/MMC");
- mmc->send_cmd = mmc_send_cmd;
- mmc->set_ios = mmc_set_ios;
- mmc->init = mmc_init_setup;
- mmc->priv = priv_data;
-
+#ifdef OMAP_HSMMC_USE_GPIO
+ /* on error gpio values are set to -1, which is what we want */
priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd");
- if (priv_data->cd_gpio != -1)
- mmc->getcd = omap_mmc_getcd;
-
priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
- if (priv_data->wp_gpio != -1)
- mmc->getwp = omap_mmc_getwp;
+#endif
+
+ cfg = &priv_data->cfg;
- mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
- mmc->host_caps = (MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
- MMC_MODE_HC) & ~host_caps_mask;
+ cfg->name = "OMAP SD/MMC";
+ cfg->ops = &omap_hsmmc_ops;
- mmc->f_min = 400000;
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+ cfg->host_caps = host_caps_val & ~host_caps_mask;
+
+ cfg->f_min = 400000;
if (f_max != 0)
- mmc->f_max = f_max;
+ cfg->f_max = f_max;
else {
- if (mmc->host_caps & MMC_MODE_HS) {
- if (mmc->host_caps & MMC_MODE_HS_52MHz)
- mmc->f_max = 52000000;
+ if (cfg->host_caps & MMC_MODE_HS) {
+ if (cfg->host_caps & MMC_MODE_HS_52MHz)
+ cfg->f_max = 52000000;
else
- mmc->f_max = 26000000;
+ cfg->f_max = 26000000;
} else
- mmc->f_max = 20000000;
+ cfg->f_max = 20000000;
}
- mmc->b_max = 0;
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
#if defined(CONFIG_OMAP34XX)
/*
* Silicon revs 2.1 and older do not support multiblock transfers.
*/
if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
- mmc->b_max = 1;
+ cfg->b_max = 1;
#endif
-
- mmc_register(mmc);
+ mmc = mmc_create(cfg, priv_data);
- if (mmc == NULL)
- return -1;
++ if (mmc == NULL) {
++ ret = -ENOMEM;
++ goto out;
++ }
return 0;
++
++out:
++ free(priv_data);
++ return ret;
}
--- /dev/null
++menuconfig NOR_FLASH
++ bool "NOR flash support"
++
++if NOR_FLASH
++
++config CONFIG_FLASH_CFI_DRIVER
++ bool "CFI flash driver"
++
++endif
++
++config SYS_NO_FLASH
++ bool
++ default y
++ depends on !NOR_FLASH
++
++config MTD_PARTITIONS
++ bool "Support MTD partition tables"
++ depends on MTD_DEVICE
++ default y
++
+source "drivers/mtd/nand/Kconfig"
--- /dev/null
- menu "NAND Device Support"
++menuconfig NAND
++ bool "NAND Device Support"
++
++if NAND
++
++config SYS_NAND_USE_FLASH_BBT
++ bool "Use a flash based bad block table"
+
+config SYS_NAND_SELF_INIT
+ bool
+ help
+ This option, if enabled, provides more flexible and linux-like
+ NAND initialization process.
+
+if !SPL_BUILD
+
+config NAND_DENALI
+ bool "Support Denali NAND controller"
+ select SYS_NAND_SELF_INIT
+ help
+ Enable support for the Denali NAND controller.
+
+config SYS_NAND_DENALI_64BIT
+ bool "Use 64-bit variant of Denali NAND controller"
+ depends on NAND_DENALI
+ help
+ The Denali NAND controller IP has some variations in terms of
+ the bus interface. The DMA setup sequence is completely differenct
+ between 32bit / 64bit AXI bus variants.
+
+ If your Denali NAND controller is the 64-bit variant, say Y.
+ Otherwise (32 bit), say N.
+
+config NAND_DENALI_SPARE_AREA_SKIP_BYTES
+ int "Number of bytes skipped in OOB area"
+ depends on NAND_DENALI
+ range 0 63
+ help
+ This option specifies the number of bytes to skip from the beginning
+ of OOB area before last ECC sector data starts. This is potentially
+ used to preserve the bad block marker in the OOB area.
+
+endif
+
+if SPL_BUILD
+
+config SPL_NAND_DENALI
+ bool "Support Denali NAND controller for SPL"
+ help
+ This is a small implementation of the Denali NAND controller
+ for use on SPL.
+
+endif
+
- endmenu
++config NAND_MXC
++ bool "Support Freescale i.MX NAND controller"
++ select SYS_NAND_SELF_INIT if SPL
++ help
++ Enable support for the Freescale NAND controller found on
++ i.MX processors.
++
++config NAND_MXS
++ bool "Support Freescale GPMI NAND controller"
++ select SYS_NAND_SELF_INIT if SPL
++ help
++ Enable support for the Freescale GPMI NAND controller found
++ on i.MX28 and i.MX6 processors.
++
++config NAND_MXS_NO_BBM_SWAP
++ bool "disable bad block mark swapping"
++ depends on NAND_MXS && MX6
++ select SYS_NAND_USE_FLASH_BBT
++
++endif
*
* SPDX-License-Identifier: GPL-2.0+
*/
+ //#define DEBUG
#include <common.h>
#include <linux/mtd/mtd.h>
#define MXS_NAND_COMMAND_BUFFER_SIZE 32
+ /* BCH timeout in microseconds */
#define MXS_NAND_BCH_TIMEOUT 10000
+ static struct bch_regs *bch_regs = (void *)BCH_BASE_ADDRESS;
+ static struct gpmi_regs *gpmi_regs = (void *)GPMI_BASE_ADDRESS;
struct mxs_nand_info {
int cur_chip;
uint32_t desc_index;
};
+ #ifdef DEBUG
+ #define dump_reg(b, r) __dump_reg(&b->r, #r)
+ static inline void __dump_reg(void *addr, const char *name)
+ {
+ printf("%16s[%p]=%08x\n", name, addr, readl(addr));
+ }
+
+ #define dump_bch_reg(n) __dump_reg(&bch_regs->hw_bch_##n, #n)
+ #define dump_gpmi_reg(n) __dump_reg(&gpmi_regs->hw_gpmi_##n, #n)
+ static inline void dump_regs(void)
+ {
+ printf("BCH:\n");
+ dump_bch_reg(ctrl);
+ dump_bch_reg(status0);
+ dump_bch_reg(mode);
+ dump_bch_reg(debug0);
+ dump_bch_reg(dbgkesread);
+ dump_bch_reg(dbgcsferead);
+ dump_bch_reg(dbgsyndegread);
+ dump_bch_reg(dbgahbmread);
+ dump_bch_reg(blockname);
+ dump_bch_reg(version);
+
+ printf("\nGPMI:\n");
+ dump_gpmi_reg(ctrl0);
+ dump_gpmi_reg(eccctrl);
+ dump_gpmi_reg(ecccount);
+ dump_gpmi_reg(payload);
+ dump_gpmi_reg(auxiliary);
+ dump_gpmi_reg(ctrl1);
+ dump_gpmi_reg(data);
+ dump_gpmi_reg(stat);
+ dump_gpmi_reg(debug);
+ dump_gpmi_reg(version);
+ dump_gpmi_reg(debug2);
+ dump_gpmi_reg(debug3);
+ }
+
+ static inline int dbg_addr(void *addr)
+ {
+ if (((unsigned long)addr & ~0xfff) == BCH_BASE_ADDRESS)
+ return 1;
+ return 1;
+ }
+
+ static inline u32 mxs_readl(void *addr,
+ const char *fn, int ln)
+ {
+ u32 val = readl(addr);
+ static void *last_addr;
+ static u32 last_val;
+
+ if (!dbg_addr(addr))
+ return val;
+
+ if (addr != last_addr || last_val != val) {
+ printf("%s@%d: Read %08x from %p\n", fn, ln, val, addr);
+ last_addr = addr;
+ last_val = val;
+ }
+ return val;
+ }
+
+ static inline void mxs_writel(u32 val, void *addr,
+ const char *fn, int ln)
+ {
+ if (dbg_addr(addr))
+ printf("%s@%d: Writing %08x to %p...", fn, ln, val, addr);
+ writel(val, addr);
+ if (dbg_addr(addr))
+ printf(" result: %08x\n", readl(addr));
+ }
+
+ #undef readl
+ #define readl(a) mxs_readl(a, __func__, __LINE__)
+
+ #undef writel
+ #define writel(v, a) mxs_writel(v, a, __func__, __LINE__)
+ static inline void memdump(const void *addr, size_t len)
+ {
+ const char *buf = addr;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (i % 16 == 0) {
+ if (i > 0)
+ printf("\n");
+ printf("%p:", &buf[i]);
+ }
+ printf(" %02x", buf[i]);
+ }
+ printf("\n");
+ }
+ #else
+ static inline void memdump(void *addr, size_t len)
+ {
+ }
+
+ static inline void dump_regs(void)
+ {
+ }
+ #endif
+
struct nand_ecclayout fake_ecc_layout;
/*
info->desc_index = 0;
}
- static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+ static uint32_t mxs_nand_ecc_chunk_cnt(struct mtd_info *mtd)
{
- return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+ struct nand_chip *nand = mtd->priv;
+ return mtd->writesize / nand->ecc.size;
}
- static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+ static inline uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
{
return ecc_strength * 13;
}
return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
}
+ static int mxs_nand_gpmi_init(void)
+ {
+ int ret;
+
+ /* Reset the GPMI block. */
+ ret = mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+ if (ret)
+ return ret;
+
+ /*
+ * Choose NAND mode, set IRQ polarity, disable write protection and
+ * select BCH ECC.
+ */
+ clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+ GPMI_CTRL1_GPMI_MODE,
+ GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+ GPMI_CTRL1_BCH_MODE);
+ writel(0x500 << 16, &gpmi_regs->hw_gpmi_timing1);
+ return 0;
+ }
+
static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
uint32_t page_oob_size)
{
- if (page_data_size == 2048)
- return 8;
+ if (page_data_size == 2048) {
+ if (page_oob_size == 64)
+ return 8;
+
+ if (page_oob_size == 112)
+ return 14;
+ }
if (page_data_size == 4096) {
if (page_oob_size == 128)
if (page_oob_size == 218)
return 16;
+
+ if (page_oob_size == 224)
+ return 16;
}
return 0;
return block_mark_bit_offset;
}
- static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+ static inline uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
{
uint32_t ecc_strength;
ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
}
- static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+ static inline uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
{
uint32_t ecc_strength;
ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
*/
static int mxs_nand_wait_for_bch_complete(void)
{
- struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
int timeout = MXS_NAND_BCH_TIMEOUT;
int ret;
ret = mxs_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
BCH_CTRL_COMPLETE_IRQ, timeout);
+ if (ret) {
+ debug("%s@%d: %d\n", __func__, __LINE__, ret);
+ mxs_nand_gpmi_init();
+ }
writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
/* Execute the DMA chain. */
ret = mxs_dma_go(channel);
- if (ret)
- printf("MXS NAND: Error sending command\n");
+ if (ret) {
+ int i;
+
+ printf("MXS NAND: Error sending command %08lx\n", d->cmd.pio_words[0]);
+ for (i = 0; i < nand_info->cmd_queue_len; i++) {
+ printf("%02x ", nand_info->cmd_buf[i]);
+ }
+ printf("\n");
+ }
mxs_nand_return_dma_descs(nand_info);
{
struct nand_chip *chip = mtd->priv;
struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_gpmi_regs *gpmi_regs =
- (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
uint32_t tmp;
tmp = readl(&gpmi_regs->hw_gpmi_stat);
* swapping the block mark, or swapping it *back* -- but it doesn't matter
* because the the operation is the same.
*/
+ #ifndef CONFIG_NAND_MXS_NO_BBM_SWAP
static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
uint8_t *data_buf, uint8_t *oob_buf)
{
dst = oob_buf[0];
+ debug("Swapping byte %02x @ %03x.%d with %02x @ %03x\n",
+ src & 0xff, buf_offset, bit_offset, dst & 0xff, 0);
+
oob_buf[0] = src;
data_buf[buf_offset] &= ~(0xff << bit_offset);
data_buf[buf_offset] |= dst << bit_offset;
data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
}
+ #else
+ static inline void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+ uint8_t *data_buf, uint8_t *oob_buf)
+ {
+ }
+ #endif
/*
* Read data from NAND.
return;
}
+ memset(buf, 0xee, length);
+
/* Compile the DMA descriptor - a descriptor that reads data. */
d = mxs_nand_get_dma_desc(nand_info);
d->cmd.data =
length;
mxs_dma_desc_append(channel, d);
-
+ #ifndef CONFIG_MX6Q
/*
* A DMA descriptor that waits for the command to end and the chip to
* become ready.
GPMI_CTRL0_ADDRESS_NAND_DATA;
mxs_dma_desc_append(channel, d);
-
+ #endif
/* Execute the DMA chain. */
ret = mxs_dma_go(channel);
if (ret) {
- printf("MXS NAND: DMA read error\n");
+ printf("%s: DMA read error\n", __func__);
goto rtn;
}
/* Execute the DMA chain. */
ret = mxs_dma_go(channel);
if (ret)
- printf("MXS NAND: DMA write error\n");
+ printf("%s: DMA write error\n", __func__);
mxs_nand_return_dma_descs(nand_info);
}
return buf;
}
+ static void flush_buffers(struct mtd_info *mtd, struct mxs_nand_info *nand_info)
+ {
+ flush_dcache_range((unsigned long)nand_info->data_buf,
+ (unsigned long)nand_info->data_buf +
+ mtd->writesize);
+ flush_dcache_range((unsigned long)nand_info->oob_buf,
+ (unsigned long)nand_info->oob_buf +
+ mtd->oobsize);
+ }
+
/*
* Read a page from NAND.
*/
d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+ flush_buffers(mtd, nand_info);
+
mxs_dma_desc_append(channel, d);
/* Compile the DMA descriptor - disable the BCH block. */
/* Execute the DMA chain. */
ret = mxs_dma_go(channel);
if (ret) {
- printf("MXS NAND: DMA read error\n");
+ printf("%s: DMA read error\n", __func__);
goto rtn;
}
/* Loop over status bytes, accumulating ECC status. */
status = nand_info->oob_buf + mxs_nand_aux_status_offset();
- for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+ for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd); i++) {
if (status[i] == 0x00)
continue;
GPMI_ECCCTRL_ENABLE_ECC |
GPMI_ECCCTRL_ECC_CMD_ENCODE |
GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
- d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+ d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+ flush_buffers(mtd, nand_info);
+
mxs_dma_desc_append(channel, d);
/* Flush caches */
/* Execute the DMA chain. */
ret = mxs_dma_go(channel);
if (ret) {
- printf("MXS NAND: DMA write error\n");
+ printf("%s: DMA write error\n", __func__);
goto rtn;
}
ret = mxs_nand_wait_for_bch_complete();
if (ret) {
- printf("MXS NAND: BCH write timeout\n");
+ printf("%s: BCH write timeout\n", __func__);
goto rtn;
}
/*
* Nominally, the purpose of this function is to look for or create the bad
* block table. In fact, since the we call this function at the very end of
- * the initialization process started by nand_scan(), and we doesn't have a
+ * the initialization process started by nand_scan(), and we don't have a
* more formal mechanism, we "hook" this function to continue init process.
*
* At this point, the physical NAND Flash chips have been identified and
{
struct nand_chip *nand = mtd->priv;
struct mxs_nand_info *nand_info = nand->priv;
- struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
uint32_t tmp;
/* Configure BCH and set NFC geometry */
- mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
+ if (readl(&bch_regs->hw_bch_ctrl_reg) &
+ (BCH_CTRL_SFTRST | BCH_CTRL_CLKGATE))
+ /* When booting from NAND the BCH engine will already
+ * be operational and obviously does not like being reset here.
+ * There will be occasional read errors upon boot when this
+ * reset is done.
+ */
+ mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
+ readl(&bch_regs->hw_bch_ctrl_reg);
+
+ debug("mtd->writesize=%d\n", mtd->writesize);
+ debug("mtd->oobsize=%d\n", mtd->oobsize);
+ debug("ecc_strength=%d\n", mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize));
/* Configure layout 0 */
- tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+ tmp = (mxs_nand_ecc_chunk_cnt(mtd) - 1)
<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
/* DMA buffers */
buf = memalign(MXS_DMA_ALIGNMENT, nand_info->data_buf_size);
if (!buf) {
- printf("MXS NAND: Error allocating DMA buffers\n");
+ printf("%s: Error allocating DMA buffers\n", __func__);
return -ENOMEM;
}
*/
int mxs_nand_init(struct mxs_nand_info *info)
{
- struct mxs_gpmi_regs *gpmi_regs =
- (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
- struct mxs_bch_regs *bch_regs =
- (struct mxs_bch_regs *)MXS_BCH_BASE;
- int i = 0, j;
+ int ret;
+ int i;
info->desc = malloc(sizeof(struct mxs_dma_desc *) *
MXS_NAND_DMA_DESCRIPTOR_COUNT);
- if (!info->desc)
+ if (!info->desc) {
+ printf("MXS NAND: Unable to allocate DMA descriptor table\n");
+ ret = -ENOMEM;
goto err1;
+ }
+
+ mxs_dma_init();
/* Allocate the DMA descriptors. */
for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
info->desc[i] = mxs_dma_desc_alloc();
- if (!info->desc[i])
+ if (!info->desc[i]) {
+ printf("MXS NAND: Unable to allocate DMA descriptors\n");
+ ret = -ENOMEM;
goto err2;
+ }
}
/* Init the DMA controller. */
- for (j = MXS_DMA_CHANNEL_AHB_APBH_GPMI0;
- j <= MXS_DMA_CHANNEL_AHB_APBH_GPMI7; j++) {
- if (mxs_dma_init_channel(j))
+ for (i = 0; i < CONFIG_SYS_NAND_MAX_CHIPS; i++) {
+ const int chan = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + i;
+
+ ret = mxs_dma_init_channel(chan);
+ if (ret) {
+ printf("Failed to initialize DMA channel %d\n", chan);
goto err3;
+ }
}
- /* Reset the GPMI block. */
- mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
- mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
-
- /*
- * Choose NAND mode, set IRQ polarity, disable write protection and
- * select BCH ECC.
- */
- clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
- GPMI_CTRL1_GPMI_MODE,
- GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
- GPMI_CTRL1_BCH_MODE);
+ ret = mxs_nand_gpmi_init();
+ if (ret)
+ goto err3;
return 0;
err3:
- for (--j; j >= 0; j--)
- mxs_dma_release(j);
+ for (--i; i >= 0; i--)
+ mxs_dma_release(i + MXS_DMA_CHANNEL_AHB_APBH_GPMI0);
+ i = MXS_NAND_DMA_DESCRIPTOR_COUNT - 1;
err2:
free(info->desc);
- err1:
for (--i; i >= 0; i--)
mxs_dma_desc_free(info->desc[i]);
- printf("MXS NAND: Unable to allocate DMA descriptors\n");
- return -ENOMEM;
+ err1:
+ return ret;
}
/*!
nand->priv = nand_info;
nand->options |= NAND_NO_SUBPAGE_WRITE;
-
+ #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
+ nand->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
+ #endif
nand->cmd_ctrl = mxs_nand_cmd_ctrl;
nand->dev_ready = mxs_nand_device_ready;
* Overview:
* This is the generic MTD driver for NAND flash devices. It should be
* capable of working with almost all NAND chips currently available.
- * Basic support for AG-AND chips is provided.
*
* Additional technical information is available on
* http://www.linux-mtd.infradead.org/doc/nand.html
* Enable cached programming for 2k page size chips
* Check, if mtd->ecctype should be set to MTD_ECC_HW
* if we have HW ECC support.
- * The AG-AND chips have nice features for speed improvement,
- * which are not supported yet. Read / program 4 pages in one go.
* BBT table is not serialized, has to be fixed
*
* This program is free software; you can redistribute it and/or modify
*
*/
-#include <common.h>
-
-#define ENOTSUPP 524 /* Operation is not supported */
+#ifndef __UBOOT__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand_bch.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#else
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <common.h>
#include <malloc.h>
#include <watchdog.h>
#include <linux/err.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/nand_bch.h>
-
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
-
#include <asm/io.h>
#include <asm/errno.h>
#define CONFIG_SYS_NAND_RESET_CNT 200000
#endif
+static bool is_module_text_address(unsigned long addr) {return 0;}
+#endif
+
/* Define default oob placement schemes for large and small page devices */
static struct nand_ecclayout nand_oob_8 = {
.eccbytes = 3,
.length = 78} }
};
-static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
- int new_state);
+static int nand_get_device(struct mtd_info *mtd, int new_state);
static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops);
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
+/*
+ * For devices which display every fart in the system on a separate LED. Is
+ * compiled away when LED support is disabled.
+ */
+DEFINE_LED_TRIGGER(nand_led_trigger);
static int check_offs_len(struct mtd_info *mtd,
loff_t ofs, uint64_t len)
int ret = 0;
/* Start address must align on block boundary */
- if (ofs & ((1 << chip->phys_erase_shift) - 1)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__);
+ if (ofs & ((1ULL << chip->phys_erase_shift) - 1)) {
+ pr_debug("%s: unaligned address\n", __func__);
ret = -EINVAL;
}
/* Length must align on block boundary */
- if (len & ((1 << chip->phys_erase_shift) - 1)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
- __func__);
+ if (len & ((1ULL << chip->phys_erase_shift) - 1)) {
+ pr_debug("%s: length not block aligned\n", __func__);
ret = -EINVAL;
}
* nand_release_device - [GENERIC] release chip
* @mtd: MTD device structure
*
- * Deselect, release chip lock and wake up anyone waiting on the device.
+ * Release chip lock and wake up anyone waiting on the device.
*/
static void nand_release_device(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
+#ifndef __UBOOT__
+ /* Release the controller and the chip */
+ spin_lock(&chip->controller->lock);
+ chip->controller->active = NULL;
+ chip->state = FL_READY;
+ wake_up(&chip->controller->wq);
+ spin_unlock(&chip->controller->lock);
+#else
/* De-select the NAND device */
chip->select_chip(mtd, -1);
+#endif
}
/**
* nand_read_byte - [DEFAULT] read one byte from the chip
* @mtd: MTD device structure
*
- * Default read function for 8bit buswidth.
+ * Default read function for 8bit buswidth
*/
+#ifndef __UBOOT__
+static uint8_t nand_read_byte(struct mtd_info *mtd)
+#else
uint8_t nand_read_byte(struct mtd_info *mtd)
+#endif
{
struct nand_chip *chip = mtd->priv;
return readb(chip->IO_ADDR_R);
}
/**
- * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
+ * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
* nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
* @mtd: MTD device structure
*
}
}
+/**
+ * nand_write_byte - [DEFAULT] write single byte to chip
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0]
+ */
+static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ chip->write_buf(mtd, &byte, 1);
+}
+
+/**
+ * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0] on a 16-bit wide chip.
+ */
+static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
+{
+ struct nand_chip *chip = mtd->priv;
+ uint16_t word = byte;
+
+ /*
+ * It's not entirely clear what should happen to I/O[15:8] when writing
+ * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads:
+ *
+ * When the host supports a 16-bit bus width, only data is
+ * transferred at the 16-bit width. All address and command line
+ * transfers shall use only the lower 8-bits of the data bus. During
+ * command transfers, the host may place any value on the upper
+ * 8-bits of the data bus. During address transfers, the host shall
+ * set the upper 8-bits of the data bus to 00h.
+ *
+ * One user of the write_byte callback is nand_onfi_set_features. The
+ * four parameters are specified to be written to I/O[7:0], but this is
+ * neither an address nor a command transfer. Let's assume a 0 on the
+ * upper I/O lines is OK.
+ */
+ chip->write_buf(mtd, (uint8_t *)&word, 2);
+}
+
+#if defined(__UBOOT__) && !defined(CONFIG_BLACKFIN)
+static void iowrite8_rep(void *addr, const uint8_t *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ writeb(buf[i], addr);
+}
+static void ioread8_rep(void *addr, uint8_t *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = readb(addr);
+}
+
+static void ioread16_rep(void *addr, void *buf, int len)
+{
+ int i;
+ u16 *p = (u16 *) buf;
+
+ for (i = 0; i < len; i++)
+ p[i] = readw(addr);
+}
+
+static void iowrite16_rep(void *addr, void *buf, int len)
+{
+ int i;
+ u16 *p = (u16 *) buf;
+
+ for (i = 0; i < len; i++)
+ writew(p[i], addr);
+}
+#endif
+
/**
* nand_write_buf - [DEFAULT] write buffer to chip
* @mtd: MTD device structure
*
* Default write function for 8bit buswidth.
*/
+#ifndef __UBOOT__
+static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+#else
void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+#endif
{
- int i;
struct nand_chip *chip = mtd->priv;
- for (i = 0; i < len; i++)
- writeb(buf[i], chip->IO_ADDR_W);
+ iowrite8_rep(chip->IO_ADDR_W, buf, len);
}
/**
*
* Default read function for 8bit buswidth.
*/
+#ifndef __UBOOT__
+static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+#else
void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+#endif
{
- int i;
struct nand_chip *chip = mtd->priv;
- for (i = 0; i < len; i++)
- buf[i] = readb(chip->IO_ADDR_R);
+ ioread8_rep(chip->IO_ADDR_R, buf, len);
}
+#ifdef __UBOOT__
+#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
/**
* nand_verify_buf - [DEFAULT] Verify chip data against buffer
* @mtd: MTD device structure
}
/**
- * nand_write_buf16 - [DEFAULT] write buffer to chip
+ * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
* @mtd: MTD device structure
- * @buf: data buffer
- * @len: number of bytes to write
+ * @buf: buffer containing the data to compare
+ * @len: number of bytes to compare
*
- * Default write function for 16bit buswidth.
+ * Default verify function for 16bit buswidth.
*/
-void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
+static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
{
int i;
struct nand_chip *chip = mtd->priv;
len >>= 1;
for (i = 0; i < len; i++)
- writew(p[i], chip->IO_ADDR_W);
+ if (p[i] != readw(chip->IO_ADDR_R))
+ return -EFAULT;
+ return 0;
}
+#endif
+#endif
/**
- * nand_read_buf16 - [DEFAULT] read chip data into buffer
+ * nand_write_buf16 - [DEFAULT] write buffer to chip
* @mtd: MTD device structure
- * @buf: buffer to store date
- * @len: number of bytes to read
+ * @buf: data buffer
+ * @len: number of bytes to write
*
- * Default read function for 16bit buswidth.
+ * Default write function for 16bit buswidth.
*/
-void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
+#ifndef __UBOOT__
+static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
+#else
+void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
+#endif
{
- int i;
struct nand_chip *chip = mtd->priv;
u16 *p = (u16 *) buf;
- len >>= 1;
- for (i = 0; i < len; i++)
- p[i] = readw(chip->IO_ADDR_R);
+ iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
}
/**
- * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
+ * nand_read_buf16 - [DEFAULT] read chip data into buffer
* @mtd: MTD device structure
- * @buf: buffer containing the data to compare
- * @len: number of bytes to compare
+ * @buf: buffer to store date
+ * @len: number of bytes to read
*
- * Default verify function for 16bit buswidth.
+ * Default read function for 16bit buswidth.
*/
-static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
+#ifndef __UBOOT__
+static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
+#else
+void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
+#endif
{
- int i;
struct nand_chip *chip = mtd->priv;
u16 *p = (u16 *) buf;
- len >>= 1;
- for (i = 0; i < len; i++)
- if (p[i] != readw(chip->IO_ADDR_R))
- return -EFAULT;
-
- return 0;
+ ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
}
/**
if (getchip) {
chipnr = (int)(ofs >> chip->chip_shift);
- nand_get_device(chip, mtd, FL_READING);
+ nand_get_device(mtd, FL_READING);
/* Select the NAND device */
chip->select_chip(mtd, chipnr);
i++;
} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
- if (getchip)
+ if (getchip) {
+ chip->select_chip(mtd, -1);
nand_release_device(mtd);
+ }
return res;
}
/**
- * nand_default_block_markbad - [DEFAULT] mark a block bad
+ * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
* @mtd: MTD device structure
* @ofs: offset from device start
*
* This is the default implementation, which can be overridden by a hardware
- * specific driver. We try operations in the following order, according to our
- * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
+ * specific driver. It provides the details for writing a bad block marker to a
+ * block.
+ */
+static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct mtd_oob_ops ops;
+ uint8_t buf[2] = { 0, 0 };
+ int ret = 0, res, i = 0;
+
+ ops.datbuf = NULL;
+ ops.oobbuf = buf;
+ ops.ooboffs = chip->badblockpos;
+ if (chip->options & NAND_BUSWIDTH_16) {
+ ops.ooboffs &= ~0x01;
+ ops.len = ops.ooblen = 2;
+ } else {
+ ops.len = ops.ooblen = 1;
+ }
+ ops.mode = MTD_OPS_PLACE_OOB;
+
+ /* Write to first/last page(s) if necessary */
+ if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+ ofs += mtd->erasesize - mtd->writesize;
+ do {
+ res = nand_do_write_oob(mtd, ofs, &ops);
+ if (!ret)
+ ret = res;
+
+ i++;
+ ofs += mtd->writesize;
+ } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+
+ return ret;
+}
+
+/**
+ * nand_block_markbad_lowlevel - mark a block bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ *
+ * This function performs the generic NAND bad block marking steps (i.e., bad
+ * block table(s) and/or marker(s)). We only allow the hardware driver to
+ * specify how to write bad block markers to OOB (chip->block_markbad).
+ *
+ * We try operations in the following order:
* (1) erase the affected block, to allow OOB marker to be written cleanly
- * (2) update in-memory BBT
- * (3) write bad block marker to OOB area of affected block
- * (4) update flash-based BBT
- * Note that we retain the first error encountered in (3) or (4), finish the
+ * (2) write bad block marker to OOB area of affected block (unless flag
+ * NAND_BBT_NO_OOB_BBM is present)
+ * (3) update the BBT
+ * Note that we retain the first error encountered in (2) or (3), finish the
* procedures, and dump the error in the end.
*/
-static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
{
struct nand_chip *chip = mtd->priv;
- uint8_t buf[2] = { 0, 0 };
- int block, res, ret = 0, i = 0;
- int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
+ int res, ret = 0;
- if (write_oob) {
+ if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
struct erase_info einfo;
/* Attempt erase before marking OOB */
memset(&einfo, 0, sizeof(einfo));
einfo.mtd = mtd;
einfo.addr = ofs;
- einfo.len = 1 << chip->phys_erase_shift;
+ einfo.len = 1ULL << chip->phys_erase_shift;
nand_erase_nand(mtd, &einfo, 0);
- }
-
- /* Get block number */
- block = (int)(ofs >> chip->bbt_erase_shift);
- /* Mark block bad in memory-based BBT */
- if (chip->bbt)
- chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
-
- /* Write bad block marker to OOB */
- if (write_oob) {
- struct mtd_oob_ops ops;
- loff_t wr_ofs = ofs;
-
- nand_get_device(chip, mtd, FL_WRITING);
-
- ops.datbuf = NULL;
- ops.oobbuf = buf;
- ops.ooboffs = chip->badblockpos;
- if (chip->options & NAND_BUSWIDTH_16) {
- ops.ooboffs &= ~0x01;
- ops.len = ops.ooblen = 2;
- } else {
- ops.len = ops.ooblen = 1;
- }
- ops.mode = MTD_OPS_PLACE_OOB;
-
- /* Write to first/last page(s) if necessary */
- if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
- wr_ofs += mtd->erasesize - mtd->writesize;
- do {
- res = nand_do_write_oob(mtd, wr_ofs, &ops);
- if (!ret)
- ret = res;
-
- i++;
- wr_ofs += mtd->writesize;
- } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+ /* Write bad block marker to OOB */
+ nand_get_device(mtd, FL_WRITING);
+ ret = chip->block_markbad(mtd, ofs);
nand_release_device(mtd);
}
- /* Update flash-based bad block table */
- if (chip->bbt_options & NAND_BBT_USE_FLASH) {
- res = nand_update_bbt(mtd, ofs);
+ /* Mark block bad in BBT */
+ if (chip->bbt) {
+ res = nand_markbad_bbt(mtd, ofs);
if (!ret)
ret = res;
}
{
struct nand_chip *chip = mtd->priv;
- if (!(chip->options & NAND_BBT_SCANNED)) {
+ if (!(chip->options & NAND_SKIP_BBTSCAN) &&
+ !(chip->options & NAND_BBT_SCANNED)) {
chip->options |= NAND_BBT_SCANNED;
chip->scan_bbt(mtd);
}
return nand_isbad_bbt(mtd, ofs, allowbbt);
}
+#ifndef __UBOOT__
+/**
+ * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
+ * @mtd: MTD device structure
+ * @timeo: Timeout
+ *
+ * Helper function for nand_wait_ready used when needing to wait in interrupt
+ * context.
+ */
+static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
+{
+ struct nand_chip *chip = mtd->priv;
+ int i;
+
+ /* Wait for the device to get ready */
+ for (i = 0; i < timeo; i++) {
+ if (chip->dev_ready(mtd))
+ break;
+ touch_softlockup_watchdog();
+ mdelay(1);
+ }
+}
+#endif
+
/* Wait for the ready pin, after a command. The timeout is caught later. */
void nand_wait_ready(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
+#ifndef __UBOOT__
+ unsigned long timeo = jiffies + msecs_to_jiffies(20);
+
+ /* 400ms timeout */
+ if (in_interrupt() || oops_in_progress)
+ return panic_nand_wait_ready(mtd, 400);
+
+ led_trigger_event(nand_led_trigger, LED_FULL);
+ /* Wait until command is processed or timeout occurs */
+ do {
+ if (chip->dev_ready(mtd))
+ break;
+ touch_softlockup_watchdog();
+ } while (time_before(jiffies, timeo));
+ led_trigger_event(nand_led_trigger, LED_OFF);
+#else
u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
u32 time_start;
time_start = get_timer(0);
-
/* Wait until command is processed or timeout occurs */
while (get_timer(time_start) < timeo) {
if (chip->dev_ready)
if (chip->dev_ready(mtd))
break;
}
+#endif
}
+EXPORT_SYMBOL_GPL(nand_wait_ready);
/**
* nand_command - [DEFAULT] Send command to NAND device
* @page_addr: the page address for this command, -1 if none
*
* Send command to NAND device. This function is used for small page devices
- * (256/512 Bytes per page).
+ * (512 Bytes per page).
*/
static void nand_command(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
- if (chip->options & NAND_BUSWIDTH_16)
+ if (chip->options & NAND_BUSWIDTH_16 &&
+ !nand_opcode_8bits(command))
column >>= 1;
chip->cmd_ctrl(mtd, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
}
/* Command latch cycle */
- chip->cmd_ctrl(mtd, command & 0xff,
- NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+ chip->cmd_ctrl(mtd, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
if (column != -1 || page_addr != -1) {
int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
- if (chip->options & NAND_BUSWIDTH_16)
+ if (chip->options & NAND_BUSWIDTH_16 &&
+ !nand_opcode_8bits(command))
column >>= 1;
chip->cmd_ctrl(mtd, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
case NAND_CMD_SEQIN:
case NAND_CMD_RNDIN:
case NAND_CMD_STATUS:
- case NAND_CMD_DEPLETE1:
- return;
-
- case NAND_CMD_STATUS_ERROR:
- case NAND_CMD_STATUS_ERROR0:
- case NAND_CMD_STATUS_ERROR1:
- case NAND_CMD_STATUS_ERROR2:
- case NAND_CMD_STATUS_ERROR3:
- /* Read error status commands require only a short delay */
- udelay(chip->chip_delay);
return;
case NAND_CMD_RESET:
}
/**
- * nand_get_device - [GENERIC] Get chip for selected access
+ * panic_nand_get_device - [GENERIC] Get chip for selected access
* @chip: the nand chip descriptor
* @mtd: MTD device structure
* @new_state: the state which is requested
*
+ * Used when in panic, no locks are taken.
+ */
+static void panic_nand_get_device(struct nand_chip *chip,
+ struct mtd_info *mtd, int new_state)
+{
+ /* Hardware controller shared among independent devices */
+ chip->controller->active = chip;
+ chip->state = new_state;
+}
+
+/**
+ * nand_get_device - [GENERIC] Get chip for selected access
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
+ *
* Get the device and lock it for exclusive access
*/
static int
-nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
+nand_get_device(struct mtd_info *mtd, int new_state)
{
+ struct nand_chip *chip = mtd->priv;
+#ifndef __UBOOT__
+ spinlock_t *lock = &chip->controller->lock;
+ wait_queue_head_t *wq = &chip->controller->wq;
+ DECLARE_WAITQUEUE(wait, current);
+retry:
+ spin_lock(lock);
+
+ /* Hardware controller shared among independent devices */
+ if (!chip->controller->active)
+ chip->controller->active = chip;
+
+ if (chip->controller->active == chip && chip->state == FL_READY) {
+ chip->state = new_state;
+ spin_unlock(lock);
+ return 0;
+ }
+ if (new_state == FL_PM_SUSPENDED) {
+ if (chip->controller->active->state == FL_PM_SUSPENDED) {
+ chip->state = FL_PM_SUSPENDED;
+ spin_unlock(lock);
+ return 0;
+ }
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(wq, &wait);
+ spin_unlock(lock);
+ schedule();
+ remove_wait_queue(wq, &wait);
+ goto retry;
+#else
chip->state = new_state;
return 0;
+#endif
+}
+
+/**
+ * panic_nand_wait - [GENERIC] wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND chip structure
+ * @timeo: timeout
+ *
+ * Wait for command done. This is a helper function for nand_wait used when
+ * we are in interrupt context. May happen when in panic and trying to write
+ * an oops through mtdoops.
+ */
+static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
+ unsigned long timeo)
+{
+ int i;
+ for (i = 0; i < timeo; i++) {
+ if (chip->dev_ready) {
+ if (chip->dev_ready(mtd))
+ break;
+ } else {
+ if (chip->read_byte(mtd) & NAND_STATUS_READY)
+ break;
+ }
+ mdelay(1);
+ }
}
/**
*/
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
- unsigned long timeo;
- int state = chip->state;
- u32 time_start;
- if (state == FL_ERASING)
- timeo = (CONFIG_SYS_HZ * 400) / 1000;
- else
- timeo = (CONFIG_SYS_HZ * 20) / 1000;
+ int status, state = chip->state;
+ unsigned long timeo = (state == FL_ERASING ? 400 : 20);
- if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
- chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
- else
- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+ led_trigger_event(nand_led_trigger, LED_FULL);
- time_start = get_timer(0);
+ /*
+ * Apply this short delay always to ensure that we do wait tWB in any
+ * case on any machine.
+ */
+ ndelay(100);
- while (1) {
- if (get_timer(time_start) > timeo) {
- printf("Timeout!");
- return 0x01;
- }
+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+#ifndef __UBOOT__
+ if (in_interrupt() || oops_in_progress)
+ panic_nand_wait(mtd, chip, timeo);
+ else {
+ timeo = jiffies + msecs_to_jiffies(timeo);
+ while (time_before(jiffies, timeo)) {
+ if (chip->dev_ready) {
+ if (chip->dev_ready(mtd))
+ break;
+ } else {
+ if (chip->read_byte(mtd) & NAND_STATUS_READY)
+ break;
+ }
+ cond_resched();
+ }
+ }
+#else
+ u32 timer = (CONFIG_SYS_HZ * timeo) / 1000;
+ u32 time_start;
+
+ time_start = get_timer(0);
+ while (get_timer(time_start) < timer) {
if (chip->dev_ready) {
if (chip->dev_ready(mtd))
break;
break;
}
}
+#endif
#ifdef PPCHAMELON_NAND_TIMER_HACK
time_start = get_timer(0);
while (get_timer(time_start) < 10)
;
#endif /* PPCHAMELON_NAND_TIMER_HACK */
+ led_trigger_event(nand_led_trigger, LED_OFF);
+
+ status = (int)chip->read_byte(mtd);
+ /* This can happen if in case of timeout or buggy dev_ready */
+ WARN_ON(!(status & NAND_STATUS_READY));
+ return status;
+}
+
+#ifndef __UBOOT__
+/**
+ * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
+ * @mtd: mtd info
+ * @ofs: offset to start unlock from
+ * @len: length to unlock
+ * @invert: when = 0, unlock the range of blocks within the lower and
+ * upper boundary address
+ * when = 1, unlock the range of blocks outside the boundaries
+ * of the lower and upper boundary address
+ *
+ * Returs unlock status.
+ */
+static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
+ uint64_t len, int invert)
+{
+ int ret = 0;
+ int status, page;
+ struct nand_chip *chip = mtd->priv;
- return (int)chip->read_byte(mtd);
+ /* Submit address of first page to unlock */
+ page = ofs >> chip->page_shift;
+ chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);
+
+ /* Submit address of last page to unlock */
+ page = (ofs + len) >> chip->page_shift;
+ chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1,
+ (page | invert) & chip->pagemask);
+
+ /* Call wait ready function */
+ status = chip->waitfunc(mtd, chip);
+ /* See if device thinks it succeeded */
+ if (status & NAND_STATUS_FAIL) {
+ pr_debug("%s: error status = 0x%08x\n",
+ __func__, status);
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+/**
+ * nand_unlock - [REPLACEABLE] unlocks specified locked blocks
+ * @mtd: mtd info
+ * @ofs: offset to start unlock from
+ * @len: length to unlock
+ *
+ * Returns unlock status.
+ */
+int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ int ret = 0;
+ int chipnr;
+ struct nand_chip *chip = mtd->priv;
+
+ pr_debug("%s: start = 0x%012llx, len = %llu\n",
+ __func__, (unsigned long long)ofs, len);
+
+ if (check_offs_len(mtd, ofs, len))
+ ret = -EINVAL;
+
+ /* Align to last block address if size addresses end of the device */
+ if (ofs + len == mtd->size)
+ len -= mtd->erasesize;
+
+ nand_get_device(mtd, FL_UNLOCKING);
+
+ /* Shift to get chip number */
+ chipnr = ofs >> chip->chip_shift;
+
+ chip->select_chip(mtd, chipnr);
+
+ /* Check, if it is write protected */
+ if (nand_check_wp(mtd)) {
+ pr_debug("%s: device is write protected!\n",
+ __func__);
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = __nand_unlock(mtd, ofs, len, 0);
+
+out:
+ chip->select_chip(mtd, -1);
+ nand_release_device(mtd);
+
+ return ret;
}
+EXPORT_SYMBOL(nand_unlock);
+
+/**
+ * nand_lock - [REPLACEABLE] locks all blocks present in the device
+ * @mtd: mtd info
+ * @ofs: offset to start unlock from
+ * @len: length to unlock
+ *
+ * This feature is not supported in many NAND parts. 'Micron' NAND parts do
+ * have this feature, but it allows only to lock all blocks, not for specified
+ * range for block. Implementing 'lock' feature by making use of 'unlock', for
+ * now.
+ *
+ * Returns lock status.
+ */
+int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ int ret = 0;
+ int chipnr, status, page;
+ struct nand_chip *chip = mtd->priv;
+
+ pr_debug("%s: start = 0x%012llx, len = %llu\n",
+ __func__, (unsigned long long)ofs, len);
+
+ if (check_offs_len(mtd, ofs, len))
+ ret = -EINVAL;
+
+ nand_get_device(mtd, FL_LOCKING);
+
+ /* Shift to get chip number */
+ chipnr = ofs >> chip->chip_shift;
+
+ chip->select_chip(mtd, chipnr);
+
+ /* Check, if it is write protected */
+ if (nand_check_wp(mtd)) {
+ pr_debug("%s: device is write protected!\n",
+ __func__);
+ status = MTD_ERASE_FAILED;
+ ret = -EIO;
+ goto out;
+ }
+
+ /* Submit address of first page to lock */
+ page = ofs >> chip->page_shift;
+ chip->cmdfunc(mtd, NAND_CMD_LOCK, -1, page & chip->pagemask);
+
+ /* Call wait ready function */
+ status = chip->waitfunc(mtd, chip);
+ /* See if device thinks it succeeded */
+ if (status & NAND_STATUS_FAIL) {
+ pr_debug("%s: error status = 0x%08x\n",
+ __func__, status);
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = __nand_unlock(mtd, ofs, len, 0x1);
+
+out:
+ chip->select_chip(mtd, -1);
+ nand_release_device(mtd);
+
+ return ret;
+}
+EXPORT_SYMBOL(nand_lock);
+#endif
/**
* nand_read_page_raw - [INTERN] read raw page data without ecc
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
+ unsigned int max_bitflips = 0;
chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat < 0)
+ if (stat < 0) {
mtd->ecc_stats.failed++;
- else
+ } else {
mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
}
- return 0;
+ return max_bitflips;
}
/**
- * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function
+ * nand_read_subpage - [REPLACEABLE] ECC based sub-page read function
* @mtd: mtd info structure
* @chip: nand chip info structure
* @data_offs: offset of requested data within the page
* @readlen: data length
* @bufpoi: buffer to store read data
+ * @page: page number to read
*/
static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
+ uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi,
+ int page)
{
int start_step, end_step, num_steps;
uint32_t *eccpos = chip->ecc.layout->eccpos;
int data_col_addr, i, gaps = 0;
int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
- int index = 0;
+ int index;
+ unsigned int max_bitflips = 0;
/* Column address within the page aligned to ECC size (256bytes) */
start_step = data_offs / chip->ecc.size;
end_step = (data_offs + readlen - 1) / chip->ecc.size;
num_steps = end_step - start_step + 1;
+ index = start_step * chip->ecc.bytes;
/* Data size aligned to ECC ecc.size */
datafrag_len = num_steps * chip->ecc.size;
* Send the command to read the particular ECC bytes take care
* about buswidth alignment in read_buf.
*/
- index = start_step * chip->ecc.bytes;
-
aligned_pos = eccpos[index] & ~(busw - 1);
aligned_len = eccfrag_len;
if (eccpos[index] & (busw - 1))
stat = chip->ecc.correct(mtd, p,
&chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
- if (stat < 0)
+ if (stat < 0) {
mtd->ecc_stats.failed++;
- else
+ } else {
mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
}
- return 0;
+ return max_bitflips;
}
/**
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
+ unsigned int max_bitflips = 0;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_READ);
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat < 0)
+ if (stat < 0) {
mtd->ecc_stats.failed++;
- else
+ } else {
mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
}
- return 0;
+ return max_bitflips;
}
/**
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint8_t *ecc_calc = chip->buffers->ecccalc;
+ unsigned int max_bitflips = 0;
/* Read the OOB area first */
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
- if (stat < 0)
+ if (stat < 0) {
mtd->ecc_stats.failed++;
- else
+ } else {
mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
}
- return 0;
+ return max_bitflips;
}
/**
int eccsteps = chip->ecc.steps;
uint8_t *p = buf;
uint8_t *oob = chip->oob_poi;
+ unsigned int max_bitflips = 0;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
int stat;
chip->read_buf(mtd, oob, eccbytes);
stat = chip->ecc.correct(mtd, p, oob, NULL);
- if (stat < 0)
+ if (stat < 0) {
mtd->ecc_stats.failed++;
- else
+ } else {
mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
oob += eccbytes;
if (i)
chip->read_buf(mtd, oob, i);
- return 0;
+ return max_bitflips;
}
/**
return NULL;
}
+/**
+ * nand_setup_read_retry - [INTERN] Set the READ RETRY mode
+ * @mtd: MTD device structure
+ * @retry_mode: the retry mode to use
+ *
+ * Some vendors supply a special command to shift the Vt threshold, to be used
+ * when there are too many bitflips in a page (i.e., ECC error). After setting
+ * a new threshold, the host should retry reading the page.
+ */
+static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ pr_debug("setting READ RETRY mode %d\n", retry_mode);
+
+ if (retry_mode >= chip->read_retries)
+ return -EINVAL;
+
+ if (!chip->setup_read_retry)
+ return -EOPNOTSUPP;
+
+ return chip->setup_read_retry(mtd, retry_mode);
+}
+
/**
* nand_do_read_ops - [INTERN] Read data with ECC
* @mtd: MTD device structure
{
int chipnr, page, realpage, col, bytes, aligned, oob_required;
struct nand_chip *chip = mtd->priv;
- struct mtd_ecc_stats stats;
int ret = 0;
uint32_t readlen = ops->len;
uint32_t oobreadlen = ops->ooblen;
mtd->oobavail : mtd->oobsize;
uint8_t *bufpoi, *oob, *buf;
-
- stats = mtd->ecc_stats;
+ unsigned int max_bitflips = 0;
+ int retry_mode = 0;
+ bool ecc_fail = false;
chipnr = (int)(from >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
oob_required = oob ? 1 : 0;
while (1) {
- WATCHDOG_RESET();
+ unsigned int ecc_failures = mtd->ecc_stats.failed;
+ WATCHDOG_RESET();
bytes = min(mtd->writesize - col, readlen);
aligned = (bytes == mtd->writesize);
if (realpage != chip->pagebuf || oob) {
bufpoi = aligned ? buf : chip->buffers->databuf;
+read_retry:
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
- /* Now read the page into the buffer */
+ /*
+ * Now read the page into the buffer. Absent an error,
+ * the read methods return max bitflips per ecc step.
+ */
if (unlikely(ops->mode == MTD_OPS_RAW))
ret = chip->ecc.read_page_raw(mtd, chip, bufpoi,
oob_required,
page);
else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&
- !oob)
+ !oob)
ret = chip->ecc.read_subpage(mtd, chip,
- col, bytes, bufpoi);
+ col, bytes, bufpoi,
+ page);
else
ret = chip->ecc.read_page(mtd, chip, bufpoi,
oob_required, page);
break;
}
+ max_bitflips = max_t(unsigned int, max_bitflips, ret);
+
/* Transfer not aligned data */
if (!aligned) {
if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
- !(mtd->ecc_stats.failed - stats.failed) &&
- (ops->mode != MTD_OPS_RAW))
+ !(mtd->ecc_stats.failed - ecc_failures) &&
+ (ops->mode != MTD_OPS_RAW)) {
chip->pagebuf = realpage;
- else
+ chip->pagebuf_bitflips = ret;
+ } else {
/* Invalidate page cache */
chip->pagebuf = -1;
+ }
memcpy(buf, chip->buffers->databuf + col, bytes);
}
- buf += bytes;
-
if (unlikely(oob)) {
int toread = min(oobreadlen, max_oobsize);
oobreadlen -= toread;
}
}
+
+ if (chip->options & NAND_NEED_READRDY) {
+ /* Apply delay or wait for ready/busy pin */
+ if (!chip->dev_ready)
+ udelay(chip->chip_delay);
+ else
+ nand_wait_ready(mtd);
+ }
+
+ if (mtd->ecc_stats.failed - ecc_failures) {
+ if (retry_mode + 1 < chip->read_retries) {
+ retry_mode++;
+ ret = nand_setup_read_retry(mtd,
+ retry_mode);
+ if (ret < 0)
+ break;
+
+ /* Reset failures; retry */
+ mtd->ecc_stats.failed = ecc_failures;
+ goto read_retry;
+ } else {
+ /* No more retry modes; real failure */
+ ecc_fail = true;
+ }
+ }
+
+ buf += bytes;
} else {
memcpy(buf, chip->buffers->databuf + col, bytes);
buf += bytes;
+ max_bitflips = max_t(unsigned int, max_bitflips,
+ chip->pagebuf_bitflips);
}
readlen -= bytes;
+ /* Reset to retry mode 0 */
+ if (retry_mode) {
+ ret = nand_setup_read_retry(mtd, 0);
+ if (ret < 0)
+ break;
+ retry_mode = 0;
+ }
+
if (!readlen)
break;
chip->select_chip(mtd, chipnr);
}
}
+ chip->select_chip(mtd, -1);
ops->retlen = ops->len - (size_t) readlen;
if (oob)
ops->oobretlen = ops->ooblen - oobreadlen;
- if (ret)
+ if (ret < 0)
return ret;
- if (mtd->ecc_stats.failed - stats.failed)
+ if (ecc_fail)
return -EBADMSG;
- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+ return max_bitflips;
}
/**
static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, uint8_t *buf)
{
- struct nand_chip *chip = mtd->priv;
struct mtd_oob_ops ops;
int ret;
- nand_get_device(chip, mtd, FL_READING);
+ nand_get_device(mtd, FL_READING);
ops.len = len;
ops.datbuf = buf;
ops.oobbuf = NULL;
uint8_t *buf = ops->oobbuf;
int ret = 0;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
+ pr_debug("%s: from = 0x%08Lx, len = %i\n",
__func__, (unsigned long long)from, readlen);
stats = mtd->ecc_stats;
len = mtd->oobsize;
if (unlikely(ops->ooboffs >= len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read "
- "outside oob\n", __func__);
+ pr_debug("%s: attempt to start read outside oob\n",
+ __func__);
return -EINVAL;
}
if (unlikely(from >= mtd->size ||
ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
(from >> chip->page_shift)) * len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end "
- "of device\n", __func__);
+ pr_debug("%s: attempt to read beyond end of device\n",
+ __func__);
return -EINVAL;
}
while (1) {
WATCHDOG_RESET();
+
if (ops->mode == MTD_OPS_RAW)
ret = chip->ecc.read_oob_raw(mtd, chip, page);
else
len = min(len, readlen);
buf = nand_transfer_oob(chip, buf, ops, len);
+ if (chip->options & NAND_NEED_READRDY) {
+ /* Apply delay or wait for ready/busy pin */
+ if (!chip->dev_ready)
+ udelay(chip->chip_delay);
+ else
+ nand_wait_ready(mtd);
+ }
+
readlen -= len;
if (!readlen)
break;
chip->select_chip(mtd, chipnr);
}
}
+ chip->select_chip(mtd, -1);
ops->oobretlen = ops->ooblen - readlen;
static int nand_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
- struct nand_chip *chip = mtd->priv;
int ret = -ENOTSUPP;
ops->retlen = 0;
/* Do not allow reads past end of device */
if (ops->datbuf && (from + ops->len) > mtd->size) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read "
- "beyond end of device\n", __func__);
+ pr_debug("%s: attempt to read beyond end of device\n",
+ __func__);
return -EINVAL;
}
- nand_get_device(chip, mtd, FL_READING);
+ nand_get_device(mtd, FL_READING);
switch (ops->mode) {
case MTD_OPS_PLACE_OOB:
oob += chip->ecc.prepad;
}
- chip->read_buf(mtd, oob, eccbytes);
+ chip->write_buf(mtd, oob, eccbytes);
oob += eccbytes;
if (chip->ecc.postpad) {
return 0;
}
+
+/**
+ * nand_write_subpage_hwecc - [REPLACABLE] hardware ECC based subpage write
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @offset: column address of subpage within the page
+ * @data_len: data length
+ * @buf: data buffer
+ * @oob_required: must write chip->oob_poi to OOB
+ */
+static int nand_write_subpage_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, uint32_t offset,
+ uint32_t data_len, const uint8_t *buf,
+ int oob_required)
+{
+ uint8_t *oob_buf = chip->oob_poi;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+ int ecc_size = chip->ecc.size;
+ int ecc_bytes = chip->ecc.bytes;
+ int ecc_steps = chip->ecc.steps;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+ uint32_t start_step = offset / ecc_size;
+ uint32_t end_step = (offset + data_len - 1) / ecc_size;
+ int oob_bytes = mtd->oobsize / ecc_steps;
+ int step, i;
+
+ for (step = 0; step < ecc_steps; step++) {
+ /* configure controller for WRITE access */
+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+
+ /* write data (untouched subpages already masked by 0xFF) */
+ chip->write_buf(mtd, buf, ecc_size);
+
+ /* mask ECC of un-touched subpages by padding 0xFF */
+ if ((step < start_step) || (step > end_step))
+ memset(ecc_calc, 0xff, ecc_bytes);
+ else
+ chip->ecc.calculate(mtd, buf, ecc_calc);
+
+ /* mask OOB of un-touched subpages by padding 0xFF */
+ /* if oob_required, preserve OOB metadata of written subpage */
+ if (!oob_required || (step < start_step) || (step > end_step))
+ memset(oob_buf, 0xff, oob_bytes);
+
+ buf += ecc_size;
+ ecc_calc += ecc_bytes;
+ oob_buf += oob_bytes;
+ }
+
+ /* copy calculated ECC for whole page to chip->buffer->oob */
+ /* this include masked-value(0xFF) for unwritten subpages */
+ ecc_calc = chip->buffers->ecccalc;
+ for (i = 0; i < chip->ecc.total; i++)
+ chip->oob_poi[eccpos[i]] = ecc_calc[i];
+
+ /* write OOB buffer to NAND device */
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ return 0;
+}
+
+
/**
* nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write
* @mtd: mtd info structure
* nand_write_page - [REPLACEABLE] write one page
* @mtd: MTD device structure
* @chip: NAND chip descriptor
+ * @offset: address offset within the page
+ * @data_len: length of actual data to be written
* @buf: the data to write
* @oob_required: must write chip->oob_poi to OOB
* @page: page number to write
* @raw: use _raw version of write_page
*/
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page,
- int cached, int raw)
+ uint32_t offset, int data_len, const uint8_t *buf,
+ int oob_required, int page, int cached, int raw)
{
- int status;
+ int status, subpage;
+
+ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+ chip->ecc.write_subpage)
+ subpage = offset || (data_len < mtd->writesize);
+ else
+ subpage = 0;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw))
- status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
+ status = chip->ecc.write_page_raw(mtd, chip, buf,
+ oob_required);
+ else if (subpage)
+ status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
+ buf, oob_required);
else
status = chip->ecc.write_page(mtd, chip, buf, oob_required);
*/
cached = 0;
- if (!cached || !(chip->options & NAND_CACHEPRG)) {
+ if (!cached || !NAND_HAS_CACHEPROG(chip)) {
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
status = chip->waitfunc(mtd, chip);
status = chip->waitfunc(mtd, chip);
}
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+
+#ifdef __UBOOT__
+#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
/* Send command to read back the data */
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
/* Make sure the next page prog is preceded by a status read */
chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
#endif
+#endif
+
return 0;
}
return NULL;
}
- #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
++#define NOTALIGNED(x) (((x) & (chip->subpagesize - 1)) != 0)
+
/**
* nand_do_write_ops - [INTERN] NAND write with ECC
* @mtd: MTD device structure
uint8_t *oob = ops->oobbuf;
uint8_t *buf = ops->datbuf;
- int ret, subpage;
+ int ret;
int oob_required = oob ? 1 : 0;
ops->retlen = 0;
if (!writelen)
return 0;
- column = to & (mtd->writesize - 1);
- subpage = column || (writelen & (mtd->writesize - 1));
-
- if (subpage && oob)
+#ifndef __UBOOT__
+ /* Reject writes, which are not page aligned */
+ if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
+#else
+ /* Reject writes, which are not page aligned */
+ if (NOTALIGNED(to)) {
+#endif
+ pr_notice("%s: attempt to write non page aligned data\n",
+ __func__);
return -EINVAL;
+ }
+
+ column = to & (mtd->writesize - 1);
chipnr = (int)(to >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
- printk (KERN_NOTICE "nand_do_write_ops: Device is write protected\n");
- return -EIO;
+ ret = -EIO;
+ goto err_out;
}
realpage = (int)(to >> chip->page_shift);
chip->pagebuf = -1;
/* Don't allow multipage oob writes with offset */
- if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
- return -EINVAL;
+ if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) {
+ ret = -EINVAL;
+ goto err_out;
+ }
while (1) {
- WATCHDOG_RESET();
-
int bytes = mtd->writesize;
int cached = writelen > bytes && page != blockmask;
uint8_t *wbuf = buf;
+ WATCHDOG_RESET();
/* Partial page write? */
- if (unlikely(column || writelen < mtd->writesize)) {
+ if (unlikely(column || writelen < (mtd->writesize - 1))) {
cached = 0;
bytes = min_t(int, bytes - column, (int) writelen);
chip->pagebuf = -1;
/* We still need to erase leftover OOB data */
memset(chip->oob_poi, 0xff, mtd->oobsize);
}
-
- ret = chip->write_page(mtd, chip, wbuf, oob_required, page,
- cached, (ops->mode == MTD_OPS_RAW));
+ ret = chip->write_page(mtd, chip, column, bytes, wbuf,
+ oob_required, page, cached,
+ (ops->mode == MTD_OPS_RAW));
if (ret)
break;
ops->retlen = ops->len - writelen;
if (unlikely(oob))
ops->oobretlen = ops->ooblen;
+
+err_out:
+ chip->select_chip(mtd, -1);
+ return ret;
+}
+
+/**
+ * panic_nand_write - [MTD Interface] NAND write with ECC
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
+ *
+ * NAND write with ECC. Used when performing writes in interrupt context, this
+ * may for example be called by mtdoops when writing an oops while in panic.
+ */
+static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const uint8_t *buf)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct mtd_oob_ops ops;
+ int ret;
+
+ /* Wait for the device to get ready */
+ panic_nand_wait(mtd, chip, 400);
+
+ /* Grab the device */
+ panic_nand_get_device(chip, mtd, FL_WRITING);
+
+ ops.len = len;
+ ops.datbuf = (uint8_t *)buf;
+ ops.oobbuf = NULL;
+ ops.mode = MTD_OPS_PLACE_OOB;
+
+ ret = nand_do_write_ops(mtd, to, &ops);
+
+ *retlen = ops.retlen;
return ret;
}
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf)
{
- struct nand_chip *chip = mtd->priv;
struct mtd_oob_ops ops;
int ret;
- nand_get_device(chip, mtd, FL_WRITING);
+ nand_get_device(mtd, FL_WRITING);
ops.len = len;
ops.datbuf = (uint8_t *)buf;
ops.oobbuf = NULL;
int chipnr, page, status, len;
struct nand_chip *chip = mtd->priv;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+ pr_debug("%s: to = 0x%08x, len = %i\n",
__func__, (unsigned int)to, (int)ops->ooblen);
if (ops->mode == MTD_OPS_AUTO_OOB)
/* Do not allow write past end of page */
if ((ops->ooboffs + ops->ooblen) > len) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write "
- "past end of page\n", __func__);
+ pr_debug("%s: attempt to write past end of page\n",
+ __func__);
return -EINVAL;
}
if (unlikely(ops->ooboffs >= len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start "
- "write outside oob\n", __func__);
+ pr_debug("%s: attempt to start write outside oob\n",
+ __func__);
return -EINVAL;
}
ops->ooboffs + ops->ooblen >
((mtd->size >> chip->page_shift) -
(to >> chip->page_shift)) * len)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
- "end of device\n", __func__);
+ pr_debug("%s: attempt to write beyond end of device\n",
+ __func__);
return -EINVAL;
}
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
/* Check, if it is write protected */
- if (nand_check_wp(mtd))
+ if (nand_check_wp(mtd)) {
+ chip->select_chip(mtd, -1);
return -EROFS;
+ }
/* Invalidate the page cache, if we write to the cached page */
if (page == chip->pagebuf)
else
status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
+ chip->select_chip(mtd, -1);
+
if (status)
return status;
static int nand_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
{
- struct nand_chip *chip = mtd->priv;
int ret = -ENOTSUPP;
ops->retlen = 0;
/* Do not allow writes past end of device */
if (ops->datbuf && (to + ops->len) > mtd->size) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
- "end of device\n", __func__);
+ pr_debug("%s: attempt to write beyond end of device\n",
+ __func__);
return -EINVAL;
}
- nand_get_device(chip, mtd, FL_WRITING);
+ nand_get_device(mtd, FL_WRITING);
switch (ops->mode) {
case MTD_OPS_PLACE_OOB:
chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
}
-/**
- * multi_erase_cmd - [GENERIC] AND specific block erase command function
- * @mtd: MTD device structure
- * @page: the page address of the block which will be erased
- *
- * AND multi block erase command function. Erase 4 consecutive blocks.
- */
-static void multi_erase_cmd(struct mtd_info *mtd, int page)
-{
- struct nand_chip *chip = mtd->priv;
- /* Send commands to erase a block */
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
- chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
-}
-
/**
* nand_erase - [MTD Interface] erase block(s)
* @mtd: MTD device structure
return nand_erase_nand(mtd, instr, 0);
}
-#define BBT_PAGE_MASK 0xffffff3f
/**
* nand_erase_nand - [INTERN] erase block(s)
* @mtd: MTD device structure
{
int page, status, pages_per_block, ret, chipnr;
struct nand_chip *chip = mtd->priv;
- loff_t rewrite_bbt[CONFIG_SYS_NAND_MAX_CHIPS] = {0};
- unsigned int bbt_masked_page = 0xffffffff;
loff_t len;
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
- __func__, (unsigned long long)instr->addr,
- (unsigned long long)instr->len);
+ pr_debug("%s: start = 0x%012llx, len = %llu\n",
+ __func__, (unsigned long long)instr->addr,
+ (unsigned long long)instr->len);
if (check_offs_len(mtd, instr->addr, instr->len))
return -EINVAL;
/* Grab the lock and see if the device is available */
- nand_get_device(chip, mtd, FL_ERASING);
+ nand_get_device(mtd, FL_ERASING);
/* Shift to get first page */
page = (int)(instr->addr >> chip->page_shift);
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
- __func__);
+ pr_debug("%s: device is write protected!\n",
+ __func__);
instr->state = MTD_ERASE_FAILED;
goto erase_exit;
}
- /*
- * If BBT requires refresh, set the BBT page mask to see if the BBT
- * should be rewritten. Otherwise the mask is set to 0xffffffff which
- * can not be matched. This is also done when the bbt is actually
- * erased to avoid recursive updates.
- */
- if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
- bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-
/* Loop through the pages */
len = instr->len;
while (len) {
WATCHDOG_RESET();
+
/* Check if we have a bad block, we do not erase bad blocks! */
if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
chip->page_shift, 0, allowbbt)) {
pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
- __func__, page);
+ __func__, page);
instr->state = MTD_ERASE_FAILED;
goto erase_exit;
}
/* See if block erase succeeded */
if (status & NAND_STATUS_FAIL) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, "
- "page 0x%08x\n", __func__, page);
+ pr_debug("%s: failed erase, page 0x%08x\n",
+ __func__, page);
instr->state = MTD_ERASE_FAILED;
instr->fail_addr =
((loff_t)page << chip->page_shift);
goto erase_exit;
}
- /*
- * If BBT requires refresh, set the BBT rewrite flag to the
- * page being erased.
- */
- if (bbt_masked_page != 0xffffffff &&
- (page & BBT_PAGE_MASK) == bbt_masked_page)
- rewrite_bbt[chipnr] =
- ((loff_t)page << chip->page_shift);
-
/* Increment page address and decrement length */
- len -= (1 << chip->phys_erase_shift);
+ len -= (1ULL << chip->phys_erase_shift);
page += pages_per_block;
/* Check, if we cross a chip boundary */
chipnr++;
chip->select_chip(mtd, -1);
chip->select_chip(mtd, chipnr);
-
- /*
- * If BBT requires refresh and BBT-PERCHIP, set the BBT
- * page mask to see if this BBT should be rewritten.
- */
- if (bbt_masked_page != 0xffffffff &&
- (chip->bbt_td->options & NAND_BBT_PERCHIP))
- bbt_masked_page = chip->bbt_td->pages[chipnr] &
- BBT_PAGE_MASK;
}
}
instr->state = MTD_ERASE_DONE;
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
/* Deselect and wake up anyone waiting on the device */
+ chip->select_chip(mtd, -1);
nand_release_device(mtd);
/* Do call back function */
if (!ret)
mtd_erase_callback(instr);
- /*
- * If BBT requires refresh and erase was successful, rewrite any
- * selected bad block tables.
- */
- if (bbt_masked_page == 0xffffffff || ret)
- return ret;
-
- for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
- if (!rewrite_bbt[chipnr])
- continue;
- /* Update the BBT for chip */
- MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
- "(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
- rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
- nand_update_bbt(mtd, rewrite_bbt[chipnr]);
- }
-
/* Return more or less happy */
return ret;
}
*/
static void nand_sync(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+ pr_debug("%s: called\n", __func__);
/* Grab the lock and see if the device is available */
- nand_get_device(chip, mtd, FL_SYNCING);
+ nand_get_device(mtd, FL_SYNCING);
/* Release it and go back */
nand_release_device(mtd);
}
*/
static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *chip = mtd->priv;
int ret;
ret = nand_block_isbad(mtd, ofs);
return ret;
}
- return chip->block_markbad(mtd, ofs);
+ return nand_block_markbad_lowlevel(mtd, ofs);
}
- /**
+/**
* nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
* @mtd: MTD device structure
* @chip: nand chip info structure
int addr, uint8_t *subfeature_param)
{
int status;
+ int i;
- if (!chip->onfi_version)
+#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
+ if (!chip->onfi_version ||
+ !(le16_to_cpu(chip->onfi_params.opt_cmd)
+ & ONFI_OPT_CMD_SET_GET_FEATURES))
return -EINVAL;
+#endif
chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
- chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+ for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+ chip->write_byte(mtd, subfeature_param[i]);
+
status = chip->waitfunc(mtd, chip);
if (status & NAND_STATUS_FAIL)
return -EIO;
static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
int addr, uint8_t *subfeature_param)
{
- if (!chip->onfi_version)
+ int i;
+
+#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
+ if (!chip->onfi_version ||
+ !(le16_to_cpu(chip->onfi_params.opt_cmd)
+ & ONFI_OPT_CMD_SET_GET_FEATURES))
return -EINVAL;
+#endif
/* clear the sub feature parameters */
memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
- chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+ for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+ *subfeature_param++ = chip->read_byte(mtd);
return 0;
}
+#ifndef __UBOOT__
+/**
+ * nand_suspend - [MTD Interface] Suspend the NAND flash
+ * @mtd: MTD device structure
+ */
+static int nand_suspend(struct mtd_info *mtd)
+{
+ return nand_get_device(mtd, FL_PM_SUSPENDED);
+}
+
+/**
+ * nand_resume - [MTD Interface] Resume the NAND flash
+ * @mtd: MTD device structure
+ */
+static void nand_resume(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ if (chip->state == FL_PM_SUSPENDED)
+ nand_release_device(mtd);
+ else
+ pr_err("%s called for a chip which is not in suspended state\n",
+ __func__);
+}
+#endif
+
/* Set default functions */
static void nand_set_defaults(struct nand_chip *chip, int busw)
{
if (!chip->select_chip)
chip->select_chip = nand_select_chip;
- if (!chip->read_byte)
+
+ /* set for ONFI nand */
+ if (!chip->onfi_set_features)
+ chip->onfi_set_features = nand_onfi_set_features;
+ if (!chip->onfi_get_features)
+ chip->onfi_get_features = nand_onfi_get_features;
+
+ /* If called twice, pointers that depend on busw may need to be reset */
+ if (!chip->read_byte || chip->read_byte == nand_read_byte)
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
if (!chip->read_word)
chip->read_word = nand_read_word;
chip->block_bad = nand_block_bad;
if (!chip->block_markbad)
chip->block_markbad = nand_default_block_markbad;
- if (!chip->write_buf)
+ if (!chip->write_buf || chip->write_buf == nand_write_buf)
chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
- if (!chip->read_buf)
+ if (!chip->write_byte || chip->write_byte == nand_write_byte)
+ chip->write_byte = busw ? nand_write_byte16 : nand_write_byte;
+ if (!chip->read_buf || chip->read_buf == nand_read_buf)
chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
- if (!chip->verify_buf)
- chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
if (!chip->scan_bbt)
chip->scan_bbt = nand_default_bbt;
- if (!chip->controller)
+#ifdef __UBOOT__
+#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
+ if (!chip->verify_buf)
+ chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
+#endif
+#endif
+
+ if (!chip->controller) {
chip->controller = &chip->hwcontrol;
+ spin_lock_init(&chip->controller->lock);
+ init_waitqueue_head(&chip->controller->wq);
+ }
+
}
-#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
/* Sanitize ONFI strings so we can safely print them */
+#ifndef __UBOOT__
+static void sanitize_string(uint8_t *s, size_t len)
+#else
static void sanitize_string(char *s, size_t len)
+#endif
{
ssize_t i;
return crc;
}
+#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
+/* Parse the Extended Parameter Page. */
+static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
+ struct nand_chip *chip, struct nand_onfi_params *p)
+{
+ struct onfi_ext_param_page *ep;
+ struct onfi_ext_section *s;
+ struct onfi_ext_ecc_info *ecc;
+ uint8_t *cursor;
+ int ret = -EINVAL;
+ int len;
+ int i;
+
+ len = le16_to_cpu(p->ext_param_page_length) * 16;
+ ep = kmalloc(len, GFP_KERNEL);
+ if (!ep)
+ return -ENOMEM;
+
+ /* Send our own NAND_CMD_PARAM. */
+ chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
+
+ /* Use the Change Read Column command to skip the ONFI param pages. */
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
+ sizeof(*p) * p->num_of_param_pages , -1);
+
+ /* Read out the Extended Parameter Page. */
+ chip->read_buf(mtd, (uint8_t *)ep, len);
+ if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2)
+ != le16_to_cpu(ep->crc))) {
+ pr_debug("fail in the CRC.\n");
+ goto ext_out;
+ }
+
+ /*
+ * Check the signature.
+ * Do not strictly follow the ONFI spec, maybe changed in future.
+ */
+#ifndef __UBOOT__
+ if (strncmp(ep->sig, "EPPS", 4)) {
+#else
+ if (strncmp((char *)ep->sig, "EPPS", 4)) {
+#endif
+ pr_debug("The signature is invalid.\n");
+ goto ext_out;
+ }
+
+ /* find the ECC section. */
+ cursor = (uint8_t *)(ep + 1);
+ for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) {
+ s = ep->sections + i;
+ if (s->type == ONFI_SECTION_TYPE_2)
+ break;
+ cursor += s->length * 16;
+ }
+ if (i == ONFI_EXT_SECTION_MAX) {
+ pr_debug("We can not find the ECC section.\n");
+ goto ext_out;
+ }
+
+ /* get the info we want. */
+ ecc = (struct onfi_ext_ecc_info *)cursor;
+
+ if (!ecc->codeword_size) {
+ pr_debug("Invalid codeword size\n");
+ goto ext_out;
+ }
+
+ chip->ecc_strength_ds = ecc->ecc_bits;
+ chip->ecc_step_ds = 1 << ecc->codeword_size;
+ ret = 0;
+
+ext_out:
+ kfree(ep);
+ return ret;
+}
+
+static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
+{
+ struct nand_chip *chip = mtd->priv;
+ uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
+
+ return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
+ feature);
+}
+
+/*
+ * Configure chip properties from Micron vendor-specific ONFI table
+ */
+static void nand_onfi_detect_micron(struct nand_chip *chip,
+ struct nand_onfi_params *p)
+{
+ struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
+
+ if (le16_to_cpu(p->vendor_revision) < 1)
+ return;
+
+ chip->read_retries = micron->read_retry_options;
+ chip->setup_read_retry = nand_setup_read_retry_micron;
+}
+
/*
* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
*/
int *busw)
{
struct nand_onfi_params *p = &chip->onfi_params;
- int i;
+ int i, j;
int val;
/* Try ONFI for unknown chip or LP */
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
- chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
+ for (j = 0; j < sizeof(*p); j++)
+ ((uint8_t *)p)[j] = chip->read_byte(mtd);
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc)) {
- pr_info("ONFI param page %d valid\n", i);
break;
}
}
- if (i == 3)
+ if (i == 3) {
+ pr_err("Could not find valid ONFI parameter page; aborting\n");
return 0;
+ }
/* Check version */
val = le16_to_cpu(p->revision);
chip->onfi_version = 20;
else if (val & (1 << 1))
chip->onfi_version = 10;
- else
- chip->onfi_version = 0;
if (!chip->onfi_version) {
- pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
+ pr_info("unsupported ONFI version: %d\n", val);
return 0;
}
sanitize_string(p->model, sizeof(p->model));
if (!mtd->name)
mtd->name = p->model;
+
mtd->writesize = le32_to_cpu(p->byte_per_page);
- mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
+
+ /*
+ * pages_per_block and blocks_per_lun may not be a power-of-2 size
+ * (don't ask me who thought of this...). MTD assumes that these
+ * dimensions will be power-of-2, so just truncate the remaining area.
+ */
+ mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
+ mtd->erasesize *= mtd->writesize;
+
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
- chip->chipsize = le32_to_cpu(p->blocks_per_lun);
+
+ /* See erasesize comment */
+ chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
- *busw = 0;
- if (le16_to_cpu(p->features) & 1)
+ chip->bits_per_cell = p->bits_per_cell;
+
+ if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
*busw = NAND_BUSWIDTH_16;
+ else
+ *busw = 0;
+
+ if (p->ecc_bits != 0xff) {
+ chip->ecc_strength_ds = p->ecc_bits;
+ chip->ecc_step_ds = 512;
+ } else if (chip->onfi_version >= 21 &&
+ (onfi_feature(chip) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
+
+ /*
+ * The nand_flash_detect_ext_param_page() uses the
+ * Change Read Column command which maybe not supported
+ * by the chip->cmdfunc. So try to update the chip->cmdfunc
+ * now. We do not replace user supplied command function.
+ */
+ if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
+ chip->cmdfunc = nand_command_lp;
+
+ /* The Extended Parameter Page is supported since ONFI 2.1. */
+ if (nand_flash_detect_ext_param_page(mtd, chip, p))
+ pr_warn("Failed to detect ONFI extended param page\n");
+ } else {
+ pr_warn("Could not retrieve ONFI ECC requirements\n");
+ }
+
+ if (p->jedec_id == NAND_MFR_MICRON)
+ nand_onfi_detect_micron(chip, p);
- pr_info("ONFI flash detected\n");
return 1;
}
#else
-static inline int nand_flash_detect_onfi(struct mtd_info *mtd,
- struct nand_chip *chip,
+static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int *busw)
{
return 0;
}
#endif
+/*
+ * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise.
+ */
+static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
+ int *busw)
+{
+ struct nand_jedec_params *p = &chip->jedec_params;
+ struct jedec_ecc_info *ecc;
+ int val;
+ int i, j;
+
+ /* Try JEDEC for unknown chip or LP */
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
+ if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' ||
+ chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' ||
+ chip->read_byte(mtd) != 'C')
+ return 0;
+
+ chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1);
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < sizeof(*p); j++)
+ ((uint8_t *)p)[j] = chip->read_byte(mtd);
+
+ if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) ==
+ le16_to_cpu(p->crc))
+ break;
+ }
+
+ if (i == 3) {
+ pr_err("Could not find valid JEDEC parameter page; aborting\n");
+ return 0;
+ }
+
+ /* Check version */
+ val = le16_to_cpu(p->revision);
+ if (val & (1 << 2))
+ chip->jedec_version = 10;
+ else if (val & (1 << 1))
+ chip->jedec_version = 1; /* vendor specific version */
+
+ if (!chip->jedec_version) {
+ pr_info("unsupported JEDEC version: %d\n", val);
+ return 0;
+ }
+
+ sanitize_string(p->manufacturer, sizeof(p->manufacturer));
+ sanitize_string(p->model, sizeof(p->model));
+ if (!mtd->name)
+ mtd->name = p->model;
+
+ mtd->writesize = le32_to_cpu(p->byte_per_page);
+
+ /* Please reference to the comment for nand_flash_detect_onfi. */
+ mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
+ mtd->erasesize *= mtd->writesize;
+
+ mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+
+ /* Please reference to the comment for nand_flash_detect_onfi. */
+ chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+ chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
+ chip->bits_per_cell = p->bits_per_cell;
+
+ if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS)
+ *busw = NAND_BUSWIDTH_16;
+ else
+ *busw = 0;
+
+ /* ECC info */
+ ecc = &p->ecc_info[0];
+
+ if (ecc->codeword_size >= 9) {
+ chip->ecc_strength_ds = ecc->ecc_bits;
+ chip->ecc_step_ds = 1 << ecc->codeword_size;
+ } else {
+ pr_warn("Invalid codeword size\n");
+ }
+
+ return 1;
+}
+
/*
* nand_id_has_period - Check if an ID string has a given wraparound period
* @id_data: the ID string
*
* Check if an ID string is repeated within a given sequence of bytes at
* specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a
- * period of 2). This is a helper function for nand_id_len(). Returns non-zero
+ * period of 3). This is a helper function for nand_id_len(). Returns non-zero
* if the repetition has a period of @period; otherwise, returns zero.
*/
static int nand_id_has_period(u8 *id_data, int arrlen, int period)
return arrlen;
}
+/* Extract the bits of per cell from the 3rd byte of the extended ID */
+static int nand_get_bits_per_cell(u8 cellinfo)
+{
+ int bits;
+
+ bits = cellinfo & NAND_CI_CELLTYPE_MSK;
+ bits >>= NAND_CI_CELLTYPE_SHIFT;
+ return bits + 1;
+}
+
/*
* Many new NAND share similar device ID codes, which represent the size of the
* chip. The rest of the parameters must be decoded according to generic or
{
int extid, id_len;
/* The 3rd id byte holds MLC / multichip data */
- chip->cellinfo = id_data[2];
+ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
/* The 4th id byte is the important one */
extid = id_data[3];
* ID to decide what to do.
*/
if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
- (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
- id_data[5] != 0x00) {
+ !nand_is_slc(chip) && id_data[5] != 0x00) {
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
mtd->oobsize = 512;
break;
case 6:
- default: /* Other cases are "reserved" (unknown) */
mtd->oobsize = 640;
break;
+ case 7:
+ default: /* Other cases are "reserved" (unknown) */
+ mtd->oobsize = 1024;
+ break;
}
extid >>= 2;
/* Calc blocksize */
(((extid >> 1) & 0x04) | (extid & 0x03));
*busw = 0;
} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
- (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+ !nand_is_slc(chip)) {
unsigned int tmp;
/* Calc pagesize */
extid >>= 2;
/* Get buswidth information */
*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+
+ /*
+ * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+ * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+ * follows:
+ * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
+ * 110b -> 24nm
+ * - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC
+ */
+ if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
+ nand_is_slc(chip) &&
+ (id_data[5] & 0x7) == 0x6 /* 24nm */ &&
+ !(id_data[4] & 0x80) /* !BENAND */) {
+ mtd->oobsize = 32 * mtd->writesize >> 9;
+ }
+
}
}
- /*
+/*
* Old devices have chip data hardcoded in the device ID table. nand_decode_id
* decodes a matching ID table entry and assigns the MTD size parameters for
* the chip.
*/
static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
- const struct nand_flash_dev *type, u8 id_data[8],
+ struct nand_flash_dev *type, u8 id_data[8],
int *busw)
{
int maf_id = id_data[0];
mtd->oobsize = mtd->writesize / 32;
*busw = type->options & NAND_BUSWIDTH_16;
+ /* All legacy ID NAND are small-page, SLC */
+ chip->bits_per_cell = 1;
+
/*
* Check for Spansion/AMD ID + repeating 5th, 6th byte since
* some Spansion chips have erasesize that conflicts with size
}
}
- /*
+/*
* Set the bad block marker/indicator (BBM/BBI) patterns according to some
* heuristic patterns using various detected parameters (e.g., manufacturer,
* page size, cell-type information).
* Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
* AMD/Spansion, and Macronix. All others scan only the first page.
*/
- if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+ if (!nand_is_slc(chip) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX))
chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
- else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+ else if ((nand_is_slc(chip) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX ||
maf_id == NAND_MFR_TOSHIBA ||
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
}
+static inline bool is_full_id_nand(struct nand_flash_dev *type)
+{
+ return type->id_len;
+}
+
+static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
+ struct nand_flash_dev *type, u8 *id_data, int *busw)
+{
+#ifndef __UBOOT__
+ if (!strncmp(type->id, id_data, type->id_len)) {
+#else
+ if (!strncmp((char *)type->id, (char *)id_data, type->id_len)) {
+#endif
+ mtd->writesize = type->pagesize;
+ mtd->erasesize = type->erasesize;
+ mtd->oobsize = type->oobsize;
+
+ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
+ chip->chipsize = (uint64_t)type->chipsize << 20;
+ chip->options |= type->options;
+ chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
+ chip->ecc_step_ds = NAND_ECC_STEP(type);
+
+ *busw = type->options & NAND_BUSWIDTH_16;
+
+ if (!mtd->name)
+ mtd->name = type->name;
+
+ return true;
+ }
+ return false;
+}
+
/*
* Get the flash and manufacturer id and lookup if the type is supported.
*/
-static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
struct nand_chip *chip,
- int busw,
int *maf_id, int *dev_id,
- const struct nand_flash_dev *type)
+ struct nand_flash_dev *type)
{
- const char *name;
+ int busw;
int i, maf_idx;
u8 id_data[8];
id_data[i] = chip->read_byte(mtd);
if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
- pr_info("%s: second ID read did not match "
- "%02x,%02x against %02x,%02x\n", __func__,
+ pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
*maf_id, *dev_id, id_data[0], id_data[1]);
return ERR_PTR(-ENODEV);
}
if (!type)
type = nand_flash_ids;
- for (; type->name != NULL; type++)
- if (*dev_id == type->id)
- break;
+ for (; type->name != NULL; type++) {
+ if (is_full_id_nand(type)) {
+ if (find_full_id_nand(mtd, chip, type, id_data, &busw))
+ goto ident_done;
+ } else if (*dev_id == type->dev_id) {
+ break;
+ }
+ }
chip->onfi_version = 0;
if (!type->name || !type->pagesize) {
/* Check is chip is ONFI compliant */
if (nand_flash_detect_onfi(mtd, chip, &busw))
goto ident_done;
+
+ /* Check if the chip is JEDEC compliant */
+ if (nand_flash_detect_jedec(mtd, chip, &busw))
+ goto ident_done;
}
if (!type->name)
} else {
nand_decode_id(mtd, chip, type, id_data, &busw);
}
- /* Get chip options, preserve non chip based options */
+ /* Get chip options */
chip->options |= type->options;
/*
break;
}
- /*
- * Check, if buswidth is correct. Hardware drivers should set
- * chip correct!
- */
- if (busw != (chip->options & NAND_BUSWIDTH_16)) {
- pr_info("NAND device: Manufacturer ID:"
- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
- *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
- pr_warn("NAND bus width %d instead %d bit\n",
+ if (chip->options & NAND_BUSWIDTH_AUTO) {
+ WARN_ON(chip->options & NAND_BUSWIDTH_16);
+ chip->options |= busw;
+ nand_set_defaults(chip, busw);
+ } else if (busw != (chip->options & NAND_BUSWIDTH_16)) {
+ /*
+ * Check, if buswidth is correct. Hardware drivers should set
+ * chip correct!
+ */
+ pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+ *maf_id, *dev_id);
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name);
+ pr_warn("bus width %d instead %d bit\n",
(chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
busw ? 16 : 8);
return ERR_PTR(-EINVAL);
}
chip->badblockbits = 8;
-
- /* Check for AND chips with 4 page planes */
- if (chip->options & NAND_4PAGE_ARRAY)
- chip->erase_cmd = multi_erase_cmd;
- else
- chip->erase_cmd = single_erase_cmd;
+ chip->erase_cmd = single_erase_cmd;
/* Do not replace user supplied command function! */
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp;
- name = type->name;
+ pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+ *maf_id, *dev_id);
+
#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
if (chip->onfi_version)
- name = chip->onfi_params.model;
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+ chip->onfi_params.model);
+ else if (chip->jedec_version)
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+ chip->jedec_params.model);
+ else
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+ type->name);
+#else
+ if (chip->jedec_version)
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+ chip->jedec_params.model);
+ else
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+ type->name);
+
+ pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+ type->name);
#endif
- pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
- " page size: %d, OOB size: %d\n",
- *maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
- name,
- mtd->writesize, mtd->oobsize);
+ pr_info("%dMiB, %s, page size: %d, OOB size: %d\n",
+ (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
+ mtd->writesize, mtd->oobsize);
return type;
}
* The mtd->owner field must be set to the module of the caller.
*/
int nand_scan_ident(struct mtd_info *mtd, int maxchips,
- const struct nand_flash_dev *table)
+ struct nand_flash_dev *table)
{
- int i, busw, nand_maf_id, nand_dev_id;
+ int i, nand_maf_id, nand_dev_id;
struct nand_chip *chip = mtd->priv;
- const struct nand_flash_dev *type;
+ struct nand_flash_dev *type;
- /* Get buswidth to select the correct functions */
- busw = chip->options & NAND_BUSWIDTH_16;
/* Set the default functions */
- nand_set_defaults(chip, busw);
+ nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
/* Read the flash type */
- type = nand_get_flash_type(mtd, chip, busw,
- &nand_maf_id, &nand_dev_id, table);
+ type = nand_get_flash_type(mtd, chip, &nand_maf_id,
+ &nand_dev_id, table);
if (IS_ERR(type)) {
-#ifndef CONFIG_SYS_NAND_QUIET_TEST
- pr_warn("No NAND device found\n");
-#endif
+ if (!(chip->options & NAND_SCAN_SILENT_NODEV))
+ pr_warn("No NAND device found\n");
chip->select_chip(mtd, -1);
return PTR_ERR(type);
}
+ chip->select_chip(mtd, -1);
+
/* Check for a chip array */
for (i = 1; i < maxchips; i++) {
chip->select_chip(mtd, i);
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
if (nand_maf_id != chip->read_byte(mtd) ||
- nand_dev_id != chip->read_byte(mtd))
+ nand_dev_id != chip->read_byte(mtd)) {
+ chip->select_chip(mtd, -1);
break;
+ }
+ chip->select_chip(mtd, -1);
}
+
#ifdef DEBUG
if (i > 1)
- pr_info("%d NAND chips detected\n", i);
+ pr_info("%d chips detected\n", i);
#endif
/* Store the number of chips and calc total size for mtd */
return 0;
}
+EXPORT_SYMBOL(nand_scan_ident);
/**
{
int i;
struct nand_chip *chip = mtd->priv;
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct nand_buffers *nbuf;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */
BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
!(chip->bbt_options & NAND_BBT_USE_FLASH));
- if (!(chip->options & NAND_OWN_BUFFERS))
- chip->buffers = memalign(ARCH_DMA_MINALIGN,
- sizeof(*chip->buffers));
- if (!chip->buffers)
- return chip->options & NAND_OWN_BUFFERS ? -EINVAL : -ENOMEM;
+ if (!(chip->options & NAND_OWN_BUFFERS)) {
+#ifndef __UBOOT__
+ nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
+ + mtd->oobsize * 3, GFP_KERNEL);
+ if (!nbuf)
+ return -ENOMEM;
+ nbuf->ecccalc = (uint8_t *)(nbuf + 1);
+ nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
+ nbuf->databuf = nbuf->ecccode + mtd->oobsize;
+#else
+ nbuf = kzalloc(sizeof(struct nand_buffers), GFP_KERNEL);
+#endif
+
+ chip->buffers = nbuf;
+ } else {
+ if (!chip->buffers)
+ return -ENOMEM;
+ }
/* Set the internal oob buffer location, just after the page data */
chip->oob_poi = chip->buffers->databuf + mtd->writesize;
/*
* If no default placement scheme is given, select an appropriate one.
*/
- if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
+ if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) {
switch (mtd->oobsize) {
case 8:
- chip->ecc.layout = &nand_oob_8;
+ ecc->layout = &nand_oob_8;
break;
case 16:
- chip->ecc.layout = &nand_oob_16;
+ ecc->layout = &nand_oob_16;
break;
case 64:
- chip->ecc.layout = &nand_oob_64;
+ ecc->layout = &nand_oob_64;
break;
case 128:
- chip->ecc.layout = &nand_oob_128;
+ ecc->layout = &nand_oob_128;
break;
default:
pr_warn("No oob scheme defined for oobsize %d\n",
mtd->oobsize);
+ BUG();
}
}
if (!chip->write_page)
chip->write_page = nand_write_page;
- /* set for ONFI nand */
- if (!chip->onfi_set_features)
- chip->onfi_set_features = nand_onfi_set_features;
- if (!chip->onfi_get_features)
- chip->onfi_get_features = nand_onfi_get_features;
-
/*
* Check ECC mode, default to software if 3byte/512byte hardware ECC is
* selected and we have 256 byte pagesize fallback to software ECC
*/
- switch (chip->ecc.mode) {
+ switch (ecc->mode) {
case NAND_ECC_HW_OOB_FIRST:
/* Similar to NAND_ECC_HW, but a separate read_page handle */
- if (!chip->ecc.calculate || !chip->ecc.correct ||
- !chip->ecc.hwctl) {
+ if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {
pr_warn("No ECC functions supplied; "
"hardware ECC not possible\n");
BUG();
}
- if (!chip->ecc.read_page)
- chip->ecc.read_page = nand_read_page_hwecc_oob_first;
+ if (!ecc->read_page)
+ ecc->read_page = nand_read_page_hwecc_oob_first;
case NAND_ECC_HW:
/* Use standard hwecc read page function? */
- if (!chip->ecc.read_page)
- chip->ecc.read_page = nand_read_page_hwecc;
- if (!chip->ecc.write_page)
- chip->ecc.write_page = nand_write_page_hwecc;
- if (!chip->ecc.read_page_raw)
- chip->ecc.read_page_raw = nand_read_page_raw;
- if (!chip->ecc.write_page_raw)
- chip->ecc.write_page_raw = nand_write_page_raw;
- if (!chip->ecc.read_oob)
- chip->ecc.read_oob = nand_read_oob_std;
- if (!chip->ecc.write_oob)
- chip->ecc.write_oob = nand_write_oob_std;
+ if (!ecc->read_page)
+ ecc->read_page = nand_read_page_hwecc;
+ if (!ecc->write_page)
+ ecc->write_page = nand_write_page_hwecc;
+ if (!ecc->read_page_raw)
+ ecc->read_page_raw = nand_read_page_raw;
+ if (!ecc->write_page_raw)
+ ecc->write_page_raw = nand_write_page_raw;
+ if (!ecc->read_oob)
+ ecc->read_oob = nand_read_oob_std;
+ if (!ecc->write_oob)
+ ecc->write_oob = nand_write_oob_std;
+ if (!ecc->read_subpage)
+ ecc->read_subpage = nand_read_subpage;
+ if (!ecc->write_subpage)
+ ecc->write_subpage = nand_write_subpage_hwecc;
case NAND_ECC_HW_SYNDROME:
- if ((!chip->ecc.calculate || !chip->ecc.correct ||
- !chip->ecc.hwctl) &&
- (!chip->ecc.read_page ||
- chip->ecc.read_page == nand_read_page_hwecc ||
- !chip->ecc.write_page ||
- chip->ecc.write_page == nand_write_page_hwecc)) {
+ if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) &&
+ (!ecc->read_page ||
+ ecc->read_page == nand_read_page_hwecc ||
+ !ecc->write_page ||
+ ecc->write_page == nand_write_page_hwecc)) {
pr_warn("No ECC functions supplied; "
"hardware ECC not possible\n");
BUG();
}
/* Use standard syndrome read/write page function? */
- if (!chip->ecc.read_page)
- chip->ecc.read_page = nand_read_page_syndrome;
- if (!chip->ecc.write_page)
- chip->ecc.write_page = nand_write_page_syndrome;
- if (!chip->ecc.read_page_raw)
- chip->ecc.read_page_raw = nand_read_page_raw_syndrome;
- if (!chip->ecc.write_page_raw)
- chip->ecc.write_page_raw = nand_write_page_raw_syndrome;
- if (!chip->ecc.read_oob)
- chip->ecc.read_oob = nand_read_oob_syndrome;
- if (!chip->ecc.write_oob)
- chip->ecc.write_oob = nand_write_oob_syndrome;
-
- if (mtd->writesize >= chip->ecc.size) {
- if (!chip->ecc.strength) {
+ if (!ecc->read_page)
+ ecc->read_page = nand_read_page_syndrome;
+ if (!ecc->write_page)
+ ecc->write_page = nand_write_page_syndrome;
+ if (!ecc->read_page_raw)
+ ecc->read_page_raw = nand_read_page_raw_syndrome;
+ if (!ecc->write_page_raw)
+ ecc->write_page_raw = nand_write_page_raw_syndrome;
+ if (!ecc->read_oob)
+ ecc->read_oob = nand_read_oob_syndrome;
+ if (!ecc->write_oob)
+ ecc->write_oob = nand_write_oob_syndrome;
+
+ if (mtd->writesize >= ecc->size) {
+ if (!ecc->strength) {
pr_warn("Driver must set ecc.strength when using hardware ECC\n");
BUG();
}
}
pr_warn("%d byte HW ECC not possible on "
"%d byte page size, fallback to SW ECC\n",
- chip->ecc.size, mtd->writesize);
- chip->ecc.mode = NAND_ECC_SOFT;
+ ecc->size, mtd->writesize);
+ ecc->mode = NAND_ECC_SOFT;
case NAND_ECC_SOFT:
- chip->ecc.calculate = nand_calculate_ecc;
- chip->ecc.correct = nand_correct_data;
- chip->ecc.read_page = nand_read_page_swecc;
- chip->ecc.read_subpage = nand_read_subpage;
- chip->ecc.write_page = nand_write_page_swecc;
- chip->ecc.read_page_raw = nand_read_page_raw;
- chip->ecc.write_page_raw = nand_write_page_raw;
- chip->ecc.read_oob = nand_read_oob_std;
- chip->ecc.write_oob = nand_write_oob_std;
- if (!chip->ecc.size)
- chip->ecc.size = 256;
- chip->ecc.bytes = 3;
- chip->ecc.strength = 1;
+ ecc->calculate = nand_calculate_ecc;
+ ecc->correct = nand_correct_data;
+ ecc->read_page = nand_read_page_swecc;
+ ecc->read_subpage = nand_read_subpage;
+ ecc->write_page = nand_write_page_swecc;
+ ecc->read_page_raw = nand_read_page_raw;
+ ecc->write_page_raw = nand_write_page_raw;
+ ecc->read_oob = nand_read_oob_std;
+ ecc->write_oob = nand_write_oob_std;
+ if (!ecc->size)
+ ecc->size = 256;
+ ecc->bytes = 3;
+ ecc->strength = 1;
break;
case NAND_ECC_SOFT_BCH:
if (!mtd_nand_has_bch()) {
- pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");
- return -EINVAL;
+ pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n");
+ BUG();
}
- chip->ecc.calculate = nand_bch_calculate_ecc;
- chip->ecc.correct = nand_bch_correct_data;
- chip->ecc.read_page = nand_read_page_swecc;
- chip->ecc.read_subpage = nand_read_subpage;
- chip->ecc.write_page = nand_write_page_swecc;
- chip->ecc.read_page_raw = nand_read_page_raw;
- chip->ecc.write_page_raw = nand_write_page_raw;
- chip->ecc.read_oob = nand_read_oob_std;
- chip->ecc.write_oob = nand_write_oob_std;
+ ecc->calculate = nand_bch_calculate_ecc;
+ ecc->correct = nand_bch_correct_data;
+ ecc->read_page = nand_read_page_swecc;
+ ecc->read_subpage = nand_read_subpage;
+ ecc->write_page = nand_write_page_swecc;
+ ecc->read_page_raw = nand_read_page_raw;
+ ecc->write_page_raw = nand_write_page_raw;
+ ecc->read_oob = nand_read_oob_std;
+ ecc->write_oob = nand_write_oob_std;
/*
* Board driver should supply ecc.size and ecc.bytes values to
* select how many bits are correctable; see nand_bch_init()
* for details. Otherwise, default to 4 bits for large page
* devices.
*/
- if (!chip->ecc.size && (mtd->oobsize >= 64)) {
- chip->ecc.size = 512;
- chip->ecc.bytes = 7;
+ if (!ecc->size && (mtd->oobsize >= 64)) {
+ ecc->size = 512;
+ ecc->bytes = 7;
}
- chip->ecc.priv = nand_bch_init(mtd,
- chip->ecc.size,
- chip->ecc.bytes,
- &chip->ecc.layout);
- if (!chip->ecc.priv)
+ ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
+ &ecc->layout);
+ if (!ecc->priv) {
pr_warn("BCH ECC initialization failed!\n");
- chip->ecc.strength =
- chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);
+ BUG();
+ }
+ ecc->strength = ecc->bytes * 8 / fls(8 * ecc->size);
break;
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. "
- "This is not recommended !!\n");
- chip->ecc.read_page = nand_read_page_raw;
- chip->ecc.write_page = nand_write_page_raw;
- chip->ecc.read_oob = nand_read_oob_std;
- chip->ecc.read_page_raw = nand_read_page_raw;
- chip->ecc.write_page_raw = nand_write_page_raw;
- chip->ecc.write_oob = nand_write_oob_std;
- chip->ecc.size = mtd->writesize;
- chip->ecc.bytes = 0;
+ "This is not recommended!\n");
+ ecc->read_page = nand_read_page_raw;
+ ecc->write_page = nand_write_page_raw;
+ ecc->read_oob = nand_read_oob_std;
+ ecc->read_page_raw = nand_read_page_raw;
+ ecc->write_page_raw = nand_write_page_raw;
+ ecc->write_oob = nand_write_oob_std;
+ ecc->size = mtd->writesize;
+ ecc->bytes = 0;
+ ecc->strength = 0;
break;
default:
- pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
+ pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode);
BUG();
}
/* For many systems, the standard OOB write also works for raw */
- if (!chip->ecc.read_oob_raw)
- chip->ecc.read_oob_raw = chip->ecc.read_oob;
- if (!chip->ecc.write_oob_raw)
- chip->ecc.write_oob_raw = chip->ecc.write_oob;
+ if (!ecc->read_oob_raw)
+ ecc->read_oob_raw = ecc->read_oob;
+ if (!ecc->write_oob_raw)
+ ecc->write_oob_raw = ecc->write_oob;
/*
* The number of bytes available for a client to place data into
* the out of band area.
*/
- chip->ecc.layout->oobavail = 0;
- for (i = 0; chip->ecc.layout->oobfree[i].length
- && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
- chip->ecc.layout->oobavail +=
- chip->ecc.layout->oobfree[i].length;
- mtd->oobavail = chip->ecc.layout->oobavail;
+ ecc->layout->oobavail = 0;
+ for (i = 0; ecc->layout->oobfree[i].length
+ && i < ARRAY_SIZE(ecc->layout->oobfree); i++)
+ ecc->layout->oobavail += ecc->layout->oobfree[i].length;
+ mtd->oobavail = ecc->layout->oobavail;
/*
* Set the number of read / write steps for one page depending on ECC
* mode.
*/
- chip->ecc.steps = mtd->writesize / chip->ecc.size;
- if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
+ ecc->steps = mtd->writesize / ecc->size;
+ if (ecc->steps * ecc->size != mtd->writesize) {
pr_warn("Invalid ECC parameters\n");
+ pr_warn("steps=%d size=%d writesize=%d\n",
+ chip->ecc.steps, chip->ecc.size, mtd->writesize);
BUG();
}
- chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
+ ecc->total = ecc->steps * ecc->bytes;
/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
- if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
- !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
- switch (chip->ecc.steps) {
+ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
+ switch (ecc->steps) {
case 2:
mtd->subpage_sft = 1;
break;
/* Initialize state */
chip->state = FL_READY;
- /* De-select the device */
- chip->select_chip(mtd, -1);
-
/* Invalidate the pagebuffer reference */
chip->pagebuf = -1;
/* Large page NAND with SOFT_ECC should support subpage reads */
- if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
+ if ((ecc->mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
chip->options |= NAND_SUBPAGE_READ;
/* Fill in remaining MTD driver data */
- mtd->type = MTD_NANDFLASH;
+ mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
MTD_CAP_NANDFLASH;
mtd->_erase = nand_erase;
+#ifndef __UBOOT__
mtd->_point = NULL;
mtd->_unpoint = NULL;
+#endif
mtd->_read = nand_read;
mtd->_write = nand_write;
+ mtd->_panic_write = panic_nand_write;
mtd->_read_oob = nand_read_oob;
mtd->_write_oob = nand_write_oob;
mtd->_sync = nand_sync;
mtd->_lock = NULL;
mtd->_unlock = NULL;
+#ifndef __UBOOT__
+ mtd->_suspend = nand_suspend;
+ mtd->_resume = nand_resume;
+#endif
mtd->_block_isbad = nand_block_isbad;
mtd->_block_markbad = nand_block_markbad;
+ mtd->writebufsize = mtd->writesize;
/* propagate ecc info to mtd_info */
- mtd->ecclayout = chip->ecc.layout;
- mtd->ecc_strength = chip->ecc.strength;
+ mtd->ecclayout = ecc->layout;
+ mtd->ecc_strength = ecc->strength;
+ mtd->ecc_step_size = ecc->size;
/*
* Initialize bitflip_threshold to its default prior scan_bbt() call.
* scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be
if (!mtd->bitflip_threshold)
mtd->bitflip_threshold = mtd->ecc_strength;
- /* Check, if we should skip the bad block table scan */
- if (chip->options & NAND_SKIP_BBTSCAN)
- chip->options |= NAND_BBT_SCANNED;
-
return 0;
}
+EXPORT_SYMBOL(nand_scan_tail);
+
+/*
+ * is_module_text_address() isn't exported, and it's mostly a pointless
+ * test if this is a module _anyway_ -- they'd have to try _really_ hard
+ * to call us from in-kernel code if the core NAND support is modular.
+ */
+#ifdef MODULE
+#define caller_is_module() (1)
+#else
+#define caller_is_module() \
+ is_module_text_address((unsigned long)__builtin_return_address(0))
+#endif
/**
* nand_scan - [NAND Interface] Scan for the NAND device
{
int ret;
+ /* Many callers got this wrong, so check for it for a while... */
+ if (!mtd->owner && caller_is_module()) {
+ pr_crit("%s called with NULL mtd->owner!\n", __func__);
+ BUG();
+ }
+
ret = nand_scan_ident(mtd, maxchips, NULL);
if (!ret)
ret = nand_scan_tail(mtd);
return ret;
}
+EXPORT_SYMBOL(nand_scan);
+#ifndef __UBOOT__
/**
* nand_release - [NAND Interface] Free resources held by the NAND device
* @mtd: MTD device structure
if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
-#ifdef CONFIG_MTD_PARTITIONS
- /* Deregister partitions */
- del_mtd_partitions(mtd);
-#endif
+ mtd_device_unregister(mtd);
/* Free bad block table memory */
kfree(chip->bbt);
& NAND_BBT_DYNAMICSTRUCT)
kfree(chip->badblock_pattern);
}
+EXPORT_SYMBOL_GPL(nand_release);
+
+static int __init nand_base_init(void)
+{
+ led_trigger_register_simple("nand-disk", &nand_led_trigger);
+ return 0;
+}
+
+static void __exit nand_base_exit(void)
+{
+ led_trigger_unregister_simple(nand_led_trigger);
+}
+#endif
+
+module_init(nand_base_init);
+module_exit(nand_base_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Generic NAND flash driver code");
}
/* Shift the offset from byte addressing to word addressing. */
- if (this->options & NAND_BUSWIDTH_16)
+ if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
offs >>= 1;
/* Begin command latch cycle */
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
{
- unsigned int block, lastblock;
+ unsigned int block, lastblock, bad = 0;
unsigned int page;
+ const int ppb = CONFIG_SYS_NAND_BLOCK_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;
+ int maxbad;
+ #ifdef CONFIG_SYS_NAND_MAXBAD
+ maxbad = CONFIG_SYS_NAND_MAXBAD;
+ #else
+ maxbad = mtd.size;
+ #endif
/*
* offs has to be aligned to a page address!
*/
* Skip bad blocks
*/
while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
- nand_read_page(block, page, dst);
+ if (nand_chip.ecc.read_page) {
+ int ret;
+
+ ret = nand_chip.ecc.read_page(&mtd, &nand_chip,
+ dst, block * ppb + page);
+ if (ret) {
+ if (page > 0)
+ dst -= (page - 1) * CONFIG_SYS_NAND_PAGE_SIZE;
+ bad++;
+ lastblock++;
+ break;
+ }
+ } else {
+ nand_read_page(block, page, dst);
+ }
dst += CONFIG_SYS_NAND_PAGE_SIZE;
page++;
}
page = 0;
} else {
+ printf("Skipping bad block %d\n", block);
+ bad++;
lastblock++;
}
+ if (maxbad > 0 && bad > maxbad) {
+ printf("Too many bad blocks encountered\n");
+ return -1;
+ }
+
block++;
}
/* nand_init() - initialize data to make nand usable by SPL */
void nand_init(void)
{
+ static struct nand_buffers ecc_buf;
+
/*
* Init board specific nand support
*/
mtd.priv = &nand_chip;
+ mtd.erasesize = CONFIG_SYS_NAND_BLOCK_SIZE;
+ mtd.writesize = CONFIG_SYS_NAND_PAGE_SIZE;
+ mtd.oobsize = CONFIG_SYS_NAND_OOBSIZE;
+
nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
(void __iomem *)CONFIG_SYS_NAND_BASE;
+ nand_chip.oob_poi = ecc_buf.databuf;
+ nand_chip.buffers = &ecc_buf;
+
board_nand_init(&nand_chip);
#ifdef CONFIG_SPL_NAND_SOFTECC
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/mem.h>
-#include <asm/arch/cpu.h>
-#include <asm/omap_gpmc.h>
+#include <linux/mtd/omap_gpmc.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/bch.h>
#include <linux/compiler.h>
#include <nand.h>
-#ifdef CONFIG_AM33XX
-#include <asm/arch/elm.h>
+#include <linux/mtd/omap_elm.h>
+
+#define BADBLOCK_MARKER_LENGTH 2
+#define SECTOR_BYTES 512
+#define ECCCLEAR (0x1 << 8)
+#define ECCRESULTREG1 (0x1 << 0)
+/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
+#define BCH4_BIT_PAD 4
+
+#ifdef CONFIG_BCH
+static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
+ 0x97, 0x79, 0xe5, 0x24, 0xb5};
#endif
+static uint8_t cs_next;
+static __maybe_unused struct nand_ecclayout omap_ecclayout;
-static uint8_t cs;
-static __maybe_unused struct nand_ecclayout hw_nand_oob =
- GPMC_NAND_HW_ECC_LAYOUT;
-static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
- GPMC_NAND_HW_BCH8_ECC_LAYOUT;
+/*
+ * Driver configurations
+ */
+struct omap_nand_info {
+ struct bch_control *control;
+ enum omap_ecc ecc_scheme;
+ int cs;
+};
+
+/* We are wasting a bit of memory but al least we are safe */
+static struct omap_nand_info omap_nand_info[GPMC_MAX_CS];
+ static struct gpmc __iomem *gpmc_cfg = (void __iomem *)GPMC_BASE;
+
+ #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
+ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
+ static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+ static struct nand_bbt_descr bbt_main_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+ NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 0, /* may be overwritten depending on ECC layout */
+ .len = 4,
+ .veroffs = 4, /* may be overwritten depending on ECC layout */
+ .maxblocks = 4,
+ .pattern = bbt_pattern,
+ };
+
+ static struct nand_bbt_descr bbt_mirror_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+ NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 0, /* may be overwritten depending on ECC layout */
+ .len = 4,
+ .veroffs = 4, /* may be overwritten depending on ECC layout */
+ .maxblocks = 4,
+ .pattern = mirror_pattern,
+ };
+ #endif
+
+ #define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+ #define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
+
+ #define PREFETCH_ENABLEOPTIMIZEDACCESS (0x1 << 27)
+
+ #define GPMC_PREFETCH_STATUS_FIFO_CNT(val) (((val) >> 24) & 0x7F)
+ #define GPMC_PREFETCH_STATUS_COUNT(val) ((val) & 0x00003fff)
+
+ #define CS_NUM_SHIFT 24
+ #define ENABLE_PREFETCH (0x1 << 7)
+ #define DMA_MPU_MODE 2
+
+ #define OMAP_NAND_TIMEOUT_MS 5000
+
+ #define PRINT_REG(x) debug("+++ %.15s (0x%08x)=0x%08x\n", #x, &gpmc_cfg->x, readl(&gpmc_cfg->x))
+
+ #ifdef CONFIG_SYS_GPMC_PREFETCH_ENABLE
+ /**
+ * gpmc_prefetch_enable - configures and starts prefetch transfer
+ * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
+ * @count: number of bytes to be transferred
+ * @is_write: prefetch read(0) or write post(1) mode
+ */
+ static inline void gpmc_prefetch_enable(int cs, int fifo_th,
+ unsigned int count, int is_write)
+ {
+ writel(count, &gpmc_cfg->pref_config2);
+
+ /* Set the prefetch read / post write and enable the engine.
+ * Set which cs is has requested for.
+ */
+ uint32_t val = (cs << CS_NUM_SHIFT) |
+ PREFETCH_ENABLEOPTIMIZEDACCESS |
+ PREFETCH_FIFOTHRESHOLD(fifo_th) |
+ ENABLE_PREFETCH |
+ !!is_write;
+ writel(val, &gpmc_cfg->pref_config1);
+
+ /* Start the prefetch engine */
+ writel(0x1, &gpmc_cfg->pref_control);
+ }
+
+ /**
+ * gpmc_prefetch_reset - disables and stops the prefetch engine
+ */
+ static inline void gpmc_prefetch_reset(void)
+ {
+ /* Stop the PFPW engine */
+ writel(0x0, &gpmc_cfg->pref_control);
+
+ /* Reset/disable the PFPW engine */
+ writel(0x0, &gpmc_cfg->pref_config1);
+ }
+
+ //#define FIFO_IOADDR (nand->IO_ADDR_R)
+ #define FIFO_IOADDR PISMO1_NAND_BASE
+
+ /**
+ * read_buf_pref - read data from NAND controller into buffer
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
+ */
+ static void read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
+ {
+ gpmc_prefetch_enable(cs, PREFETCH_FIFOTHRESHOLD_MAX, len, 0);
+ do {
+ // Get number of bytes waiting in the FIFO
+ uint32_t read_bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(readl(&gpmc_cfg->pref_status));
+
+ if (read_bytes == 0)
+ continue;
+ // Alignment of Destination Buffer
+ while (read_bytes && ((unsigned int)buf & 3)) {
+ *buf++ = readb(FIFO_IOADDR);
+ read_bytes--;
+ len--;
+ }
+ // Use maximum word size (32bit) inside this loop, because speed is limited by
+ // GPMC bus arbitration with a maximum transfer rate of 3.000.000/sec.
+ len -= read_bytes & ~3;
+ while (read_bytes >= 4) {
+ *((uint32_t*)buf) = readl(FIFO_IOADDR);
+ buf += 4;
+ read_bytes -= 4;
+ }
+ // Transfer the last (non-aligned) bytes only at the last iteration,
+ // to maintain full speed up to the end of the transfer.
+ if (read_bytes == len) {
+ while (read_bytes) {
+ *buf++ = readb(FIFO_IOADDR);
+ read_bytes--;
+ }
+ len = 0;
+ }
+ } while (len > 0);
+ gpmc_prefetch_reset();
+ }
+
+ /*
+ * write_buf_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+ static void write_buf_pref(struct mtd_info *mtd, const u_char *buf, int len)
+ {
+ /* configure and start prefetch transfer */
+ gpmc_prefetch_enable(cs, PREFETCH_FIFOTHRESHOLD_MAX, len, 1);
+
+ while (len) {
+ // Get number of free bytes in the FIFO
+ uint32_t write_bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(readl(&gpmc_cfg->pref_status));
+
+ // don't write more bytes than requested
+ if (write_bytes > len)
+ write_bytes = len;
+
+ // Alignment of Source Buffer
+ while (write_bytes && ((unsigned int)buf & 3)) {
+ writeb(*buf++, FIFO_IOADDR);
+ write_bytes--;
+ len--;
+ }
+
+ // Use maximum word size (32bit) inside this loop, because speed is limited by
+ // GPMC bus arbitration with a maximum transfer rate of 3.000.000/sec.
+ len -= write_bytes & ~3;
+ while (write_bytes >= 4) {
+ writel(*((uint32_t*)buf), FIFO_IOADDR);
+ buf += 4;
+ write_bytes -= 4;
+ }
+
+ // Transfer the last (non-aligned) bytes only at the last iteration,
+ // to maintain full speed up to the end of the transfer.
+ if (write_bytes == len) {
+ while (write_bytes) {
+ writeb(*buf++, FIFO_IOADDR);
+ write_bytes--;
+ }
+ len = 0;
+ }
+ }
+
+ /* wait for data to be flushed out before resetting the prefetch */
+ while ((len = GPMC_PREFETCH_STATUS_COUNT(readl(&gpmc_cfg->pref_status)))) {
+ debug("%u bytes still in FIFO\n", PREFETCH_FIFOTHRESHOLD_MAX - len);
+ ndelay(1);
+ }
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+ }
+ #endif /* CONFIG_SYS_GPMC_PREFETCH_ENABLE */
+
/*
* omap_nand_hwcontrol - Set the address pointers corretly for the
* following address/data/command operation
uint32_t ctrl)
{
register struct nand_chip *this = mtd->priv;
+ struct omap_nand_info *info = this->priv;
+ int cs = info->cs;
/*
* Point the IO_ADDR to DATA and ADDRESS registers instead
writeb(cmd, this->IO_ADDR_W);
}
-#ifdef CONFIG_SPL_BUILD
/* Check wait pin as dev ready indicator */
-int omap_spl_dev_ready(struct mtd_info *mtd)
+static int omap_dev_ready(struct mtd_info *mtd)
{
- return gpmc_cfg->status & (1 << 8);
+ return readl(&gpmc_cfg->status) & (1 << 8);
}
-#endif
-
-/*
- * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
- * GPMC controller
- * @mtd: MTD device structure
- *
- */
-static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
-{
- /*
- * Init ECC Control Register
- * Clear all ECC | Enable Reg1
- */
- writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
- writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL, &gpmc_cfg->ecc_size_config);
-}
/*
* gen_true_ecc - This function will generate true ECC value, which
}
/*
- * omap_calculate_ecc - Generate non-inverted ECC bytes.
- *
- * Using noninverted ECC can be considered ugly since writing a blank
- * page ie. padding will clear the ECC bytes. This is no problem as
- * long nobody is trying to write data on the seemingly unused page.
- * Reading an erased page will produce an ECC mismatch between
- * generated and read ECC bytes that has to be dealt with separately.
- * E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
- * is used, the result of read will be 0x0 while the ECC offsets of the
- * spare area will be 0xFF which will result in an ECC mismatch.
- * @mtd: MTD structure
- * @dat: unused
- * @ecc_code: ecc_code buffer
- */
-static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
- const uint8_t *dat, uint8_t *ecc_code)
-{
- u_int32_t val;
-
- /* Start Reading from HW ECC1_Result = 0x200 */
- val = readl(&gpmc_cfg->ecc1_result);
-
- ecc_code[0] = val & 0xFF;
- ecc_code[1] = (val >> 16) & 0xFF;
- ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
-
- /*
- * Stop reading anymore ECC vals and clear old results
- * enable will be called if more reads are required
- */
- writel(0x000, &gpmc_cfg->ecc_config);
-
- return 0;
-}
-
-/*
- * omap_enable_ecc - This function enables the hardware ecc functionality
- * @mtd: MTD device structure
- * @mode: Read/Write mode
- */
-static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
-{
- struct nand_chip *chip = mtd->priv;
- uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-
- switch (mode) {
- case NAND_ECC_READ:
- case NAND_ECC_WRITE:
- /* Clear the ecc result registers, select ecc reg as 1 */
- writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
- /*
- * Size 0 = 0xFF, Size1 is 0xFF - both are 512 bytes
- * tell all regs to generate size0 sized regs
- * we just have a single ECC engine for all CS
- */
- writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL,
- &gpmc_cfg->ecc_size_config);
- val = (dev_width << 7) | (cs << 1) | (1 << 0);
- writel(val, &gpmc_cfg->ecc_config);
- break;
- default:
- printf("Error: Unrecognized Mode[%d]!\n", mode);
- }
-}
-
-/*
- * Generic BCH interface
- */
-struct nand_bch_priv {
- uint8_t mode;
- uint8_t type;
- uint8_t nibbles;
- struct bch_control *control;
-};
-
-/* bch types */
-#define ECC_BCH4 0
-#define ECC_BCH8 1
-#define ECC_BCH16 2
-
-/* GPMC ecc engine settings */
-#define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */
-#define BCH_WRAPMODE_6 6 /* BCH wrap mode 6 */
-
-/* BCH nibbles for diff bch levels */
-#define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1)
-#define ECC_BCH4_NIBBLES 13
-#define ECC_BCH8_NIBBLES 26
-#define ECC_BCH16_NIBBLES 52
-
-/*
- * This can be a single instance cause all current users have only one NAND
- * with nearly the same setup (BCH8, some with ELM and others with sw BCH
- * library).
- * When some users with other BCH strength will exists this have to change!
- */
-static __maybe_unused struct nand_bch_priv bch_priv = {
- .mode = NAND_ECC_HW_BCH,
- .type = ECC_BCH8,
- .nibbles = ECC_BCH8_NIBBLES,
- .control = NULL,
-};
-
-/*
- * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
- * GPMC controller
+ * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
* @mtd: MTD device structure
* @mode: Read/Write mode
*/
__maybe_unused
-static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
+static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
{
- uint32_t val;
- uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-#ifdef CONFIG_AM33XX
- uint32_t unused_length = 0;
-#endif
- uint32_t wr_mode = BCH_WRAPMODE_6;
- struct nand_bch_priv *bch = chip->priv;
-
- /* Clear the ecc result registers, select ecc reg as 1 */
- writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
-#ifdef CONFIG_AM33XX
- wr_mode = BCH_WRAPMODE_1;
-
- switch (bch->nibbles) {
- case ECC_BCH4_NIBBLES:
- unused_length = 3;
- break;
- case ECC_BCH8_NIBBLES:
- unused_length = 2;
+ struct nand_chip *nand = mtd->priv;
+ struct omap_nand_info *info = nand->priv;
+ unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
+ unsigned int ecc_algo = 0;
+ unsigned int bch_type = 0;
+ unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
+ u32 ecc_size_config_val = 0;
+ u32 ecc_config_val = 0;
+ int cs = info->cs;
+
+ /* configure GPMC for specific ecc-scheme */
+ switch (info->ecc_scheme) {
+ case OMAP_ECC_HAM1_CODE_SW:
+ return;
+ case OMAP_ECC_HAM1_CODE_HW:
+ ecc_algo = 0x0;
+ bch_type = 0x0;
+ bch_wrapmode = 0x00;
+ eccsize0 = 0xFF;
+ eccsize1 = 0xFF;
break;
- case ECC_BCH16_NIBBLES:
- unused_length = 0;
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+ case OMAP_ECC_BCH8_CODE_HW:
+ ecc_algo = 0x1;
+ bch_type = 0x1;
+ if (mode == NAND_ECC_WRITE) {
+ bch_wrapmode = 0x01;
+ eccsize0 = 0; /* extra bits in nibbles per sector */
+ eccsize1 = 28; /* OOB bits in nibbles per sector */
+ } else {
+ bch_wrapmode = 0x01;
+ eccsize0 = 26; /* ECC bits in nibbles per sector */
+ eccsize1 = 2; /* non-ECC bits in nibbles per sector */
+ }
break;
- }
-
- /*
- * This is ecc_size_config for ELM mode.
- * Here we are using different settings for read and write access and
- * also depending on BCH strength.
- */
- switch (mode) {
- case NAND_ECC_WRITE:
- /* write access only setup eccsize1 config */
- val = ((unused_length + bch->nibbles) << 22);
+ case OMAP_ECC_BCH16_CODE_HW:
+ ecc_algo = 0x1;
+ bch_type = 0x2;
+ if (mode == NAND_ECC_WRITE) {
+ bch_wrapmode = 0x01;
+ eccsize0 = 0; /* extra bits in nibbles per sector */
+ eccsize1 = 52; /* OOB bits in nibbles per sector */
+ } else {
+ bch_wrapmode = 0x01;
+ eccsize0 = 52; /* ECC bits in nibbles per sector */
+ eccsize1 = 0; /* non-ECC bits in nibbles per sector */
+ }
break;
-
- case NAND_ECC_READ:
default:
- /*
- * by default eccsize0 selected for ecc1resultsize
- * eccsize0 config.
- */
- val = (bch->nibbles << 12);
- /* eccsize1 config */
- val |= (unused_length << 22);
- break;
+ return;
}
-#else
- /*
- * This ecc_size_config setting is for BCH sw library.
- *
- * Note: we only support BCH8 currently with BCH sw library!
- * Should be really easy to adopt to BCH4, however some omap3 have
- * flaws with BCH4.
- *
- * Here we are using wrapping mode 6 both for reading and writing, with:
- * size0 = 0 (no additional protected byte in spare area)
- * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
- */
- val = (32 << 22) | (0 << 12);
-#endif
- /* ecc size configuration */
- writel(val, &gpmc_cfg->ecc_size_config);
-
- /*
- * Configure the ecc engine in gpmc
- * We assume 512 Byte sector pages for access to NAND.
- */
- val = 1 << 16; /* select BCH mode */
- val |= bch->type << 12; /* setup BCH type */
- val |= wr_mode << 8; /* setup wrapping mode */
- val |= dev_width << 7; /* setup device width (16 or 8 bit) */
- val |= (chip->ecc.size / 512 - 1) << 4; /* set ECC size */
- val |= cs << 1; /* setup chip select to work on */
- val |= 1 << 0; /* enable ECC engine */
-
- debug("set ECC_CONFIG=0x%08x\n", val);
- writel(val, &gpmc_cfg->ecc_config);
-}
-
-/*
- * omap_enable_ecc_bch - This function enables the bch h/w ecc functionality
- * @mtd: MTD device structure
- * @mode: Read/Write mode
- */
-__maybe_unused
-static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
-{
- struct nand_chip *chip = mtd->priv;
-
- omap_hwecc_init_bch(chip, mode);
-}
-
-/*
- * omap_ecc_disable - Disable H/W ECC calculation
- *
- * @mtd: MTD device structure
- */
-static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
-{
- writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
+ /* Clear ecc and enable bits */
+ writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
+ /* Configure ecc size for BCH */
+ ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
+ writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
+
+ /* Configure device details for BCH engine */
+ ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */
+ (bch_type << 12) | /* BCH4/BCH8/BCH16 */
+ (bch_wrapmode << 8) | /* wrap mode */
+ (dev_width << 7) | /* bus width */
+ (0x0 << 4) | /* number of sectors */
+ (cs << 1) | /* ECC CS */
+ (0x1)); /* enable ECC */
+ writel(ecc_config_val, &gpmc_cfg->ecc_config);
}
/*
- * BCH8 support (needs ELM and thus AM33xx-only)
- */
-#ifdef CONFIG_AM33XX
-/*
- * omap_read_bch8_result - Read BCH result for BCH8 level
- *
- * @mtd: MTD device structure
- * @big_endian: When set read register 3 first
- * @ecc_code: Read syndrome from BCH result registers
+ * omap_calculate_ecc - Read ECC result
+ * @mtd: MTD structure
+ * @dat: unused
+ * @ecc_code: ecc_code buffer
+ * Using noninverted ECC can be considered ugly since writing a blank
+ * page ie. padding will clear the ECC bytes. This is no problem as
+ * long nobody is trying to write data on the seemingly unused page.
+ * Reading an erased page will produce an ECC mismatch between
+ * generated and read ECC bytes that has to be dealt with separately.
+ * E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
+ * is used, the result of read will be 0x0 while the ECC offsets of the
+ * spare area will be 0xFF which will result in an ECC mismatch.
*/
-static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
+static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc_code)
{
- uint32_t *ptr;
- int8_t i = 0, j, k;
struct nand_chip *chip = mtd->priv;
- int num_steps = chip->ecc.size / 512;
-
- for (k = 0; k < num_steps; k++) {
- if (big_endian) {
- ptr = &gpmc_cfg->bch_result_0_3[k].bch_result_x[3];
- ecc_code[i++] = readl(ptr) & 0xFF;
+ struct omap_nand_info *info = chip->priv;
+ uint32_t *ptr, val = 0;
+ int8_t i = 0, j;
+
+ switch (info->ecc_scheme) {
+ case OMAP_ECC_HAM1_CODE_HW:
+ val = readl(&gpmc_cfg->ecc1_result);
+ ecc_code[0] = val & 0xFF;
+ ecc_code[1] = (val >> 16) & 0xFF;
+ ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
+ break;
+#ifdef CONFIG_BCH
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+#endif
+ case OMAP_ECC_BCH8_CODE_HW:
+ ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
+ val = readl(ptr);
+ ecc_code[i++] = (val >> 0) & 0xFF;
+ ptr--;
+ for (j = 0; j < 3; j++) {
+ val = readl(ptr);
+ ecc_code[i++] = (val >> 24) & 0xFF;
+ ecc_code[i++] = (val >> 16) & 0xFF;
+ ecc_code[i++] = (val >> 8) & 0xFF;
+ ecc_code[i++] = (val >> 0) & 0xFF;
ptr--;
- for (j = 0; j < 3; j++) {
- ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
- ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
- ecc_code[i++] = (readl(ptr) >> 8) & 0xFF;
- ecc_code[i++] = readl(ptr) & 0xFF;
- ptr--;
- }
- } else {
- ptr = &gpmc_cfg->bch_result_0_3[k].bch_result_x[0];
- for (j = 0; j < 3; j++) {
- ecc_code[i++] = readl(ptr) & 0xFF;
- ecc_code[i++] = (readl(ptr) >> 8) & 0xFF;
- ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
- ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
- ptr++;
- }
- ecc_code[i++] = readl(ptr) & 0xFF;
}
- ecc_code[i++] = 0; /* 14th byte is always zero */
+ break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]);
+ ecc_code[i++] = (val >> 8) & 0xFF;
+ ecc_code[i++] = (val >> 0) & 0xFF;
+ val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]);
+ ecc_code[i++] = (val >> 24) & 0xFF;
+ ecc_code[i++] = (val >> 16) & 0xFF;
+ ecc_code[i++] = (val >> 8) & 0xFF;
+ ecc_code[i++] = (val >> 0) & 0xFF;
+ val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]);
+ ecc_code[i++] = (val >> 24) & 0xFF;
+ ecc_code[i++] = (val >> 16) & 0xFF;
+ ecc_code[i++] = (val >> 8) & 0xFF;
+ ecc_code[i++] = (val >> 0) & 0xFF;
+ for (j = 3; j >= 0; j--) {
+ val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j]
+ );
+ ecc_code[i++] = (val >> 24) & 0xFF;
+ ecc_code[i++] = (val >> 16) & 0xFF;
+ ecc_code[i++] = (val >> 8) & 0xFF;
+ ecc_code[i++] = (val >> 0) & 0xFF;
+ }
+ break;
+ default:
+ return -EINVAL;
}
-}
-
-/*
- * omap_rotate_ecc_bch - Rotate the syndrome bytes
- *
- * @mtd: MTD device structure
- * @calc_ecc: ECC read from ECC registers
- * @syndrome: Rotated syndrome will be returned in this array
- *
- */
-static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
- uint8_t *syndrome)
-{
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *bch = chip->priv;
- uint8_t n_bytes = 0;
- int8_t i, j;
-
- switch (bch->type) {
- case ECC_BCH4:
- n_bytes = 8;
+ /* ECC scheme specific syndrome customizations */
+ switch (info->ecc_scheme) {
+ case OMAP_ECC_HAM1_CODE_HW:
break;
+#ifdef CONFIG_BCH
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
- case ECC_BCH16:
- n_bytes = 28;
+ for (i = 0; i < chip->ecc.bytes; i++)
+ *(ecc_code + i) = *(ecc_code + i) ^
+ bch8_polynomial[i];
break;
-
- case ECC_BCH8:
- default:
- n_bytes = 13;
+#endif
+ case OMAP_ECC_BCH8_CODE_HW:
+ ecc_code[chip->ecc.bytes - 1] = 0x00;
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ break;
+ default:
+ return -EINVAL;
}
-
- for (i = 0, j = n_bytes - 1; i < n_bytes; i++, j--)
- syndrome[i] = calc_ecc[j];
+ return 0;
}
+#ifdef CONFIG_NAND_OMAP_ELM
/*
- * omap_calculate_ecc_bch - Read BCH ECC result
- *
- * @mtd: MTD structure
- * @dat: unused
- * @ecc_code: ecc_code buffer
- */
-static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc_code)
+ * omap_reverse_list - re-orders list elements in reverse order [internal]
+ * @list: pointer to start of list
+ * @length: length of list
+*/
+static void omap_reverse_list(u8 *list, unsigned int length)
{
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *bch = chip->priv;
- uint8_t big_endian = 1;
- int8_t ret = 0;
-
- if (bch->type == ECC_BCH8)
- omap_read_bch8_result(mtd, big_endian, ecc_code);
- else /* BCH4 and BCH16 currently not supported */
- ret = -1;
-
- /*
- * Stop reading anymore ECC vals and clear old results
- * enable will be called if more reads are required
- */
- omap_ecc_disable(mtd);
-
- return ret;
-}
-
-/*
- * omap_fix_errors_bch - Correct bch error in the data
- *
- * @mtd: MTD device structure
- * @data: Data read from flash
- * @error_count:Number of errors in data
- * @error_loc: Locations of errors in the data
- *
- */
-static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
- uint32_t error_count, uint32_t *error_loc)
-{
- struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *bch = chip->priv;
- uint8_t count = 0;
- uint32_t error_byte_pos;
- uint32_t error_bit_mask;
- uint32_t last_bit = (bch->nibbles * 4) - 1;
-
- /* Flip all bits as specified by the error location array. */
- /* FOR( each found error location flip the bit ) */
- for (count = 0; count < error_count; count++) {
- if (error_loc[count] > last_bit) {
- /* Remove the ECC spare bits from correction. */
- error_loc[count] -= (last_bit + 1);
- /* Offset bit in data region */
- error_byte_pos = ((512 * 8) -
- (error_loc[count]) - 1) / 8;
- /* Error Bit mask */
- error_bit_mask = 0x1 << (error_loc[count] % 8);
- /* Toggle the error bit to make the correction. */
- data[error_byte_pos] ^= error_bit_mask;
- }
+ unsigned int i, j;
+ unsigned int half_length = length / 2;
+ u8 tmp;
+ for (i = 0, j = length - 1; i < half_length; i++, j--) {
+ tmp = list[i];
+ list[i] = list[j];
+ list[j] = tmp;
}
}
uint8_t *read_ecc, uint8_t *calc_ecc)
{
struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *bch = chip->priv;
- uint8_t syndrome[28];
- uint32_t error_count = 0;
- uint32_t error_loc[8];
- uint32_t i, ecc_flag;
- int k, ecc_bytes, num_steps;
-
- num_steps = chip->ecc.size / 512;
- ecc_bytes = chip->ecc.bytes / num_steps;
-
- for (k = 0; k < num_steps; k++) {
- ecc_flag = 0;
- /* check if area is flashed */
- for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++)
- if (read_ecc[i] != 0xff)
- ecc_flag = 1;
-
- if (ecc_flag) {
- ecc_flag = 0;
- /* check if any ecc error */
- for (i = 0; (i < ecc_bytes) && !ecc_flag; i++)
- if (calc_ecc[i] != 0)
- ecc_flag = 1;
- }
-
- if (!ecc_flag)
- return 0;
-
- elm_reset();
- elm_config((enum bch_level)(bch->type));
+ struct omap_nand_info *info = chip->priv;
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
+ uint32_t error_count = 0, error_max;
+ uint32_t error_loc[ELM_MAX_ERROR_COUNT];
+ enum bch_level bch_type;
+ uint32_t i, ecc_flag = 0;
+ uint8_t count;
+ uint32_t byte_pos, bit_pos;
+ int err = 0;
+
+ /* check calculated ecc */
+ for (i = 0; i < ecc->bytes && !ecc_flag; i++) {
+ if (calc_ecc[i] != 0x00)
+ ecc_flag = 1;
+ }
+ if (!ecc_flag)
+ return 0;
+
+ /* check for whether its a erased-page */
+ ecc_flag = 0;
+ for (i = 0; i < ecc->bytes && !ecc_flag; i++) {
+ if (read_ecc[i] != 0xff)
+ ecc_flag = 1;
+ }
+ if (!ecc_flag)
+ return 0;
- /*
- * while reading ECC result we read it in big endian.
- * Hence while loading to ELM we have rotate to get the right endian.
- */
- omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
+ /*
+ * while reading ECC result we read it in big endian.
+ * Hence while loading to ELM we have rotate to get the right endian.
+ */
+ switch (info->ecc_scheme) {
+ case OMAP_ECC_BCH8_CODE_HW:
+ bch_type = BCH_8_BIT;
+ omap_reverse_list(calc_ecc, ecc->bytes - 1);
+ break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ bch_type = BCH_16_BIT;
+ omap_reverse_list(calc_ecc, ecc->bytes);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* use elm module to check for errors */
+ elm_config(bch_type);
+ err = elm_check_error(calc_ecc, bch_type, &error_count, error_loc);
+ if (err)
+ return err;
- /* use elm module to check for errors */
- if (elm_check_error(syndrome, bch->nibbles, &error_count,
- error_loc) != 0) {
- printf("ECC: uncorrectable.\n");
- return -1;
+ /* correct bch error */
+ for (count = 0; count < error_count; count++) {
+ switch (info->ecc_scheme) {
+ case OMAP_ECC_BCH8_CODE_HW:
+ /* 14th byte in ECC is reserved to match ROM layout */
+ error_max = SECTOR_BYTES + (ecc->bytes - 1);
+ break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ error_max = SECTOR_BYTES + ecc->bytes;
+ break;
+ default:
+ return -EINVAL;
+ }
+ byte_pos = error_max - (error_loc[count] / 8) - 1;
+ bit_pos = error_loc[count] % 8;
+ if (byte_pos < SECTOR_BYTES) {
+ dat[byte_pos] ^= 1 << bit_pos;
+ printf("nand: bit-flip corrected @data=%d\n", byte_pos);
+ } else if (byte_pos < error_max) {
+ read_ecc[byte_pos - SECTOR_BYTES] ^= 1 << bit_pos;
+ printf("nand: bit-flip corrected @oob=%d\n", byte_pos -
+ SECTOR_BYTES);
+ } else {
+ err = -EBADMSG;
+ printf("nand: error: invalid bit-flip location\n");
}
-
- /* correct bch error */
- if (error_count > 0)
- omap_fix_errors_bch(mtd, dat, error_count, error_loc);
- dat += 512;
- read_ecc += ecc_bytes;
- calc_ecc += ecc_bytes;
}
- return 0;
+ return (err) ? err : error_count;
}
/**
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
- uint8_t *oob = chip->oob_poi;
+ uint8_t *oob = &chip->oob_poi[eccpos[0]];
uint32_t data_pos;
uint32_t oob_pos;
data_pos = 0;
/* oob area start */
- oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
- oob += chip->ecc.layout->eccpos[0];
+ oob_pos = (eccsize * eccsteps) + eccpos[0];
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
oob += eccbytes) {
chip->ecc.hwctl(mtd, NAND_ECC_READ);
/* read data */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1);
chip->read_buf(mtd, p, eccsize);
/* read respective ecc from oob area */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
chip->read_buf(mtd, oob, eccbytes);
/* read syndrome */
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
}
return 0;
}
-#endif /* CONFIG_AM33XX */
+#endif /* CONFIG_NAND_OMAP_ELM */
/*
* OMAP3 BCH8 support (with BCH library)
*/
-#ifdef CONFIG_NAND_OMAP_BCH8
-/*
- * omap_calculate_ecc_bch - Read BCH ECC result
- *
- * @mtd: MTD device structure
- * @dat: The pointer to data on which ecc is computed (unused here)
- * @ecc: The ECC output buffer
- */
-static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc)
-{
- int ret = 0;
- size_t i;
- unsigned long nsectors, val1, val2, val3, val4;
-
- nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
-
- for (i = 0; i < nsectors; i++) {
- /* Read hw-computed remainder */
- val1 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[0]);
- val2 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[1]);
- val3 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[2]);
- val4 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]);
-
- /*
- * Add constant polynomial to remainder, in order to get an ecc
- * sequence of 0xFFs for a buffer filled with 0xFFs.
- */
- *ecc++ = 0xef ^ (val4 & 0xFF);
- *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
- *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
- *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
- *ecc++ = 0xed ^ (val3 & 0xFF);
- *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
- *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
- *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
- *ecc++ = 0x97 ^ (val2 & 0xFF);
- *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
- *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
- *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
- *ecc++ = 0xb5 ^ (val1 & 0xFF);
- }
-
- /*
- * Stop reading anymore ECC vals and clear old results
- * enable will be called if more reads are required
- */
- omap_ecc_disable(mtd);
-
- return ret;
-}
-
+#ifdef CONFIG_BCH
/**
- * omap_correct_data_bch - Decode received data and correct errors
+ * omap_correct_data_bch_sw - Decode received data and correct errors
* @mtd: MTD device structure
* @data: page data
* @read_ecc: ecc read from nand flash
* @calc_ecc: ecc read from HW ECC registers
*/
-static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
+static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
u_char *read_ecc, u_char *calc_ecc)
{
int i, count;
/* cannot correct more than 8 errors */
unsigned int errloc[8];
struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *chip_priv = chip->priv;
- struct bch_control *bch = chip_priv->control;
+ struct omap_nand_info *info = chip->priv;
- count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
+ count = decode_bch(info->control, NULL, 512, read_ecc, calc_ecc,
+ NULL, errloc);
if (count > 0) {
/* correct errors */
for (i = 0; i < count; i++) {
data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
printf("corrected bitflip %u\n", errloc[i]);
#ifdef DEBUG
- puts("read_ecc: ");
+ printf("read_ecc: ");
/*
* BCH8 have 13 bytes of ECC; BCH4 needs adoption
* here!
*/
for (i = 0; i < 13; i++)
printf("%02x ", read_ecc[i]);
- puts("\n");
- puts("calc_ecc: ");
+ printf("\n");
+ printf("calc_ecc: ");
for (i = 0; i < 13; i++)
printf("%02x ", calc_ecc[i]);
- puts("\n");
+ printf("\n");
#endif
}
} else if (count < 0) {
- puts("ecc unrecoverable error\n");
+ printf("ecc unrecoverable error\n");
}
return count;
}
static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
- struct nand_bch_priv *chip_priv = chip->priv;
- struct bch_control *bch = NULL;
+ struct omap_nand_info *info = chip->priv;
- if (chip_priv)
- bch = chip_priv->control;
+ if (info->control) {
+ free_bch(info->control);
+ info->control = NULL;
+ }
+}
+#endif /* CONFIG_BCH */
+
+/**
+ * omap_select_ecc_scheme - configures driver for particular ecc-scheme
+ * @nand: NAND chip device structure
+ * @ecc_scheme: ecc scheme to configure
+ * @pagesize: number of main-area bytes per page of NAND device
+ * @oobsize: number of OOB/spare bytes per page of NAND device
+ */
+static int omap_select_ecc_scheme(struct nand_chip *nand,
+ enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
+ struct omap_nand_info *info = nand->priv;
+ struct nand_ecclayout *ecclayout = &omap_ecclayout;
+ int eccsteps = pagesize / SECTOR_BYTES;
+ int i;
+
+ switch (ecc_scheme) {
+ case OMAP_ECC_HAM1_CODE_SW:
+ debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
+ /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
+ * initialized in nand_scan_tail(), so just set ecc.mode */
+ info->control = NULL;
+ nand->ecc.mode = NAND_ECC_SOFT;
+ nand->ecc.layout = NULL;
+ nand->ecc.size = 0;
+ break;
- if (bch) {
- free_bch(bch);
- chip_priv->control = NULL;
+ case OMAP_ECC_HAM1_CODE_HW:
+ debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ info->control = NULL;
+ /* populate ecc specific fields */
+ memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 1;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 3;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data;
+ nand->ecc.calculate = omap_calculate_ecc;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ for (i = 0; i < ecclayout->eccbytes; i++) {
+ if (nand->options & NAND_BUSWIDTH_16)
+ ecclayout->eccpos[i] = i + 2;
+ else
+ ecclayout->eccpos[i] = i + 1;
+ }
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+ BADBLOCK_MARKER_LENGTH;
+ break;
+
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+#ifdef CONFIG_BCH
+ debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* check if BCH S/W library can be used for error detection */
+ info->control = init_bch(13, 8, 0x201b);
+ if (!info->control) {
+ printf("nand: error: could not init_bch()\n");
+ return -ENODEV;
+ }
+ /* populate ecc specific fields */
+ memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 8;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 13;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data_bch_sw;
+ nand->ecc.calculate = omap_calculate_ecc;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
+ for (i = 1; i < ecclayout->eccbytes; i++) {
+ if (i % nand->ecc.bytes)
+ ecclayout->eccpos[i] =
+ ecclayout->eccpos[i - 1] + 1;
+ else
+ ecclayout->eccpos[i] =
+ ecclayout->eccpos[i - 1] + 2;
+ }
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+ BADBLOCK_MARKER_LENGTH;
+ break;
+#else
+ printf("nand: error: CONFIG_BCH required for ECC\n");
+ return -EINVAL;
+#endif
+
+ case OMAP_ECC_BCH8_CODE_HW:
+#ifdef CONFIG_NAND_OMAP_ELM
+ debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* intialize ELM for ECC error detection */
+ elm_init();
+ info->control = NULL;
+ /* populate ecc specific fields */
+ memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 8;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 14;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data_bch;
+ nand->ecc.calculate = omap_calculate_ecc;
+ nand->ecc.read_page = omap_read_page_bch;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ for (i = 0; i < ecclayout->eccbytes; i++)
+ ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+ BADBLOCK_MARKER_LENGTH;
+ break;
+#else
+ printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
+ return -EINVAL;
+#endif
+
+ case OMAP_ECC_BCH16_CODE_HW:
+#ifdef CONFIG_NAND_OMAP_ELM
+ debug("nand: using OMAP_ECC_BCH16_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((26 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (26 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* intialize ELM for ECC error detection */
+ elm_init();
+ /* populate ecc specific fields */
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 26;
+ nand->ecc.strength = 16;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data_bch;
+ nand->ecc.calculate = omap_calculate_ecc;
+ nand->ecc.read_page = omap_read_page_bch;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ for (i = 0; i < ecclayout->eccbytes; i++)
+ ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
+ BADBLOCK_MARKER_LENGTH;
+ break;
+#else
+ printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
+ return -EINVAL;
+#endif
+ default:
+ debug("nand: error: ecc scheme not enabled or supported\n");
+ return -EINVAL;
}
+
+ /* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
+ if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
+ nand->ecc.layout = ecclayout;
+
+ info->ecc_scheme = ecc_scheme;
+ return 0;
}
-#endif /* CONFIG_NAND_OMAP_BCH8 */
#ifndef CONFIG_SPL_BUILD
/*
* @eccstrength - the number of bits that could be corrected
* (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
*/
-void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
+int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
{
struct nand_chip *nand;
struct mtd_info *mtd;
+ int err = 0;
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[nand_curr_device].name) {
- printf("Error: Can't switch ecc, no devices available\n");
- return;
+ printf("nand: error: no NAND devices found\n");
+ return -ENODEV;
}
mtd = &nand_info[nand_curr_device];
nand = mtd->priv;
-
nand->options |= NAND_OWN_BUFFERS;
-
- /* Reset ecc interface */
- nand->ecc.mode = NAND_ECC_NONE;
- nand->ecc.read_page = NULL;
- nand->ecc.write_page = NULL;
- nand->ecc.read_oob = NULL;
- nand->ecc.write_oob = NULL;
- nand->ecc.hwctl = NULL;
- nand->ecc.correct = NULL;
- nand->ecc.calculate = NULL;
- nand->ecc.strength = eccstrength;
-
+ nand->options &= ~NAND_SUBPAGE_READ;
/* Setup the ecc configurations again */
if (hardware) {
if (eccstrength == 1) {
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_nand_oob;
- nand->ecc.size = 512;
- nand->ecc.bytes = 3;
- nand->ecc.hwctl = omap_enable_hwecc;
- nand->ecc.correct = omap_correct_data;
- nand->ecc.calculate = omap_calculate_ecc;
- omap_hwecc_init(nand);
- printf("1-bit hamming HW ECC selected\n");
- }
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
- else if (eccstrength == 8) {
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_bch8_nand_oob;
- nand->ecc.size = 512;
-#ifdef CONFIG_AM33XX
- nand->ecc.bytes = 14;
- nand->ecc.read_page = omap_read_page_bch;
-#else
- nand->ecc.bytes = 13;
-#endif
- nand->ecc.hwctl = omap_enable_ecc_bch;
- nand->ecc.correct = omap_correct_data_bch;
- nand->ecc.calculate = omap_calculate_ecc_bch;
- omap_hwecc_init_bch(nand, NAND_ECC_READ);
- printf("8-bit BCH HW ECC selected\n");
+ err = omap_select_ecc_scheme(nand,
+ OMAP_ECC_HAM1_CODE_HW,
+ mtd->writesize, mtd->oobsize);
+ } else if (eccstrength == 8) {
+ err = omap_select_ecc_scheme(nand,
+ OMAP_ECC_BCH8_CODE_HW,
+ mtd->writesize, mtd->oobsize);
+ } else {
+ printf("nand: error: unsupported ECC scheme\n");
+ return -EINVAL;
}
-#endif
} else {
- nand->ecc.mode = NAND_ECC_SOFT;
- /* Use mtd default settings */
- nand->ecc.layout = NULL;
- nand->ecc.size = 0;
- printf("SW ECC selected\n");
+ err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
+ mtd->writesize, mtd->oobsize);
}
/* Update NAND handling after ECC mode switch */
- nand_scan_tail(mtd);
-
- nand->options &= ~NAND_OWN_BUFFERS;
+ if (!err)
+ err = nand_scan_tail(mtd);
+ return err;
}
#endif /* CONFIG_SPL_BUILD */
int board_nand_init(struct nand_chip *nand)
{
int32_t gpmc_config = 0;
- cs = 0;
-
+ int cs = cs_next++;
+ int err = 0;
/*
* xloader/Uboot's gpmc configuration would have configured GPMC for
* nand type of memory. The following logic scans and latches on to the
cs++;
}
if (cs >= GPMC_MAX_CS) {
- printf("NAND: Unable to find NAND settings in "
+ printf("nand: error: Unable to find NAND settings in "
"GPMC Configuration - quitting\n");
return -ENODEV;
}
nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
-
- nand->cmd_ctrl = omap_nand_hwcontrol;
- nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_NO_SUBPAGE_WRITE;
- /* If we are 16 bit dev, our gpmc config tells us that */
- if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
- nand->options |= NAND_BUSWIDTH_16;
-
+ omap_nand_info[cs].control = NULL;
+ omap_nand_info[cs].cs = cs;
+ nand->priv = &omap_nand_info[cs];
+ nand->cmd_ctrl = omap_nand_hwcontrol;
+ nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
nand->chip_delay = 100;
+ nand->ecc.layout = &omap_ecclayout;
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
-#ifdef CONFIG_AM33XX
- /* AM33xx uses the ELM */
- /* required in case of BCH */
- elm_init();
-#else
- /*
- * Whereas other OMAP based SoC do not have the ELM, they use the BCH
- * SW library.
- */
- bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */);
- if (!bch_priv.control) {
- printf("Failed to initialize BCH engine\n");
- return -ENODEV;
- }
-#endif
- /* BCH info that will be correct for SPL or overridden otherwise. */
- nand->priv = &bch_priv;
-#endif
-
- /* Default ECC mode */
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_bch8_nand_oob;
-#ifdef CONFIG_SYS_GPMC_PREFETCH_ENABLE
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE * 4;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES * 4;
+ /* configure driver and controller based on NAND device bus-width */
+ gpmc_config = readl(&gpmc_cfg->cs[cs].config1);
+#if defined(CONFIG_SYS_NAND_BUSWIDTH_16BIT)
+ nand->options |= NAND_BUSWIDTH_16;
+ writel(gpmc_config | (0x1 << 12), &gpmc_cfg->cs[cs].config1);
#else
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
-#endif
- nand->ecc.strength = 8;
- nand->ecc.hwctl = omap_enable_ecc_bch;
- nand->ecc.correct = omap_correct_data_bch;
- nand->ecc.calculate = omap_calculate_ecc_bch;
-#ifdef CONFIG_AM33XX
- nand->ecc.read_page = omap_read_page_bch;
+ nand->options &= ~NAND_BUSWIDTH_16;
+ writel(gpmc_config & ~(0x1 << 12), &gpmc_cfg->cs[cs].config1);
#endif
- omap_hwecc_init_bch(nand, NAND_ECC_READ);
+ /* select ECC scheme */
+#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
+ err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
+ CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
#else
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
- nand->ecc.mode = NAND_ECC_SOFT;
-#else
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_nand_oob;
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
- nand->ecc.hwctl = omap_enable_hwecc;
- nand->ecc.correct = omap_correct_data;
- nand->ecc.calculate = omap_calculate_ecc;
- nand->ecc.strength = 1;
- omap_hwecc_init(nand);
-#endif
+ /* pagesize and oobsize are not required to configure sw ecc-scheme */
+ err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
+ 0, 0);
#endif
+ if (err)
+ return err;
+ #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
+ if (nand->ecc.layout) {
+ bbt_main_descr.offs = nand->ecc.layout->oobfree[0].offset;
+ bbt_main_descr.veroffs = bbt_main_descr.offs +
+ sizeof(bbt_pattern);
+
+ bbt_mirror_descr.offs = nand->ecc.layout->oobfree[0].offset;
+ bbt_mirror_descr.veroffs = bbt_mirror_descr.offs +
+ sizeof(mirror_pattern);
+ }
+
+ nand->bbt_options |= NAND_BBT_USE_FLASH;
+ nand->bbt_td = &bbt_main_descr;
+ nand->bbt_md = &bbt_mirror_descr;
+ #endif
#ifdef CONFIG_SPL_BUILD
if (nand->options & NAND_BUSWIDTH_16)
nand->read_buf = nand_read_buf16;
else
nand->read_buf = nand_read_buf;
- nand->dev_ready = omap_spl_dev_ready;
-#else
-#ifdef CONFIG_SYS_GPMC_PREFETCH_ENABLE
- nand->write_buf = write_buf_pref;
- nand->read_buf = read_buf_pref;
-#endif /* CONFIG_SYS_GPMC_PREFETCH_ENABLE */
-#endif /* CONFIG_SPL_BUILD */
+#endif
+
+ nand->dev_ready = omap_dev_ready;
return 0;
}
--- /dev/null
++menuconfig NETDEVICES
++ bool "Network device support"
++ depends on NET
++
++if NETDEVICES
++
++config MII
++ bool
++
++config FEC_MXC
++ bool "Freescale FEC ethernet controller"
++ select MII
++
++config GET_FEC_MAC_ADDR_FROM_IIM
++ bool "Read FEC MAC address from fuses"
++ depends on FEC_MXC
++
++if FEC_MXC
++
++config FEC_MXC_MULTI
++ bool "Support multiple ethernet interfaces"
++ depends on MX28 || MX6
++
++config FEC_MXC_PHYADDR
++ int "FEC Ethernet PHY address"
++ default 0
++ depends on !FEC_MXC_MULTI
++
++endif
++
++source "drivers/net/phy/Kconfig"
++
++endif
#include <malloc.h>
#include <net.h>
#include <netdev.h>
- #include <cpsw.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <phy.h>
#include <asm/arch/cpu.h>
#define BITMASK(bits) (BIT(bits) - 1)
+
#define PHY_REG_MASK 0x1f
#define PHY_ID_MASK 0x1f
#define NUM_DESCS (PKTBUFSRX * 2)
#define PKT_MIN 60
#define PKT_MAX (1500 + 14 + 4 + 4)
#define CLEAR_BIT 1
+
+ /* MAC_CONTROL register bits */
#define GIGABITEN BIT(7)
#define FULLDUPLEXEN BIT(0)
+ #define MAC_CTRL_CMD_IDLE BIT(11)
#define MIIEN BIT(15)
+ /* MAC_STATUS register bits */
+ #define MAC_STAT_IDLE BIT(31)
+
/* DMA Registers */
#define CPDMA_TXCONTROL 0x004
#define CPDMA_RXCONTROL 0x014
#define CPDMA_SOFTRESET 0x01c
+ #define CPDMA_DMACONTROL 0x020
+ #define CPDMA_DMASTATUS 0x024
#define CPDMA_RXFREE 0x0e0
#define CPDMA_TXHDP_VER1 0x100
#define CPDMA_TXHDP_VER2 0x200
#define CPDMA_RXCP_VER1 0x160
#define CPDMA_RXCP_VER2 0x260
-#define CPDMA_RAM_ADDR 0x4a102000
-
+ #define DMACONTROL_CMD_IDLE BIT(3)
+
+ #define DMASTATUS_IDLE BIT(31)
+
/* Descriptor mode bits */
#define CPDMA_DESC_SOP BIT(31)
#define CPDMA_DESC_EOP BIT(30)
#define USERACCESS_GO BIT(31)
#define USERACCESS_WRITE BIT(30)
#define USERACCESS_ACK BIT(29)
- #define USERACCESS_READ (0)
- #define USERACCESS_DATA (0xffff)
+ #define USERACCESS_READ 0
+ #define USERACCESS_DATA 0xffff
} user[0];
};
u32 hw_buffer;
u32 hw_len;
u32 hw_mode;
- /* software fields */
- u32 sw_buffer;
- u32 sw_len;
+ } __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+
+ struct cpsw_desc {
+ void *sw_buffer;
+ struct cpsw_desc *next;
+ struct cpdma_desc *dma_desc;
};
struct cpdma_chan {
- struct cpdma_desc *head, *tail;
+ struct cpsw_desc *head, *tail;
void *hdp, *cp, *rxfree;
};
- #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld)
- #define desc_read(desc, fld) __raw_readl(&(desc)->fld)
- #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld))
+ #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->dma_desc->fld)
+ #define desc_read(desc, fld) __raw_readl(&(desc)->dma_desc->fld)
+ #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->dma_desc->fld))
#define chan_write(chan, fld, val) __raw_writel((u32)(val), (chan)->fld)
#define chan_read(chan, fld) __raw_readl((chan)->fld)
#define chan_read_ptr(chan, fld) ((void *)__raw_readl((chan)->fld))
+#define for_active_slave(slave, priv) \
+ slave = (priv)->slaves + (priv)->data.active_slave; if (slave)
#define for_each_slave(slave, priv) \
for (slave = (priv)->slaves; slave != (priv)->slaves + \
- (priv)->data.slaves; slave++)
+ (priv)->data->slaves; slave++)
struct cpsw_priv {
struct eth_device *dev;
- struct cpsw_platform_data data;
+ struct cpsw_platform_data *data;
int host_port;
struct cpsw_regs *regs;
struct cpsw_host_regs *host_port_regs;
void *ale_regs;
- struct cpdma_desc *descs;
- struct cpdma_desc *desc_free;
+ struct cpsw_desc descs[NUM_DESCS];
+ struct cpsw_desc *desc_free;
struct cpdma_chan rx_chan, tx_chan;
struct cpsw_slave *slaves;
struct phy_device *phydev;
struct mii_dev *bus;
- u32 mdio_link;
u32 phy_mask;
};
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
- for (idx = 0; idx < priv->data.ale_entries; idx++) {
+ for (idx = 0; idx < priv->data->ale_entries; idx++) {
u8 entry_addr[6];
cpsw_ale_read(priv, idx, ale_entry);
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
- for (idx = 0; idx < priv->data.ale_entries; idx++) {
+ for (idx = 0; idx < priv->data->ale_entries; idx++) {
cpsw_ale_read(priv, idx, ale_entry);
type = cpsw_ale_get_entry_type(ale_entry);
if (type == ALE_TYPE_FREE)
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
- for (idx = 0; idx < priv->data.ale_entries; idx++) {
+ for (idx = 0; idx < priv->data->ale_entries; idx++) {
cpsw_ale_read(priv, idx, ale_entry);
type = cpsw_ale_get_entry_type(ale_entry);
if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
/* wait until hardware is ready for another user access */
static inline u32 wait_for_user_access(void)
{
- u32 reg = 0;
int timeout = MDIO_TIMEOUT;
+ u32 reg;
- while (timeout-- &&
- ((reg = __raw_readl(&mdio_regs->user[0].access)) & USERACCESS_GO))
- udelay(10);
-
- if (timeout == -1) {
- printf("wait_for_user_access Timeout\n");
- return -ETIMEDOUT;
+ while ((reg = __raw_readl(&mdio_regs->user[0].access)) & USERACCESS_GO) {
+ udelay(1000);
+ if (--timeout <= 0) {
+ printf("TIMEOUT waiting for USERACCESS_GO\n");
+ break;
+ }
}
+
return reg;
}
{
int timeout = MDIO_TIMEOUT;
- while (timeout-- &&
- ((__raw_readl(&mdio_regs->control) & CONTROL_IDLE) == 0))
- udelay(10);
-
- if (timeout == -1)
- printf("wait_for_idle Timeout\n");
+ while ((__raw_readl(&mdio_regs->control) & CONTROL_IDLE) == 0) {
+ if (--timeout <= 0) {
+ printf("TIMEOUT waiting for state machine idle\n");
+ break;
+ }
+ udelay(1000);
+ }
}
static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
int dev_addr, int phy_reg)
{
- unsigned short data;
+ int data;
u32 reg;
if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
return -EINVAL;
- wait_for_user_access();
+ if (wait_for_user_access() & USERACCESS_GO)
+ /* promote error from previous access */
+ return -ETIME;
+
reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
(phy_id << 16));
__raw_writel(reg, &mdio_regs->user[0].access);
reg = wait_for_user_access();
+ if (reg & USERACCESS_GO)
+ return -ETIME;
data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
return data;
if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
return -EINVAL;
- wait_for_user_access();
+ if (wait_for_user_access() & USERACCESS_GO)
+ /* promote error from previous access */
+ return -ETIME;
+
reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
(phy_id << 16) | (data & USERACCESS_DATA));
__raw_writel(reg, &mdio_regs->user[0].access);
- wait_for_user_access();
+ if (wait_for_user_access() & USERACCESS_GO)
+ return -ETIME;
return 0;
}
/* Set a self-clearing bit in a register, and wait for it to clear */
static inline void setbit_and_wait_for_clear32(void *addr)
{
+ int loops = 0;
+
__raw_writel(CLEAR_BIT, addr);
while (__raw_readl(addr) & CLEAR_BIT)
- ;
+ loops++;
+ debug("%s: reset finished after %u loops\n", __func__, loops);
}
#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
__raw_writel(mac_lo(priv->dev->enetaddr), &slave->regs->sa_lo);
}
+ #define NUM_TRIES 50
static void cpsw_slave_update_link(struct cpsw_slave *slave,
struct cpsw_priv *priv, int *link)
{
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy;
u32 mac_control = 0;
-
- phy = priv->phydev;
-
- if (!phy)
- return;
-
- phy_startup(phy);
- *link = phy->link;
-
- if (*link) { /* link up */
- mac_control = priv->data.mac_control;
- if (phy->speed == 1000)
- mac_control |= GIGABITEN;
- if (phy->duplex == DUPLEX_FULL)
- mac_control |= FULLDUPLEXEN;
- if (phy->speed == 100)
- mac_control |= MIIEN;
- }
+ int retries = NUM_TRIES;
+
+ do {
+ phy_startup(phy);
+ *link = phy->link;
+
+ if (*link) { /* link up */
+ mac_control = priv->data->mac_control;
+ if (phy->speed == 1000)
+ mac_control |= GIGABITEN;
+ if (phy->duplex == DUPLEX_FULL)
+ mac_control |= FULLDUPLEXEN;
+ if (phy->speed == 100)
+ mac_control |= MIIEN;
+ } else {
+ udelay(10000);
+ }
+ } while (!*link && retries-- > 0);
+ debug("%s: mac_control: %08x -> %08x after %u loops\n", __func__,
+ slave->mac_control, mac_control, NUM_TRIES - retries);
if (mac_control == slave->mac_control)
return;
int link = 0;
struct cpsw_slave *slave;
- for_each_slave(slave, priv)
+ for_active_slave(slave, priv)
cpsw_slave_update_link(slave, priv, &link);
- priv->mdio_link = readl(&mdio_regs->link);
- return link;
-}
-
-static int cpsw_check_link(struct cpsw_priv *priv)
-{
- u32 link;
-
- link = __raw_readl(&mdio_regs->link) & priv->phy_mask;
- if (link && (link == priv->mdio_link))
- return 1;
- return cpsw_update_link(priv);
+ return link;
}
static inline u32 cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
{
u32 slave_port;
+ debug("%s\n", __func__);
setbit_and_wait_for_clear32(&slave->sliver->soft_reset);
/* setup priority mapping */
cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave_port);
- priv->phy_mask |= 1 << slave->data->phy_id;
+ priv->phy_mask |= 1 << slave->data->phy_addr;
}
- static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
+ static void cpdma_desc_get(struct cpsw_desc *desc)
+ {
+ invalidate_dcache_range((u32)desc->dma_desc, (u32)(&desc->dma_desc[1]));
+ }
+
+ static void cpdma_desc_put(struct cpsw_desc *desc)
+ {
+ flush_dcache_range((u32)desc->dma_desc, (u32)(&desc->dma_desc[1]));
+ }
+
+ static struct cpsw_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
{
- struct cpdma_desc *desc = priv->desc_free;
+ struct cpsw_desc *desc = priv->desc_free;
- if (desc)
- priv->desc_free = desc_read_ptr(desc, hw_next);
+ if (desc) {
+ cpdma_desc_get(desc);
+ priv->desc_free = desc->next;
+ }
return desc;
}
- static void cpdma_desc_free(struct cpsw_priv *priv, struct cpdma_desc *desc)
+ static void cpdma_desc_free(struct cpsw_priv *priv, struct cpsw_desc *desc)
{
if (desc) {
- desc_write(desc, hw_next, priv->desc_free);
+ desc_write(desc, hw_next, priv->desc_free->dma_desc);
+ cpdma_desc_put(desc);
+ desc->next = priv->desc_free;
priv->desc_free = desc;
}
}
static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
void *buffer, int len)
{
- struct cpdma_desc *desc, *prev;
+ struct cpsw_desc *desc, *prev;
u32 mode;
+ if (!buffer) {
+ printf("ERROR: %s() NULL buffer\n", __func__);
+ return -EINVAL;
+ }
+
+ flush_dcache_range((u32)buffer, (u32)buffer + len);
+
desc = cpdma_desc_alloc(priv);
if (!desc)
return -ENOMEM;
+ debug("%s@%d: %cX desc %p DMA %p\n", __func__, __LINE__,
+ chan == &priv->rx_chan ? 'R' : 'T', desc, desc->dma_desc);
if (len < PKT_MIN)
len = PKT_MIN;
mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+ desc->next = NULL;
desc_write(desc, hw_next, 0);
desc_write(desc, hw_buffer, buffer);
desc_write(desc, hw_len, len);
desc_write(desc, hw_mode, mode | len);
- desc_write(desc, sw_buffer, buffer);
- desc_write(desc, sw_len, len);
+ desc->sw_buffer = buffer;
+
+ cpdma_desc_put(desc);
if (!chan->head) {
/* simple case - first packet enqueued */
chan->head = desc;
chan->tail = desc;
- chan_write(chan, hdp, desc);
+ chan_write(chan, hdp, desc->dma_desc);
goto done;
}
/* not the first packet - enqueue at the tail */
prev = chan->tail;
- desc_write(prev, hw_next, desc);
+
+ prev->next = desc;
+ cpdma_desc_get(prev);
+ desc_write(prev, hw_next, desc->dma_desc);
+ cpdma_desc_put(prev);
+
chan->tail = desc;
/* next check if EOQ has been triggered already */
if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ)
- chan_write(chan, hdp, desc);
+ chan_write(chan, hdp, desc->dma_desc);
done:
if (chan->rxfree)
chan_write(chan, rxfree, 1);
+ debug("%s@%d\n", __func__, __LINE__);
return 0;
}
static int cpdma_process(struct cpsw_priv *priv, struct cpdma_chan *chan,
void **buffer, int *len)
{
- struct cpdma_desc *desc = chan->head;
+ struct cpsw_desc *desc = chan->head;
u32 status;
if (!desc)
return -ENOENT;
+ cpdma_desc_get(desc);
+
status = desc_read(desc, hw_mode);
+ if (status & CPDMA_DESC_OWNER)
+ return -EBUSY;
if (len)
*len = status & 0x7ff;
if (buffer)
- *buffer = desc_read_ptr(desc, sw_buffer);
-
- if (status & CPDMA_DESC_OWNER) {
- if (chan_read(chan, hdp) == 0) {
- if (desc_read(desc, hw_mode) & CPDMA_DESC_OWNER)
- chan_write(chan, hdp, desc);
- }
-
- return -EBUSY;
- }
+ *buffer = desc->sw_buffer;
+ debug("%s@%d: buffer=%p\n", __func__, __LINE__, desc->sw_buffer);
- chan->head = desc_read_ptr(desc, hw_next);
- chan_write(chan, cp, desc);
+ chan->head = desc->next;
+ chan_write(chan, cp, desc->dma_desc);
cpdma_desc_free(priv, desc);
return 0;
struct cpsw_slave *slave;
int i, ret;
+ debug("%s\n", __func__);
/* soft reset the controller and initialize priv */
setbit_and_wait_for_clear32(&priv->regs->soft_reset);
/* enable statistics collection only on the host port */
__raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
+ __raw_writel(0x7, &priv->regs->stat_port_en);
cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
ALE_SECURE);
cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << priv->host_port);
- for_each_slave(slave, priv)
+ for_active_slave(slave, priv)
cpsw_slave_init(slave, priv);
cpsw_update_link(priv);
/* init descriptor pool */
for (i = 0; i < NUM_DESCS; i++) {
+ struct cpsw_desc *next_desc = (i < (NUM_DESCS - 1)) ?
+ &priv->descs[i + 1] : NULL;
+
+ priv->descs[i].next = next_desc;
desc_write(&priv->descs[i], hw_next,
- (i == (NUM_DESCS - 1)) ? 0 : &priv->descs[i+1]);
+ next_desc ? next_desc->dma_desc : 0);
+ cpdma_desc_put(&priv->descs[i]);
}
priv->desc_free = &priv->descs[0];
/* initialize channels */
- if (priv->data.version == CPSW_CTRL_VERSION_2) {
+ if (priv->data->version == CPSW_CTRL_VERSION_2) {
memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
- priv->rx_chan.hdp = priv->dma_regs + CPDMA_RXHDP_VER2;
- priv->rx_chan.cp = priv->dma_regs + CPDMA_RXCP_VER2;
- priv->rx_chan.rxfree = priv->dma_regs + CPDMA_RXFREE;
+ priv->rx_chan.hdp = priv->dma_regs + CPDMA_RXHDP_VER2;
+ priv->rx_chan.cp = priv->dma_regs + CPDMA_RXCP_VER2;
+ priv->rx_chan.rxfree = priv->dma_regs + CPDMA_RXFREE;
memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
- priv->tx_chan.hdp = priv->dma_regs + CPDMA_TXHDP_VER2;
- priv->tx_chan.cp = priv->dma_regs + CPDMA_TXCP_VER2;
+ priv->tx_chan.hdp = priv->dma_regs + CPDMA_TXHDP_VER2;
+ priv->tx_chan.cp = priv->dma_regs + CPDMA_TXCP_VER2;
} else {
memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
- priv->rx_chan.hdp = priv->dma_regs + CPDMA_RXHDP_VER1;
- priv->rx_chan.cp = priv->dma_regs + CPDMA_RXCP_VER1;
- priv->rx_chan.rxfree = priv->dma_regs + CPDMA_RXFREE;
+ priv->rx_chan.hdp = priv->dma_regs + CPDMA_RXHDP_VER1;
+ priv->rx_chan.cp = priv->dma_regs + CPDMA_RXCP_VER1;
+ priv->rx_chan.rxfree = priv->dma_regs + CPDMA_RXFREE;
memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
- priv->tx_chan.hdp = priv->dma_regs + CPDMA_TXHDP_VER1;
- priv->tx_chan.cp = priv->dma_regs + CPDMA_TXCP_VER1;
+ priv->tx_chan.hdp = priv->dma_regs + CPDMA_TXHDP_VER1;
+ priv->tx_chan.cp = priv->dma_regs + CPDMA_TXCP_VER1;
}
/* clear dma state */
setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
- if (priv->data.version == CPSW_CTRL_VERSION_2) {
- for (i = 0; i < priv->data.channels; i++) {
- __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER2 + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER2 + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER2 + 4
- * i);
+ if (priv->data->version == CPSW_CTRL_VERSION_2) {
+ for (i = 0; i < priv->data->channels; i++) {
+ __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER2 + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER2 + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER2 + 4 * i);
}
} else {
- for (i = 0; i < priv->data.channels; i++) {
- __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER1 + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER1 + 4
- * i);
- __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER1 + 4
- * i);
+ for (i = 0; i < priv->data->channels; i++) {
+ __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER1 + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER1 + 4 * i);
+ __raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER1 + 4 * i);
}
}
}
}
- return 0;
+ return ret;
}
static void cpsw_halt(struct eth_device *dev)
{
struct cpsw_priv *priv = dev->priv;
+ struct cpsw_slave *slave;
+ int idle = 0;
+ int timeout = 1000000;
+
+ __raw_writel(DMACONTROL_CMD_IDLE, priv->dma_regs + CPDMA_DMACONTROL);
+ while (!(__raw_readl(priv->dma_regs + CPDMA_DMASTATUS) &
+ DMASTATUS_IDLE) && (--timeout >= 0))
+ udelay(1);
+
+ timeout = 1000000;
+ while (!idle) {
+ idle = 1;
+ for_each_slave(slave, priv) {
+ if (!(__raw_readl(&slave->sliver->mac_status) &
+ MAC_STAT_IDLE)) {
+ idle = 0;
+ break;
+ }
+ }
+ if (idle || --timeout < 0)
+ break;
+ udelay(1);
+ }
+ if (!idle)
+ printf("CPSW: Aborting DMA transfers; packets may be lost\n");
writel(0, priv->dma_regs + CPDMA_TXCONTROL);
writel(0, priv->dma_regs + CPDMA_RXCONTROL);
/* clear dma state */
setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
- priv->data.control(0);
+ debug("%s\n", __func__);
+ priv->data->control(0);
}
static int cpsw_send(struct eth_device *dev, void *packet, int length)
{
- struct cpsw_priv *priv = dev->priv;
+ struct cpsw_priv *priv = dev->priv;
void *buffer;
int len;
- int timeout = CPDMA_TIMEOUT;
- flush_dcache_range((unsigned long)packet,
- (unsigned long)packet + length);
- if (!priv->data->mac_control && !cpsw_check_link(priv)) {
- printf("%s: Cannot send packet; link is down\n", __func__);
- return -EIO;
- }
/* first reap completed packets */
- while (timeout-- &&
- (cpdma_process(priv, &priv->tx_chan, &buffer, &len) >= 0))
- ;
-
- if (timeout == -1) {
- printf("cpdma_process timeout\n");
- return -ETIMEDOUT;
- }
+ while (cpdma_process(priv, &priv->tx_chan, &buffer, &len) == 0)
+ /* NOP */;
return cpdma_submit(priv, &priv->tx_chan, packet, length);
}
void *buffer;
int len;
- while (cpdma_process(priv, &priv->rx_chan, &buffer, &len) >= 0) {
- invalidate_dcache_range((unsigned long)buffer,
- (unsigned long)buffer + PKTSIZE_ALIGN);
- NetReceive(buffer, len);
- cpdma_submit(priv, &priv->rx_chan, buffer, PKTSIZE);
+ while (cpdma_process(priv, &priv->rx_chan, &buffer, &len) == 0) {
+ if (buffer) {
+ NetReceive(buffer, len);
+ cpdma_submit(priv, &priv->rx_chan, buffer, PKTSIZE);
+ } else {
+ printf("NULL buffer returned from cpdma_process\n");
+ return -EIO;
+ }
}
return 0;
struct cpsw_priv *priv)
{
void *regs = priv->regs;
- struct cpsw_slave_data *data = priv->data.slave_data + slave_num;
+ struct cpsw_slave_data *data = priv->data->slave_data + slave_num;
+
+ debug("%s@%d: slave[%d] %p\n", __func__, __LINE__,
+ slave_num, slave);
slave->slave_num = slave_num;
slave->data = data;
slave->regs = regs + data->slave_reg_ofs;
{
struct cpsw_priv *priv = (struct cpsw_priv *)dev->priv;
struct phy_device *phydev;
- u32 supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full);
+ u32 supported = PHY_GBIT_FEATURES;
- phydev = phy_connect(priv->bus,
- slave->data->phy_addr,
- dev,
- slave->data->phy_if);
+ if (slave->data->phy_id < 0) {
+ u32 phy_addr;
+
+ for (phy_addr = 0; phy_addr < 32; phy_addr++) {
+ debug("Trying to connect to PHY @ addr %02x\n",
+ phy_addr);
+ phydev = phy_connect(priv->bus, phy_addr,
+ dev, slave->data->phy_if);
+ if (phydev)
+ break;
+ }
+ } else {
+ phydev = phy_connect(priv->bus,
+ slave->data->phy_id,
+ dev,
+ slave->data->phy_if);
+ }
+ if (!phydev) {
+ printf("Failed to connect to PHY\n");
+ return -EINVAL;
+ }
+ if (!phydev)
+ return -1;
+
phydev->supported &= supported;
phydev->advertising = phydev->supported;
priv->phydev = phydev;
phy_config(phydev);
- return 1;
+ return 0;
}
int cpsw_register(struct cpsw_platform_data *data)
{
+ int ret = 1;
struct cpsw_priv *priv;
struct cpsw_slave *slave;
void *regs = (void *)data->cpsw_base;
struct eth_device *dev;
+ int i;
+ int idx = 0;
+
+ debug("%s@%d\n", __func__, __LINE__);
dev = calloc(sizeof(*dev), 1);
if (!dev)
return -ENOMEM;
}
- priv->data = *data;
+ priv->data = data;
priv->dev = dev;
- priv->slaves = malloc(sizeof(struct cpsw_slave) * data->slaves);
+ priv->slaves = calloc(sizeof(struct cpsw_slave), data->slaves);
if (!priv->slaves) {
free(dev);
free(priv);
return -ENOMEM;
}
- for (i = 0; i < NUM_DESCS; i++) {
- priv->descs[i].dma_desc = memalign(CONFIG_SYS_CACHELINE_SIZE,
- sizeof(struct cpsw_desc) * NUM_DESCS);
- if (!priv->descs[i].dma_desc) {
- while (--i >= 0) {
- free(priv->descs[i].dma_desc);
- }
- free(priv->slaves);
- free(priv);
- free(dev);
- return -ENOMEM;
- }
- debug("DMA desc[%d] allocated @ %p desc_size %u\n",
- i, priv->descs[i].dma_desc,
- sizeof(*priv->descs[i].dma_desc));
- }
-
priv->host_port = data->host_port_num;
priv->regs = regs;
priv->host_port_regs = regs + data->host_port_reg_ofs;
priv->dma_regs = regs + data->cpdma_reg_ofs;
priv->ale_regs = regs + data->ale_reg_ofs;
+ priv->descs = (void *)regs + data->bd_ram_ofs;
- int idx = 0;
-
for_each_slave(slave, priv) {
cpsw_slave_setup(slave, idx, priv);
idx = idx + 1;
cpsw_mdio_init(dev->name, data->mdio_base, data->mdio_div);
priv->bus = miiphy_get_dev_by_name(dev->name);
- for_active_slave(slave, priv)
- cpsw_phy_init(dev, slave);
-
- return 1;
- for_each_slave(slave, priv) {
++ for_active_slave(slave, priv) {
+ ret = cpsw_phy_init(dev, slave);
+ if (ret < 0)
+ break;
+ }
+ return ret;
}
#include <common.h>
#include <malloc.h>
#include <net.h>
+#include <netdev.h>
#include <miiphy.h>
- #include "fec_mxc.h"
+ #include <asm/arch/sys_proto.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <linux/compiler.h>
+ #include "fec_mxc.h"
+
DECLARE_GLOBAL_DATA_PTR;
/*
*/
#define FEC_XFER_TIMEOUT 5000
+/*
+ * The standard 32-byte DMA alignment does not work on mx6solox, which requires
+ * 64-byte alignment in the DMA RX FEC buffer.
+ * Introduce the FEC_DMA_RX_MINALIGN which can cover mx6solox needs and also
+ * satisfies the alignment on other SoCs (32-bytes)
+ */
+#define FEC_DMA_RX_MINALIGN 64
+
#ifndef CONFIG_MII
#error "CONFIG_MII has to be defined!"
#endif
uint8_t head[16]; /**< MAC header(6 + 6 + 2) + 2(aligned) */
};
+ static int rx_idx;
+
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
static void swap_packet(uint32_t *packet, int length)
{
{
uint32_t reg; /* convenient holder for the PHY register */
uint32_t phy; /* convenient holder for the PHY */
- uint32_t start;
+ ulong start;
int val;
/*
start = get_timer(0);
while (!(readl(ð->ievent) & FEC_IEVENT_MII)) {
if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+ if (readl(ð->ievent) & FEC_IEVENT_MII)
+ break;
printf("Read MDIO failed...\n");
return -1;
}
* it's now safe to read the PHY's register
*/
val = (unsigned short)readl(ð->mii_data);
- debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,
+ debug("%s: phy: %02x reg:%02x val:%#06x\n", __func__, phyAddr,
regAddr, val);
return val;
}
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
- writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1,
- ð->mii_speed);
+ register u32 speed = DIV_ROUND_UP(imx_get_fecclk(), 5000000);
+#ifdef FEC_QUIRK_ENET_MAC
+ speed--;
+#endif
+ speed <<= 1;
+ writel(speed, ð->mii_speed);
debug("%s: mii_speed %08x\n", __func__, readl(ð->mii_speed));
}
{
uint32_t reg; /* convenient holder for the PHY register */
uint32_t phy; /* convenient holder for the PHY */
- uint32_t start;
+ ulong start;
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
start = get_timer(0);
while (!(readl(ð->ievent) & FEC_IEVENT_MII)) {
if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+ if (readl(ð->ievent) & FEC_IEVENT_MII)
+ break;
printf("Write MDIO failed...\n");
return -1;
}
* clear MII interrupt bit
*/
writel(FEC_IEVENT_MII, ð->ievent);
- debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,
+ debug("%s: phy: %02x reg:%02x val:%#06x\n", __func__, phyAddr,
regAddr, data);
return 0;
}
-int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
+static int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr,
+ int regAddr)
{
return fec_mdio_read(bus->priv, phyAddr, regAddr);
}
-int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
- u16 data)
+static int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr,
+ int regAddr, u16 data)
{
return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
}
}
#endif
- static int fec_rx_task_enable(struct fec_priv *fec)
+ static inline void fec_rx_task_enable(struct fec_priv *fec)
{
- writel(FEC_R_DES_ACTIVE_RDAR, &fec->eth->r_des_active);
- return 0;
+ writel(1 << 24, &fec->eth->r_des_active);
}
- static int fec_rx_task_disable(struct fec_priv *fec)
+ static inline void fec_rx_task_disable(struct fec_priv *fec)
{
- return 0;
}
- static int fec_tx_task_enable(struct fec_priv *fec)
+ static inline void fec_tx_task_enable(struct fec_priv *fec)
{
- writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->x_des_active);
- return 0;
+ writel(1 << 24, &fec->eth->x_des_active);
}
- static int fec_tx_task_disable(struct fec_priv *fec)
+ static inline void fec_tx_task_disable(struct fec_priv *fec)
{
- return 0;
}
/**
* @param[in] dsize desired size of each receive buffer
* @return 0 on success
*
- * For this task we need additional memory for the data buffers. And each
- * data buffer requires some alignment. Thy must be aligned to a specific
- * boundary each.
+ * Init all RX descriptors to default values.
*/
-static int fec_rbd_init(struct fec_priv *fec, int count, int dsize)
+static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
{
uint32_t size;
+ uint8_t *data;
int i;
/*
- * Allocate memory for the buffers. This allocation respects the
- * alignment
+ * Reload the RX descriptors with default values and wipe
+ * the RX buffers.
*/
size = roundup(dsize, ARCH_DMA_MINALIGN);
for (i = 0; i < count; i++) {
- uint32_t data_ptr = readl(&fec->rbd_base[i].data_pointer);
- if (data_ptr == 0) {
- uint8_t *data = memalign(ARCH_DMA_MINALIGN,
- size);
- if (!data) {
- printf("%s: error allocating rxbuf %d\n",
- __func__, i);
- goto err;
- }
- writel((uint32_t)data, &fec->rbd_base[i].data_pointer);
- } /* needs allocation */
- writew(FEC_RBD_EMPTY, &fec->rbd_base[i].status);
- writew(0, &fec->rbd_base[i].data_length);
+ data = (uint8_t *)fec->rbd_base[i].data_pointer;
+ memset(data, 0, dsize);
+ flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+
+ fec->rbd_base[i].status = FEC_RBD_EMPTY;
+ fec->rbd_base[i].data_length = 0;
}
/* Mark the last RBD to close the ring. */
- writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[i - 1].status);
+ fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
fec->rbd_index = 0;
- return 0;
-
-err:
- for (; i >= 0; i--) {
- uint32_t data_ptr = readl(&fec->rbd_base[i].data_pointer);
- free((void *)data_ptr);
- }
-
- return -ENOMEM;
+ flush_dcache_range((unsigned)fec->rbd_base,
+ (unsigned)fec->rbd_base + size);
}
/**
unsigned addr = (unsigned)fec->tbd_base;
unsigned size = roundup(2 * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
- writew(0x0000, &fec->tbd_base[0].status);
- writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
+
+ memset(fec->tbd_base, 0, size);
+ fec->tbd_base[0].status = 0;
+ fec->tbd_base[1].status = FEC_TBD_WRAP;
fec->tbd_index = 0;
flush_dcache_range(addr, addr + size);
}
*/
static int fec_open(struct eth_device *edev)
{
- struct fec_priv *fec = (struct fec_priv *)edev->priv;
+ struct fec_priv *fec = edev->priv;
int speed;
uint32_t addr, size;
int i;
*/
writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
&fec->eth->ecntrl);
-#if defined(CONFIG_MX25) || defined(CONFIG_MX53)
+#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
udelay(100);
/*
* setup the MII gasket for RMII mode
{
u32 ecr = readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_SPEED;
u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T;
+
if (speed == _1000BASET)
ecr |= FEC_ECNTRL_SPEED;
else if (speed != _100BASET)
writel(ecr, &fec->eth->ecntrl);
writel(rcr, &fec->eth->r_cntrl);
}
+ #elif defined(CONFIG_MX28)
+ {
+ u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T;
+
+ if (speed == _10BASET)
+ rcr |= FEC_RCNTRL_RMII_10T;
+ writel(rcr, &fec->eth->r_cntrl);
+ }
#endif
debug("%s:Speed=%i\n", __func__, speed);
*/
fec_rx_task_enable(fec);
- udelay(100000);
+ // udelay(100000);
return 0;
}
static int fec_init(struct eth_device *dev, bd_t* bd)
{
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
- uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
+ struct fec_priv *fec = dev->priv;
+ uint32_t *mib_ptr = (uint32_t *)&fec->eth->rmon_t_drop;
- uint32_t size;
- int i, ret;
+ int i;
/* Initialize MAC address */
fec_set_hwaddr(dev);
/*
- * Allocate transmit descriptors, there are two in total. This
- * allocation respects cache alignment.
+ * Setup transmit descriptors, there are two in total.
*/
- if (!fec->tbd_base) {
- size = roundup(2 * sizeof(struct fec_bd),
- ARCH_DMA_MINALIGN);
- fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
- if (!fec->tbd_base) {
- ret = -ENOMEM;
- goto err1;
- }
- memset(fec->tbd_base, 0, size);
- fec_tbd_init(fec);
- }
+ fec_tbd_init(fec);
- /*
- * Allocate receive descriptors. This allocation respects cache
- * alignment.
- */
- if (!fec->rbd_base) {
- size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd),
- ARCH_DMA_MINALIGN);
- fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
- if (!fec->rbd_base) {
- ret = -ENOMEM;
- goto err2;
- }
- memset(fec->rbd_base, 0, size);
- /*
- * Initialize RxBD ring
- */
- if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
- ret = -ENOMEM;
- goto err3;
- }
- flush_dcache_range((unsigned)fec->rbd_base,
- (unsigned)fec->rbd_base + size);
- }
+ /* Setup receive descriptors. */
+ fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
fec_reg_setup(fec);
/* clear MIB RAM */
- for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
- writel(0, i);
+ for (i = 0; i <= 0xfc >> 2; i++)
+ writel(0, &mib_ptr[i]);
/* FIFO receive start register */
writel(0x520, &fec->eth->r_fstart);
#endif
fec_open(dev);
return 0;
-
-err3:
- free(fec->rbd_base);
-err2:
- free(fec->tbd_base);
-err1:
- return ret;
}
/**
static void fec_halt(struct eth_device *dev)
{
struct fec_priv *fec = (struct fec_priv *)dev->priv;
- int counter = 0xffff;
+ int counter = 1000;
/*
* issue graceful stop command to the FEC transmitter if necessary
* wait for graceful stop to register
*/
while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
- udelay(1);
+ udelay(100);
/*
* Disable SmartDMA tasks
* This routine transmits one frame. This routine only accepts
* 6-byte Ethernet addresses.
*/
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct fec_priv *fec = dev->priv;
/*
* Check for valid length of data.
flush_dcache_range(addr, end);
writew(length, &fec->tbd_base[fec->tbd_index].data_length);
- writel(addr, &fec->tbd_base[fec->tbd_index].data_pointer);
+ writel((unsigned long)packet,
+ &fec->tbd_base[fec->tbd_index].data_pointer);
/*
* update BD's status now
* This block:
* - is always the last in a chain (means no chain)
- * - should transmitt the CRC
+ * - should transmit the CRC
* - might be the last BD in the list, so the address counter should
* wrap (-> keep the WRAP flag)
*/
break;
}
- if (!timeout)
+ if (!timeout) {
ret = -EINVAL;
+ goto out;
+ }
- invalidate_dcache_range(addr, addr + size);
- if (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY)
+ /*
+ * The TDAR bit is cleared when the descriptors are all out from TX
+ * but on mx6solox we noticed that the READY bit is still not cleared
+ * right after TDAR.
+ * These are two distinct signals, and in IC simulation, we found that
+ * TDAR always gets cleared prior than the READY bit of last BD becomes
+ * cleared.
+ * In mx6solox, we use a later version of FEC IP. It looks like that
+ * this intrinsic behaviour of TDAR bit has changed in this newer FEC
+ * version.
+ *
+ * Fix this by polling the READY bit of BD after the TDAR polling,
+ * which covers the mx6solox case and does not harm the other SoCs.
+ */
+ timeout = FEC_XFER_TIMEOUT;
+ while (--timeout) {
+ invalidate_dcache_range(addr, addr + size);
+ if (!(readw(&fec->tbd_base[fec->tbd_index].status) &
+ FEC_TBD_READY))
+ break;
+ }
+
+ if (!timeout)
ret = -EINVAL;
+out:
debug("fec_send: status 0x%x index %d ret %i\n",
readw(&fec->tbd_base[fec->tbd_index].status),
fec->tbd_index, ret);
uint16_t bd_status;
uint32_t addr, size, end;
int i;
- ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
/*
* Check if any critical events have happened
*/
ievent = readl(&fec->eth->ievent);
- writel(ievent, &fec->eth->ievent);
- debug("fec_recv: ievent 0x%lx\n", ievent);
+ if (ievent)
+ writel(ievent, &fec->eth->ievent);
+
+ if (ievent)
+ debug("fec_recv: ievent 0x%lx\n", ievent);
if (ievent & FEC_IEVENT_BABR) {
fec_halt(dev);
fec_init(dev, fec->bd);
invalidate_dcache_range(addr, addr + size);
bd_status = readw(&rbd->status);
- debug("fec_recv: status 0x%x\n", bd_status);
-
if (!(bd_status & FEC_RBD_EMPTY)) {
+ debug("fec_recv: status 0x%04x len %u\n", bd_status,
+ readw(&rbd->data_length) - 4);
if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
((readw(&rbd->data_length) - 4) > 14)) {
/*
*/
frame = (struct nbuf *)readl(&rbd->data_pointer);
frame_length = readw(&rbd->data_length) - 4;
+
/*
* Invalidate data cache over the buffer
*/
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
swap_packet((uint32_t *)frame->data, frame_length);
#endif
- memcpy(buff, frame->data, frame_length);
- NetReceive(buff, frame_length);
+ memcpy((void *)NetRxPackets[rx_idx], frame->data, frame_length);
+ NetReceive(NetRxPackets[rx_idx], frame_length);
+ rx_idx = (rx_idx + 1) % PKTBUFSRX;
len = frame_length;
} else {
if (bd_status & FEC_RBD_ERR)
fec_rx_task_enable(fec);
fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
+ debug("fec_recv: stop\n");
}
- debug("fec_recv: stop\n");
return len;
}
sprintf(dest, (dev_id == -1) ? "FEC" : "FEC%i", dev_id);
}
+static int fec_alloc_descs(struct fec_priv *fec)
+{
+ unsigned int size;
+ int i;
+ uint8_t *data;
+
+ /* Allocate TX descriptors. */
+ size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+ fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
+ if (!fec->tbd_base)
+ goto err_tx;
+
+ /* Allocate RX descriptors. */
+ size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+ fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
+ if (!fec->rbd_base)
+ goto err_rx;
+
+ memset(fec->rbd_base, 0, size);
+
+ /* Allocate RX buffers. */
+
+ /* Maximum RX buffer size. */
+ size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
+ for (i = 0; i < FEC_RBD_NUM; i++) {
+ data = memalign(FEC_DMA_RX_MINALIGN, size);
+ if (!data) {
+ printf("%s: error allocating rxbuf %d\n", __func__, i);
+ goto err_ring;
+ }
+
+ memset(data, 0, size);
+
+ fec->rbd_base[i].data_pointer = (uint32_t)data;
+ fec->rbd_base[i].status = FEC_RBD_EMPTY;
+ fec->rbd_base[i].data_length = 0;
+ /* Flush the buffer to memory. */
+ flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ }
+
+ /* Mark the last RBD to close the ring. */
+ fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
+
+ fec->rbd_index = 0;
+ fec->tbd_index = 0;
+
+ return 0;
+
+err_ring:
+ for (; i >= 0; i--)
+ free((void *)fec->rbd_base[i].data_pointer);
+ free(fec->rbd_base);
+err_rx:
+ free(fec->tbd_base);
+err_tx:
+ return -ENOMEM;
+}
+
+static void fec_free_descs(struct fec_priv *fec)
+{
+ int i;
+
+ for (i = 0; i < FEC_RBD_NUM; i++)
+ free((void *)fec->rbd_base[i].data_pointer);
+ free(fec->rbd_base);
+ free(fec->tbd_base);
+}
+
#ifdef CONFIG_PHYLIB
int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
struct mii_dev *bus, struct phy_device *phydev)
int ret = 0;
/* create and fill edev struct */
- edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+ edev = calloc(sizeof(struct eth_device), 1);
if (!edev) {
puts("fec_mxc: not enough malloc memory for eth_device\n");
ret = -ENOMEM;
goto err1;
}
- fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
+ fec = calloc(sizeof(struct fec_priv), 1);
if (!fec) {
puts("fec_mxc: not enough malloc memory for fec_priv\n");
ret = -ENOMEM;
goto err2;
}
- memset(edev, 0, sizeof(*edev));
- memset(fec, 0, sizeof(*fec));
-
+ ret = fec_alloc_descs(fec);
+ if (ret)
+ goto err3;
+
edev->priv = fec;
edev->init = fec_init;
edev->send = fec_send;
while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
printf("FEC MXC: Timeout reseting chip\n");
- goto err3;
+ goto err4;
}
udelay(10);
}
eth_register(edev);
if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
- debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
+ if (dev_id < 0)
+ debug("got MAC address from fuse: %pM\n", ethaddr);
+ else
+ debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
memcpy(edev->enetaddr, ethaddr, 6);
+ if (!getenv("ethaddr"))
+ eth_setenv_enetaddr("ethaddr", ethaddr);
}
return ret;
+err4:
+ fec_free_descs(fec);
err3:
free(fec);
err2:
#ifndef __FEC_MXC_H
#define __FEC_MXC_H
- void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
-
/**
* Layout description of the FEC
*/
uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */
-#if defined(CONFIG_MX25) || defined(CONFIG_MX53)
+#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */
uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */
uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */
#define FEC_X_DES_ACTIVE_TDAR 0x01000000
#define FEC_R_DES_ACTIVE_RDAR 0x01000000
-#if defined(CONFIG_MX25) || defined(CONFIG_MX53)
+#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
/* defines for MIIGSK */
/* RMII frequency control: 0=50MHz, 1=5MHz */
#define MIIGSK_CFGR_FRCONT (1 << 6)
--- /dev/null
--- /dev/null
++config PHYLIB
++ bool "Generic PHY support"
++
++config PHY_SMSC
++ bool "SMSC PHY support"
#include <phy.h>
#include <errno.h>
#include <linux/err.h>
+#include <linux/compiler.h>
/* Generic PHY support and helper functions */
/* Setup standard advertisement */
oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
--
if (adv < 0)
return adv;
if (phydev->supported & (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full)) {
oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
--
if (adv < 0)
return adv;
*/
static int genphy_setup_forced(struct phy_device *phydev)
{
- int err;
int ctl = 0;
phydev->pause = phydev->asym_pause = 0;
if (DUPLEX_FULL == phydev->duplex)
ctl |= BMCR_FULLDPLX;
- err = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
-
- return err;
+ return phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
}
int ctl;
ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
--
if (ctl < 0)
return ctl;
/* Don't isolate the PHY if we're negotiating */
ctl &= ~(BMCR_ISOLATE);
- ctl = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
-
- return ctl;
+ return phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
}
*/
int genphy_update_link(struct phy_device *phydev)
{
- unsigned int mii_reg;
+ int mii_reg;
+ int bmcr;
/*
* Wait if the link is up, and autonegotiation is in progress
* (ie - we're capable and it's not done)
*/
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+ if (mii_reg < 0)
+ return mii_reg;
/*
* If we already saw the link up, and it hasn't gone down, then
if (phydev->link && mii_reg & BMSR_LSTATUS)
return 0;
+ bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
+ if (!(bmcr & BMCR_ANENABLE))
+ return 0;
+
if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
int i = 0;
udelay(1000); /* 1 ms */
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+ if (mii_reg < 0)
+ return mii_reg;
}
printf(" done\n");
phydev->link = 1;
} else {
/* Read the link a second time to clear the latched state */
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+ if (mii_reg < 0)
+ return mii_reg;
if (mii_reg & BMSR_LSTATUS)
phydev->link = 1;
{
int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+ if (mii_reg < 0)
+ return mii_reg;
+
/* We're using autonegotiation */
- if (mii_reg & BMSR_ANEGCAPABLE) {
+ if (phydev->supported & SUPPORTED_Autoneg) {
+ int ret;
- u16 lpa;
- u16 gblpa = 0;
- int estatus = 0;
+ u32 lpa = 0;
- int gblpa = 0;
++ u32 gblpa = 0;
+ u32 estatus = 0;
/* Check for gigabit capability */
- if (mii_reg & BMSR_ERCAP) {
+ if (phydev->supported & (SUPPORTED_1000baseT_Full |
+ SUPPORTED_1000baseT_Half)) {
/* We want a list of states supported by
* both PHYs in the link
*/
- gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
- if (gblpa < 0) {
+ ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
- if (ret < 0)
- return ret;
++ if (ret < 0) {
+ debug("Could not read MII_STAT1000. Ignoring gigabit capability\n");
- gblpa = 0;
++ ret = 0;
+ }
- gblpa &= phy_read(phydev,
- MDIO_DEVAD_NONE, MII_CTRL1000) << 2;
+ gblpa = ret;
+
+ ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
+ if (ret < 0)
+ return ret;
+ gblpa &= ret << 2;
}
/* Set the baseline so we only have to set them
return 0;
}
- lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
- lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
+ ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
+ if (ret < 0)
+ return ret;
+ lpa = ret;
+
+ ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
+ if (ret < 0)
+ return ret;
+ lpa &= ret;
if (lpa & (LPA_100FULL | LPA_100HALF)) {
phydev->speed = SPEED_100;
if ((mii_reg & BMSR_ESTATEN) && !(mii_reg & BMSR_ERCAP))
estatus = phy_read(phydev, MDIO_DEVAD_NONE,
MII_ESTATUS);
+ if (estatus < 0)
+ return estatus;
if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_XHALF |
ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) {
}
} else {
- u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+ int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+
+ if (bmcr < 0)
+ return bmcr;
phydev->speed = SPEED_10;
phydev->duplex = DUPLEX_HALF;
/* Do we support autonegotiation? */
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
--
if (val < 0)
return val;
#ifdef CONFIG_PHY_BROADCOM
phy_broadcom_init();
#endif
+#ifdef CONFIG_PHY_CORTINA
+ phy_cortina_init();
+#endif
#ifdef CONFIG_PHY_DAVICOM
phy_davicom_init();
#endif
#ifdef CONFIG_PHY_ET1011C
phy_et1011c_init();
#endif
-#ifdef CONFIG_PHY_ICPLUS
- phy_icplus_init();
-#endif
#ifdef CONFIG_PHY_LXT
phy_lxt_init();
#endif
return generic_for_interface(interface);
}
+ static int aneg_enabled(struct phy_device *phydev)
+ {
+ static const char *aneg = "_aneg";
+ char varname[strlen(phydev->bus->name) + strlen(aneg) + 1];
+
+ snprintf(varname, sizeof(varname), "%s%s", phydev->bus->name, aneg);
+ return getenv_yesno(varname);
+ }
+
+ static int phy_get_speed(struct phy_device *phydev)
+ {
+ int ret;
+ static const char *aneg = "_speed";
+ char varname[strlen(phydev->bus->name) + strlen(aneg) + 1];
+ ulong val;
+
+ snprintf(varname, sizeof(varname), "%s%s", phydev->bus->name, aneg);
+
+ val = getenv_ulong(varname, 10, 100);
+ switch (val) {
+ case 1000:
+ ret = SPEED_1000;
+ break;
+ case 100:
+ ret = SPEED_100;
+ break;
+ case 10:
+ ret = SPEED_10;
+ break;
+ default:
+ printf("Improper setting '%s' for %s; assuming 100\n",
+ getenv(varname), varname);
+ ret = SPEED_100;
+ }
+ return ret;
+ }
+
+ static int phy_get_duplex(struct phy_device *phydev)
+ {
+ int ret = DUPLEX_FULL;
+ static const char *aneg = "_duplex";
+ char varname[strlen(phydev->bus->name) + strlen(aneg) + 4];
+ const char *val;
+
+ snprintf(varname, sizeof(varname), "%s%d%s",
+ phydev->bus->name, phydev->addr, aneg);
+
+ val = getenv(varname);
+ if (val != NULL) {
+ if (strcasecmp(val, "full") != 0) {
+ if (strcasecmp(val, "half") == 0) {
+ ret = DUPLEX_HALF;
+ } else {
+ printf("Improper setting '%s' for %s; assuming 'full'\n",
+ val, varname);
+ printf("Expected one of: 'full', 'half'\n");
+ }
+ }
+ }
+
+ return ret;
+ }
+
static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
int phy_id,
phy_interface_t interface)
dev->link = 1;
dev->interface = interface;
- dev->autoneg = AUTONEG_ENABLE;
-
dev->addr = addr;
dev->phy_id = phy_id;
dev->bus = bus;
dev->drv = get_phy_driver(dev, interface);
+ if (aneg_enabled(dev)) {
+ dev->autoneg = AUTONEG_ENABLE;
+ } else {
+ dev->autoneg = AUTONEG_DISABLE;
+ dev->speed = phy_get_speed(dev);
+ dev->duplex = phy_get_duplex(dev);
+
+ switch (dev->speed) {
+ case SPEED_1000:
+ if (dev->duplex == DUPLEX_FULL)
+ dev->supported &= SUPPORTED_1000baseT_Full;
+ else
+ dev->supported &= SUPPORTED_1000baseT_Half;
+ break;
+ case SPEED_100:
+ if (dev->duplex == DUPLEX_FULL)
+ dev->supported &= SUPPORTED_100baseT_Full;
+ else
+ dev->supported &= SUPPORTED_100baseT_Half;
+ break;
+ case SPEED_10:
+ if (dev->duplex == DUPLEX_FULL)
+ dev->supported &= SUPPORTED_10baseT_Full;
+ else
+ dev->supported &= SUPPORTED_10baseT_Half;
+ break;
+ default:
+ printf("Unsupported speed: %d\n", dev->speed);
+ }
+ }
+
phy_probe(dev);
bus->phymap[addr] = dev;
while (phy_mask) {
int addr = ffs(phy_mask) - 1;
int r = get_phy_id(bus, addr, devad, &phy_id);
- if (r < 0)
- return ERR_PTR(r);
/* If the PHY ID is mostly f's, we didn't find anything */
- if ((phy_id & 0x1fffffff) != 0x1fffffff)
+ if (r == 0 && (phy_id & 0x1fffffff) != 0x1fffffff)
return phy_device_create(bus, addr, phy_id, interface);
phy_mask &= ~(1 << addr);
}
if (phydev)
return phydev;
}
- printf("Phy not found\n");
+ printf("Phy %d not found\n", ffs(phy_mask) - 1);
return phy_device_create(bus, ffs(phy_mask) - 1, 0xffffffff, interface);
}
int phy_reset(struct phy_device *phydev)
{
+ int err;
int reg;
int timeout = 500;
int devad = MDIO_DEVAD_NONE;
reg |= BMCR_RESET;
- if (phy_write(phydev, devad, MII_BMCR, reg) < 0) {
+ err = phy_write(phydev, devad, MII_BMCR, reg);
+ if (err < 0) {
debug("PHY reset failed\n");
- return -1;
+ return err;
}
#ifdef CONFIG_PHY_RESET_DELAY
* auto-clearing). This should happen within 0.5 seconds per the
* IEEE spec.
*/
- while ((reg & BMCR_RESET) && timeout--) {
+ while ((reg & BMCR_RESET) && timeout-- >= 0) {
reg = phy_read(phydev, devad, MII_BMCR);
if (reg < 0) {
debug("PHY status read failed\n");
- return -1;
+ return reg;
}
udelay(1000);
}
if (reg & BMCR_RESET) {
puts("PHY reset timed out\n");
- return -1;
+ return -ETIMEDOUT;
}
return 0;
return 0;
}
-static int __board_phy_config(struct phy_device *phydev)
+__weak int board_phy_config(struct phy_device *phydev)
{
if (phydev->drv->config)
return phydev->drv->config(phydev);
return 0;
}
-int board_phy_config(struct phy_device *phydev)
- __attribute__((weak, alias("__board_phy_config")));
-
int phy_config(struct phy_device *phydev)
{
/* Invoke an optional board-specific helper */
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*
- * Some code get from linux kenrel
+ * Some code copied from linux kernel
* Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
*/
#include <miiphy.h>
+ #include <errno.h>
+
+ #define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
+ #define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
+ #define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
+/* This code does not check the partner abilities. */
static int smsc_parse_status(struct phy_device *phydev)
{
- int mii_reg;
+ int bmcr;
+ int aneg_exp;
+ int mii_adv;
+ int lpa;
+
+ aneg_exp = phy_read(phydev, MDIO_DEVAD_NONE, MII_EXPANSION);
+ if (aneg_exp < 0)
+ return aneg_exp;
+
+ if (aneg_exp & EXPANSION_MFAULTS) {
+ /* second read to clear latched status */
+ aneg_exp = phy_read(phydev, MDIO_DEVAD_NONE, MII_EXPANSION);
+ if (aneg_exp & EXPANSION_MFAULTS)
+ return -EIO;
+ }
- mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+ bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+ if (bmcr & BMCR_ANENABLE) {
+ lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
+ if (lpa < 0)
+ return lpa;
+ mii_adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
+ if (mii_adv < 0)
+ return mii_adv;
+ lpa &= mii_adv;
- if (mii_reg & (BMSR_100FULL | BMSR_100HALF))
- phydev->speed = SPEED_100;
- else
- phydev->speed = SPEED_10;
+ if (!(aneg_exp & EXPANSION_NWAY)) {
+ /* parallel detection */
+ phydev->duplex = DUPLEX_HALF;
+ if (lpa & (LPA_100HALF | LPA_100FULL))
+ phydev->speed = SPEED_100;
+ else
+ phydev->speed = SPEED_10;
+ }
- if (mii_reg & (BMSR_10FULL | BMSR_100FULL))
- phydev->duplex = DUPLEX_FULL;
- else
- phydev->duplex = DUPLEX_HALF;
+ if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phydev->speed = SPEED_100;
+ if (lpa & LPA_100FULL)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+ } else if (lpa & (LPA_10FULL | LPA_10HALF)) {
+ phydev->speed = SPEED_10;
+ if (lpa & LPA_10FULL)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+ } else {
+ return -EINVAL;
+ }
+ } else {
+ if (bmcr & BMCR_SPEED100)
+ phydev->speed = SPEED_100;
+ else
+ phydev->speed = SPEED_10;
+ if (bmcr & BMCR_FULLDPLX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+ }
return 0;
}
static int smsc_startup(struct phy_device *phydev)
{
- genphy_update_link(phydev);
- smsc_parse_status(phydev);
- return 0;
+ int ret;
+
+ if (!phydev->link) {
+ /* Disable EDPD to wake up PHY */
+ ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_LAN83C185_CTRL_STATUS);
+
+ if (ret < 0)
+ return ret;
+
+ if (ret & MII_LAN83C185_EDPWRDOWN) {
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_LAN83C185_CTRL_STATUS,
+ ret & ~MII_LAN83C185_EDPWRDOWN);
+ if (ret < 0)
+ return ret;
+
+ /* Sleep 64 ms to allow ~5 link test pulses to be sent */
+ udelay(64 * 1000);
+ }
+ }
+
+ ret = genphy_update_link(phydev);
+ if (ret < 0)
+ return ret;
+ return smsc_parse_status(phydev);
+ }
+
+ static int smsc_mdix_setup(struct phy_device *phydev)
+ {
+ int ret;
+ static const char *mdix = "_mdi";
+ char varname[strlen(phydev->bus->name) + strlen(mdix) + 1];
+ const char *val;
+
+ snprintf(varname, sizeof(varname), "%s%s", phydev->bus->name, mdix);
+
+ val = getenv(varname);
+ if (val) {
+ if (strcasecmp(val, "auto") == 0) {
+ ret = 0;
+ } else if (strcasecmp(val, "mdix") == 0) {
+ ret = 1;
+ } else if (strcasecmp(val, "mdi") == 0) {
+ ret = 2;
+ } else {
+ printf("Improper setting '%s' for %s\n", val, varname);
+ printf("Expected one of: 'auto', 'mdi', 'mdix'\n");
+ return -EINVAL;
+ }
+ } else {
+ ret = 0;
+ }
+ return ret;
+ }
+
+ static int smsc_config(struct phy_device *phydev)
+ {
+ int mdix = smsc_mdix_setup(phydev);
+
+ if (mdix < 0) {
+ return mdix;
+ } else if (mdix) {
+ int ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1b,
+ (1 << 15) | ((mdix & 1) << 13));
+ if (ret) {
+ printf("Failed to setup MDI/MDIX mode: %d\n", ret);
+ return ret;
+ }
+ }
+ return genphy_config_aneg(phydev);
}
static struct phy_driver lan8700_driver = {
.name = "SMSC LAN8710/LAN8720",
.uid = 0x0007c0f0,
.mask = 0xffff0,
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_BASIC_FEATURES,
- .config = &genphy_config_aneg,
- .startup = &genphy_startup,
+ .config = &smsc_config,
+ .startup = &smsc_startup,
.shutdown = &genphy_shutdown,
};
*/
#include <common.h>
+#include <dm.h>
+#include <errno.h>
#include <watchdog.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
+#include <dm/platform_data/serial_mxc.h>
#include <serial.h>
#include <linux/compiler.h>
-#define __REG(x) (*((volatile u32 *)(x)))
-
-#ifndef CONFIG_MXC_UART_BASE
-#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
-#endif
-
-#define UART_PHYS CONFIG_MXC_UART_BASE
-
-/* Register definitions */
-#define URXD 0x0 /* Receiver Register */
-#define UTXD 0x40 /* Transmitter Register */
-#define UCR1 0x80 /* Control Register 1 */
-#define UCR2 0x84 /* Control Register 2 */
-#define UCR3 0x88 /* Control Register 3 */
-#define UCR4 0x8c /* Control Register 4 */
-#define UFCR 0x90 /* FIFO Control Register */
-#define USR1 0x94 /* Status Register 1 */
-#define USR2 0x98 /* Status Register 2 */
-#define UESC 0x9c /* Escape Character Register */
-#define UTIM 0xa0 /* Escape Timer Register */
-#define UBIR 0xa4 /* BRM Incremental Register */
-#define UBMR 0xa8 /* BRM Modulator Register */
-#define UBRC 0xac /* Baud Rate Count Register */
-#define UTS 0xb4 /* UART Test Register (mx31) */
-
/* UART Control Register Bit Fields.*/
#define URXD_CHARRDY (1<<15)
#define URXD_ERR (1<<14)
#define UCR3_DSR (1<<10) /* Data set ready */
#define UCR3_DCD (1<<9) /* Data carrier detect */
#define UCR3_RI (1<<8) /* Ring indicator */
-#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */
+#define UCR3_ADNIMP (1<<7) /* Autobaud Detection Not Improved */
#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
#define UTS_RXFULL (1<<3) /* RxFIFO full */
#define UTS_SOFTRST (1<<0) /* Software reset */
+#ifndef CONFIG_DM_SERIAL
+
+#ifndef CONFIG_MXC_UART_BASE
+#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
+#endif
+
+#define UART_PHYS CONFIG_MXC_UART_BASE
+
+#define __REG(x) (*((volatile u32 *)(x)))
+
+/* Register definitions */
+#define URXD 0x0 /* Receiver Register */
+#define UTXD 0x40 /* Transmitter Register */
+#define UCR1 0x80 /* Control Register 1 */
+#define UCR2 0x84 /* Control Register 2 */
+#define UCR3 0x88 /* Control Register 3 */
+#define UCR4 0x8c /* Control Register 4 */
+#define UFCR 0x90 /* FIFO Control Register */
+#define USR1 0x94 /* Status Register 1 */
+#define USR2 0x98 /* Status Register 2 */
+#define UESC 0x9c /* Escape Character Register */
+#define UTIM 0xa0 /* Escape Timer Register */
+#define UBIR 0xa4 /* BRM Incremental Register */
+#define UBMR 0xa8 /* BRM Modulator Register */
+#define UBRC 0xac /* Baud Rate Count Register */
+#define UTS 0xb4 /* UART Test Register (mx31) */
+
DECLARE_GLOBAL_DATA_PTR;
static void mxc_serial_setbrg(void)
static void mxc_serial_putc(const char c)
{
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+
__REG(UART_PHYS + UTXD) = c;
/* wait for transmitter to be ready */
while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY))
WATCHDOG_RESET();
-
- /* If \n, also do \r */
- if (c == '\n')
- serial_putc ('\r');
}
/*
while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST));
- __REG(UART_PHYS + UCR3) = 0x0704;
+ __REG(UART_PHYS + UCR3) = 0x0704 | UCR3_ADNIMP;
__REG(UART_PHYS + UCR4) = 0x8000;
__REG(UART_PHYS + UESC) = 0x002b;
__REG(UART_PHYS + UTIM) = 0x0;
{
return &mxc_serial_drv;
}
+#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+struct mxc_uart {
+ u32 rxd;
+ u32 spare0[15];
+
+ u32 txd;
+ u32 spare1[15];
+
+ u32 cr1;
+ u32 cr2;
+ u32 cr3;
+ u32 cr4;
+
+ u32 fcr;
+ u32 sr1;
+ u32 sr2;
+ u32 esc;
+
+ u32 tim;
+ u32 bir;
+ u32 bmr;
+ u32 brc;
+
+ u32 onems;
+ u32 ts;
+};
+
+int mxc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+ u32 clk = imx_get_uartclk();
+
+ writel(4 << 7, &uart->fcr); /* divide input clock by 2 */
+ writel(0xf, &uart->bir);
+ writel(clk / (2 * baudrate), &uart->bmr);
+
+ writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
+ &uart->cr2);
+ writel(UCR1_UARTEN, &uart->cr1);
+
+ return 0;
+}
+
+static int mxc_serial_probe(struct udevice *dev)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+
+ writel(0, &uart->cr1);
+ writel(0, &uart->cr2);
+ while (!(readl(&uart->cr2) & UCR2_SRST));
+ writel(0x704 | UCR3_ADNIMP, &uart->cr3);
+ writel(0x8000, &uart->cr4);
+ writel(0x2b, &uart->esc);
+ writel(0, &uart->tim);
+ writel(0, &uart->ts);
+
+ return 0;
+}
+
+static int mxc_serial_getc(struct udevice *dev)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+
+ if (readl(&uart->ts) & UTS_RXEMPTY)
+ return -EAGAIN;
+
+ return readl(&uart->rxd) & URXD_RX_DATA;
+}
+
+static int mxc_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+
+ if (!(readl(&uart->ts) & UTS_TXEMPTY))
+ return -EAGAIN;
+
+ writel(ch, &uart->txd);
+
+ return 0;
+}
+
+static int mxc_serial_pending(struct udevice *dev, bool input)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+ uint32_t sr2 = readl(&uart->sr2);
+
+ if (input)
+ return sr2 & USR2_RDR ? 1 : 0;
+ else
+ return sr2 & USR2_TXDC ? 0 : 1;
+}
+
+static const struct dm_serial_ops mxc_serial_ops = {
+ .putc = mxc_serial_putc,
+ .pending = mxc_serial_pending,
+ .getc = mxc_serial_getc,
+ .setbrg = mxc_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_mxc) = {
+ .name = "serial_mxc",
+ .id = UCLASS_SERIAL,
+ .probe = mxc_serial_probe,
+ .ops = &mxc_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif
#define USBPHY_CTRL_CLKGATE 0x40000000
#define USBPHY_CTRL_ENUTMILEVEL3 0x00008000
#define USBPHY_CTRL_ENUTMILEVEL2 0x00004000
+#define USBPHY_CTRL_OTG_ID 0x08000000
#define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000
#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000
--#define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000
--#define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000
--#define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000
--#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040
++#define ANADIG_USB_PLL_480_CTRL_BYPASS 0x00010000
++#define ANADIG_USB_PLL_480_CTRL_ENABLE 0x00002000
++#define ANADIG_USB_PLL_480_CTRL_POWER 0x00001000
++#define ANADIG_USB_PLL_480_CTRL_EN_USB_CLKS 0x00000040
#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */
#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */
/* USBCMD */
-#define UH1_USBCMD_OFFSET 0x140
#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
#define UCMD_RESET (1 << 1) /* controller reset */
-static void usbh1_internal_phy_clock_gate(int on)
+static const unsigned phy_bases[] = {
+ USB_PHY0_BASE_ADDR,
+ USB_PHY1_BASE_ADDR,
+};
+
+static void usb_internal_phy_clock_gate(int index, int on)
{
- void __iomem *phy_reg = (void __iomem *)USB_PHY1_BASE_ADDR;
+ void __iomem *phy_reg;
+
+ if (index >= ARRAY_SIZE(phy_bases))
+ return;
+ phy_reg = (void __iomem *)phy_bases[index];
phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
__raw_writel(USBPHY_CTRL_CLKGATE, phy_reg);
}
-static void usbh1_power_config(void)
+static void usb_power_config(int index)
{
struct anatop_regs __iomem *anatop =
(struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
+ void __iomem *chrg_detect;
+ void __iomem *pll_480_ctrl_clr;
+ void __iomem *pll_480_ctrl_set;
+
+ switch (index) {
+ case 0:
+ chrg_detect = &anatop->usb1_chrg_detect;
+ pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr;
+ pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set;
+ break;
+ case 1:
+ chrg_detect = &anatop->usb2_chrg_detect;
+ pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr;
+ pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set;
+ break;
+ default:
+ return;
+ }
/*
- * Some phy and power's special controls for host1
+ * Some phy and power's special controls
* 1. The external charger detector needs to be disabled
* or the signal at DP will be poor
- * 2. The PLL's power and output to usb for host 1
+ * 2. The PLL's power and output to usb
* is totally controlled by IC, so the Software only needs
* to enable them at initializtion.
*/
__raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B |
ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
- &anatop->usb2_chrg_detect);
+ chrg_detect);
-- __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS,
- &anatop->usb2_pll_480_ctrl_clr);
++ __raw_writel(ANADIG_USB_PLL_480_CTRL_BYPASS,
+ pll_480_ctrl_clr);
-- __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE |
-- ANADIG_USB2_PLL_480_CTRL_POWER |
-- ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
- &anatop->usb2_pll_480_ctrl_set);
++ __raw_writel(ANADIG_USB_PLL_480_CTRL_ENABLE |
++ ANADIG_USB_PLL_480_CTRL_POWER |
++ ANADIG_USB_PLL_480_CTRL_EN_USB_CLKS,
+ pll_480_ctrl_set);
}
-static int usbh1_phy_enable(void)
+/* Return 0 : host node, <>0 : device mode */
+static int usb_phy_enable(int index, struct usb_ehci *ehci)
{
- void __iomem *phy_reg = (void __iomem *)USB_PHY1_BASE_ADDR;
- void __iomem *phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
- void __iomem *usb_cmd = (void __iomem *)(USBOH3_USB_BASE_ADDR +
- USB_H1REGS_OFFSET +
- UH1_USBCMD_OFFSET);
+ void __iomem *phy_reg;
+ void __iomem *phy_ctrl;
+ void __iomem *usb_cmd;
u32 val;
+ if (index >= ARRAY_SIZE(phy_bases))
+ return 0;
+
+ phy_reg = (void __iomem *)phy_bases[index];
+ phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
+ usb_cmd = (void __iomem *)&ehci->usbcmd;
+
/* Stop then Reset */
val = __raw_readl(usb_cmd);
val &= ~UCMD_RUN_STOP;
/* Power up the PHY */
__raw_writel(0, phy_reg + USBPHY_PWD);
/* enable FS/LS device */
- val = __raw_readl(phy_reg + USBPHY_CTRL);
+ val = __raw_readl(phy_ctrl);
val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3);
- __raw_writel(val, phy_reg + USBPHY_CTRL);
+ __raw_writel(val, phy_ctrl);
return 0;
}
-static void usbh1_oc_config(void)
+/* Base address for this IP block is 0x02184800 */
+struct usbnc_regs {
+ u32 ctrl[4]; /* otg/host1-3 */
+ u32 uh2_hsic_ctrl;
+ u32 uh3_hsic_ctrl;
+ u32 otg_phy_ctrl_0;
+ u32 uh1_phy_ctrl_0;
+};
+
+static void usb_oc_config(int index)
{
- void __iomem *usb_base = (void __iomem *)USBOH3_USB_BASE_ADDR;
- void __iomem *usbother_base = usb_base + USB_OTHERREGS_OFFSET;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ USB_OTHERREGS_OFFSET);
+ void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
u32 val;
- val = __raw_readl(usbother_base + USB_H1_CTRL_OFFSET);
+ val = __raw_readl(ctrl);
#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
/* mx6qarm2 seems to required a different setting*/
val &= ~UCTRL_OVER_CUR_POL;
#else
val |= UCTRL_OVER_CUR_POL;
#endif
- __raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET);
+ __raw_writel(val, ctrl);
- val = __raw_readl(usbother_base + USB_H1_CTRL_OFFSET);
+ val = __raw_readl(ctrl);
val |= UCTRL_OVER_CUR_DIS;
- __raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET);
+ __raw_writel(val, ctrl);
+}
+
+int usb_phy_mode(int port)
+{
+ void __iomem *phy_reg;
+ void __iomem *phy_ctrl;
+ u32 val;
+
+ phy_reg = (void __iomem *)phy_bases[port];
+ phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
+
+ val = __raw_readl(phy_ctrl);
+
+ if (val & USBPHY_CTRL_OTG_ID)
+ return USB_INIT_DEVICE;
+ else
+ return USB_INIT_HOST;
+}
+
+int __weak board_usb_phy_mode(int port)
+{
+ return usb_phy_mode(port);
}
int __weak board_ehci_hcd_init(int port)
return 0;
}
-int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
+int __weak board_ehci_power(int port, int on)
{
- struct usb_ehci *ehci;
+ return 0;
+}
+int ehci_hcd_init(int index, enum usb_init_type init,
+ struct ehci_hccr **hccr, struct ehci_hcor **hcor)
+{
+ enum usb_init_type type;
+ struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR +
+ (0x200 * index));
+
+ if (index > 3)
+ return -EINVAL;
enable_usboh3_clk(1);
mdelay(1);
/* Do board specific initialization */
- board_ehci_hcd_init(CONFIG_MXC_USB_PORT);
-
-#if CONFIG_MXC_USB_PORT == 1
- /* USB Host 1 */
- usbh1_power_config();
- usbh1_oc_config();
- usbh1_internal_phy_clock_gate(1);
- usbh1_phy_enable();
-#else
-#error "MXC USB port not yet supported"
-#endif
+ board_ehci_hcd_init(index);
+
+ usb_power_config(index);
+ usb_oc_config(index);
+ usb_internal_phy_clock_gate(index, 1);
+ usb_phy_enable(index, ehci);
+ type = board_usb_phy_mode(index);
- ehci = (struct usb_ehci *)(USBOH3_USB_BASE_ADDR +
- (0x200 * CONFIG_MXC_USB_PORT));
*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
*hcor = (struct ehci_hcor *)((uint32_t)*hccr +
HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
- setbits_le32(&ehci->usbmode, CM_HOST);
+ if ((type == init) || (type == USB_INIT_DEVICE))
+ board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1);
+ if (type != init)
+ return -ENODEV;
+ if (type == USB_INIT_DEVICE)
+ return 0;
+ setbits_le32(&ehci->usbmode, CM_HOST);
__raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
setbits_le32(&ehci->portsc, USB_EN);
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
- * Linux IPU driver for MX51:
+ * Linux IPU driver
*
- * (C) Copyright 2005-2010 Freescale Semiconductor, Inc.
+ * (C) Copyright 2005-2011 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* #define DEBUG */
#include <common.h>
+ #include <ipu.h>
#include <linux/types.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/crm_regs.h>
- #include "ipu.h"
+ #include <asm/arch/clock.h>
+
#include "ipu_regs.h"
- extern struct mxc_ccm_reg *mxc_ccm;
- extern u32 *ipu_cpmem_base;
+ static struct mxc_ccm_reg __maybe_unused *mxc_ccm = (void *)CCM_BASE_ADDR;
struct ipu_ch_param_word {
uint32_t data[5];
#define ipu_ch_param_addr(ch) (((struct ipu_ch_param *)ipu_cpmem_base) + (ch))
#define _param_word(base, w) \
- (((struct ipu_ch_param *)(base))->word[(w)].data)
+ (((struct ipu_ch_param *)(base))->word[w].data)
- #define ipu_ch_param_set_field(base, w, bit, size, v) { \
- int i = (bit) / 32; \
- int off = (bit) % 32; \
- _param_word(base, w)[i] |= (v) << off; \
- if (((bit) + (size) - 1) / 32 > i) { \
+ #define ipu_ch_param_set_field(base, w, bit, size, v) { \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ _param_word(base, w)[i] |= (v) << off; \
+ if (((bit) + (size) - 1) / 32 > i) { \
_param_word(base, w)[i + 1] |= (v) >> (off ? (32 - off) : 0); \
- } \
+ } \
}
- #define ipu_ch_param_mod_field(base, w, bit, size, v) { \
- int i = (bit) / 32; \
- int off = (bit) % 32; \
- u32 mask = (1UL << size) - 1; \
- u32 temp = _param_word(base, w)[i]; \
- temp &= ~(mask << off); \
- _param_word(base, w)[i] = temp | (v) << off; \
- if (((bit) + (size) - 1) / 32 > i) { \
- temp = _param_word(base, w)[i + 1]; \
- temp &= ~(mask >> (32 - off)); \
- _param_word(base, w)[i + 1] = \
+ #define ipu_ch_param_mod_field(base, w, bit, size, v) { \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ u32 mask = (1UL << size) - 1; \
+ u32 temp = _param_word(base, w)[i]; \
+ temp &= ~(mask << off); \
+ _param_word(base, w)[i] = temp | (v) << off; \
+ if (((bit) + (size) - 1) / 32 > i) { \
+ temp = _param_word(base, w)[i + 1]; \
+ temp &= ~(mask >> (32 - off)); \
+ _param_word(base, w)[i + 1] = \
temp | ((v) >> (off ? (32 - off) : 0)); \
- } \
+ } \
}
- #define ipu_ch_param_read_field(base, w, bit, size) ({ \
- u32 temp2; \
- int i = (bit) / 32; \
- int off = (bit) % 32; \
- u32 mask = (1UL << size) - 1; \
- u32 temp1 = _param_word(base, w)[i]; \
- temp1 = mask & (temp1 >> off); \
- if (((bit)+(size) - 1) / 32 > i) { \
- temp2 = _param_word(base, w)[i + 1]; \
- temp2 &= mask >> (off ? (32 - off) : 0); \
- temp1 |= temp2 << (off ? (32 - off) : 0); \
- } \
- temp1; \
+ #define ipu_ch_param_read_field(base, w, bit, size) ({ \
+ u32 temp2; \
+ int i = (bit) / 32; \
+ int off = (bit) % 32; \
+ u32 mask = (1UL << size) - 1; \
+ u32 temp1 = _param_word(base, w)[i]; \
+ temp1 = mask & (temp1 >> off); \
+ if (((bit)+(size) - 1) / 32 > i) { \
+ temp2 = _param_word(base, w)[i + 1]; \
+ temp2 &= mask >> (off ? (32 - off) : 0); \
+ temp1 |= temp2 << (off ? (32 - off) : 0); \
+ } \
+ temp1; \
})
- #define IPU_SW_RST_TOUT_USEC (10000)
-
- void clk_enable(struct clk *clk)
- {
- if (clk) {
- if (clk->usecount++ == 0) {
- clk->enable(clk);
- }
- }
- }
-
- void clk_disable(struct clk *clk)
- {
- if (clk) {
- if (!(--clk->usecount)) {
- if (clk->disable)
- clk->disable(clk);
- }
- }
- }
-
- int clk_get_usecount(struct clk *clk)
- {
- if (clk == NULL)
- return 0;
-
- return clk->usecount;
- }
-
- u32 clk_get_rate(struct clk *clk)
- {
- if (!clk)
- return 0;
-
- return clk->rate;
- }
-
- struct clk *clk_get_parent(struct clk *clk)
- {
- if (!clk)
- return 0;
-
- return clk->parent;
- }
-
- int clk_set_rate(struct clk *clk, unsigned long rate)
- {
- if (clk && clk->set_rate)
- clk->set_rate(clk, rate);
- return clk->rate;
- }
-
- long clk_round_rate(struct clk *clk, unsigned long rate)
- {
- if (clk == NULL || !clk->round_rate)
- return 0;
-
- return clk->round_rate(clk, rate);
- }
-
- int clk_set_parent(struct clk *clk, struct clk *parent)
- {
- clk->parent = parent;
- if (clk->set_parent)
- return clk->set_parent(clk, parent);
- return 0;
- }
+ #define IPU_SW_RST_TOUT_USEC 10000
static int clk_ipu_enable(struct clk *clk)
{
- u32 reg;
-
- reg = __raw_readl(clk->enable_reg);
- reg |= MXC_CCM_CCGR_CG_MASK << clk->enable_shift;
- __raw_writel(reg, clk->enable_reg);
-
- #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
- /* Handshake with IPU when certain clock rates are changed. */
- reg = __raw_readl(&mxc_ccm->ccdr);
- reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
- __raw_writel(reg, &mxc_ccm->ccdr);
-
- /* Handshake with IPU when LPM is entered as its enabled. */
- reg = __raw_readl(&mxc_ccm->clpcr);
- reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
- __raw_writel(reg, &mxc_ccm->clpcr);
- #endif
+ ipu_clk_enable();
return 0;
}
static void clk_ipu_disable(struct clk *clk)
{
- u32 reg;
-
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift);
- __raw_writel(reg, clk->enable_reg);
-
- #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
- /*
- * No handshake with IPU whe dividers are changed
- * as its not enabled.
- */
- reg = __raw_readl(&mxc_ccm->ccdr);
- reg |= MXC_CCM_CCDR_IPU_HS_MASK;
- __raw_writel(reg, &mxc_ccm->ccdr);
-
- /* No handshake with IPU when LPM is entered as its not enabled. */
- reg = __raw_readl(&mxc_ccm->clpcr);
- reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
- __raw_writel(reg, &mxc_ccm->clpcr);
- #endif
+ ipu_clk_disable();
}
-
static struct clk ipu_clk = {
.name = "ipu_clk",
.rate = CONFIG_IPUV3_CLK,
- #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
- .enable_reg = (u32 *)(CCM_BASE_ADDR +
- offsetof(struct mxc_ccm_reg, CCGR5)),
- .enable_shift = MXC_CCM_CCGR5_IPU_OFFSET,
- #else
- .enable_reg = (u32 *)(CCM_BASE_ADDR +
- offsetof(struct mxc_ccm_reg, CCGR3)),
- .enable_shift = MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET,
- #endif
.enable = clk_ipu_enable,
.disable = clk_ipu_disable,
- .usecount = 0,
};
+ static int clk_ldb_enable(struct clk *clk)
+ {
+ ldb_clk_enable(0);
+ ldb_clk_enable(1);
+ return 0;
+ }
+
+ static void clk_ldb_disable(struct clk *clk)
+ {
+ ldb_clk_disable(0);
+ ldb_clk_disable(1);
+ }
+
static struct clk ldb_clk = {
.name = "ldb_clk",
.rate = 65000000,
- .usecount = 0,
+ .enable = clk_ldb_enable,
+ .disable = clk_ldb_disable,
};
/* Globals */
struct clk *g_ipu_clk;
struct clk *g_ldb_clk;
- unsigned char g_ipu_clk_enabled;
struct clk *g_di_clk[2];
struct clk *g_pixel_clk[2];
unsigned char g_dc_di_assignment[10];
- uint32_t g_channel_init_mask;
- uint32_t g_channel_enable_mask;
+ int g_ipu_clk_enabled;
+ u32 *ipu_dc_tmpl_reg;
+ static uint32_t g_channel_init_mask;
+ static uint32_t g_channel_enable_mask;
static int ipu_dc_use_count;
static int ipu_dp_use_count;
static int ipu_dmfc_use_count;
static int ipu_di_use_count[2];
- u32 *ipu_cpmem_base;
- u32 *ipu_dc_tmpl_reg;
+ static u32 *ipu_cpmem_base;
/* Static functions */
unsigned long rate)
{
u32 div, div1;
- u32 tmp;
+ u64 tmp;
/*
* Calculate divider
* Fractional part is 4 bits,
* so simply multiply by 2^4 to get fractional part.
*/
- tmp = (clk->parent->rate * 16);
+ tmp = (u64)clk->parent->rate * 16;
div = tmp / rate;
if (div < 0x10) /* Min DI disp clock divider is 1 */
else
div &= 0xFF8;
}
- return (clk->parent->rate * 16) / div;
+ tmp /= div;
+ #if 1
+ debug("%s: requested rate: %lu.%03luMHz parent_rate: %lu.%03luMHz actual rate: %llu.%03lluMHz div: %u.%u\n", __func__,
+ rate / 1000000, rate / 1000 % 1000,
+ clk->parent->rate / 1000000, clk->parent->rate / 1000 % 1000,
+ tmp / 1000000, tmp / 1000 % 1000, div / 16, div % 16);
+ #endif
+ return tmp;
}
static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
{
- u32 div = (clk->parent->rate * 16) / rate;
+ u32 div = ((u64)clk->parent->rate * 16) / rate;
+
+ debug("%s: parent_rate: %lu.%03luMHz actual rate: %lu.%03luMHz div: %u.%u\n", __func__,
+ clk->parent->rate / 1000000, clk->parent->rate / 1000 % 1000,
+ rate / 1000000, rate / 1000 % 1000, div / 16, div % 16);
__raw_writel(div, DI_BS_CLKGEN0(clk->id));
/* Setup pixel clock timing */
__raw_writel((div / 16) << 16, DI_BS_CLKGEN1(clk->id));
- clk->rate = (clk->parent->rate * 16) / div;
+ clk->rate = ((u64)clk->parent->rate * 16) / div;
+ debug("%s: pix_clk=%lu.%03luMHz\n", __func__,
+ clk->rate / 1000000, clk->rate / 1000 % 1000);
return 0;
}
u32 disp_gen = __raw_readl(IPU_DISP_GEN);
disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
__raw_writel(disp_gen, IPU_DISP_GEN);
-
}
static int ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
{
- u32 di_gen = __raw_readl(DI_GENERAL(clk->id));
+ int ret;
+ u32 di_gen;
+
+ ret = clk_enable(clk);
+ if (ret)
+ return ret;
+
+ di_gen = __raw_readl(DI_GENERAL(clk->id));
if (parent == g_ipu_clk)
di_gen &= ~DI_GEN_DI_CLK_EXT;
else if (!IS_ERR(g_di_clk[clk->id]) && parent == g_ldb_clk)
di_gen |= DI_GEN_DI_CLK_EXT;
else
- return -EINVAL;
+ goto err;
+ ret = clk_enable(parent);
+ if (ret)
+ goto err;
__raw_writel(di_gen, DI_GENERAL(clk->id));
ipu_pixel_clk_recalc(clk);
- return 0;
+ clk->disable(clk->parent);
+ clk->parent = parent;
+ err:
+ clk_disable(clk);
+ return ret;
}
static struct clk pixel_clk[] = {
{
- .name = "pixel_clk",
- .id = 0,
- .recalc = ipu_pixel_clk_recalc,
- .set_rate = ipu_pixel_clk_set_rate,
- .round_rate = ipu_pixel_clk_round_rate,
- .set_parent = ipu_pixel_clk_set_parent,
- .enable = ipu_pixel_clk_enable,
- .disable = ipu_pixel_clk_disable,
- .usecount = 0,
+ .name = "pixel_clk",
+ .id = 0,
+ .recalc = ipu_pixel_clk_recalc,
+ .set_rate = ipu_pixel_clk_set_rate,
+ .round_rate = ipu_pixel_clk_round_rate,
+ .set_parent = ipu_pixel_clk_set_parent,
+ .enable = ipu_pixel_clk_enable,
+ .disable = ipu_pixel_clk_disable,
},
{
- .name = "pixel_clk",
- .id = 1,
- .recalc = ipu_pixel_clk_recalc,
- .set_rate = ipu_pixel_clk_set_rate,
- .round_rate = ipu_pixel_clk_round_rate,
- .set_parent = ipu_pixel_clk_set_parent,
- .enable = ipu_pixel_clk_enable,
- .disable = ipu_pixel_clk_disable,
- .usecount = 0,
+ .name = "pixel_clk",
+ .id = 1,
+ .recalc = ipu_pixel_clk_recalc,
+ .set_rate = ipu_pixel_clk_set_rate,
+ .round_rate = ipu_pixel_clk_round_rate,
+ .set_parent = ipu_pixel_clk_set_parent,
+ .enable = ipu_pixel_clk_enable,
+ .disable = ipu_pixel_clk_disable,
+ },
+ };
+
+ static int clk_ipu_di_enable(struct clk *clk)
+ {
+ ipu_di_clk_enable(clk->id);
+ return 0;
+ }
+
+ static void clk_ipu_di_disable(struct clk *clk)
+ {
+ ipu_di_clk_disable(clk->id);
+ }
+
+ static struct clk di_clk[] = {
+ {
+ .name = "ipu_di_clk",
+ .id = 0,
+ .enable = clk_ipu_di_enable,
+ .disable = clk_ipu_di_disable,
+ },
+ {
+ .name = "ipu_di_clk",
+ .id = 1,
+ .enable = clk_ipu_di_enable,
+ .disable = clk_ipu_di_disable,
},
};
/*
* This function resets IPU
*/
-void ipu_reset(void)
+static void ipu_reset(void)
{
u32 *reg;
u32 value;
*
* @return Returns 0 on success or negative error code on error
*/
- int ipu_probe(void)
+ int ipu_probe(int di, ipu_di_clk_parent_t di_clk_parent, int di_clk_val)
{
- unsigned long ipu_base;
+ int ret;
+ void *ipu_base;
+ unsigned long start;
#if defined CONFIG_MX51
u32 temp;
-
u32 *reg_hsc_mcd = (u32 *)MIPI_HSC_BASE_ADDR;
u32 *reg_hsc_mxt_conf = (u32 *)(MIPI_HSC_BASE_ADDR + 0x800);
__raw_writel(0xF00, reg_hsc_mcd);
- /* CSI mode reserved*/
+ /* CSI mode reserved */
temp = __raw_readl(reg_hsc_mxt_conf);
__raw_writel(temp | 0x0FF, reg_hsc_mxt_conf);
temp = __raw_readl(reg_hsc_mxt_conf);
__raw_writel(temp | 0x10000, reg_hsc_mxt_conf);
#endif
-
- ipu_base = IPU_CTRL_BASE_ADDR;
- ipu_cpmem_base = (u32 *)(ipu_base + IPU_CPMEM_REG_BASE);
- ipu_dc_tmpl_reg = (u32 *)(ipu_base + IPU_DC_TMPL_REG_BASE);
+ ipu_base = (void *)IPU_SOC_BASE_ADDR;
+ /* base fixup */
+ if (gd->arch.ipu_hw_rev == IPUV3_HW_REV_IPUV3H) /* IPUv3H */
+ ipu_base += IPUV3H_REG_BASE;
+ else if (gd->arch.ipu_hw_rev == IPUV3_HW_REV_IPUV3M) /* IPUv3M */
+ ipu_base += IPUV3M_REG_BASE;
+ else /* IPUv3D, v3E, v3EX */
+ ipu_base += IPUV3DEX_REG_BASE;
+ ipu_cpmem_base = ipu_base + IPU_CPMEM_REG_BASE;
+ ipu_dc_tmpl_reg = ipu_base + IPU_DC_TMPL_REG_BASE;
+
+ printf("IPU HW Rev: %d\n", gd->arch.ipu_hw_rev);
g_pixel_clk[0] = &pixel_clk[0];
g_pixel_clk[1] = &pixel_clk[1];
+ g_di_clk[0] = &di_clk[0];
+ g_di_clk[1] = &di_clk[1];
+ g_di_clk[di]->rate = di_clk_val;
+
g_ipu_clk = &ipu_clk;
debug("ipu_clk = %u\n", clk_get_rate(g_ipu_clk));
+
g_ldb_clk = &ldb_clk;
debug("ldb_clk = %u\n", clk_get_rate(g_ldb_clk));
- ipu_reset();
- clk_set_parent(g_pixel_clk[0], g_ipu_clk);
- clk_set_parent(g_pixel_clk[1], g_ipu_clk);
- clk_enable(g_ipu_clk);
+ ret = clk_enable(g_ipu_clk);
+ if (ret)
+ return ret;
+ ipu_reset();
- g_di_clk[0] = NULL;
- g_di_clk[1] = NULL;
+ if (di_clk_parent == DI_PCLK_LDB) {
+ clk_set_parent(g_pixel_clk[di], g_ldb_clk);
+ } else {
+ clk_set_parent(g_pixel_clk[0], g_ipu_clk);
+ clk_set_parent(g_pixel_clk[1], g_ipu_clk);
+ }
__raw_writel(0x807FFFFF, IPU_MEM_RST);
- while (__raw_readl(IPU_MEM_RST) & 0x80000000)
- ;
+ start = get_timer_masked();
+ while (__raw_readl(IPU_MEM_RST) & 0x80000000) {
+ if (get_timer(start) > CONFIG_SYS_HZ)
+ return -ETIME;
+ }
ipu_init_dc_mappings();
void ipu_dump_registers(void)
{
- debug("IPU_CONF = \t0x%08X\n", __raw_readl(IPU_CONF));
- debug("IDMAC_CONF = \t0x%08X\n", __raw_readl(IDMAC_CONF));
- debug("IDMAC_CHA_EN1 = \t0x%08X\n",
+ debug("IPU_CONF 0x%08X\n", __raw_readl(IPU_CONF));
+ debug("IDMAC_CONF 0x%08X\n", __raw_readl(IDMAC_CONF));
+ debug("IDMAC_CHA_EN1 0x%08X\n",
__raw_readl(IDMAC_CHA_EN(0)));
- debug("IDMAC_CHA_EN2 = \t0x%08X\n",
+ debug("IDMAC_CHA_EN2 0x%08X\n",
__raw_readl(IDMAC_CHA_EN(32)));
- debug("IDMAC_CHA_PRI1 = \t0x%08X\n",
+ debug("IDMAC_CHA_PRI1 0x%08X\n",
__raw_readl(IDMAC_CHA_PRI(0)));
- debug("IDMAC_CHA_PRI2 = \t0x%08X\n",
+ debug("IDMAC_CHA_PRI2 0x%08X\n",
__raw_readl(IDMAC_CHA_PRI(32)));
- debug("IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
+ debug("IPU_CHA_DB_MODE_SEL0 0x%08X\n",
__raw_readl(IPU_CHA_DB_MODE_SEL(0)));
- debug("IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
+ debug("IPU_CHA_DB_MODE_SEL1 0x%08X\n",
__raw_readl(IPU_CHA_DB_MODE_SEL(32)));
- debug("DMFC_WR_CHAN = \t0x%08X\n",
+ debug("DMFC_WR_CHAN 0x%08X\n",
__raw_readl(DMFC_WR_CHAN));
- debug("DMFC_WR_CHAN_DEF = \t0x%08X\n",
+ debug("DMFC_WR_CHAN_DEF 0x%08X\n",
__raw_readl(DMFC_WR_CHAN_DEF));
- debug("DMFC_DP_CHAN = \t0x%08X\n",
+ debug("DMFC_DP_CHAN 0x%08X\n",
__raw_readl(DMFC_DP_CHAN));
- debug("DMFC_DP_CHAN_DEF = \t0x%08X\n",
+ debug("DMFC_DP_CHAN_DEF 0x%08X\n",
__raw_readl(DMFC_DP_CHAN_DEF));
- debug("DMFC_IC_CTRL = \t0x%08X\n",
+ debug("DMFC_IC_CTRL 0x%08X\n",
__raw_readl(DMFC_IC_CTRL));
- debug("IPU_FS_PROC_FLOW1 = \t0x%08X\n",
+ debug("IPU_FS_PROC_FLOW1 0x%08X\n",
__raw_readl(IPU_FS_PROC_FLOW1));
- debug("IPU_FS_PROC_FLOW2 = \t0x%08X\n",
+ debug("IPU_FS_PROC_FLOW2 0x%08X\n",
__raw_readl(IPU_FS_PROC_FLOW2));
- debug("IPU_FS_PROC_FLOW3 = \t0x%08X\n",
+ debug("IPU_FS_PROC_FLOW3 0x%08X\n",
__raw_readl(IPU_FS_PROC_FLOW3));
- debug("IPU_FS_DISP_FLOW1 = \t0x%08X\n",
+ debug("IPU_FS_DISP_FLOW1 0x%08X\n",
__raw_readl(IPU_FS_DISP_FLOW1));
}
break;
default:
printf("Missing channel initialization\n");
- break;
}
/* Enable IPU sub module */
ipu_conf |= IPU_CONF_DMFC_EN;
if (ipu_di_use_count[0] == 1) {
ipu_conf |= IPU_CONF_DI0_EN;
+ clk_enable(g_di_clk[0]);
}
if (ipu_di_use_count[1] == 1) {
ipu_conf |= IPU_CONF_DI1_EN;
+ clk_enable(g_di_clk[1]);
}
__raw_writel(ipu_conf, IPU_CONF);
if (idma_is_set(IDMAC_CHA_EN, in_dma) ||
idma_is_set(IDMAC_CHA_EN, out_dma)) {
- printf(
- "Channel %d is not disabled, disable first\n",
+ printf("Channel %d is not disabled, disable first\n",
IPU_CHAN_ID(channel));
return;
}
ipu_conf &= ~IPU_CONF_DP_EN;
if (ipu_dmfc_use_count == 0)
ipu_conf &= ~IPU_CONF_DMFC_EN;
- if (ipu_di_use_count[0] == 0) {
+ if (ipu_di_use_count[0] == 0 && ipu_conf & IPU_CONF_DI0_EN) {
ipu_conf &= ~IPU_CONF_DI0_EN;
+ clk_disable(g_di_clk[0]);
}
- if (ipu_di_use_count[1] == 0) {
+ if (ipu_di_use_count[1] == 0 && ipu_conf & IPU_CONF_DI1_EN) {
ipu_conf &= ~IPU_CONF_DI1_EN;
+ clk_disable(g_di_clk[1]);
}
__raw_writel(ipu_conf, IPU_CONF);
+ /* clear interrupt status */
+ __raw_writel(__raw_readl(IPU_STAT), IPU_STAT);
+
if (ipu_conf == 0) {
clk_disable(g_ipu_clk);
g_ipu_clk_enabled = 0;
}
-
}
static inline void ipu_ch_param_dump(int ch)
{
uint32_t u_offset = 0;
uint32_t v_offset = 0;
- struct ipu_ch_param params;
-
- memset(¶ms, 0, sizeof(params));
- ipu_ch_param_set_field(¶ms, 0, 125, 13, width - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 125, 13, width - 1);
if ((ch == 8) || (ch == 9) || (ch == 10)) {
- ipu_ch_param_set_field(¶ms, 0, 138, 12, (height / 2) - 1);
- ipu_ch_param_set_field(¶ms, 1, 102, 14, (stride * 2) - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 138, 12, (height / 2) - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 102, 14, (stride * 2) - 1);
} else {
- ipu_ch_param_set_field(¶ms, 0, 138, 12, height - 1);
- ipu_ch_param_set_field(¶ms, 1, 102, 14, stride - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 138, 12, height - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 102, 14, stride - 1);
}
- ipu_ch_param_set_field(¶ms, 1, 0, 29, addr0 >> 3);
- ipu_ch_param_set_field(¶ms, 1, 29, 29, addr1 >> 3);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 0, 29, addr0 >> 3);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 29, 29, addr1 >> 3);
switch (pixel_fmt) {
case IPU_PIX_FMT_GENERIC:
/*Represents 8-bit Generic data */
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 5); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 63); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 5); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 6); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 63); /* burst size */
break;
case IPU_PIX_FMT_GENERIC_32:
/*Represents 32-bit Generic data */
break;
case IPU_PIX_FMT_RGB565:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 15); /* burst size */
- ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16);
+ ipu_ch_params_set_packing(ipu_ch_param_addr(ch), 5, 0, 6, 5, 5, 11, 8, 16);
break;
case IPU_PIX_FMT_BGR24:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 1); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 19); /* burst size */
- ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
+ ipu_ch_params_set_packing(ipu_ch_param_addr(ch), 8, 0, 8, 8, 8, 16, 8, 24);
break;
case IPU_PIX_FMT_RGB24:
case IPU_PIX_FMT_YUV444:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 1); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 19); /* burst size */
- ipu_ch_params_set_packing(¶ms, 8, 16, 8, 8, 8, 0, 8, 24);
+ ipu_ch_params_set_packing(ipu_ch_param_addr(ch), 8, 16, 8, 8, 8, 0, 8, 24);
break;
case IPU_PIX_FMT_BGRA32:
case IPU_PIX_FMT_BGR32:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 15); /* burst size */
- ipu_ch_params_set_packing(¶ms, 8, 8, 8, 16, 8, 24, 8, 0);
+ ipu_ch_params_set_packing(ipu_ch_param_addr(ch), 8, 8, 8, 16, 8, 24, 8, 0);
break;
case IPU_PIX_FMT_RGBA32:
case IPU_PIX_FMT_RGB32:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 15); /* burst size */
- ipu_ch_params_set_packing(¶ms, 8, 24, 8, 16, 8, 8, 8, 0);
+ ipu_ch_params_set_packing(ipu_ch_param_addr(ch), 8, 24, 8, 16, 8, 8, 8, 0);
break;
case IPU_PIX_FMT_ABGR32:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 0); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 7); /* pix format */
- ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
+ ipu_ch_params_set_packing(ipu_ch_param_addr(ch), 8, 0, 8, 8, 8, 16, 8, 24);
break;
case IPU_PIX_FMT_UYVY:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 0xA); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 0xA); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 15); /* burst size */
break;
case IPU_PIX_FMT_YUYV:
- ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 0x8); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 107, 3, 3); /* bits/pixel */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 0x8); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 31); /* burst size */
break;
case IPU_PIX_FMT_YUV420P2:
case IPU_PIX_FMT_YUV420P:
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 2); /* pix format */
if (uv_stride < stride / 2)
uv_stride = stride / 2;
v_offset = u_offset + (uv_stride * height / 2);
/* burst size */
if ((ch == 8) || (ch == 9) || (ch == 10)) {
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 15);
uv_stride = uv_stride*2;
} else {
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 31);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 31);
}
break;
case IPU_PIX_FMT_YVU422P:
/* BPP & pixel format */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 1); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 31); /* burst size */
if (uv_stride < stride / 2)
uv_stride = stride / 2;
break;
case IPU_PIX_FMT_YUV422P:
/* BPP & pixel format */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 1); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 31); /* burst size */
if (uv_stride < stride / 2)
uv_stride = stride / 2;
break;
case IPU_PIX_FMT_NV12:
/* BPP & pixel format */
- ipu_ch_param_set_field(¶ms, 1, 85, 4, 4); /* pix format */
- ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 85, 4, 4); /* pix format */
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 78, 7, 31); /* burst size */
uv_stride = stride;
u_offset = (u == 0) ? stride * height : u;
break;
default:
- puts("mxc ipu: unimplemented pixel format\n");
- break;
+ printf("mxc ipu: unimplemented pixel format: %08x\n",
+ pixel_fmt);
}
if (uv_stride)
- ipu_ch_param_set_field(¶ms, 1, 128, 14, uv_stride - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 1, 128, 14, uv_stride - 1);
/* Get the uv offset from user when need cropping */
if (u || v) {
if (v_offset/8 > 0x3fffff)
puts("The value of V offset exceeds IPU limitation\n");
- ipu_ch_param_set_field(¶ms, 0, 46, 22, u_offset / 8);
- ipu_ch_param_set_field(¶ms, 0, 68, 22, v_offset / 8);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 46, 22, u_offset / 8);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 68, 22, v_offset / 8);
debug("initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ch));
- memcpy(ipu_ch_param_addr(ch), ¶ms, sizeof(params));
};
/*
stride = width * bytes_per_pixel(pixel_fmt);
if (stride % 4) {
- printf(
- "Stride not 32-bit aligned, stride = %d\n", stride);
+ printf("Stride %d not 32-bit aligned\n", stride);
return -EINVAL;
}
/* Build parameter memory data for DMA channel */
}
if ((channel == MEM_DC_SYNC) || (channel == MEM_BG_SYNC) ||
- (channel == MEM_FG_SYNC))
+ (channel == MEM_FG_SYNC)) {
+ reg = __raw_readl(IDMAC_WM_EN(in_dma));
+ __raw_writel(reg | idma_mask(in_dma), IDMAC_WM_EN(in_dma));
+
ipu_dp_dc_enable(channel);
+ }
g_channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
uint32_t bytes_per_pixel(uint32_t fmt)
{
switch (fmt) {
- case IPU_PIX_FMT_GENERIC: /*generic data */
+ case IPU_PIX_FMT_GENERIC: /* generic data */
case IPU_PIX_FMT_RGB332:
case IPU_PIX_FMT_YUV420P:
case IPU_PIX_FMT_YUV422P:
return 1;
- break;
case IPU_PIX_FMT_RGB565:
case IPU_PIX_FMT_YUYV:
case IPU_PIX_FMT_UYVY:
return 2;
- break;
case IPU_PIX_FMT_BGR24:
case IPU_PIX_FMT_RGB24:
return 3;
- break;
- case IPU_PIX_FMT_GENERIC_32: /*generic data */
+ case IPU_PIX_FMT_GENERIC_32: /* generic data */
case IPU_PIX_FMT_BGR32:
case IPU_PIX_FMT_BGRA32:
case IPU_PIX_FMT_RGB32:
case IPU_PIX_FMT_RGBA32:
case IPU_PIX_FMT_ABGR32:
return 4;
- break;
default:
return 1;
- break;
}
return 0;
}
case IPU_PIX_FMT_LVDS666:
case IPU_PIX_FMT_LVDS888:
return RGB;
- break;
default:
return YCbCr;
- break;
}
return RGB;
}
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
- * Linux IPU driver for MX51:
+ * Linux IPU driver
*
- * (C) Copyright 2005-2010 Freescale Semiconductor, Inc.
+ * (C) Copyright 2005-2011 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* #define DEBUG */
#include <common.h>
+ #include <ipu.h>
#include <linux/types.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
- #include "ipu.h"
#include "ipu_regs.h"
enum csc_type_t {
struct dp_csc_param_t {
int mode;
- void *coeff;
+ const int (*coeff)[5][3];
};
#define SYNC_WAVE 0
#define DC_DISP_ID_SERIAL 2
#define DC_DISP_ID_ASYNC 3
- int dmfc_type_setup;
+ static int dmfc_type_setup;
static int dmfc_size_28, dmfc_size_29, dmfc_size_24, dmfc_size_27, dmfc_size_23;
- int g_di1_tvout;
-
- extern struct clk *g_ipu_clk;
- extern struct clk *g_ldb_clk;
- extern struct clk *g_di_clk[2];
- extern struct clk *g_pixel_clk[2];
-
- extern unsigned char g_ipu_clk_enabled;
- extern unsigned char g_dc_di_assignment[];
+ static int g_di1_tvout;
void ipu_dmfc_init(int dmfc_type, int first)
{
static enum csc_type_t fg_csc_type = CSC_NONE, bg_csc_type = CSC_NONE;
static int color_key_4rgb = 1;
-void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
+static void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
unsigned char srm_mode_update)
{
u32 reg;
}
}
-int ipu_chan_is_interlaced(ipu_channel_t channel)
-{
- if (channel == MEM_DC_SYNC)
- return !!(__raw_readl(DC_WR_CH_CONF_1) &
- DC_WR_CH_CONF_FIELD_MODE);
- else if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))
- return !!(__raw_readl(DC_WR_CH_CONF_5) &
- DC_WR_CH_CONF_FIELD_MODE);
- return 0;
-}
-
void ipu_dp_dc_enable(ipu_channel_t channel)
{
int di;
uint32_t csc;
uint32_t dc_chan = 0;
int timeout = 50;
+ int irq = 0;
dc_swap = swap;
if (channel == MEM_DC_SYNC) {
dc_chan = 1;
+ irq = IPU_IRQ_DC_FC_1;
} else if (channel == MEM_BG_SYNC) {
dc_chan = 5;
+ irq = IPU_IRQ_DP_SF_END;
} else if (channel == MEM_FG_SYNC) {
/* Disable FG channel */
dc_chan = 5;
reg ^= DC_WR_CH_CONF_PROG_DI_ID;
__raw_writel(reg, DC_WR_CH_CONF(dc_chan));
} else {
- timeout = 50;
-
- /* Wait for DC triple buffer to empty */
- if (g_dc_di_assignment[dc_chan] == 0)
- while ((__raw_readl(DC_STAT) & 0x00000002)
- != 0x00000002) {
- udelay(2000);
- timeout -= 2;
- if (timeout <= 0)
- break;
- }
- else if (g_dc_di_assignment[dc_chan] == 1)
- while ((__raw_readl(DC_STAT) & 0x00000020)
- != 0x00000020) {
- udelay(2000);
- timeout -= 2;
- if (timeout <= 0)
- break;
- }
+ /* Make sure that we leave at the irq starting edge */
+ __raw_writel(IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
+ do {
+ reg = __raw_readl(IPUIRQ_2_STATREG(irq));
+ } while (!(reg & IPUIRQ_2_MASK(irq)));
reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
/* IPU_PIX_FMT_LVDS666 */
ipu_dc_map_clear(4);
ipu_dc_map_config(4, 0, 5, 0xFC);
- ipu_dc_map_config(4, 1, 13, 0xFC);
- ipu_dc_map_config(4, 2, 21, 0xFC);
+ ipu_dc_map_config(4, 1, 11, 0xFC);
+ ipu_dc_map_config(4, 2, 17, 0xFC);
}
-int ipu_pixfmt_to_map(uint32_t fmt)
+static int ipu_pixfmt_to_map(uint32_t fmt)
{
switch (fmt) {
case IPU_PIX_FMT_GENERIC:
case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_LVDS888:
return 0;
case IPU_PIX_FMT_RGB666:
return 1;
return 4;
}
- return -1;
+ return -EINVAL;
}
-/*
- * This function is called to adapt synchronous LCD panel to IPU restriction.
- */
-void adapt_panel_to_ipu_restricitions(uint32_t *pixel_clk,
- uint16_t width, uint16_t height,
- uint16_t h_start_width,
- uint16_t h_end_width,
- uint16_t v_start_width,
- uint16_t *v_end_width)
-{
- if (*v_end_width < 2) {
- uint16_t total_width = width + h_start_width + h_end_width;
- uint16_t total_height_old = height + v_start_width +
- (*v_end_width);
- uint16_t total_height_new = height + v_start_width + 2;
- *v_end_width = 2;
- *pixel_clk = (*pixel_clk) * total_width * total_height_new /
- (total_width * total_height_old);
- printf("WARNING: adapt panel end blank lines\n");
- }
-}
-
/*
* This function is called to initialize a synchronous LCD panel.
*
* fail.
*/
- int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
- uint16_t width, uint16_t height,
- uint32_t pixel_fmt,
- uint16_t h_start_width, uint16_t h_sync_width,
- uint16_t h_end_width, uint16_t v_start_width,
- uint16_t v_sync_width, uint16_t v_end_width,
- uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
+ int ipu_init_sync_panel(int disp, uint32_t pixel_clk,
+ uint16_t width, uint16_t height,
+ uint32_t pixel_fmt,
+ uint16_t h_start_width, uint16_t h_sync_width,
+ uint16_t h_end_width, uint16_t v_start_width,
+ uint16_t v_sync_width, uint16_t v_end_width,
+ uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
{
uint32_t reg;
uint32_t di_gen, vsync_cnt;
if ((v_sync_width == 0) || (h_sync_width == 0))
return -EINVAL;
- adapt_panel_to_ipu_restricitions(&pixel_clk, width, height,
- h_start_width, h_end_width,
- v_start_width, &v_end_width);
+ /* adapt panel to ipu restricitions */
+ if (v_end_width < 2) {
+ v_end_width = 2;
+ puts("WARNING: v_end_width (lower_margin) must be >= 2, adjusted\n");
+ }
+
h_total = width + h_sync_width + h_start_width + h_end_width;
v_total = height + v_sync_width + v_start_width + v_end_width;
/* Init clocking */
- debug("pixel clk = %d\n", pixel_clk);
+ debug("pixel clk = %dHz\n", pixel_clk);
if (sig.ext_clk) {
- if (!(g_di1_tvout && (disp == 1))) { /*not round div for tvout*/
+ if (!(g_di1_tvout && (disp == 1))) { /* don't round div for tvout */
/*
* Set the PLL to be an even multiple
* of the pixel clock.
rounded_pixel_clk =
clk_round_rate(g_pixel_clk[disp],
pixel_clk);
- div = clk_get_rate(di_parent) /
- rounded_pixel_clk;
- if (div % 2)
- div++;
- if (clk_get_rate(di_parent) != div *
- rounded_pixel_clk)
- clk_set_rate(di_parent,
- div * rounded_pixel_clk);
- udelay(10000);
- clk_set_rate(g_di_clk[disp],
- 2 * rounded_pixel_clk);
- udelay(10000);
+ if (di_parent != NULL) {
+ div = clk_get_rate(di_parent) /
+ rounded_pixel_clk;
+ if (div % 2)
+ div++;
+ if (clk_get_rate(di_parent) != div *
+ rounded_pixel_clk)
+ clk_set_rate(di_parent,
+ div * rounded_pixel_clk);
+ udelay(10000);
+ clk_set_rate(g_di_clk[disp],
+ 2 * rounded_pixel_clk);
+ udelay(10000);
+ }
}
}
clk_set_parent(g_pixel_clk[disp], g_ldb_clk);
if (clk_get_usecount(g_pixel_clk[disp]) != 0)
clk_set_parent(g_pixel_clk[disp], g_ipu_clk);
}
- rounded_pixel_clk = clk_round_rate(g_pixel_clk[disp], pixel_clk);
- clk_set_rate(g_pixel_clk[disp], rounded_pixel_clk);
- udelay(5000);
- /* Get integer portion of divider */
- div = clk_get_rate(clk_get_parent(g_pixel_clk[disp])) /
- rounded_pixel_clk;
-
- ipu_di_data_wave_config(disp, SYNC_WAVE, div - 1, div - 1);
+
+ /* Enable for a divide by 2 clock change. */
+ reg = __raw_readl(IPU_PM);
+ reg &= ~(0x7f << 7);
+ reg |= 0x20 << 7;
+ reg &= ~(0x7f << 23);
+ reg |= 0x20 << 23;
+ __raw_writel(reg, IPU_PM);
+
+ di_gen = 0;
+
+ if (pixel_fmt != IPU_PIX_FMT_LVDS666 &&
+ pixel_fmt != IPU_PIX_FMT_LVDS888) {
+ rounded_pixel_clk = clk_round_rate(g_pixel_clk[disp], pixel_clk);
+ clk_set_rate(g_pixel_clk[disp], rounded_pixel_clk);
+ udelay(5000);
+ /* Get integer portion of divider */
+ div = clk_get_rate(clk_get_parent(g_pixel_clk[disp])) /
+ rounded_pixel_clk;
+ ipu_di_data_wave_config(disp, SYNC_WAVE, div - 1, div - 1);
+ } else {
+ rounded_pixel_clk = clk_get_rate(clk_get_parent(g_pixel_clk[disp]));
+ clk_set_rate(g_pixel_clk[disp], rounded_pixel_clk);
+ div = 1;
+ ipu_di_data_wave_config(disp, SYNC_WAVE, 0, 0);
+ di_gen |= (6 << 24);
+ di_gen |= DI_GEN_DI_CLK_EXT;
+ }
ipu_di_data_pin_config(disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
map = ipu_pixfmt_to_map(pixel_fmt);
if (map < 0) {
- debug("IPU_DISP: No MAP\n");
- return -EINVAL;
+ printf("IPU_DISP: No MAP for pixel format: %c%c%c%c\n",
+ pixel_fmt, pixel_fmt >> 8, pixel_fmt >> 16,
+ pixel_fmt >> 24);
+ return map;
}
- di_gen = __raw_readl(DI_GENERAL(disp));
-
if (sig.interlaced) {
/* Setup internal HSYNC waveform */
ipu_di_sync_config(
/* set gentime select and tag sel */
reg = __raw_readl(DI_SW_GEN1(disp, 9));
reg &= 0x1FFFFFFF;
- reg |= (3 - 1)<<29 | 0x00008000;
+ reg |= ((3 - 1) << 29) | 0x00008000;
__raw_writel(reg, DI_SW_GEN1(disp, 9));
__raw_writel(v_total / 2 - 1, DI_SCR_CONF(disp));
__raw_writel(0, DI_STP_REP(disp, 7));
__raw_writel(0, DI_STP_REP(disp, 9));
+ h_total = ((width + h_start_width + h_sync_width) / 2) - 2;
+ ipu_di_sync_config(disp, 6, 1, 0, 2, DI_SYNC_CLK, h_total,
+ DI_SYNC_INT_HSYNC, 0, DI_SYNC_NONE,
+ DI_SYNC_NONE, 0, 0);
+
/* Init template microcode */
if (disp) {
- ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5);
- ipu_dc_write_tmpl(3, WROD(0), 0, map, SYNC_WAVE, 4, 5);
- ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5);
+ ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5);
+ ipu_dc_write_tmpl(3, WROD(0), 0, map, SYNC_WAVE, 4, 5);
+ ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5);
} else {
- ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5);
- ipu_dc_write_tmpl(6, WROD(0), 0, map, SYNC_WAVE, 4, 5);
- ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5);
+ ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5);
+ ipu_dc_write_tmpl(6, WROD(0), 0, map, SYNC_WAVE, 4, 5);
+ ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5);
}
if (sig.Hsync_pol)
if (sig.Vsync_pol)
di_gen |= DI_GEN_POLARITY_3;
- if (sig.clk_pol)
+ if (!sig.clk_pol)
di_gen |= DI_GEN_POL_CLK;
+ /* Set the clock to stop at counter 6. */
+ di_gen |= 0x6000000;
}
__raw_writel(di_gen, DI_GENERAL(disp));
- __raw_writel((--vsync_cnt << DI_VSYNC_SEL_OFFSET) |
- 0x00000002, DI_SYNC_AS_GEN(disp));
+ if (sig.interlaced)
+ __raw_writel((--vsync_cnt << DI_VSYNC_SEL_OFFSET) |
+ 0x00000002, DI_SYNC_AS_GEN(disp));
+ else
+ __raw_writel((--vsync_cnt << DI_VSYNC_SEL_OFFSET),
+ DI_SYNC_AS_GEN(disp));
reg = __raw_readl(DI_POL(disp));
reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
*
* @return Returns 0 on success or negative error code on fail
*/
- int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable,
+ int ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable,
uint8_t alpha)
{
+ int ret;
uint32_t reg;
unsigned char bg_chan;
else
bg_chan = 0;
- if (!g_ipu_clk_enabled)
- clk_enable(g_ipu_clk);
+ ret = clk_enable(g_ipu_clk);
+ if (ret)
+ return ret;
if (bg_chan) {
reg = __raw_readl(DP_COM_CONF());
reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
__raw_writel(reg, IPU_SRM_PRI2);
- if (!g_ipu_clk_enabled)
- clk_disable(g_ipu_clk);
+ clk_disable(g_ipu_clk);
return 0;
}
*
* @return Returns 0 on success or negative error code on fail
*/
- int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable,
+ int ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable,
uint32_t color_key)
{
+ int ret;
uint32_t reg;
int y, u, v;
int red, green, blue;
(channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)))
return -EINVAL;
- if (!g_ipu_clk_enabled)
- clk_enable(g_ipu_clk);
+ ret = clk_enable(g_ipu_clk);
+ if (ret)
+ return ret;
color_key_4rgb = 1;
/* Transform color key from rgb to yuv if CSC is enabled */
reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
__raw_writel(reg, IPU_SRM_PRI2);
- if (!g_ipu_clk_enabled)
- clk_disable(g_ipu_clk);
+ clk_disable(g_ipu_clk);
return 0;
}
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
- * Linux IPU driver for MX51:
+ * Linux IPU driver:
*
- * (C) Copyright 2005-2009 Freescale Semiconductor, Inc.
+ * (C) Copyright 2005-2011 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __IPU_REGS_INCLUDED__
#define __IPU_REGS_INCLUDED__
+ #include <asm/arch/imx-regs.h>
+
#define IPU_DISP0_BASE 0x00000000
#define IPU_MCU_T_DEFAULT 8
- #define IPU_DISP1_BASE (IPU_MCU_T_DEFAULT << 25)
+ #define IPU_DISP1_BASE (gd->arch.ipu_hw_rev < IPUV3_HW_REV_IPUV3H ? \
+ (IPU_MCU_T_DEFAULT << 25) : \
+ 0x00000000)
+
+ #define IPUV3DEX_REG_BASE 0x1E000000
+ #define IPUV3M_REG_BASE 0x1E000000
+ #define IPUV3H_REG_BASE 0x00200000
+
#define IPU_CM_REG_BASE 0x00000000
#define IPU_STAT_REG_BASE 0x00000200
#define IPU_IDMAC_REG_BASE 0x00008000
#define IPU_SMFC_REG_BASE 0x00050000
#define IPU_DC_REG_BASE 0x00058000
#define IPU_DMFC_REG_BASE 0x00060000
- #define IPU_VDI_REG_BASE 0x00680000
- #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
- #define IPU_CPMEM_REG_BASE 0x01000000
- #define IPU_LUT_REG_BASE 0x01020000
- #define IPU_SRM_REG_BASE 0x01040000
- #define IPU_TPM_REG_BASE 0x01060000
- #define IPU_DC_TMPL_REG_BASE 0x01080000
- #define IPU_ISP_TBPR_REG_BASE 0x010C0000
- #elif defined(CONFIG_MX6)
- #define IPU_CPMEM_REG_BASE 0x00100000
- #define IPU_LUT_REG_BASE 0x00120000
- #define IPU_SRM_REG_BASE 0x00140000
- #define IPU_TPM_REG_BASE 0x00160000
- #define IPU_DC_TMPL_REG_BASE 0x00180000
- #define IPU_ISP_TBPR_REG_BASE 0x001C0000
- #endif
-
- #define IPU_CTRL_BASE_ADDR (IPU_SOC_BASE_ADDR + IPU_SOC_OFFSET)
+ #define IPU_VDI_REG_BASE 0x00068000
+ #define IPU_CPMEM_REG_BASE (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ 0x00100000 : \
+ 0x01000000)
+ #define IPU_LUT_REG_BASE (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ 0x00120000 : \
+ 0x01020000)
+ #define IPU_SRM_REG_BASE (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ 0x00140000 : \
+ 0x01040000)
+ #define IPU_TPM_REG_BASE (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ 0x00160000 : \
+ 0x01060000)
+ #define IPU_DC_TMPL_REG_BASE (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ 0x00180000 : \
+ 0x01080000)
+ #define IPU_ISP_TBPR_REG_BASE (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ 0x001C0000 : \
+ 0x010C0000)
+
+ #define IPU_DISP_REG_BASE_ADDR (gd->arch.ipu_hw_rev >= IPUV3_HW_REV_IPUV3H ? \
+ IPU_SOC_BASE_ADDR + IPUV3H_REG_BASE : \
+ IPU_SOC_BASE_ADDR + IPUV3M_REG_BASE)
extern u32 *ipu_dc_tmpl_reg;
+ extern struct clk *g_ipu_clk;
+ extern struct clk *g_ldb_clk;
+ extern struct clk *g_di_clk[2];
+ extern struct clk *g_pixel_clk[2];
+
+ extern int g_ipu_clk_enabled;
+ extern unsigned char g_dc_di_assignment[];
#define DC_EVT_NF 0
#define DC_EVT_NL 1
DI_DW_GEN_ACCESS_SIZE_OFFSET = 24,
DI_DW_GEN_COMPONENT_SIZE_OFFSET = 16,
- DI_GEN_DI_CLK_EXT = 0x100000,
+ DI_GEN_DI_CLK_EXT = 0x00100000,
DI_GEN_POLARITY_1 = 0x00000001,
DI_GEN_POLARITY_2 = 0x00000002,
DI_GEN_POLARITY_3 = 0x00000004,
DI_GEN_POLARITY_6 = 0x00000020,
DI_GEN_POLARITY_7 = 0x00000040,
DI_GEN_POLARITY_8 = 0x00000080,
- DI_GEN_POL_CLK = 0x20000,
+ DI_GEN_POL_CLK = 0x00020000,
DI_POL_DRDY_DATA_POLARITY = 0x00000080,
DI_POL_DRDY_POLARITY_15 = 0x00000010,
u32 gpr;
u32 reserved0[26];
u32 ch_db_mode_sel[2];
- u32 reserved1[16];
+ u32 reserved1[4];
u32 alt_ch_db_mode_sel[2];
u32 reserved2[2];
u32 ch_trb_mode_sel[2];
u32 sub_addr[5];
u32 bndm_en[2];
u32 sc_cord[2];
- u32 reserved[45];
+ u32 reserved[44];
u32 ch_busy[2];
};
u32 stat;
};
- #define IPU_CM_REG ((struct ipu_cm *)(IPU_CTRL_BASE_ADDR + \
+ #define IPU_CM_REG ((struct ipu_cm *)(IPU_DISP_REG_BASE_ADDR + \
IPU_CM_REG_BASE))
#define IPU_CONF (&IPU_CM_REG->conf)
#define IPU_SRM_PRI1 (&IPU_CM_REG->srm_pri1)
#define IPU_FS_DISP_FLOW1 (&IPU_CM_REG->fs_disp_flow[0])
#define IPU_DISP_GEN (&IPU_CM_REG->disp_gen)
#define IPU_MEM_RST (&IPU_CM_REG->mem_rst)
+ #define IPU_PM (&IPU_CM_REG->pm)
#define IPU_GPR (&IPU_CM_REG->gpr)
- #define IPU_CHA_DB_MODE_SEL(ch) (&IPU_CM_REG->ch_db_mode_sel[ch / 32])
+ #define IPU_CHA_DB_MODE_SEL(ch) (&IPU_CM_REG->ch_db_mode_sel[(ch) / 32])
- #define IPU_STAT ((struct ipu_stat *)(IPU_CTRL_BASE_ADDR + \
+ #define IPU_STAT ((struct ipu_stat *)(IPU_DISP_REG_BASE_ADDR + \
IPU_STAT_REG_BASE))
- #define IPU_CHA_CUR_BUF(ch) (&IPU_STAT->cur_buf[ch / 32])
- #define IPU_CHA_BUF0_RDY(ch) (&IPU_STAT->ch_buf0_rdy[ch / 32])
- #define IPU_CHA_BUF1_RDY(ch) (&IPU_STAT->ch_buf1_rdy[ch / 32])
+#define IPU_INT_STAT(n) (&IPU_STAT->int_stat[(n) - 1])
+ #define IPU_CHA_CUR_BUF(ch) (&IPU_STAT->cur_buf[(ch) / 32])
+ #define IPU_CHA_BUF0_RDY(ch) (&IPU_STAT->ch_buf0_rdy[(ch) / 32])
+ #define IPU_CHA_BUF1_RDY(ch) (&IPU_STAT->ch_buf1_rdy[(ch) / 32])
+#define IPUIRQ_2_STATREG(irq) (IPU_INT_STAT(1) + ((irq) / 32))
+#define IPUIRQ_2_MASK(irq) (1UL << ((irq) & 0x1F))
#define IPU_INT_CTRL(n) (&IPU_CM_REG->int_ctrl[(n) - 1])
- #define IDMAC_REG ((struct ipu_idmac *)(IPU_CTRL_BASE_ADDR + \
+ #define IDMAC_REG ((struct ipu_idmac *)(IPU_DISP_REG_BASE_ADDR + \
IPU_IDMAC_REG_BASE))
#define IDMAC_CONF (&IDMAC_REG->conf)
- #define IDMAC_CHA_EN(ch) (&IDMAC_REG->ch_en[ch / 32])
- #define IDMAC_CHA_PRI(ch) (&IDMAC_REG->ch_pri[ch / 32])
+ #define IDMAC_CHA_EN(ch) (&IDMAC_REG->ch_en[(ch) / 32])
+ #define IDMAC_CHA_PRI(ch) (&IDMAC_REG->ch_pri[(ch) / 32])
+ #define IDMAC_WM_EN(ch) (&IDMAC_REG->wm_en[(ch) / 32])
+
+ #define DI_REG(di) ((struct ipu_di *)(IPU_DISP_REG_BASE_ADDR + \
+ (((di) == 1) ? IPU_DI1_REG_BASE : \
+ IPU_DI0_REG_BASE)))
- #define DI_REG(di) ((struct ipu_di *)(IPU_CTRL_BASE_ADDR + \
- ((di == 1) ? IPU_DI1_REG_BASE : \
- IPU_DI0_REG_BASE)))
#define DI_GENERAL(di) (&DI_REG(di)->general)
#define DI_BS_CLKGEN0(di) (&DI_REG(di)->bs_clkgen0)
#define DI_BS_CLKGEN1(di) (&DI_REG(di)->bs_clkgen1)
- #define DI_SW_GEN0(di, gen) (&DI_REG(di)->sw_gen0[gen - 1])
- #define DI_SW_GEN1(di, gen) (&DI_REG(di)->sw_gen1[gen - 1])
- #define DI_STP_REP(di, gen) (&DI_REG(di)->stp_rep[(gen - 1) / 2])
+ #define DI_SW_GEN0(di, gen) (&DI_REG(di)->sw_gen0[(gen) - 1])
+ #define DI_SW_GEN1(di, gen) (&DI_REG(di)->sw_gen1[(gen) - 1])
+ #define DI_STP_REP(di, gen) (&DI_REG(di)->stp_rep[((gen) - 1) / 2])
#define DI_SYNC_AS_GEN(di) (&DI_REG(di)->sync_as)
#define DI_DW_GEN(di, gen) (&DI_REG(di)->dw_gen[gen])
- #define DI_DW_SET(di, gen, set) (&DI_REG(di)->dw_set[gen + 12 * set])
+ #define DI_DW_SET(di, gen, set) (&DI_REG(di)->dw_set[(gen) + 12 * set])
#define DI_POL(di) (&DI_REG(di)->pol)
#define DI_SCR_CONF(di) (&DI_REG(di)->scr_conf)
- #define DMFC_REG ((struct ipu_dmfc *)(IPU_CTRL_BASE_ADDR + \
+ #define DMFC_REG ((struct ipu_dmfc *)(IPU_DISP_REG_BASE_ADDR + \
IPU_DMFC_REG_BASE))
#define DMFC_WR_CHAN (&DMFC_REG->wr_chan)
#define DMFC_WR_CHAN_DEF (&DMFC_REG->wr_chan_def)
#define DMFC_GENERAL1 (&DMFC_REG->general[0])
#define DMFC_IC_CTRL (&DMFC_REG->ic_ctrl)
-
- #define DC_REG ((struct ipu_dc *)(IPU_CTRL_BASE_ADDR + \
+ #define DC_REG ((struct ipu_dc *)(IPU_DISP_REG_BASE_ADDR + \
IPU_DC_REG_BASE))
- #define DC_MAP_CONF_PTR(n) (&DC_REG->dc_map_ptr[n / 2])
- #define DC_MAP_CONF_VAL(n) (&DC_REG->dc_map_val[n / 2])
+ #define DC_MAP_CONF_PTR(n) (&DC_REG->dc_map_ptr[(n) / 2])
+ #define DC_MAP_CONF_VAL(n) (&DC_REG->dc_map_val[(n) / 2])
+ DECLARE_GLOBAL_DATA_PTR;
static inline struct ipu_dc_ch *dc_ch_offset(int ch)
{
printf("%s: invalid channel %d\n", __func__, ch);
return NULL;
}
-
}
- #define DC_RL_CH(ch, evt) (&dc_ch_offset(ch)->rl[evt / 2])
+ #define DC_RL_CH(ch, evt) (&dc_ch_offset(ch)->rl[(evt) / 2])
#define DC_WR_CH_CONF(ch) (&dc_ch_offset(ch)->wr_ch_conf)
#define DC_WR_CH_ADDR(ch) (&dc_ch_offset(ch)->wr_ch_addr)
#define DP_ASYNC0 0x60
#define DP_ASYNC1 0xBC
- #define DP_REG ((struct ipu_dp *)(IPU_CTRL_BASE_ADDR + \
+ #define DP_REG ((struct ipu_dp *)(IPU_DISP_REG_BASE_ADDR + \
IPU_DP_REG_BASE))
#define DP_COM_CONF() (&DP_REG->com_conf_sync)
#define DP_GRAPH_WIND_CTRL() (&DP_REG->graph_wind_ctrl_sync)
#define DP_CSC_1() (&DP_REG->csc_sync[1])
/* DC template opcodes */
- #define WROD(lf) (0x18 | (lf << 1))
+ #define WROD(lf) (0x18 | ((lf) << 1))
#endif
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
- * MX51 Linux framebuffer:
+ * IPUv3 Linux framebuffer:
*
- * (C) Copyright 2004-2010 Freescale Semiconductor, Inc.
+ * (C) Copyright 2004-2011 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
+ /* #define DEBUG */
#include <common.h>
#include <asm/errno.h>
+#include <asm/global_data.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/fb.h>
#include <asm/io.h>
#include <malloc.h>
+ #include <lcd.h>
+ #include <ipu.h>
#include <video_fb.h>
- #include "videomodes.h"
- #include "ipu.h"
- #include "mxcfb.h"
+ #include <mxcfb.h>
+
#include "ipu_regs.h"
+ #include "videomodes.h"
DECLARE_GLOBAL_DATA_PTR;
static int mxcfb_map_video_memory(struct fb_info *fbi);
static int mxcfb_unmap_video_memory(struct fb_info *fbi);
- /* graphics setup */
- static GraphicDevice panel;
- static struct fb_videomode const *gmode;
- static uint8_t gdisp;
- static uint32_t gpixfmt;
+ void lcd_initcolregs(void)
+ {
+ }
+
+ void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
+ {
+ }
static void fb_videomode_to_var(struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
case 16:
pixfmt = IPU_PIX_FMT_RGB565;
break;
+ case 8:
+ pixfmt = IPU_PIX_FMT_GENERIC;
}
return pixfmt;
}
static int setup_disp_channel1(struct fb_info *fbi)
{
ipu_channel_params_t params;
- struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ struct mxcfb_info *mxc_fbi = fbi->par;
memset(¶ms, 0, sizeof(params));
params.mem_dp_bg_sync.di = mxc_fbi->ipu_di;
static int setup_disp_channel2(struct fb_info *fbi)
{
int retval = 0;
- struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ struct mxcfb_info *mxc_fbi = fbi->par;
mxc_fbi->cur_ipu_buf = 1;
if (mxc_fbi->alpha_chan_en)
fbi->var.xoffset = fbi->var.yoffset = 0;
- debug("%s: %x %d %d %d %lx %lx\n",
+ debug("%s: ch: %08x xres: %d yres: %d line_length: %d mem: %08lx .. %08lx\n",
__func__,
mxc_fbi->ipu_ch,
fbi->var.xres,
fbi->fix.line_length,
fbi->fix.smem_start,
fbi->fix.smem_start +
- (fbi->fix.line_length * fbi->var.yres));
+ (fbi->fix.line_length * fbi->var.yres) - 1);
retval = ipu_init_channel_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
bpp_to_pixfmt(fbi),
int retval = 0;
u32 mem_len;
ipu_di_signal_cfg_t sig_cfg;
- struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
+ struct mxcfb_info *mxc_fbi = fbi->par;
uint32_t out_pixel_fmt;
ipu_disable_channel(mxc_fbi->ipu_ch);
if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
sig_cfg.clkidle_en = 1;
- debug("pixclock = %lu Hz\n", PICOS2KHZ(fbi->var.pixclock) * 1000UL);
+ debug("pixclock = %lu.%03lu MHz\n",
+ PICOS2KHZ(fbi->var.pixclock) / 1000,
+ PICOS2KHZ(fbi->var.pixclock) % 1000);
- if (ipu_init_sync_panel(mxc_fbi->ipu_di,
+ retval = ipu_init_sync_panel(mxc_fbi->ipu_di,
(PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
fbi->var.xres, fbi->var.yres,
out_pixel_fmt,
fbi->var.upper_margin,
fbi->var.vsync_len,
fbi->var.lower_margin,
- 0, sig_cfg) != 0) {
- puts("mxcfb: Error initializing panel.\n");
- return -EINVAL;
+ 0, sig_cfg);
+ if (retval != 0) {
+ printf("mxc_ipuv3_fb: Error %d initializing panel\n", retval);
+ return retval;
}
retval = setup_disp_channel2(fbi);
fbi->fix.smem_len = fbi->var.yres_virtual *
fbi->fix.line_length;
}
- fbi->screen_base = (char *)memalign(ARCH_DMA_MINALIGN,
- fbi->fix.smem_len);
- fbi->fix.smem_start = (unsigned long)fbi->screen_base;
- if (fbi->screen_base == 0) {
++
+ fbi->fix.smem_len = roundup(fbi->fix.smem_len, ARCH_DMA_MINALIGN);
- fbi->screen_base = malloc(fbi->fix.smem_len);
+ if (gd->fb_base)
+ fbi->screen_base = (void *)gd->fb_base;
+ else
++ fbi->screen_base = (char *)memalign(ARCH_DMA_MINALIGN,
++ fbi->fix.smem_len);
+ if (fbi->screen_base == NULL) {
puts("Unable to allocate framebuffer memory\n");
fbi->fix.smem_len = 0;
- fbi->fix.smem_start = 0;
return -EBUSY;
}
+ fbi->fix.smem_start = (unsigned long)fbi->screen_base;
debug("allocated fb @ paddr=0x%08X, size=%d.\n",
(uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
fbi->screen_size = fbi->fix.smem_len;
- /* Clear the screen */
- memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
-
+ gd->fb_base = fbi->fix.smem_start;
+
return 0;
}
*/
static struct fb_info *mxcfb_init_fbinfo(void)
{
- #define BYTES_PER_LONG 4
- #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
struct fb_info *fbi;
struct mxcfb_info *mxcfbi;
- char *p;
- int size = sizeof(struct mxcfb_info) + PADDING +
+ void *p;
+ int size = ALIGN(sizeof(struct mxcfb_info), sizeof(long)) +
sizeof(struct fb_info);
- debug("%s: %d %d %d %d\n",
+ debug("%s: %d %d %d\n",
__func__,
- PADDING,
size,
sizeof(struct mxcfb_info),
sizeof(struct fb_info));
memset(p, 0, size);
- fbi = (struct fb_info *)p;
- fbi->par = p + sizeof(struct fb_info) + PADDING;
+ fbi = p;
+ fbi->par = p + ALIGN(sizeof(struct fb_info), sizeof(long));
- mxcfbi = (struct mxcfb_info *)fbi->par;
- debug("Framebuffer structures at: fbi=0x%x mxcfbi=0x%x\n",
- (unsigned int)fbi, (unsigned int)mxcfbi);
+ mxcfbi = fbi->par;
+ debug("Framebuffer structures at: fbi=%p mxcfbi=%p\n",
+ fbi, mxcfbi);
fbi->var.activate = FB_ACTIVATE_NOW;
/*
* Probe routine for the framebuffer driver. It is called during the
- * driver binding process. The following functions are performed in
+ * driver binding process. The following functions are performed in
* this routine: Framebuffer initialization, Memory allocation and
* mapping, Framebuffer registration, IPU initialization.
*
* @return Appropriate error code to the kernel common code
*/
- static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp,
- struct fb_videomode const *mode)
+ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode, int di)
{
struct fb_info *fbi;
struct mxcfb_info *mxcfbi;
- int ret = 0;
/*
* Initialize FB structures
*/
fbi = mxcfb_init_fbinfo();
- if (!fbi) {
- ret = -ENOMEM;
- goto err0;
- }
- mxcfbi = (struct mxcfb_info *)fbi->par;
+ if (!fbi)
+ return -ENOMEM;
+
+ mxcfbi = fbi->par;
if (!g_dp_in_use) {
mxcfbi->ipu_ch = MEM_BG_SYNC;
mxcfbi->blank = FB_BLANK_POWERDOWN;
}
- mxcfbi->ipu_di = disp;
+ mxcfbi->ipu_di = di;
ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80);
ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0);
mxcfb_info[mxcfbi->ipu_di] = fbi;
/* Need dummy values until real panel is configured */
+ fbi->var.xres = panel_info.vl_col;
+ fbi->var.yres = panel_info.vl_row;
mxcfbi->ipu_di_pix_fmt = interface_pix_fmt;
fb_videomode_to_var(&fbi->var, mode);
- fbi->var.bits_per_pixel = 16;
+ fbi->var.bits_per_pixel = NBITS(panel_info.vl_bpix);
fbi->fix.line_length = fbi->var.xres * (fbi->var.bits_per_pixel / 8);
fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length;
mxcfb_set_par(fbi);
- panel.winSizeX = mode->xres;
- panel.winSizeY = mode->yres;
- panel.plnSizeX = mode->xres;
- panel.plnSizeY = mode->yres;
+ lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
- panel.frameAdrs = (u32)fbi->screen_base;
- panel.memSize = fbi->screen_size;
-
- panel.gdfBytesPP = 2;
- panel.gdfIndex = GDF_16BIT_565RGB;
+ debug("MXC IPUV3 configured\n"
+ "XRES = %d YRES = %d BitsXpixel = %d\n",
+ panel_info.vl_col,
+ panel_info.vl_row,
+ panel_info.vl_bpix);
ipu_dump_registers();
return 0;
+ }
- err0:
- return ret;
+ ulong calc_fbsize(void)
+ {
+ return (panel_info.vl_col * panel_info.vl_row *
+ NBITS(panel_info.vl_bpix)) / 8;
}
void ipuv3_fb_shutdown(void)
ipu_uninit_channel(mxc_fbi->ipu_ch);
}
}
+ clk_enable(g_ipu_clk);
for (i = 0; i < ARRAY_SIZE(stat->int_stat); i++) {
__raw_writel(__raw_readl(&stat->int_stat[i]),
&stat->int_stat[i]);
}
+ clk_disable(g_ipu_clk);
}
- void *video_hw_init(void)
+ int ipuv3_fb_init(struct fb_videomode *mode, int di, unsigned int interface_pix_fmt,
+ ipu_di_clk_parent_t di_clk_parent, unsigned long di_clk_val, int bpp)
{
int ret;
- ret = ipu_probe();
- if (ret)
- puts("Error initializing IPU\n");
-
- ret = mxcfb_probe(gpixfmt, gdisp, gmode);
- debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs);
-
- return (void *)&panel;
- }
-
- void video_set_lut(unsigned int index, /* color number */
- unsigned char r, /* red */
- unsigned char g, /* green */
- unsigned char b /* blue */
- )
- {
- return;
- }
+ default_bpp = bpp;
- int ipuv3_fb_init(struct fb_videomode const *mode,
- uint8_t disp,
- uint32_t pixfmt)
- {
- gmode = mode;
- gdisp = disp;
- gpixfmt = pixfmt;
+ ret = ipu_probe(di, di_clk_parent, di_clk_val);
+ if (ret) {
+ printf("Error initializing IPU\n");
+ return ret;
+ }
- return 0;
+ return mxcfb_probe(interface_pix_fmt, mode, di);
}
#include <common.h>
#include <malloc.h>
#include <video_fb.h>
+ #include <mxcfb.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
#include <asm/errno.h>
#include <asm/io.h>
+#include <asm/imx-common/dma.h>
+
#include "videomodes.h"
#define PS2KHZ(ps) (1000000000UL / (ps))
+ DECLARE_GLOBAL_DATA_PTR;
+
static GraphicDevice panel;
+struct mxs_dma_desc desc;
+
+/**
+ * mxsfb_system_setup() - Fine-tune LCDIF configuration
+ *
+ * This function is used to adjust the LCDIF configuration. This is usually
+ * needed when driving the controller in System-Mode to operate an 8080 or
+ * 6800 connected SmartLCD.
+ */
+__weak void mxsfb_system_setup(void)
+{
+}
/*
* DENX M28EVK:
* Freescale mx23evk/mx28evk with a Seiko 4.3'' WVGA panel:
* setenv videomode
* video=ctfb:x:800,y:480,depth:24,mode:0,pclk:29851,
- * le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
+ * le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
*/
static void mxs_lcd_init(GraphicDevice *panel,
struct ctfb_res_modes *mode, int bpp)
{
struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
- uint32_t word_len = 0, bus_width = 0;
- uint8_t valid_data = 0;
+ uint32_t word_len, bus_width;
+ uint8_t valid_data;
+ uint32_t vctrl0 = 0;
/* Kick in the LCDIF clock */
mxs_set_lcdclk(PS2KHZ(mode->pixclock));
bus_width = LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT;
valid_data = 0xf;
break;
+ default:
+ printf("Invalid color depth: %d\n", bpp);
+ hang();
}
writel(bus_width | word_len | LCDIF_CTRL_DOTCLK_MODE |
writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET,
®s->hw_lcdif_ctrl1);
+
+ mxsfb_system_setup();
+
writel((mode->yres << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | mode->xres,
®s->hw_lcdif_transfer_count);
- writel(LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL |
+ if (!(mode->sync & FB_SYNC_OE_LOW_ACT))
+ vctrl0 |= LCDIF_VDCTRL0_ENABLE_POL;
+
+ if (mode->sync & FB_SYNC_CLK_LAT_FALL)
+ vctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL;
+
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+ vctrl0 |= LCDIF_VDCTRL0_HSYNC_POL;
+
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ vctrl0 |= LCDIF_VDCTRL0_VSYNC_POL;
+
+ writel(vctrl0 | LCDIF_VDCTRL0_ENABLE_PRESENT |
LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT |
LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
mode->vsync_len, ®s->hw_lcdif_vdctrl0);
/* Flush FIFO first */
writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_set);
+#ifndef CONFIG_VIDEO_MXS_MODE_SYSTEM
/* Sync signals ON */
setbits_le32(®s->hw_lcdif_vdctrl4, LCDIF_VDCTRL4_SYNC_SIGNALS_ON);
+#endif
/* FIFO cleared */
writel(LCDIF_CTRL1_FIFO_CLEAR, ®s->hw_lcdif_ctrl1_clr);
{
int bpp = -1;
char *penv;
- void *fb;
struct ctfb_res_modes mode;
puts("Video: ");
panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP;
- /* Allocate framebuffer */
- fb = memalign(ARCH_DMA_MINALIGN,
- roundup(panel.memSize, ARCH_DMA_MINALIGN));
- if (!fb) {
- printf("MXSFB: Error allocating framebuffer!\n");
- return NULL;
- }
-
- /* Wipe framebuffer */
- memset(fb, 0, panel.memSize);
-
- panel.frameAdrs = (u32)fb;
+ panel.frameAdrs = gd->fb_base;
printf("%s\n", panel.modeIdent);
/* Start framebuffer */
mxs_lcd_init(&panel, &mode, bpp);
- return &panel;
+#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
+ /*
+ * If the LCD runs in system mode, the LCD refresh has to be triggered
+ * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid
+ * having to set this bit manually after every single change in the
+ * framebuffer memory, we set up specially crafted circular DMA, which
+ * sets the RUN bit, then waits until it gets cleared and repeats this
+ * infinitelly. This way, we get smooth continuous updates of the LCD.
+ */
+ struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+
+ memset(&desc, 0, sizeof(struct mxs_dma_desc));
+ desc.address = (dma_addr_t)&desc;
+ desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+ MXS_DMA_DESC_WAIT4END |
+ (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ desc.cmd.pio_words[0] = readl(®s->hw_lcdif_ctrl) | LCDIF_CTRL_RUN;
+ desc.cmd.next = (uint32_t)&desc.cmd;
+
+ /* Execute the DMA chain. */
+ mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc);
+#endif
+
+ return (void *)&panel;
}
--- /dev/null
++config HW_WATCHDOG
++ bool "Generic SoC specific watchdog support"
++ depends on !MX6
++
++config IMX_WATCHDOG
++ bool "Freescale i.MX watchdog support"
++ depends on MX31 || MX35 || MX5 || MX6 || VF610 || LS102XA
# SPDX-License-Identifier: GPL-2.0+
#
- obj-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o
- obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
- ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 vf610 ls102xa))
- obj-y += imx_watchdog.o
-include $(TOPDIR)/config.mk
-
-LIB := $(obj)libwatchdog.o
-
-COBJS-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o
-COBJS-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
-ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 vf610))
-COBJS-y += imx_watchdog.o
--endif
- obj-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o
- obj-$(CONFIG_S5P) += s5p_wdt.o
- obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
- obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
- obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
- obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
-COBJS-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o
-COBJS-$(CONFIG_S5P) += s5p_wdt.o
-COBJS-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
-COBJS-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
-
-COBJS := $(COBJS-y)
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(call cmd_link_o_target, $(OBJS))
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
++obj-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o
++obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o
++obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
++obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
++obj-$(CONFIG_IMX_WATCHDOG) += imx_watchdog.o
++obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
++obj-$(CONFIG_S5P) += s5p_wdt.o
++obj-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o
++obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
#define WCR_WDBG 0x02
#define WCR_WDE 0x04 /* WDOG enable */
#define WCR_WDT 0x08
+#define WCR_SRS 0x10
#define WCR_WDW 0x80
#define SET_WCR_WT(x) (x << 8)
#define CONFIG_WATCHDOG_TIMEOUT_MSECS 128000
#endif
timeout = (CONFIG_WATCHDOG_TIMEOUT_MSECS / 500) - 1;
- writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT |
+ writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT | WCR_SRS |
WCR_WDW | SET_WCR_WT(timeout), &wdog->wcr);
hw_watchdog_reset();
}
{
struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
- writew(WCR_WDE, &wdog->wcr);
- writew(0x5555, &wdog->wsr);
- writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 second timeout */
while (1) {
- /*
- * spin for .5 seconds before reset
- */
+ writew(0, &wdog->wcr); /* clear SRS initiating SOFT reset */
}
}
--- /dev/null
+#
+# Device Tree Control
+#
+# TODO:
+# This feature is not currently supported for SPL,
+# but this restriction should be removed in the future.
+
+config SUPPORT_OF_CONTROL
+ bool
+
+menu "Device Tree Control"
+ depends on !SPL_BUILD
+ depends on SUPPORT_OF_CONTROL
+
+config OF_CONTROL
+ bool "Run-time configuration via Device Tree"
+ help
+ This feature provides for run-time configuration of U-Boot
+ via a flattened device tree.
+
+choice
+ prompt "Provider of DTB for DT control"
+ depends on OF_CONTROL
+
+config OF_SEPARATE
+ bool "Separate DTB for DT control"
+ depends on !SANDBOX
+ help
+ If this option is enabled, the device tree will be built and
+ placed as a separate u-boot.dtb file alongside the U-Boot image.
+
+config OF_EMBED
+ bool "Embedded DTB for DT control"
+ help
+ If this option is enabled, the device tree will be picked up and
+ built into the U-Boot image.
+
+config OF_HOSTFILE
+ bool "Host filed DTB for DT control"
+ depends on SANDBOX
+ help
+ If this option is enabled, DTB will be read from a file on startup.
+ This is only useful for Sandbox. Use the -d flag to U-Boot to
+ specify the file to read.
+
+endchoice
+
+config DEFAULT_DEVICE_TREE
+ string "Default Device Tree for DT control"
+ help
+ This option specifies the default Device Tree used for DT control.
+ It can be overridden from the command line:
+ $ make DEVICE_TREE=<device-tree-name>
+
++config FDT_FIXUP_PARTITIONS
++ bool
++ depends on MTD_PARTITIONS && OF_LIBFDT
++
+endmenu
/*
+ * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Terry Lv <r65388@freescale.com>
+ *
* Copyright (C) Freescale Semiconductor, Inc. 2006.
* Author: Jason Jin<Jason.jin@freescale.com>
* Zhang Wei<wei.zhang@freescale.com>
#define AHCI_PCI_BAR 0x24
#define AHCI_MAX_SG 56 /* hardware max is 64K */
+ #define AHCI_MAX_CMD_SLOT 32
#define AHCI_CMD_SLOT_SZ 32
#define AHCI_MAX_CMD_SLOT 32
#define AHCI_RX_FIS_SZ 256
#define AHCI_CMD_TBL_HDR 0x80
#define AHCI_CMD_TBL_CDB 0x40
- #define AHCI_CMD_TBL_SZ AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16)
+ #define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16))
#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ * AHCI_MAX_CMD_SLOT + \
AHCI_CMD_TBL_SZ + AHCI_RX_FIS_SZ)
#define AHCI_CMD_ATAPI (1 << 5)
#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */
#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */
+#ifdef CONFIG_SUNXI_AHCI
+#define PORT_P0DMACR 0x70 /* SUNXI specific "DMA register" */
+#endif
+
/* PORT_IRQ_{STAT,MASK} bits */
#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */
#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
| PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS \
| PORT_IRQ_D2H_REG_FIS
+/* PORT_SCR_STAT bits */
+#define PORT_SCR_STAT_DET_MASK 0x3
+#define PORT_SCR_STAT_DET_COMINIT 0x1
+#define PORT_SCR_STAT_DET_PHYRDY 0x3
+
/* PORT_CMD bits */
#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */
#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */
#define AHCI_MAX_PORTS 32
-/* SETFEATURES stuff */
-#define SETFEATURES_XFER 0x03
-#define XFER_UDMA_7 0x47
-#define XFER_UDMA_6 0x46
-#define XFER_UDMA_5 0x45
-#define XFER_UDMA_4 0x44
-#define XFER_UDMA_3 0x43
-#define XFER_UDMA_2 0x42
-#define XFER_UDMA_1 0x41
-#define XFER_UDMA_0 0x40
-#define XFER_MW_DMA_2 0x22
-#define XFER_MW_DMA_1 0x21
-#define XFER_MW_DMA_0 0x20
-#define XFER_SW_DMA_2 0x12
-#define XFER_SW_DMA_1 0x11
-#define XFER_SW_DMA_0 0x10
-#define XFER_PIO_4 0x0C
-#define XFER_PIO_3 0x0B
-#define XFER_PIO_2 0x0A
-#define XFER_PIO_1 0x09
-#define XFER_PIO_0 0x08
-#define XFER_PIO_SLOW 0x00
-
#define ATA_FLAG_SATA (1 << 3)
#define ATA_FLAG_NO_LEGACY (1 << 4) /* no legacy mode check */
#define ATA_FLAG_MMIO (1 << 6) /* use MMIO, not PIO */
u32 host_flags;
u32 host_set_flags;
u32 mmio_base;
- u32 pio_mask;
+ u32 pio_mask;
u32 udma_mask;
u32 flags;
u32 cap; /* cache of HOST_CAP register */
};
int ahci_init(u32 base);
+int ahci_reset(u32 base);
#endif
* an error value of -1.
*/
- GPIOF_INPUT,
- GPIOF_OUTPUT_INIT_LOW,
- GPIOF_OUTPUT_INIT_HIGH,
+ enum gpio_flags {
++ GPIOFLAG_INPUT,
++ GPIOFLAG_OUTPUT_INIT_LOW,
++ GPIOFLAG_OUTPUT_INIT_HIGH,
+ };
+
+ struct gpio {
+ unsigned int gpio;
+ enum gpio_flags flags;
+ const char *label;
+ };
+
/**
- * Request a gpio. This should be called before any of the other functions
- * are used on this gpio.
+ * Request a GPIO. This should be called before any of the other functions
+ * are used on this GPIO.
+ *
+ * Note: With driver model, the label is allocated so there is no need for
+ * the caller to preserve it.
*
* @param gp GPIO number
* @param label User label for this GPIO
*/
int gpio_request(unsigned gpio, const char *label);
++/**
++ * Request a GPIO and configure it
++ * @param gpios pointer to array of gpio defs
++ * @param count number of GPIOs to set up
++ */
++int gpio_request_one(unsigned gpio, enum gpio_flags flags, const char *label);
++
++/**
++ * Request a set of GPIOs and configure them
++ * @param gpios pointer to array of gpio defs
++ * @param count number of GPIOs to set up
++ */
++int gpio_request_array(const struct gpio *gpios, int count);
++
/**
* Stop using the GPIO. This function should not alter pin configuration.
*
*/
int gpio_free(unsigned gpio);
++/**
++ * Release a set of GPIOs
++ * @param gpios pointer to array of gpio defs
++ * @param count number of GPIOs to set up
++ */
++int gpio_free_array(const struct gpio *gpios, int count);
++
/**
* Make a GPIO an input.
*
*/
int gpio_set_value(unsigned gpio, int value);
+/* State of a GPIO, as reported by get_function() */
+enum gpio_func_t {
+ GPIOF_INPUT = 0,
+ GPIOF_OUTPUT,
+ GPIOF_UNUSED, /* Not claimed */
+ GPIOF_UNKNOWN, /* Not known */
+ GPIOF_FUNC, /* Not used as a GPIO */
+
+ GPIOF_COUNT,
+};
+
+struct udevice;
+
/**
- * Request a GPIO and configure it
- * @param gpios pointer to array of gpio defs
- * @param count number of GPIOs to set up
+ * gpio_get_status() - get the current GPIO status as a string
+ *
+ * Obtain the current GPIO status as a string which can be presented to the
+ * user. A typical string is:
+ *
+ * "b4: in: 1 [x] sdmmc_cd"
+ *
+ * which means this is GPIO bank b, offset 4, currently set to input, current
+ * value 1, [x] means that it is requested and the owner is 'sdmmc_cd'
+ *
+ * @dev: Device to check
+ * @offset: Offset of device GPIO to check
+ * @buf: Place to put string
+ * @buffsize: Size of string including \0
*/
-int gpio_request_one(unsigned gpio, enum gpio_flags flags, const char *label);
+int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize);
/**
- * Request a set of GPIOs and configure them
- * @param gpios pointer to array of gpio defs
- * @param count number of GPIOs to set up
+ * gpio_get_function() - get the current function for a GPIO pin
+ *
+ * Note this returns GPIOF_UNUSED if the GPIO is not requested.
+ *
+ * @dev: Device to check
+ * @offset: Offset of device GPIO to check
+ * @namep: If non-NULL, this is set to the nane given when the GPIO
+ * was requested, or -1 if it has not been requested
+ * @return -ENODATA if the driver returned an unknown function,
+ * -ENODEV if the device is not active, -EINVAL if the offset is invalid.
+ * GPIOF_UNUSED if the GPIO has not been requested. Otherwise returns the
+ * function from enum gpio_func_t.
*/
-int gpio_request_array(const struct gpio *gpios, int count);
+int gpio_get_function(struct udevice *dev, int offset, const char **namep);
/**
- * Release a set of GPIOs
- * @param gpios pointer to array of gpio defs
- * @param count number of GPIOs to set up
+ * gpio_get_raw_function() - get the current raw function for a GPIO pin
+ *
+ * Note this does not return GPIOF_UNUSED - it will always return the GPIO
+ * driver's view of a pin function, even if it is not correctly set up.
+ *
+ * @dev: Device to check
+ * @offset: Offset of device GPIO to check
+ * @namep: If non-NULL, this is set to the nane given when the GPIO
+ * was requested, or -1 if it has not been requested
+ * @return -ENODATA if the driver returned an unknown function,
+ * -ENODEV if the device is not active, -EINVAL if the offset is invalid.
+ * Otherwise returns the function from enum gpio_func_t.
*/
-int gpio_free_array(const struct gpio *gpios, int count);
+int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep);
+
+/**
+ * gpio_requestf() - request a GPIO using a format string for the owner
+ *
+ * This is a helper function for gpio_request(). It allows you to provide
+ * a printf()-format string for the GPIO owner. It calls gpio_request() with
+ * the string that is created
+ */
+int gpio_requestf(unsigned gpio, const char *fmt, ...)
+ __attribute__ ((format (__printf__, 2, 3)));
+
+/**
+ * struct struct dm_gpio_ops - Driver model GPIO operations
+ *
+ * Refer to functions above for description. These function largely copy
+ * the old API.
+ *
+ * This is trying to be close to Linux GPIO API. Once the U-Boot uses the
+ * new DM GPIO API, this should be really easy to flip over to the Linux
+ * GPIO API-alike interface.
+ *
+ * Also it would be useful to standardise additional functions like
+ * pullup, slew rate and drive strength.
+ *
+ * gpio_request)( and gpio_free() are optional - if NULL then they will
+ * not be called.
+ *
+ * Note that @offset is the offset from the base GPIO of the device. So
+ * offset 0 is the device's first GPIO and offset o-1 is the last GPIO,
+ * where o is the number of GPIO lines controlled by the device. A device
+ * is typically used to control a single bank of GPIOs. Within complex
+ * SoCs there may be many banks and therefore many devices all referring
+ * to the different IO addresses within the SoC.
+ *
+ * The uclass combines all GPIO devices together to provide a consistent
+ * numbering from 0 to n-1, where n is the number of GPIOs in total across
+ * all devices. Be careful not to confuse offset with gpio in the parameters.
+ */
+struct dm_gpio_ops {
+ int (*request)(struct udevice *dev, unsigned offset, const char *label);
+ int (*free)(struct udevice *dev, unsigned offset);
+ int (*direction_input)(struct udevice *dev, unsigned offset);
+ int (*direction_output)(struct udevice *dev, unsigned offset,
+ int value);
+ int (*get_value)(struct udevice *dev, unsigned offset);
+ int (*set_value)(struct udevice *dev, unsigned offset, int value);
+ /**
+ * get_function() Get the GPIO function
+ *
+ * @dev: Device to check
+ * @offset: GPIO offset within that device
+ * @return current function - GPIOF_...
+ */
+ int (*get_function)(struct udevice *dev, unsigned offset);
+};
+
+/**
+ * struct gpio_dev_priv - information about a device used by the uclass
+ *
+ * The uclass combines all active GPIO devices into a unified numbering
+ * scheme. To do this it maintains some private information about each
+ * device.
+ *
+ * To implement driver model support in your GPIO driver, add a probe
+ * handler, and set @gpio_count and @bank_name correctly in that handler.
+ * This tells the uclass the name of the GPIO bank and the number of GPIOs
+ * it contains.
+ *
+ * @bank_name: Name of the GPIO device (e.g 'a' means GPIOs will be called
+ * 'A0', 'A1', etc.
+ * @gpio_count: Number of GPIOs in this device
+ * @gpio_base: Base GPIO number for this device. For the first active device
+ * this will be 0; the numbering for others will follow sequentially so that
+ * @gpio_base for device 1 will equal the number of GPIOs in device 0.
+ * @name: Array of pointers to the name for each GPIO in this bank. The
+ * value of the pointer will be NULL if the GPIO has not been claimed.
+ */
+struct gpio_dev_priv {
+ const char *bank_name;
+ unsigned gpio_count;
+ unsigned gpio_base;
+ char **name;
+};
+
+/* Access the GPIO operations for a device */
+#define gpio_get_ops(dev) ((struct dm_gpio_ops *)(dev)->driver->ops)
+
+/**
+ * gpio_get_bank_info - Return information about a GPIO bank/device
+ *
+ * This looks up a device and returns both its GPIO base name and the number
+ * of GPIOs it controls.
+ *
+ * @dev: Device to look up
+ * @offset_count: Returns number of GPIOs within this bank
+ * @return bank name of this device
+ */
+const char *gpio_get_bank_info(struct udevice *dev, int *offset_count);
+
+/**
+ * gpio_lookup_name - Look up a GPIO name and return its details
+ *
+ * This is used to convert a named GPIO into a device, offset and GPIO
+ * number.
+ *
+ * @name: GPIO name to look up
+ * @devp: Returns pointer to device which contains this GPIO
+ * @offsetp: Returns the offset number within this device
+ * @gpiop: Returns the absolute GPIO number, numbered from 0
+ */
+int gpio_lookup_name(const char *name, struct udevice **devp,
+ unsigned int *offsetp, unsigned int *gpiop);
+
+/**
+ * get_gpios() - Turn the values of a list of GPIOs into an integer
+ *
+ * This puts the value of the first GPIO into bit 0, the second into bit 1,
+ * etc. then returns the resulting integer.
+ *
+ * @gpio_list: List of GPIOs to collect
+ * @return resulting integer value
+ */
+unsigned gpio_get_values_as_int(const int *gpio_list);
#endif /* _ASM_GENERIC_GPIO_H_ */
* (C) Copyright 2009 DENX Software Engineering
* Author: John Rigby <jrigby@gmail.com>
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_H
*/
#define CONFIG_MX25
#define CONFIG_MX25_CLK32 32000 /* OSC32K frequency */
-#define CONFIG_SYS_HZ 1000
+#define CONFIG_SYS_TIMER_RATE CONFIG_MX25_CLK32
+#define CONFIG_SYS_TIMER_COUNTER \
+ (&((struct gpt_regs *)IMX_GPT1_BASE)->counter)
#define CONFIG_SYS_MONITOR_LEN (256 << 10) /* 256 kB for U-Boot */
-#define CONFIG_SPL
#define CONFIG_SPL_TARGET "u-boot-with-spl.bin"
#define CONFIG_SPL_LDSCRIPT "arch/$(ARCH)/cpu/u-boot-spl.lds"
#define CONFIG_SPL_MAX_SIZE 2048
* Flash & Environment
*/
/* No NOR flash present */
--#define CONFIG_SYS_NO_FLASH
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET CONFIG_SYS_MONITOR_LEN
#define CONFIG_ENV_SIZE (128 * 1024) /* 128 kB NAND block size */
#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
/* NAND */
--#define CONFIG_NAND_MXC
#define CONFIG_MXC_NAND_REGS_BASE (0xBB000000)
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE (0xBB000000)
#define CONFIG_SYS_NAND_LARGEPAGE
/* U-Boot general configuration */
-#define CONFIG_SYS_PROMPT "=> " /* Monitor Command Prompt */
#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */
/* Print buffer sz */
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
/* U-Boot commands */
#include <config_cmd_default.h>
--#define CONFIG_CMD_NAND
--#define CONFIG_CMD_CACHE
/*
* Ethernet
*/
--#define CONFIG_FEC_MXC
--#define CONFIG_FEC_MXC_PHYADDR 0x1f
--#define CONFIG_MII
--#define CONFIG_CMD_NET
#define CONFIG_BOARD_LATE_INIT
#define CONFIG_ENV_OVERWRITE
--- /dev/null
-#include <asm/sizes.h>
+ /*
+ * Copyright (C) 2012 <LW@KARO-electronics.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+
+ #ifndef __CONFIG_H
+ #define __CONFIG_H
+
+ #define CONFIG_MX28 /* must be defined before including regs-base.h */
+
-#define LCD_BPP LCD_COLOR24
++#include <linux/sizes.h>
+ #include <asm/arch/regs-base.h>
+
+ /*
+ * Ka-Ro TX28 board - SoC configuration
+ */
+ #define CONFIG_MXS_GPIO /* GPIO control */
+ #define CONFIG_SYS_HZ 1000 /* Ticks per second */
+ #define PHYS_SDRAM_1_SIZE CONFIG_SDRAM_SIZE
+ #ifdef CONFIG_TX28_S
+ #define TX28_MOD_SUFFIX "1"
+ #else
+ #define CONFIG_SYS_SPL_FIXED_BATT_SUPPLY
+ #define TX28_MOD_SUFFIX "0"
+ #endif
+ #define IRAM_BASE_ADDR 0x00000000
+
+ #ifndef CONFIG_SPL_BUILD
+ #define CONFIG_SKIP_LOWLEVEL_INIT
+ #define CONFIG_SHOW_ACTIVITY
+ #define CONFIG_ARCH_CPU_INIT
+ #define CONFIG_ARCH_MISC_INIT /* init vector table after relocation */
+ #define CONFIG_DISPLAY_CPUINFO
+ #define CONFIG_DISPLAY_BOARDINFO
+ #define CONFIG_BOARD_LATE_INIT
+ #define CONFIG_BOARD_EARLY_INIT_F
+
+ /* LCD Logo and Splash screen support */
+ #define CONFIG_LCD
+ #ifdef CONFIG_LCD
+ #define CONFIG_SPLASH_SCREEN
+ #define CONFIG_SPLASH_SCREEN_ALIGN
+ #define CONFIG_VIDEO_MXS
+ #define CONFIG_LCD_LOGO
-#define CONFIG_SYS_NO_FLASH
++#define LCD_BPP LCD_COLOR32
+ #define CONFIG_CMD_BMP
+ #define CONFIG_VIDEO_BMP_RLE8
+ #endif /* CONFIG_LCD */
+ #endif /* CONFIG_SPL_BUILD */
+
+ /*
+ * Memory configuration options
+ */
+ #define CONFIG_NR_DRAM_BANKS 0x1 /* 1 bank of SDRAM */
+ #define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
+ #define CONFIG_STACKSIZE SZ_64K
+ #define CONFIG_SYS_MALLOC_LEN SZ_4M
+ #define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* Memtest start address */
+ #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + SZ_4M)
+
+ /*
+ * U-Boot general configurations
+ */
+ #define CONFIG_SYS_LONGHELP
+ #define CONFIG_SYS_PROMPT "TX28 U-Boot > "
+ #define CONFIG_SYS_CBSIZE 2048 /* Console I/O buffer size */
+ #define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+ /* Print buffer size */
+ #define CONFIG_SYS_MAXARGS 256 /* Max number of command args */
+ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+ #define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+ #define CONFIG_AUTO_COMPLETE /* Command auto complete */
+ #define CONFIG_CMDLINE_EDITING /* Command history etc */
+
+ #define CONFIG_SYS_64BIT_VSPRINTF
-#define CONFIG_OF_LIBFDT
+
+ /*
+ * Flattened Device Tree (FDT) support
+ */
-#define CONFIG_FDT_FIXUP_PARTITIONS
-#define CONFIG_OF_BOARD_SETUP
+ #ifdef CONFIG_OF_LIBFDT
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_MMC
-#define CONFIG_CMD_NAND
-#define CONFIG_CMD_MTDPARTS
-#define CONFIG_CMD_BOOTCE
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_MEMTEST
+ #endif
+
+ /*
+ * Boot Linux
+ */
+ #define xstr(s) str(s)
+ #define str(s) #s
+ #define __pfx(x, s) (x##s)
+ #define _pfx(x, s) __pfx(x, s)
+
+ #define CONFIG_CMDLINE_TAG
+ #define CONFIG_SETUP_MEMORY_TAGS
+ #define CONFIG_BOOTDELAY 3
+ #define CONFIG_ZERO_BOOTDELAY_CHECK
+ #define CONFIG_SYS_AUTOLOAD "no"
+ #define CONFIG_BOOTFILE "uImage"
+ #define CONFIG_BOOTARGS "init=/linuxrc console=ttyAMA0,115200 ro debug panic=1"
+ #define CONFIG_BOOTCOMMAND "run bootcmd_${boot_mode} bootm_cmd"
+ #ifdef CONFIG_TX28_S
+ #define CONFIG_LOADADDR 41000000
+ #else
+ #define CONFIG_LOADADDR 43000000
+ #endif
+ #define CONFIG_FDTADDR 41000000
+ #define CONFIG_SYS_LOAD_ADDR _pfx(0x, CONFIG_LOADADDR)
+ #define CONFIG_SYS_FDT_ADDR _pfx(0x, CONFIG_FDTADDR)
+ #define CONFIG_U_BOOT_IMG_SIZE SZ_1M
+
+ /*
+ * Extra Environment Settings
+ */
+ #ifdef CONFIG_ENV_IS_NOWHERE
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "autoload=no\0" \
+ "bootdelay=-1\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0"
+ #else
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "baseboard=stk5-v3\0" \
+ "bootargs_jffs2=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mtdblock3 rootfstype=jffs2\0" \
+ "bootargs_mmc=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mmcblk0p3 rootwait\0" \
+ "bootargs_nfs=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock" \
+ " ip=dhcp\0" \
+ "bootargs_ubifs=run default_bootargs;set bootargs ${bootargs}" \
+ " ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs\0" \
+ "bootcmd_jffs2=set autostart no;run bootargs_jffs2" \
+ ";nboot linux\0" \
+ "bootcmd_mmc=set autostart no;run bootargs_mmc" \
+ ";fatload mmc 0 ${loadaddr} uImage\0" \
+ "bootcmd_nand=set autostart no;run bootargs_ubifs;nboot linux\0"\
+ "bootcmd_net=set autoload y;set autostart n;run bootargs_nfs" \
+ ";dhcp\0" \
+ "bootm_cmd=bootm ${loadaddr} - ${fdtaddr}\0" \
+ "boot_mode=nand\0" \
+ "default_bootargs=set bootargs " CONFIG_BOOTARGS \
+ " ${append_bootargs}\0" \
+ "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \
+ "fdtsave=fdt resize;nand erase.part dtb" \
+ ";nand write ${fdtaddr} dtb ${fdtsize}\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0" \
+ "nfsroot=/tftpboot/rootfs\0" \
+ "otg_mode=device\0" \
+ "touchpanel=tsc2007\0" \
+ "video_mode=VGA\0"
+ #endif /* CONFIG_ENV_IS_NOWHERE */
+
+ #define MTD_NAME "gpmi-nand"
+ #define MTDIDS_DEFAULT "nand0=" MTD_NAME
+
+ /*
+ * U-Boot Commands
+ */
+ #include <config_cmd_default.h>
-#define CONFIG_FEC_MXC
+
+ /*
+ * Serial Driver
+ */
+ #define CONFIG_PL011_SERIAL
+ #define CONFIG_PL011_CLOCK 24000000
+ #define CONFIG_PL01x_PORTS { \
+ (void *)MXS_UARTDBG_BASE, \
+ }
+ #define CONFIG_CONS_INDEX 0 /* do not change! */
+ #define CONFIG_BAUDRATE 115200 /* Default baud rate */
+ #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, }
+ #define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+ /*
+ * Ethernet Driver
+ */
-#define CONFIG_FEC_MXC_MULTI
+ #ifdef CONFIG_FEC_MXC
+ /* This is required for the FEC driver to work with cache enabled */
+ #define CONFIG_SYS_ARM_CACHE_WRITETHROUGH
+ #define CONFIG_SYS_CACHELINE_SIZE 32
+
+ #ifndef CONFIG_TX28_S
-#define CONFIG_FEC_MXC_PHYADDR 0x00
+ #else
+ #define IMX_FEC_BASE MXS_ENET0_BASE
-#define CONFIG_PHY_SMSC
-#define CONFIG_PHYLIB
-#define CONFIG_MII
+ #endif
+
-#define CONFIG_GET_FEC_MAC_ADDR_FROM_IIM
+ #define CONFIG_FEC_XCV_TYPE RMII
-#define CONFIG_CMD_DHCP
-#define CONFIG_CMD_PING
+ #define CONFIG_NET_MULTI
+ #define CONFIG_CMD_MII
-#define CONFIG_ENV_IS_IN_NAND
-#define CONFIG_ENV_IS_IN_MMC
+ /* Add for working with "strict" DHCP server */
+ #define CONFIG_BOOTP_SUBNETMASK
+ #define CONFIG_BOOTP_GATEWAY
+ #define CONFIG_BOOTP_DNS
+ #define CONFIG_BOOTP_RANDOM_ID
+ #endif
+
+ #ifndef CONFIG_ENV_IS_NOWHERE
+ /* define one of the following options:
-#define CONFIG_ENV_IS_IN_NAND
+ */
-#define CONFIG_MTD_DEVICE
+ #endif
+ #define CONFIG_ENV_OVERWRITE
+
+ /*
+ * NAND flash driver
+ */
+ #ifdef CONFIG_CMD_NAND
+ #define CONFIG_SYS_NAND_BLOCK_SIZE SZ_128K
-#define CONFIG_CMD_NAND_TRIMFFS
+ #define CONFIG_NAND_MXS
+ #define CONFIG_APBH_DMA
+ #define CONFIG_APBH_DMA_BURST
+ #define CONFIG_APBH_DMA_BURST8
+ #define CONFIG_SYS_NAND_U_BOOT_OFFS CONFIG_SYS_NAND_BLOCK_SIZE
-#define CONFIG_SYS_NAND_USE_FLASH_BBT
+ #define CONFIG_SYS_MXS_DMA_CHANNEL 4
+ #define CONFIG_SYS_NAND_MAX_CHIPS 0x1
+ #define CONFIG_SYS_MAX_NAND_DEVICE 0x1
+ #define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_CMD_ROMUPDATE
+ #define CONFIG_SYS_NAND_BASE 0x00000000
-#define CONFIG_MMC
-#define CONFIG_GENERIC_MMC
+ #else
+ #undef CONFIG_ENV_IS_IN_NAND
+ #endif /* CONFIG_CMD_NAND */
+
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #define CONFIG_ENV_OFFSET (CONFIG_U_BOOT_IMG_SIZE + CONFIG_SYS_NAND_U_BOOT_OFFS)
+ #define CONFIG_ENV_SIZE SZ_128K
+ #define CONFIG_ENV_RANGE (3 * CONFIG_SYS_NAND_BLOCK_SIZE)
+ #endif /* CONFIG_ENV_IS_IN_NAND */
+
+ #ifdef CONFIG_ENV_OFFSET_REDUND
+ #define CONFIG_SYS_ENV_PART_STR xstr(CONFIG_SYS_ENV_PART_SIZE) \
+ "(env)," \
+ xstr(CONFIG_SYS_ENV_PART_SIZE) \
+ "(env2),"
+ #define CONFIG_SYS_USERFS_PART_STR xstr(CONFIG_SYS_USERFS_PART_SIZE2) "(userfs)"
+ #else
+ #define CONFIG_SYS_ENV_PART_STR xstr(CONFIG_SYS_ENV_PART_SIZE) \
+ "(env),"
+ #define CONFIG_SYS_USERFS_PART_STR xstr(CONFIG_SYS_USERFS_PART_SIZE) "(userfs)"
+ #endif /* CONFIG_ENV_OFFSET_REDUND */
+
+ /*
+ * MMC Driver
+ */
+ #ifdef CONFIG_CMD_MMC
+ #define CONFIG_MXS_MMC
+ #define CONFIG_BOUNCE_BUFFER
+
+ #define CONFIG_DOS_PARTITION
+ #define CONFIG_CMD_FAT
+ #define CONFIG_FAT_WRITE
+ #define CONFIG_CMD_EXT2
+
+ /*
+ * Environments on MMC
+ */
+ #ifdef CONFIG_ENV_IS_IN_MMC
+ #define CONFIG_SYS_MMC_ENV_DEV 0
+ /* Associated with the MMC layout defined in mmcops.c */
+ #define CONFIG_ENV_OFFSET SZ_1K
+ #define CONFIG_ENV_SIZE (SZ_128K - CONFIG_ENV_OFFSET)
+ #define CONFIG_DYNAMIC_MMC_DEVNO
+ #endif /* CONFIG_ENV_IS_IN_MMC */
+ #else
+ #undef CONFIG_ENV_IS_IN_MMC
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_ENV_IS_NOWHERE
+ #undef CONFIG_ENV_SIZE
+ #define CONFIG_ENV_SIZE SZ_4K
+ #endif
+
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "1m@" xstr(CONFIG_SYS_NAND_U_BOOT_OFFS) "(u-boot)," \
+ CONFIG_SYS_ENV_PART_STR \
+ "6m(linux),32m(rootfs)," CONFIG_SYS_USERFS_PART_STR \
+ ",512k@" xstr(CONFIG_SYS_NAND_DTB_OFFSET) "(dtb)" \
+ ",512k@" xstr(CONFIG_SYS_NAND_BBT_OFFSET) "(bbt)ro"
+
+ #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
+ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - /* Fix this */ \
+ GENERATED_GBL_DATA_SIZE)
+
+ /* Defines for SPL */
+ #define CONFIG_SPL
+ #define CONFIG_SPL_START_S_PATH "arch/arm/cpu/arm926ejs/mxs"
+ #define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds"
+ #define CONFIG_SPL_LIBCOMMON_SUPPORT
+ #define CONFIG_SPL_LIBGENERIC_SUPPORT
+ #define CONFIG_SPL_SERIAL_SUPPORT
+ #define CONFIG_SPL_GPIO_SUPPORT
+ #define CONFIG_SYS_SPL_VDDD_VAL 1500
+ #define CONFIG_SYS_SPL_BATT_BO_LEVEL 2800
+ #define CONFIG_SYS_SPL_VDDMEM_VAL 0 /* VDDMEM is not utilized on TX28 */
+
+ #endif /* __CONFIGS_TX28_H */
--- /dev/null
-#include <asm/sizes.h>
+ /*
+ * tx48.h
+ *
+ * Copyright (C) 2012-2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * based on: am335x_evm
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+
+ #ifndef __CONFIG_H
+ #define __CONFIG_H
+
+ #define CONFIG_AM33XX /* must be set before including omap.h */
+
-#define CONFIG_VIDEO_DA8XX
++#include <linux/sizes.h>
+ #include <asm/arch/omap.h>
+
+ /*
+ * Ka-Ro TX48 board - SoC configuration
+ */
+ #define CONFIG_OMAP
+ #define CONFIG_AM33XX_GPIO
+ #define CONFIG_SYS_HZ 1000 /* Ticks per second */
+
+ #ifndef CONFIG_SPL_BUILD
+ #define CONFIG_SKIP_LOWLEVEL_INIT
+ #define CONFIG_SHOW_ACTIVITY
+ #define CONFIG_DISPLAY_CPUINFO
+ #define CONFIG_DISPLAY_BOARDINFO
+ #define CONFIG_BOARD_LATE_INIT
+
+ /* LCD Logo and Splash screen support */
+ #define CONFIG_LCD
+ #ifdef CONFIG_LCD
+ #define CONFIG_SPLASH_SCREEN
+ #define CONFIG_SPLASH_SCREEN_ALIGN
-#define LCD_BPP LCD_COLOR24
++#define CONFIG_AM335X_LCD
+ #define DAVINCI_LCD_CNTL_BASE 0x4830e000
+ #define CONFIG_LCD_LOGO
-#define CONFIG_SYS_NO_FLASH
++#define LCD_BPP LCD_COLOR32
+ #define CONFIG_CMD_BMP
+ #define CONFIG_VIDEO_BMP_RLE8
+ #endif /* CONFIG_LCD */
+ #endif /* CONFIG_SPL_BUILD */
+
+ /* Clock Defines */
+ #define V_OSCK 24000000 /* Clock output from T2 */
+ #define V_SCLK V_OSCK
+
+ /*
+ * Memory configuration options
+ */
+ #define CONFIG_SYS_SDRAM_DDR3
+ #define CONFIG_NR_DRAM_BANKS 0x1 /* '1' would be converted to 'y' by define2mk.sed */
+ #define PHYS_SDRAM_1 0x80000000 /* SDRAM Bank #1 */
+ #define CONFIG_MAX_RAM_BANK_SIZE SZ_1G
+
+ #define CONFIG_STACKSIZE SZ_64K
+ #define CONFIG_SYS_MALLOC_LEN SZ_4M
+
+ #define CONFIG_SYS_MEMTEST_START (PHYS_SDRAM_1 + SZ_64M)
+ #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + SZ_8M)
+
+ #define CONFIG_SYS_CACHELINE_SIZE 64
+
+ /*
+ * U-Boot general configurations
+ */
+ #define CONFIG_SYS_LONGHELP
+ #define CONFIG_SYS_PROMPT "TX48 U-Boot > "
+ #define CONFIG_SYS_CBSIZE 2048 /* Console I/O buffer size */
+ #define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+ /* Print buffer size */
+ #define CONFIG_SYS_MAXARGS 256 /* Max number of command args */
+ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+ #define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+ #define CONFIG_AUTO_COMPLETE /* Command auto complete */
+ #define CONFIG_CMDLINE_EDITING /* Command history etc */
+
+ #define CONFIG_SYS_64BIT_VSPRINTF
-#define CONFIG_OF_LIBFDT
-#define CONFIG_OF_BOARD_SETUP
+
+ /*
+ * Flattened Device Tree (FDT) support
+ */
-#define CONFIG_HW_WATCHDOG
+
+ /*
+ * Boot Linux
+ */
+ #define xstr(s) str(s)
+ #define str(s) #s
+ #define __pfx(x, s) (x##s)
+ #define _pfx(x, s) __pfx(x, s)
+
+ #define CONFIG_CMDLINE_TAG
+ #define CONFIG_SETUP_MEMORY_TAGS
+ #define CONFIG_BOOTDELAY 3
+ #define CONFIG_ZERO_BOOTDELAY_CHECK
+ #define CONFIG_SYS_AUTOLOAD "no"
+ #define CONFIG_BOOTFILE "uImage"
+ #define CONFIG_BOOTARGS "init=/linuxrc console=ttyO0,115200 ro debug panic=1"
+ #define CONFIG_BOOTCOMMAND "run bootcmd_${boot_mode} bootm_cmd"
+ #define CONFIG_LOADADDR 83000000
+ #define CONFIG_FDTADDR 81000000
+ #define CONFIG_SYS_LOAD_ADDR _pfx(0x, CONFIG_LOADADDR)
+ #define CONFIG_SYS_FDT_ADDR _pfx(0x, CONFIG_FDTADDR)
+ #define CONFIG_U_BOOT_IMG_SIZE SZ_1M
-#define CONFIG_FDT_FIXUP_PARTITIONS
+
+ /*
+ * Extra Environment Settings
+ */
+ #define CONFIG_SYS_CPU_CLK_STR xstr(CONFIG_SYS_MPU_CLK)
+
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "baseboard=stk5-v3\0" \
+ "bootargs_jffs2=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mtdblock4 rootfstype=jffs2\0" \
+ "bootargs_mmc=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mmcblk0p2 rootwait\0" \
+ "bootargs_nfs=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock" \
+ " ip=dhcp\0" \
+ "bootargs_ubifs=run default_bootargs;set bootargs ${bootargs}" \
+ " ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs\0" \
+ "bootcmd_jffs2=set autostart no;run bootargs_jffs2" \
+ ";nboot linux\0" \
+ "bootcmd_mmc=set autostart no;run bootargs_mmc" \
+ ";fatload mmc 0 ${loadaddr} uImage\0" \
+ "bootcmd_nand=set autostart no;run bootargs_ubifs" \
+ ";nboot linux\0" \
+ "bootcmd_net=set autoload y;set autostart n;run bootargs_nfs" \
+ ";dhcp\0" \
+ "bootm_cmd=bootm ${loadaddr} - ${fdtaddr}\0" \
+ "boot_mode=nand\0" \
+ "cpu_clk=" CONFIG_SYS_CPU_CLK_STR "\0" \
+ "default_bootargs=set bootargs " CONFIG_BOOTARGS \
+ " ${append_bootargs}\0" \
+ "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \
+ "fdtsave=fdt resize;nand erase.part dtb" \
+ ";nand write ${fdtaddr} dtb ${fdtsize}\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0" \
+ "nfsroot=/tftpboot/rootfs\0" \
+ "otg_mode=device\0" \
+ "touchpanel=tsc2007\0" \
+ "video_mode=VGA\0"
+
+ #define MTD_NAME "omap2-nand.0"
+ #define MTDIDS_DEFAULT "nand0=" MTD_NAME
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_MMC
-#define CONFIG_CMD_NAND
-#define CONFIG_CMD_MTDPARTS
-#define CONFIG_CMD_BOOTCE
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_MEMTEST
+
+ /*
+ * U-Boot Commands
+ */
+ #include <config_cmd_default.h>
-#define CONFIG_PHY_SMSC
-#define CONFIG_PHYLIB
-#define CONFIG_MII
+
+ /*
+ * Serial Driver
+ */
+ #define CONFIG_SYS_NS16550
+ #define CONFIG_SYS_NS16550_SERIAL
+ #define CONFIG_SYS_NS16550_MEM32
+ #define CONFIG_SYS_NS16550_REG_SIZE (-4)
+ #define CONFIG_SYS_NS16550_CLK 48000000
+ #define CONFIG_SYS_NS16550_COM1 0x44e09000 /* UART0 */
+ #define CONFIG_SYS_NS16550_COM2 0x48022000 /* UART1 */
+ #define CONFIG_SYS_NS16550_COM6 0x481aa000 /* UART5 */
+
+ #define CONFIG_SYS_NS16550_COM3 0x481aa000 /* UART2 */
+ #define CONFIG_SYS_NS16550_COM4 0x481aa000 /* UART3 */
+ #define CONFIG_SYS_NS16550_COM5 0x481aa000 /* UART4 */
+ #define CONFIG_CONS_INDEX 1 /* one based! */
+ #define CONFIG_BAUDRATE 115200 /* Default baud rate */
+ #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, }
+ #define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+ /*
+ * Ethernet Driver
+ */
+ #ifdef CONFIG_CMD_NET
+ #define CONFIG_DRIVER_TI_CPSW
+ #define CONFIG_NET_MULTI
+ #define CONFIG_PHY_GIGE
-#define CONFIG_CMD_DHCP
-#define CONFIG_CMD_PING
+ #define CONFIG_CMD_MII
-#define CONFIG_MTD_DEVICE
-#define CONFIG_ENV_IS_IN_NAND
+ /* Add for working with "strict" DHCP server */
+ #define CONFIG_BOOTP_SUBNETMASK
+ #define CONFIG_BOOTP_GATEWAY
+ #define CONFIG_BOOTP_DNS
+ #define CONFIG_BOOTP_DNS2
+ #endif
+
+ /*
+ * NAND flash driver
+ */
+ #ifdef CONFIG_CMD_NAND
-#define CONFIG_CMD_NAND_TRIMFFS
+ #define CONFIG_NAND_OMAP_GPMC
+ #ifndef CONFIG_SPL_BUILD
+ #define CONFIG_SYS_GPMC_PREFETCH_ENABLE
+ #endif
+ #define GPMC_NAND_ECC_LP_x8_LAYOUT
+ #define GPMC_NAND_HW_ECC_LAYOUT_KERNEL GPMC_NAND_HW_ECC_LAYOUT
+ #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x20000
+ #define CONFIG_SYS_NAND_PAGE_SIZE 2048
+ #define CONFIG_SYS_NAND_OOBSIZE 64
+ #define CONFIG_SYS_NAND_ECCSIZE 512
+ #define CONFIG_SYS_NAND_ECCBYTES 14
-#define CONFIG_SYS_NAND_USE_FLASH_BBT
+ #define CONFIG_SYS_NAND_MAX_CHIPS 0x1
+ #define CONFIG_SYS_NAND_MAXBAD 20 /* Max. number of bad blocks guaranteed by manufacturer */
+ #define CONFIG_SYS_MAX_NAND_DEVICE 0x1
+ #define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_ENV_IS_IN_MMC
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #define CONFIG_ENV_OVERWRITE
+ #define CONFIG_ENV_OFFSET (CONFIG_U_BOOT_IMG_SIZE + CONFIG_SYS_NAND_U_BOOT_OFFS)
+ #define CONFIG_ENV_SIZE SZ_128K
+ #define CONFIG_ENV_RANGE 0x60000
+ #endif /* CONFIG_ENV_IS_IN_NAND */
+ #define CONFIG_SYS_NAND_BASE 0x00100000
+ #define CONFIG_SYS_NAND_SIZE SZ_128M
+ #define NAND_BASE CONFIG_SYS_NAND_BASE
+ #endif /* CONFIG_CMD_NAND */
+
+ /*
+ * MMC Driver
+ */
+ #ifdef CONFIG_CMD_MMC
+ #ifndef CONFIG_ENV_IS_IN_NAND
-#define CONFIG_MMC
-#define CONFIG_GENERIC_MMC
+ #endif
+ #define CONFIG_OMAP_HSMMC
+ #define CONFIG_OMAP_MMC_DEV_1
+
+ #define CONFIG_DOS_PARTITION
+ #define CONFIG_CMD_FAT
+ #define CONFIG_FAT_WRITE
+ #define CONFIG_CMD_EXT2
+
+ /*
+ * Environments on MMC
+ */
+ #ifdef CONFIG_ENV_IS_IN_MMC
+ #define CONFIG_SYS_MMC_ENV_DEV 0
+ #define CONFIG_ENV_OVERWRITE
+ /* Associated with the MMC layout defined in mmcops.c */
+ #define CONFIG_ENV_OFFSET SZ_1K
+ #define CONFIG_ENV_SIZE (SZ_128K - CONFIG_ENV_OFFSET)
+ #define CONFIG_DYNAMIC_MMC_DEVNO
+ #endif /* CONFIG_ENV_IS_IN_MMC */
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_ENV_OFFSET_REDUND
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "128k(u-boot-spl)," \
+ "1m(u-boot)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env2),6m(linux),32m(rootfs),89216k(userfs),512k@0x7f00000(dtb),512k@0x7f80000(bbt)ro"
+ #else
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "128k(u-boot-spl)," \
+ "1m(u-boot)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env),6m(linux),32m(rootfs),89600k(userfs),512k@0x7f00000(dtb),512k@0x7f80000(bbt)ro"
+ #endif
+
+ #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
+ #define SRAM0_SIZE SZ_64K
+ #define OCMC_SRAM_BASE 0x40300000
+ #define CONFIG_SPL_STACK (OCMC_SRAM_BASE + 0xb800)
+ #define CONFIG_SYS_INIT_SP_ADDR (PHYS_SDRAM_1 + SZ_32K)
+
+ /* Platform/Board specific defs */
+ #define CONFIG_SYS_TIMERBASE 0x48040000 /* Use Timer2 */
+ #define CONFIG_SYS_PTV 2 /* Divisor: 2^(PTV+1) => 8 */
+
+ /* Defines for SPL */
+ #define CONFIG_SPL
+ #define CONFIG_SPL_FRAMEWORK
+ #define CONFIG_SPL_MAX_SIZE (SRAM_SCRATCH_SPACE_ADDR - CONFIG_SPL_TEXT_BASE)
+ #define CONFIG_SPL_GPIO_SUPPORT
+ #ifdef CONFIG_NAND_OMAP_GPMC
+ #define CONFIG_SPL_NAND_SUPPORT
+ #define CONFIG_SPL_NAND_DRIVERS
+ #define CONFIG_SPL_NAND_BASE
+ #define CONFIG_SPL_NAND_ECC
+ #define CONFIG_SPL_NAND_AM33XX_BCH
+ #define CONFIG_SYS_NAND_5_ADDR_CYCLE
+ #define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \
+ CONFIG_SYS_NAND_PAGE_SIZE)
+ #define CONFIG_SYS_NAND_BLOCK_SIZE SZ_128K
+ #define CONFIG_SYS_NAND_BAD_BLOCK_POS NAND_LARGE_BADBLOCK_POS
+ #define CONFIG_SYS_NAND_ECCPOS { 2, 3, 4, 5, 6, 7, 8, 9, \
+ 10, 11, 12, 13, 14, 15, 16, 17, \
+ 18, 19, 20, 21, 22, 23, 24, 25, \
+ 26, 27, 28, 29, 30, 31, 32, 33, \
+ 34, 35, 36, 37, 38, 39, 40, 41, \
+ 42, 43, 44, 45, 46, 47, 48, 49, \
+ 50, 51, 52, 53, 54, 55, 56, 57, }
+ #endif
+
+ #define CONFIG_SPL_BSS_START_ADDR PHYS_SDRAM_1
+ #define CONFIG_SPL_BSS_MAX_SIZE SZ_512K
+
+ #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */
+
+ #define CONFIG_SPL_LIBCOMMON_SUPPORT
+ #define CONFIG_SPL_LIBGENERIC_SUPPORT
+ #define CONFIG_SPL_SERIAL_SUPPORT
+ #define CONFIG_SPL_YMODEM_SUPPORT
+ #define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
+
+ /*
+ * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM
+ * 64 bytes before this address should be set aside for u-boot.img's
+ * header. That is 0x800FFFC0--0x80100000 should not be used for any
+ * other needs.
+ */
+ #define CONFIG_SYS_SPL_MALLOC_START (PHYS_SDRAM_1 + SZ_2M + SZ_32K)
+ #define CONFIG_SYS_SPL_MALLOC_SIZE SZ_1M
+
+ #endif /* __CONFIG_H */
--- /dev/null
-#include <asm/sizes.h>
+ /*
+ * Copyright (C) 2012-2014 <LW@KARO-electronics.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+
+ #ifndef __CONFIG_H
+ #define __CONFIG_H
+
+ #define CONFIG_MX51 /* must be set before including imx-regs.h */
+
-#define LCD_BPP LCD_COLOR24
++#include <linux/sizes.h>
+ #include <asm/arch/imx-regs.h>
+
+ /*
+ * Ka-Ro TX51 board - SoC configuration
+ */
+ #define CONFIG_SYS_MX5_IOMUX_V3
+ #define CONFIG_MXC_GPIO /* GPIO control */
+ #define CONFIG_SYS_MX5_HCLK 24000000
+ #define CONFIG_SYS_DDR_CLKSEL 0
+ #define CONFIG_SYS_HZ 1000 /* Ticks per second */
+ #define CONFIG_SHOW_ACTIVITY
+ #define CONFIG_DISPLAY_BOARDINFO
+ #define CONFIG_BOARD_LATE_INIT
+ #define CONFIG_BOARD_EARLY_INIT_F
+
+ #if CONFIG_SYS_CPU_CLK == 600
+ #define TX51_MOD_PREFIX "6"
+ #elif CONFIG_SYS_CPU_CLK == 800
+ #define TX51_MOD_PREFIX "8"
+ #define CONFIG_MX51_PLL_ERRATA
+ #else
+ #error Invalid CPU clock
+ #endif
+
+ /* LCD Logo and Splash screen support */
+ #define CONFIG_LCD
+ #ifdef CONFIG_LCD
+ #define CONFIG_SPLASH_SCREEN
+ #define CONFIG_SPLASH_SCREEN_ALIGN
+ #define CONFIG_VIDEO_IPUV3
+ #define CONFIG_IPUV3_CLK 133000000
+ #define CONFIG_LCD_LOGO
-#define CONFIG_SYS_NO_FLASH
++#define LCD_BPP LCD_COLOR32
+ #define CONFIG_CMD_BMP
+ #define CONFIG_VIDEO_BMP_RLE8
+ #endif /* CONFIG_LCD */
+
+ /*
+ * Memory configuration options
+ */
+ #define PHYS_SDRAM_1 0x90000000 /* Base address of bank 1 */
+ #define PHYS_SDRAM_1_SIZE SZ_128M
+ #if CONFIG_NR_DRAM_BANKS > 1
+ #define PHYS_SDRAM_2 0x98000000 /* Base address of bank 2 */
+ #define PHYS_SDRAM_2_SIZE SZ_128M
+ #endif
+ #define CONFIG_STACKSIZE SZ_128K
+ #define CONFIG_SYS_MALLOC_LEN SZ_8M
+ #define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* Memtest start address */
+ #define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1 + SZ_4M) /* 4 MB RAM test */
+ #define CONFIG_SYS_SDRAM_CLK 166
+ #define CONFIG_SYS_CLKTL_CBCDR 0x01e35100
+
+ /*
+ * U-Boot general configurations
+ */
+ #define CONFIG_SYS_LONGHELP
+ #define CONFIG_SYS_PROMPT "TX51 U-Boot > "
+ #define CONFIG_SYS_CBSIZE 2048 /* Console I/O buffer size */
+ #define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+ /* Print buffer size */
+ #define CONFIG_SYS_MAXARGS 256 /* Max number of command args */
+ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+ #define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+ #define CONFIG_AUTO_COMPLETE /* Command auto complete */
+ #define CONFIG_CMDLINE_EDITING /* Command history etc */
+
+ #define CONFIG_SYS_64BIT_VSPRINTF
-#define CONFIG_OF_LIBFDT
-#define CONFIG_OF_BOARD_SETUP
+
+ /*
+ * Flattened Device Tree (FDT) support
+ */
-#define CONFIG_HW_WATCHDOG
+
+ /*
+ * Boot Linux
+ */
+ #define xstr(s) str(s)
+ #define str(s) #s
+ #define __pfx(x, s) (x##s)
+ #define _pfx(x, s) __pfx(x, s)
+
+ #define CONFIG_CMDLINE_TAG
+ #define CONFIG_SETUP_MEMORY_TAGS
+ #define CONFIG_BOOTDELAY 3
+ #define CONFIG_ZERO_BOOTDELAY_CHECK
+ #define CONFIG_SYS_AUTOLOAD "no"
+ #define CONFIG_BOOTFILE "uImage"
+ #define CONFIG_BOOTARGS "init=/linuxrc console=ttymxc0,115200 ro debug panic=1"
+ #define CONFIG_BOOTCOMMAND "run bootcmd_${boot_mode} bootm_cmd"
+ #define CONFIG_LOADADDR 94000000
+ #define CONFIG_FDTADDR 91000000
+ #define CONFIG_SYS_LOAD_ADDR _pfx(0x, CONFIG_LOADADDR)
+ #define CONFIG_SYS_FDT_ADDR _pfx(0x, CONFIG_FDTADDR)
+ #define CONFIG_U_BOOT_IMG_SIZE SZ_1M
-#define CONFIG_FDT_FIXUP_PARTITIONS
+
+ /*
+ * Extra Environment Settings
+ */
+ #define CONFIG_SYS_CPU_CLK_STR xstr(CONFIG_SYS_CPU_CLK)
+
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "baseboard=stk5-v3\0" \
+ "bootargs_jffs2=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mtdblock3 rootfstype=jffs2\0" \
+ "bootargs_mmc=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mmcblk0p2 rootwait\0" \
+ "bootargs_nfs=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock" \
+ " ip=dhcp\0" \
+ "bootargs_ubifs=run default_bootargs;set bootargs ${bootargs}" \
+ " ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs\0" \
+ "bootcmd_jffs2=set autostart no;run bootargs_jffs2" \
+ ";nboot linux\0" \
+ "bootcmd_mmc=set autostart no;run bootargs_mmc" \
+ ";fatload mmc 0 ${loadaddr} uImage\0" \
+ "bootcmd_nand=set autostart no;run bootargs_ubifs" \
+ ";nboot linux\0" \
+ "bootcmd_net=set autoload y;set autostart n;run bootargs_nfs" \
+ ";dhcp\0" \
+ "bootm_cmd=bootm ${loadaddr} - ${fdtaddr}\0" \
+ "boot_mode=nand\0" \
+ "cpu_clk=" CONFIG_SYS_CPU_CLK_STR "\0" \
+ "default_bootargs=set bootargs " CONFIG_BOOTARGS \
+ " ${append_bootargs}\0" \
+ "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \
+ "fdtsave=fdt resize;nand erase.part dtb" \
+ ";nand write ${fdtaddr} dtb ${fdtsize}\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0" \
+ "nfsroot=/tftpboot/rootfs\0" \
+ "otg_mode=device\0" \
+ "touchpanel=tsc2007\0" \
+ "video_mode=VGA\0"
+
+ #define MTD_NAME "mxc_nand"
+ #define MTDIDS_DEFAULT "nand0=" MTD_NAME
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_MMC
-#define CONFIG_CMD_NAND
-#define CONFIG_CMD_MTDPARTS
-#define CONFIG_CMD_BOOTCE
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_MEMTEST
+
+ /*
+ * U-Boot Commands
+ */
+ #include <config_cmd_default.h>
-#define CONFIG_FEC_MXC
+
+ /*
+ * Serial Driver
+ */
+ #define CONFIG_MXC_UART
+ #define CONFIG_MXC_UART_BASE UART1_BASE
+ #define CONFIG_MXC_GPIO
+ #define CONFIG_BAUDRATE 115200 /* Default baud rate */
+ #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, }
+ #define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+ /*
+ * Ethernet Driver
+ */
-#define CONFIG_FEC_MXC_PHYADDR 0x1f
-#define CONFIG_PHYLIB
-#define CONFIG_PHY_SMSC
-#define CONFIG_MII
+ #ifdef CONFIG_FEC_MXC
+ #define IMX_FEC_BASE FEC_BASE_ADDR
-#define CONFIG_GET_FEC_MAC_ADDR_FROM_IIM
+ #define CONFIG_FEC_XCV_TYPE MII100
-#define CONFIG_CMD_DHCP
-#define CONFIG_CMD_PING
+ #define CONFIG_CMD_MII
-#define CONFIG_MTD_DEVICE
-#define CONFIG_ENV_IS_IN_NAND
-#define CONFIG_NAND_MXC
+ /* Add for working with "strict" DHCP server */
+ #define CONFIG_BOOTP_SUBNETMASK
+ #define CONFIG_BOOTP_GATEWAY
+ #define CONFIG_BOOTP_DNS
+ #endif
+
+ /*
+ * NAND flash driver
+ */
+ #ifdef CONFIG_CMD_NAND
-#define CONFIG_CMD_NAND_TRIMFFS
+ #define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR_AXI
+ #define CONFIG_MXC_NAND_IP_REGS_BASE NFC_BASE_ADDR
+ #define CONFIG_MXC_NAND_HWECC
-#define CONFIG_SYS_NAND_USE_FLASH_BBT
+ #define CONFIG_SYS_NAND_MAX_CHIPS 0x1
+ #define CONFIG_SYS_MAX_NAND_DEVICE 0x1
+ #define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_CMD_ROMUPDATE
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #define CONFIG_ENV_OVERWRITE
+ #define CONFIG_ENV_OFFSET CONFIG_U_BOOT_IMG_SIZE
+ #define CONFIG_ENV_SIZE 0x20000 /* 128 KiB */
+ #define CONFIG_ENV_RANGE 0x60000
+ #endif
+ #define CONFIG_SYS_NAND_BASE 0x00000000
-#define CONFIG_ENV_IS_IN_MMC
+ #endif /* CONFIG_CMD_NAND */
+
+ /*
+ * MMC Driver
+ */
+ #ifdef CONFIG_CMD_MMC
+ #ifndef CONFIG_ENV_IS_IN_NAND
-#define CONFIG_MMC
-#define CONFIG_GENERIC_MMC
-#define CONFIG_FSL_ESDHC
+ #endif
+ #define CONFIG_SYS_FSL_ESDHC_ADDR 0
+
+ #define CONFIG_DOS_PARTITION
+ #define CONFIG_CMD_FAT
+ #define CONFIG_FAT_WRITE
+ #define CONFIG_CMD_EXT2
+
+ /*
+ * Environments on MMC
+ */
+ #ifdef CONFIG_ENV_IS_IN_MMC
+ #define CONFIG_SYS_MMC_ENV_DEV 0
+ #define CONFIG_ENV_OVERWRITE
+ /* Associated with the MMC layout defined in mmcops.c */
+ #define CONFIG_ENV_OFFSET SZ_1K
+ #define CONFIG_ENV_SIZE (SZ_128K - CONFIG_ENV_OFFSET)
+ #define CONFIG_DYNAMIC_MMC_DEVNO
+ #endif /* CONFIG_ENV_IS_IN_MMC */
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_ENV_OFFSET_REDUND
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "1m(u-boot)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env2),6m(linux),32m(rootfs),89344k(userfs),512k@0x7f00000(dtb),512k@0x7f80000(bbt)ro"
+ #else
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "1m(u-boot)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env),6m(linux),32m(rootfs),89728k(userfs),512k@0x7f00000(dtb),512k@0x7f80000(bbt)ro"
+ #endif
+
+ #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
+ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - /* Fix this */ \
+ GENERATED_GBL_DATA_SIZE)
+
+ #ifdef CONFIG_CMD_IIM
+ #define CONFIG_FSL_IIM
+ #endif
+
+ #endif /* __CONFIG_H */
--- /dev/null
-#define CONFIG_MX53 /* must be set before including imx-regs.h */
-
-#include <asm/sizes.h>
+ /*
+ * Copyright (C) 2012-2014 <LW@KARO-electronics.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+
+ #ifndef __CONFIG_H
+ #define __CONFIG_H
+
-#define CONFIG_TX53 /* TX53 SoM */
++#include <linux/sizes.h>
+ #include <asm/arch/imx-regs.h>
+
+ /*
+ * Ka-Ro TX53 board - SoC configuration
+ */
-#define LCD_BPP LCD_COLOR24
+ #define CONFIG_SYS_MX5_IOMUX_V3
+ #define CONFIG_MXC_GPIO /* GPIO control */
+ #define CONFIG_SYS_MX5_HCLK 24000000
+ #define CONFIG_SYS_DDR_CLKSEL 0
+ #define CONFIG_SYS_HZ 1000 /* Ticks per second */
+ #define CONFIG_SHOW_ACTIVITY
+ #define CONFIG_DISPLAY_BOARDINFO
+ #define CONFIG_BOARD_LATE_INIT
+ #define CONFIG_BOARD_EARLY_INIT_F
+
+ /* LCD Logo and Splash screen support */
+ #define CONFIG_LCD
+ #ifdef CONFIG_LCD
+ #define CONFIG_SPLASH_SCREEN
+ #define CONFIG_SPLASH_SCREEN_ALIGN
+ #define CONFIG_VIDEO_IPUV3
+ #define CONFIG_IPUV3_CLK 200000000
+ #define CONFIG_LCD_LOGO
-#define CONFIG_SYS_NO_FLASH
++#define LCD_BPP LCD_COLOR32
+ #define CONFIG_CMD_BMP
+ #define CONFIG_VIDEO_BMP_RLE8
+ #endif /* CONFIG_LCD */
+
+ /*
+ * Memory configuration options
+ */
+ #ifndef CONFIG_SYS_SDRAM_SIZE
+ #define CONFIG_SYS_SDRAM_SIZE (SZ_512M * CONFIG_NR_DRAM_BANKS)
+ #endif
+
+ #define PHYS_SDRAM_1 0x70000000 /* Base address of bank 1 */
+ #define PHYS_SDRAM_1_SIZE (CONFIG_SYS_SDRAM_SIZE / CONFIG_NR_DRAM_BANKS)
+ #if CONFIG_NR_DRAM_BANKS > 1
+ #define PHYS_SDRAM_2 0xb0000000 /* Base address of bank 2 */
+ #define PHYS_SDRAM_2_SIZE PHYS_SDRAM_1_SIZE
+ #endif
+ #define CONFIG_STACKSIZE SZ_128K
+ #define CONFIG_SYS_MALLOC_LEN SZ_8M
+ #define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* Memtest start address */
+ #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + SZ_4M)
+ #define CONFIG_SYS_SDRAM_CLK 400
+
+ /*
+ * U-Boot general configurations
+ */
+ #define CONFIG_SYS_LONGHELP
+ #define CONFIG_SYS_PROMPT "TX53 U-Boot > "
+ #define CONFIG_SYS_CBSIZE 2048 /* Console I/O buffer size */
+ #define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+ /* Print buffer size */
+ #define CONFIG_SYS_MAXARGS 256 /* Max number of command args */
+ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+ #define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+ #define CONFIG_AUTO_COMPLETE /* Command auto complete */
+ #define CONFIG_CMDLINE_EDITING /* Command history etc */
+
+ #define CONFIG_SYS_64BIT_VSPRINTF
-#define CONFIG_OF_LIBFDT
-#define CONFIG_OF_BOARD_SETUP
+
+ /*
+ * Flattened Device Tree (FDT) support
+ */
-#define CONFIG_HW_WATCHDOG
+
+ /*
+ * Boot Linux
+ */
+ #define xstr(s) str(s)
+ #define str(s) #s
+ #define __pfx(x, s) (x##s)
+ #define _pfx(x, s) __pfx(x, s)
+
+ #define CONFIG_CMDLINE_TAG
+ #define CONFIG_SETUP_MEMORY_TAGS
+ #define CONFIG_BOOTDELAY 3
+ #define CONFIG_ZERO_BOOTDELAY_CHECK
+ #define CONFIG_SYS_AUTOLOAD "no"
+ #define CONFIG_BOOTFILE "uImage"
+ #define CONFIG_BOOTARGS "init=/linuxrc console=ttymxc0,115200 ro debug panic=1"
+ #define CONFIG_BOOTCOMMAND "run bootcmd_${boot_mode} bootm_cmd"
+ #define CONFIG_LOADADDR 78000000
+ #define CONFIG_FDTADDR 71000000
+ #define CONFIG_SYS_LOAD_ADDR _pfx(0x, CONFIG_LOADADDR)
+ #define CONFIG_SYS_FDT_ADDR _pfx(0x, CONFIG_FDTADDR)
+ #define CONFIG_U_BOOT_IMG_SIZE SZ_1M
-#define CONFIG_FDT_FIXUP_PARTITIONS
+ #ifndef CONFIG_SYS_LVDS_IF
+ #define DEFAULT_VIDEO_MODE "VGA"
+ #else
+ #define DEFAULT_VIDEO_MODE "HSD100PXN1"
+ #endif
+
+ /*
+ * Extra Environment Settings
+ */
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "baseboard=stk5-v3\0" \
+ "bootargs_jffs2=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mtdblock3 rootfstype=jffs2\0" \
+ "bootargs_mmc=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mmcblk0p2 rootwait\0" \
+ "bootargs_nfs=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock" \
+ " ip=dhcp\0" \
+ "bootargs_ubifs=run default_bootargs;set bootargs ${bootargs}" \
+ " ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs\0" \
+ "bootcmd_jffs2=set autostart no;run bootargs_jffs2" \
+ ";nboot linux\0" \
+ "bootcmd_mmc=set autostart no;run bootargs_mmc" \
+ ";fatload mmc 0 ${loadaddr} uImage\0" \
+ "bootcmd_nand=set autostart no;run bootargs_ubifs" \
+ ";nboot linux\0" \
+ "bootcmd_net=set autoload y;set autostart n;run bootargs_nfs" \
+ ";dhcp\0" \
+ "bootm_cmd=bootm ${loadaddr} - ${fdtaddr}\0" \
+ "boot_mode=nand\0" \
+ "cpu_clk=800\0" \
+ "default_bootargs=set bootargs " CONFIG_BOOTARGS \
+ " ${append_bootargs}\0" \
+ "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \
+ "fdtsave=fdt resize;nand erase.part dtb" \
+ ";nand write ${fdtaddr} dtb ${fdtsize}\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0" \
+ "nfsroot=/tftpboot/rootfs\0" \
+ "otg_mode=device\0" \
+ "touchpanel=tsc2007\0" \
+ "video_mode=" DEFAULT_VIDEO_MODE "\0"
+
+ #define MTD_NAME "mxc_nand"
+ #define MTDIDS_DEFAULT "nand0=" MTD_NAME
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_MMC
-#define CONFIG_CMD_NAND
-#define CONFIG_CMD_MTDPARTS
-#define CONFIG_CMD_BOOTCE
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_I2C
-#define CONFIG_CMD_MEMTEST
+
+ /*
+ * U-Boot Commands
+ */
+ #include <config_cmd_default.h>
-#define CONFIG_FEC_MXC
+
+ /*
+ * Serial Driver
+ */
+ #define CONFIG_MXC_UART
+ #define CONFIG_MXC_UART_BASE UART1_BASE
+ #define CONFIG_BAUDRATE 115200 /* Default baud rate */
+ #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, }
+ #define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+ /*
+ * GPIO driver
+ */
+ #define CONFIG_MXC_GPIO
+
+ /*
+ * Ethernet Driver
+ */
-#define CONFIG_FEC_MXC_PHYADDR 0
-#define CONFIG_PHYLIB
-#define CONFIG_PHY_SMSC
-#define CONFIG_MII
+ #ifdef CONFIG_FEC_MXC
+ #define IMX_FEC_BASE FEC_BASE_ADDR
-#define CONFIG_GET_FEC_MAC_ADDR_FROM_IIM
+ #define CONFIG_FEC_XCV_TYPE MII100
-#define CONFIG_CMD_DHCP
-#define CONFIG_CMD_PING
+ #define CONFIG_CMD_MII
-#define CONFIG_HARD_I2C
+ /* Add for working with "strict" DHCP server */
+ #define CONFIG_BOOTP_SUBNETMASK
+ #define CONFIG_BOOTP_GATEWAY
+ #define CONFIG_BOOTP_DNS
+ #endif
+
+ /*
+ * I2C Configs
+ */
+ #ifdef CONFIG_CMD_I2C
-#define CONFIG_MTD_DEVICE
-#define CONFIG_ENV_IS_IN_NAND
-#define CONFIG_NAND_MXC
+ #define CONFIG_I2C_MXC
+ #define CONFIG_SYS_I2C_BASE I2C1_BASE_ADDR
+ #define CONFIG_SYS_I2C_MX6_PORT1
+ #define CONFIG_SYS_I2C_SPEED 400000
+ #define CONFIG_SYS_I2C_SLAVE 0x34
+ #endif
+
+ /*
+ * NAND flash driver
+ */
+ #ifdef CONFIG_CMD_NAND
-#define CONFIG_CMD_NAND_TRIMFFS
+ #define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR_AXI
+ #define CONFIG_MXC_NAND_IP_REGS_BASE NFC_BASE_ADDR
+ #define CONFIG_MXC_NAND_HWECC
-#define CONFIG_SYS_NAND_USE_FLASH_BBT
+ #define CONFIG_SYS_NAND_MAX_CHIPS 0x1
+ #define CONFIG_SYS_MAX_NAND_DEVICE 0x1
+ #define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_CMD_ROMUPDATE
+ #ifdef CONFIG_ENV_IS_IN_NAND
+ #define CONFIG_ENV_OVERWRITE
+ #define CONFIG_ENV_OFFSET CONFIG_U_BOOT_IMG_SIZE
+ #define CONFIG_ENV_SIZE 0x20000 /* 128 KiB */
+ #define CONFIG_ENV_RANGE 0x60000
+ #endif
+ #define CONFIG_SYS_NAND_BASE 0x00000000
-#define CONFIG_ENV_IS_IN_MMC
+ #endif /* CONFIG_CMD_NAND */
+
+ /*
+ * MMC Driver
+ */
+ #ifdef CONFIG_CMD_MMC
+ #ifndef CONFIG_ENV_IS_IN_NAND
-#define CONFIG_MMC
-#define CONFIG_GENERIC_MMC
-#define CONFIG_FSL_ESDHC
+ #endif
+ #define CONFIG_SYS_FSL_ESDHC_ADDR 0
+
+ #define CONFIG_DOS_PARTITION
+ #define CONFIG_CMD_FAT
+ #define CONFIG_FAT_WRITE
+ #define CONFIG_CMD_EXT2
+
+ /*
+ * Environments on MMC
+ */
+ #ifdef CONFIG_ENV_IS_IN_MMC
+ #define CONFIG_SYS_MMC_ENV_DEV 0
+ #define CONFIG_ENV_OVERWRITE
+ /* Associated with the MMC layout defined in mmcops.c */
+ #define CONFIG_ENV_OFFSET SZ_1K
+ #define CONFIG_ENV_SIZE (SZ_128K - CONFIG_ENV_OFFSET)
+ #define CONFIG_DYNAMIC_MMC_DEVNO
+ #endif /* CONFIG_ENV_IS_IN_MMC */
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_ENV_OFFSET_REDUND
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "1m(u-boot)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env2),6m(linux),32m(rootfs),89344k(userfs),512k@0x7f00000(dtb),512k@0x7f80000(bbt)ro"
+ #else
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ "1m(u-boot)," \
+ xstr(CONFIG_ENV_RANGE) \
+ "(env),6m(linux),32m(rootfs),89728k(userfs),512k@0x7f00000(dtb),512k@0x7f80000(bbt)ro"
+ #endif
+
+ #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
+ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - /* Fix this */ \
+ GENERATED_GBL_DATA_SIZE)
+
+ #ifdef CONFIG_CMD_IIM
+ #define CONFIG_FSL_IIM
+ #endif
+
+ #endif /* __CONFIG_H */
--- /dev/null
- * Copyright (C) 2012 <LW@KARO-electronics.de>
+ /*
-#include <asm/sizes.h>
++ * Copyright (C) 2012-2015 <LW@KARO-electronics.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+
+ #ifndef __CONFIG_H
+ #define __CONFIG_H
+
-#ifndef CONFIG_TX6_REV
-#define CONFIG_TX6_REV 0x1 /* '1' would be converted to 'y' by define2mk.sed */
-#endif
-#define CONFIG_MX6
++#include <linux/sizes.h>
+ #include <asm/arch/imx-regs.h>
++#include "mx6_common.h"
+
+ /*
+ * Ka-Ro TX6 board - SoC configuration
+ */
-#ifndef CONFIG_MFG
+ #define CONFIG_SYS_MX6_HCLK 24000000
+ #define CONFIG_SYS_MX6_CLK32 32768
+ #define CONFIG_SYS_HZ 1000 /* Ticks per second */
+ #define CONFIG_SHOW_ACTIVITY
+ #define CONFIG_ARCH_CPU_INIT
+ #define CONFIG_DISPLAY_BOARDINFO
+ #define CONFIG_BOARD_LATE_INIT
+ #define CONFIG_BOARD_EARLY_INIT_F
++#define CONFIG_SYS_GENERIC_BOARD
+
-#define LCD_BPP LCD_COLOR24
++#ifndef CONFIG_TX6_UBOOT_MFG
+ /* LCD Logo and Splash screen support */
+ #define CONFIG_LCD
+ #ifdef CONFIG_LCD
+ #define CONFIG_SPLASH_SCREEN
+ #define CONFIG_SPLASH_SCREEN_ALIGN
+ #define CONFIG_VIDEO_IPUV3
+ #define CONFIG_IPUV3_CLK (CONFIG_SYS_SDRAM_CLK * 1000000 / 2)
+ #define CONFIG_LCD_LOGO
-#endif /* CONFIG_MFG */
++#define LCD_BPP LCD_COLOR32
+ #define CONFIG_CMD_BMP
+ #define CONFIG_VIDEO_BMP_RLE8
+ #endif /* CONFIG_LCD */
-#define CONFIG_SYS_NO_FLASH
++#endif /* CONFIG_TX6_UBOOT_MFG */
+
+ /*
+ * Memory configuration options
+ */
+ #define CONFIG_NR_DRAM_BANKS 0x1 /* # of SDRAM banks */
+ #define PHYS_SDRAM_1 0x10000000 /* Base address of bank 1 */
+ #ifdef CONFIG_SYS_SDRAM_BUS_WIDTH
+ #define PHYS_SDRAM_1_WIDTH CONFIG_SYS_SDRAM_BUS_WIDTH
++#elif defined(CONFIG_SYS_SDRAM_BUS_WIDTH_32)
++#define PHYS_SDRAM_1_WIDTH 32
++#elif defined(CONFIG_SYS_SDRAM_BUS_WIDTH_16)
++#define PHYS_SDRAM_1_WIDTH 16
+ #else
+ #define PHYS_SDRAM_1_WIDTH 64
+ #endif
+ #define PHYS_SDRAM_1_SIZE (SZ_512M / 32 * PHYS_SDRAM_1_WIDTH)
+ #ifdef CONFIG_MX6Q
+ #define CONFIG_SYS_SDRAM_CLK 528
+ #else
+ #define CONFIG_SYS_SDRAM_CLK 400
+ #endif
+ #define CONFIG_STACKSIZE SZ_128K
+ #define CONFIG_SYS_MALLOC_LEN SZ_8M
+ #define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* Memtest start address */
+ #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + SZ_4M)
+
+ /*
+ * U-Boot general configurations
+ */
+ #define CONFIG_SYS_LONGHELP
+ #if defined(CONFIG_MX6Q)
+ #define CONFIG_SYS_PROMPT "TX6Q U-Boot > "
+ #elif defined(CONFIG_MX6DL)
+ #define CONFIG_SYS_PROMPT "TX6DL U-Boot > "
+ #elif defined(CONFIG_MX6S)
+ #define CONFIG_SYS_PROMPT "TX6S U-Boot > "
+ #else
+ #error Unsupported i.MX6 processor variant
+ #endif
+ #define CONFIG_SYS_CBSIZE 2048 /* Console I/O buffer size */
+ #define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+ /* Print buffer size */
+ #define CONFIG_SYS_MAXARGS 256 /* Max number of command args */
+ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+ #define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+ #define CONFIG_AUTO_COMPLETE /* Command auto complete */
+ #define CONFIG_CMDLINE_EDITING /* Command history etc */
+
+ #define CONFIG_SYS_64BIT_VSPRINTF
-#ifndef CONFIG_MFG
-#define CONFIG_OF_LIBFDT
+
+ /*
+ * Flattened Device Tree (FDT) support
+ */
-#ifndef CONFIG_NO_NAND
-#define CONFIG_FDT_FIXUP_PARTITIONS
+ #ifdef CONFIG_OF_LIBFDT
-#define CONFIG_OF_BOARD_SETUP
++#ifdef CONFIG_TX6_NAND
+ #endif
-#endif /* CONFIG_MFG */
+ #endif /* CONFIG_OF_LIBFDT */
-#ifndef CONFIG_MFG
+
+ /*
+ * Boot Linux
+ */
+ #define xstr(s) str(s)
+ #define str(s) #s
+ #define __pfx(x, s) (x##s)
+ #define _pfx(x, s) __pfx(x, s)
+
+ #define CONFIG_CMDLINE_TAG
+ #define CONFIG_INITRD_TAG
+ #define CONFIG_SETUP_MEMORY_TAGS
-#ifndef CONFIG_MFG
++#ifndef CONFIG_TX6_UBOOT_MFG
+ #define CONFIG_BOOTDELAY 1
+ #else
+ #define CONFIG_BOOTDELAY 0
+ #endif
+ #define CONFIG_ZERO_BOOTDELAY_CHECK
+ #define CONFIG_SYS_AUTOLOAD "no"
-#endif /* CONFIG_MFG */
++#ifndef CONFIG_TX6_UBOOT_MFG
+ #define CONFIG_BOOTFILE "uImage"
+ #define CONFIG_BOOTARGS "init=/linuxrc console=ttymxc0,115200 ro debug panic=1"
+ #define CONFIG_BOOTCOMMAND "run bootcmd_${boot_mode} bootm_cmd"
+ #else
+ #define CONFIG_BOOTCOMMAND "env import " xstr(CONFIG_BOOTCMD_MFG_LOADADDR) ";run bootcmd_mfg"
+ #define CONFIG_BOOTCMD_MFG_LOADADDR 10500000
+ #define CONFIG_DELAY_ENVIRONMENT
-#define CONFIG_HW_WATCHDOG
++#endif /* CONFIG_TX6_UBOOT_MFG */
+ #define CONFIG_LOADADDR 18000000
+ #define CONFIG_FDTADDR 11000000
+ #define CONFIG_SYS_LOAD_ADDR _pfx(0x, CONFIG_LOADADDR)
+ #define CONFIG_SYS_FDT_ADDR _pfx(0x, CONFIG_FDTADDR)
-#ifndef CONFIG_MFG
+ #ifndef CONFIG_SYS_LVDS_IF
+ #define DEFAULT_VIDEO_MODE "VGA"
+ #else
+ #define DEFAULT_VIDEO_MODE "HSD100PXN1"
+ #endif
+
+ /*
+ * Extra Environments
+ */
-#endif /* CONFIG_MFG */
++#ifndef CONFIG_TX6_UBOOT_MFG
+ #ifdef CONFIG_ENV_IS_NOWHERE
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "autoload=no\0" \
+ "bootdelay=-1\0" \
+ "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0"
+ #else
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+ "autostart=no\0" \
+ "baseboard=stk5-v3\0" \
+ "bootargs_jffs2=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/mtdblock3 rootfstype=jffs2\0" \
+ "bootargs_mmc=run default_bootargs;set bootargs ${bootargs}" \
+ MMC_ROOT_STR \
+ "bootargs_nfs=run default_bootargs;set bootargs ${bootargs}" \
+ " root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock" \
+ " ip=dhcp\0" \
+ "bootargs_ubifs=run default_bootargs;set bootargs ${bootargs}" \
+ " ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs\0" \
+ "bootcmd_jffs2=set autostart no;run bootargs_jffs2" \
+ ";nboot linux\0" \
+ "bootcmd_mmc=set autostart no;run bootargs_mmc" \
+ ";fatload mmc 0 ${loadaddr} uImage\0" \
+ CONFIG_SYS_BOOT_CMD_NAND \
+ "bootcmd_net=set autoload y;set autostart n;run bootargs_nfs" \
+ ";dhcp\0" \
+ "bootm_cmd=bootm ${loadaddr} - ${fdtaddr}\0" \
+ "boot_mode=" CONFIG_SYS_DEFAULT_BOOT_MODE "\0" \
+ "cpu_clk=800\0" \
+ "default_bootargs=set bootargs " CONFIG_BOOTARGS \
+ " ${append_bootargs}\0" \
+ "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \
+ CONFIG_SYS_FDTSAVE_CMD \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0" \
+ "nfsroot=/tftpboot/rootfs\0" \
+ "otg_mode=device\0" \
+ ROOTPART_UUID_STR \
+ "touchpanel=tsc2007\0" \
+ "video_mode=" DEFAULT_VIDEO_MODE "\0"
+ #endif /* CONFIG_ENV_IS_NOWHERE */
-#ifndef CONFIG_NO_NAND
++#endif /* CONFIG_TX6_UBOOT_MFG */
+
-#define MMC_ROOT_STR " root=dev/mmcblk0p2 rootwait\0"
++#ifdef CONFIG_TX6_NAND
+ #define CONFIG_SYS_DEFAULT_BOOT_MODE "nand"
+ #define CONFIG_SYS_BOOT_CMD_NAND \
+ "bootcmd_nand=set autostart no;run bootargs_ubifs;nboot linux\0"
+ #define CONFIG_SYS_FDTSAVE_CMD \
+ "fdtsave=fdt resize;nand erase.part dtb" \
+ ";nand write ${fdtaddr} dtb ${fdtsize}\0"
+ #define MTD_NAME "gpmi-nand"
+ #define MTDIDS_DEFAULT "nand0=" MTD_NAME
+ #define CONFIG_SYS_NAND_ONFI_DETECTION
-#define CONFIG_SUPPORT_EMMC_BOOT
-#define CONFIG_MMC_BOOT_DEV 0
++#define MMC_ROOT_STR " root=/dev/mmcblk0p2 rootwait\0"
+ #define ROOTPART_UUID_STR ""
+ #else
+ #define CONFIG_SYS_DEFAULT_BOOT_MODE "mmc"
+ #define CONFIG_SYS_BOOT_CMD_NAND ""
+ #define CONFIG_SYS_FDTSAVE_CMD \
+ "fdtsave=mmc open 0 1;mmc write ${fdtaddr} " \
+ xstr(CONFIG_SYS_DTB_BLKNO) " 80;mmc close 0 1\0"
+ #define MMC_ROOT_STR " root=PARTUUID=${rootpart_uuid} rootwait\0"
+ #define ROOTPART_UUID_STR "rootpart_uuid=0cc66cc0-02\0"
+ #define MTD_NAME ""
+ #define MTDIDS_DEFAULT ""
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_MMC
-#ifndef CONFIG_NO_NAND
-#define CONFIG_CMD_NAND
-#define CONFIG_CMD_MTDPARTS
-#endif
-#define CONFIG_CMD_BOOTCE
-#define CONFIG_CMD_BOOTZ
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_I2C
-#define CONFIG_CMD_MEMTEST
++#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ #endif
++#endif /* CONFIG_TX6_NAND */
+
+ /*
+ * U-Boot Commands
+ */
+ #include <config_cmd_default.h>
-#define CONFIG_FEC_MXC
+
+ /*
+ * Serial Driver
+ */
+ #define CONFIG_MXC_UART
+ #define CONFIG_MXC_UART_BASE UART1_BASE
+ #define CONFIG_BAUDRATE 115200 /* Default baud rate */
+ #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, }
+ #define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+ /*
+ * GPIO driver
+ */
+ #define CONFIG_MXC_GPIO
+
+ /*
+ * Ethernet Driver
+ */
-#define CONFIG_SYS_CACHELINE_SIZE 64
+ #ifdef CONFIG_FEC_MXC
+ /* This is required for the FEC driver to work with cache enabled */
+ #define CONFIG_SYS_ARM_CACHE_WRITETHROUGH
-#define CONFIG_FEC_MXC_PHYADDR 0
-#define CONFIG_PHYLIB
-#define CONFIG_PHY_SMSC
-#define CONFIG_MII
+
+ #define IMX_FEC_BASE ENET_BASE_ADDR
-#define CONFIG_GET_FEC_MAC_ADDR_FROM_IIM
-#define CONFIG_CMD_MII
-#define CONFIG_CMD_DHCP
-#define CONFIG_CMD_PING
-/* Add for working with "strict" DHCP server */
-#define CONFIG_BOOTP_SUBNETMASK
-#define CONFIG_BOOTP_GATEWAY
-#define CONFIG_BOOTP_DNS
+ #define CONFIG_FEC_XCV_TYPE RMII
-#ifdef CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
+ #endif
+
+ /*
+ * I2C Configs
+ */
-#define CONFIG_SYS_I2C_MX6_PORT1
++#ifdef CONFIG_SYS_I2C
+ #define CONFIG_SYS_I2C_BASE I2C1_BASE_ADDR
-#endif
+ #define CONFIG_SYS_I2C_SPEED 400000
++#if defined(CONFIG_TX6_REV)
+ #if CONFIG_TX6_REV == 0x1
+ #define CONFIG_SYS_I2C_SLAVE 0x3c
+ #define CONFIG_LTC3676
+ #elif CONFIG_TX6_REV == 0x2
+ #define CONFIG_SYS_I2C_SLAVE 0x32
+ #define CONFIG_RN5T618
+ #elif CONFIG_TX6_REV == 0x3
+ #define CONFIG_SYS_I2C_SLAVE 0x33
+ #define CONFIG_RN5T567
+ #else
+ #error Unsupported TX6 module revision
+ #endif
-#ifndef CONFIG_ENV_IS_NOWHERE
-/* define one of the following options:
-#define CONFIG_ENV_IS_IN_NAND
-#define CONFIG_ENV_IS_IN_MMC
-*/
-#define CONFIG_ENV_IS_IN_NAND
-#endif
++#endif /* CONFIG_TX6_REV */
++/* autodetect which PMIC is present to derive TX6_REV */
++#define CONFIG_LTC3676 /* TX6_REV == 1 */
++#define CONFIG_RN5T567 /* TX6_REV == 3 */
++#endif /* CONFIG_CMD_I2C */
+
-#ifndef CONFIG_NO_NAND
-#define CONFIG_MTD_DEVICE
-#if 0
-#define CONFIG_MTD_DEBUG
-#define CONFIG_MTD_DEBUG_VERBOSE 4
-#endif
-#define CONFIG_NAND_MXS
-#define CONFIG_NAND_MXS_NO_BBM_SWAP
-#define CONFIG_APBH_DMA
-#define CONFIG_APBH_DMA_BURST
-#define CONFIG_APBH_DMA_BURST8
-#define CONFIG_CMD_NAND_TRIMFFS
+ #define CONFIG_ENV_OVERWRITE
+
+ /*
+ * NAND flash driver
+ */
-#define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_SYS_NAND_USE_FLASH_BBT
++#ifdef CONFIG_TX6_NAND
+ #define CONFIG_SYS_MXS_DMA_CHANNEL 4
+ #define CONFIG_SYS_MAX_FLASH_BANKS 0x1
+ #define CONFIG_SYS_NAND_MAX_CHIPS 0x1
+ #define CONFIG_SYS_MAX_NAND_DEVICE 0x1
-#define CONFIG_CMD_ROMUPDATE
+ #define CONFIG_SYS_NAND_BASE 0x00000000
-#endif /* CONFIG_NO_NAND */
++#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+
+ #define CONFIG_ENV_OFFSET (CONFIG_U_BOOT_IMG_SIZE + CONFIG_SYS_NAND_U_BOOT_OFFS)
+ #define CONFIG_ENV_SIZE SZ_128K
+ #define CONFIG_ENV_RANGE (3 * CONFIG_SYS_NAND_BLOCK_SIZE)
+ #else
+ #undef CONFIG_ENV_IS_IN_NAND
-#ifdef CONFIG_CMD_MMC
-#define CONFIG_MMC
-#define CONFIG_GENERIC_MMC
-#define CONFIG_FSL_ESDHC
-#define CONFIG_FSL_USDHC
++#endif /* CONFIG_TX6_NAND */
+
+ #ifdef CONFIG_ENV_OFFSET_REDUND
+ #define CONFIG_SYS_ENV_PART_STR xstr(CONFIG_SYS_ENV_PART_SIZE) \
+ "(env)," \
+ xstr(CONFIG_SYS_ENV_PART_SIZE) \
+ "(env2),"
+ #define CONFIG_SYS_USERFS_PART_STR xstr(CONFIG_SYS_USERFS_PART_SIZE) "(userfs)"
+ #else
+ #define CONFIG_SYS_ENV_PART_STR xstr(CONFIG_SYS_ENV_PART_SIZE) \
+ "(env),"
+ #define CONFIG_SYS_USERFS_PART_STR xstr(CONFIG_SYS_USERFS_PART_SIZE2) "(userfs)"
+ #endif /* CONFIG_ENV_OFFSET_REDUND */
+
+ /*
+ * MMC Driver
+ */
-
++#ifdef CONFIG_FSL_ESDHC
+ #define CONFIG_SYS_FSL_ESDHC_ADDR 0
-#ifndef CONFIG_NO_NAND
++#endif
++#ifdef CONFIG_CMD_MMC
+ #define CONFIG_DOS_PARTITION
+ #define CONFIG_CMD_FAT
+ #define CONFIG_FAT_WRITE
+ #define CONFIG_CMD_EXT2
+
+ /*
+ * Environments on MMC
+ */
+ #ifdef CONFIG_ENV_IS_IN_MMC
+ #define CONFIG_SYS_MMC_ENV_DEV 0
+ #define CONFIG_SYS_MMC_ENV_PART 0x1
+ #define CONFIG_DYNAMIC_MMC_DEVNO
+ #endif /* CONFIG_ENV_IS_IN_MMC */
+ #else
+ #undef CONFIG_ENV_IS_IN_MMC
+ #endif /* CONFIG_CMD_MMC */
+
+ #ifdef CONFIG_ENV_IS_NOWHERE
+ #undef CONFIG_ENV_SIZE
+ #define CONFIG_ENV_SIZE SZ_4K
+ #endif
+
++#ifdef CONFIG_TX6_NAND
+ #define MTDPARTS_DEFAULT "mtdparts=" MTD_NAME ":" \
+ xstr(CONFIG_SYS_U_BOOT_PART_SIZE) \
+ "@" xstr(CONFIG_SYS_NAND_U_BOOT_OFFS) \
+ "(u-boot)," \
+ CONFIG_SYS_ENV_PART_STR \
+ "6m(linux),32m(rootfs)," CONFIG_SYS_USERFS_PART_STR "," \
+ xstr(CONFIG_SYS_DTB_PART_SIZE) \
+ "@" xstr(CONFIG_SYS_NAND_DTB_OFFSET) "(dtb)," \
+ xstr(CONFIG_SYS_NAND_BBT_SIZE) \
+ "@" xstr(CONFIG_SYS_NAND_BBT_OFFSET) "(bbt)ro"
+ #else
+ #define MTDPARTS_DEFAULT ""
+ #endif
+
+ #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
+ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - /* Fix this */ \
+ GENERATED_GBL_DATA_SIZE)
+
+ #endif /* __CONFIG_H */
#ifndef __FSL_ESDHC_H__
#define __FSL_ESDHC_H__
+ #include <linux/compat.h>
#include <asm/errno.h>
#include <asm/byteorder.h>
+/* needed for the mmc_cfg definition */
+#include <mmc.h>
+
/* FSL eSDHC-specific constants */
#define SYSCTL 0x0002e02c
#define SYSCTL_INITA 0x08000000
#define ESDHC_HOSTCAPBLT_HSS 0x00200000
struct fsl_esdhc_cfg {
- u32 esdhc_base;
+ void __iomem *esdhc_base;
u32 sdhc_clk;
u8 max_bus_width;
+ struct mmc_config cfg;
};
/* Select the correct accessors depending on endianess */
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#if defined CONFIG_SYS_FSL_ESDHC_LE
+#define esdhc_read32 in_le32
+#define esdhc_write32 out_le32
+#define esdhc_clrsetbits32 clrsetbits_le32
+#define esdhc_clrbits32 clrbits_le32
+#define esdhc_setbits32 setbits_le32
+#elif defined(CONFIG_SYS_FSL_ESDHC_BE)
+#define esdhc_read32 in_be32
+#define esdhc_write32 out_be32
+#define esdhc_clrsetbits32 clrsetbits_be32
+#define esdhc_clrbits32 clrbits_be32
+#define esdhc_setbits32 setbits_be32
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
#define esdhc_read32 in_le32
#define esdhc_write32 out_le32
#define esdhc_clrsetbits32 clrsetbits_le32
static inline int fsl_esdhc_mmc_init(bd_t *bis) { return -ENOSYS; }
static inline void fdt_fixup_esdhc(void *blob, bd_t *bd) {}
#endif /* CONFIG_FSL_ESDHC */
+void __noreturn mmc_boot(void);
+void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst);
#endif /* __FSL_ESDHC_H__ */
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de
*
- * Linux IPU driver for MX51:
+ * Linux IPU driver:
*
- * (C) Copyright 2005-2010 Freescale Semiconductor, Inc.
+ * (C) Copyright 2005-2011 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
- #ifndef __ASM_ARCH_IPU_H__
- #define __ASM_ARCH_IPU_H__
+ #ifndef __IPU_H__
+ #define __IPU_H__
#include <linux/types.h>
- #include <ipu_pixfmt.h>
+ #include <linux/list.h>
+ #include <linux/fb.h>
+
+ struct clk;
#define IDMA_CHAN_INVALID 0xFF
#define HIGH_RESOLUTION_WIDTH 1024
- struct clk {
- const char *name;
- int id;
- /* Source clock this clk depends on */
- struct clk *parent;
- /* Secondary clock to enable/disable with this clock */
- struct clk *secondary;
- /* Current clock rate */
- unsigned long rate;
- /* Reference count of clock enable/disable */
- __s8 usecount;
- /* Register bit position for clock's enable/disable control. */
- u8 enable_shift;
- /* Register address for clock's enable/disable control. */
- void *enable_reg;
- u32 flags;
- /*
- * Function ptr to recalculate the clock's rate based on parent
- * clock's rate
- */
- void (*recalc) (struct clk *);
- /*
- * Function ptr to set the clock to a new rate. The rate must match a
- * supported rate returned from round_rate. Leave blank if clock is not
- * programmable
- */
- int (*set_rate) (struct clk *, unsigned long);
- /*
- * Function ptr to round the requested clock rate to the nearest
- * supported rate that is less than or equal to the requested rate.
- */
- unsigned long (*round_rate) (struct clk *, unsigned long);
- /*
- * Function ptr to enable the clock. Leave blank if clock can not
- * be gated.
- */
- int (*enable) (struct clk *);
- /*
- * Function ptr to disable the clock. Leave blank if clock can not
- * be gated.
- */
- void (*disable) (struct clk *);
- /* Function ptr to set the parent clock of the clock. */
- int (*set_parent) (struct clk *, struct clk *);
- };
-
/*
* Enumeration of Synchronous (Memory-less) panel types
*/
IPU_PANEL_TFT,
} ipu_panel_t;
+ /* IPU Pixel format definitions */
+ #define fourcc(a, b, c, d)\
+ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+
+ /*
+ * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
+ * the same used by V4L2 API.
+ */
+
+ #define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0')
+ #define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1')
+ #define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6')
+ #define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8')
+
+ #define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*< 8 RGB-3-3-2 */
+ #define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*< 16 RGB-5-5-5 */
+ #define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*< 1 6 RGB-5-6-5 */
+ #define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*< 18 RGB-6-6-6 */
+ #define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*< 18 BGR-6-6-6 */
+ #define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*< 24 BGR-8-8-8 */
+ #define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*< 24 RGB-8-8-8 */
+ #define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*< 32 BGR-8-8-8-8 */
+ #define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*< 32 BGR-8-8-8-8 */
+ #define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*< 32 RGB-8-8-8-8 */
+ #define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*< 32 RGB-8-8-8-8 */
+ #define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*< 32 ABGR-8-8-8-8 */
+
+ /* YUV Interleaved Formats */
+ #define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*< 16 YUV 4:2:2 */
+ #define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*< 16 YUV 4:2:2 */
+ #define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*< 12 YUV 4:1:1 */
+ #define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*< 24 YUV 4:4:4 */
+
+ /* two planes -- one Y, one Cb + Cr interleaved */
+ #define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
+
+ #define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*< 8 Greyscale */
+ #define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*< 9 YVU 4:1:0 */
+ #define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*< 9 YUV 4:1:0 */
+ #define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*< 12 YVU 4:2:0 */
+ #define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*< 12 YUV 4:2:0 */
+ #define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*< 12 YUV 4:2:0 */
+ #define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*< 16 YVU 4:2:2 */
+ #define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*< 16 YUV 4:2:2 */
+
/*
* IPU Driver channels definitions.
* Note these are different from IDMA channels
* Enumeration of types of buffers for a logical channel.
*/
typedef enum {
- IPU_OUTPUT_BUFFER = 0, /*< Buffer for output from IPU */
- IPU_ALPHA_IN_BUFFER = 1, /*< Buffer for input to IPU */
- IPU_GRAPH_IN_BUFFER = 2, /*< Buffer for input to IPU */
- IPU_VIDEO_IN_BUFFER = 3, /*< Buffer for input to IPU */
+ IPU_OUTPUT_BUFFER = 0, /* Buffer for output from IPU */
+ IPU_ALPHA_IN_BUFFER = 1, /* Buffer for input to IPU */
+ IPU_GRAPH_IN_BUFFER = 2, /* Buffer for input to IPU */
+ IPU_VIDEO_IN_BUFFER = 3, /* Buffer for input to IPU */
IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
} ipu_buffer_t;
+
+ /*
+ * Enumeration of version of IPU V3 .
+ */
+ typedef enum {
+ IPUV3_HW_REV_IPUV3DEX = 2, /* IPUv3D, IPUv3E IPUv3EX */
+ IPUV3_HW_REV_IPUV3M = 3, /* IPUv3M */
+ IPUV3_HW_REV_IPUV3H = 4, /* IPUv3H */
+ } ipu3_hw_rev_t;
+
+
#define IPU_PANEL_SERIAL 1
#define IPU_PANEL_PARALLEL 2
} mem_dp_fg_sync;
} ipu_channel_params_t;
+/*
+ * Enumeration of IPU interrupts.
+ */
+enum ipu_irq_line {
+ IPU_IRQ_DP_SF_END = 448 + 3,
+ IPU_IRQ_DC_FC_1 = 448 + 9,
+};
+
/*
* Bitfield of Display Interface signal polarities.
*/
YUV
} ipu_color_space_t;
+ typedef enum {
+ DI_PCLK_PLL3,
+ DI_PCLK_LDB,
+ DI_PCLK_TVE
+ } ipu_di_clk_parent_t;
+
/* Common IPU API */
+ int ipuv3_fb_init(struct fb_videomode *mode, int di,
+ unsigned int interface_pix_fmt,
+ ipu_di_clk_parent_t di_clk_parent,
+ unsigned long di_clk_val, int bpp);
+ void ipuv3_fb_shutdown(void);
+
int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params);
void ipu_uninit_channel(ipu_channel_t channel);
uint32_t bytes_per_pixel(uint32_t fmt);
- void clk_enable(struct clk *clk);
+ int clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
u32 clk_get_rate(struct clk *clk);
int clk_set_rate(struct clk *clk, unsigned long rate);
struct clk *clk_get_parent(struct clk *clk);
void ipu_dump_registers(void);
- int ipu_probe(void);
+ int ipu_probe(int di, ipu_di_clk_parent_t di_clk_parent, int di_clk_val);
void ipu_dmfc_init(int dmfc_type, int first);
void ipu_init_dc_mappings(void);
void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap);
ipu_color_space_t format_to_colorspace(uint32_t fmt);
- #endif
+ #endif /* __IPU_H */
/*
+ * Copyright (C) 2004-2010 Freescale Semiconductor, Inc.
+ *
* MPC823 and PXA LCD Controller
*
* Modeled after video interface by Paolo Scaffardi
* (C) Copyright 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _LCD_H_
void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue);
void lcd_initcolregs(void);
-int lcd_getfgcolor(void);
-
/* gunzip_bmp used if CONFIG_VIDEO_BMP_GZIP */
struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
void **alloc_addr);
unsigned int logo_on;
unsigned int logo_width;
unsigned int logo_height;
+ int logo_x_offset;
+ int logo_y_offset;
unsigned long logo_addr;
unsigned int rgb_mode;
unsigned int resolution;
void *priv; /* Pointer to driver-specific data */
} vidinfo_t;
-#endif /* CONFIG_MPC823, CONFIG_CPU_PXA25X, CONFIG_MCC200, CONFIG_ATMEL_LCD */
+#endif /* CONFIG_MPC823, CONFIG_CPU_PXA25X, CONFIG_ATMEL_LCD */
extern vidinfo_t panel_info;
/* Video functions */
+ void lcd_disable(void);
+ void lcd_panel_disable(void);
+
void lcd_putc(const char c);
void lcd_puts(const char *s);
void lcd_printf(const char *fmt, ...);
int lcd_dt_simplefb_add_node(void *blob);
int lcd_dt_simplefb_enable_existing_node(void *blob);
+/* Update the LCD / flush the cache */
+void lcd_sync(void);
+
/************************************************************************/
/* ** BITMAP DISPLAY SUPPORT */
/************************************************************************/
#define LCD_COLOR4 2
#define LCD_COLOR8 3
#define LCD_COLOR16 4
-#define LCD_COLOR24 5
-
+#define LCD_COLOR32 5
/*----------------------------------------------------------------------*/
#if defined(CONFIG_LCD_INFO_BELOW_LOGO)
# define LCD_INFO_X 0
# define CONSOLE_COLOR_GREY 14
# define CONSOLE_COLOR_WHITE 15 /* Must remain last / highest */
- #else
+#elif LCD_BPP == LCD_COLOR32
+/*
+ * 32bpp color definitions
+ */
+# define CONSOLE_COLOR_RED 0x00ff0000
+# define CONSOLE_COLOR_GREEN 0x0000ff00
+# define CONSOLE_COLOR_YELLOW 0x00ffff00
+# define CONSOLE_COLOR_BLUE 0x000000ff
+# define CONSOLE_COLOR_MAGENTA 0x00ff00ff
+# define CONSOLE_COLOR_CYAN 0x0000ffff
+# define CONSOLE_COLOR_GREY 0x00aaaaaa
+# define CONSOLE_COLOR_BLACK 0x00000000
+# define CONSOLE_COLOR_WHITE 0x00ffffff /* Must remain last / highest*/
+# define NBYTES(bit_code) (NBITS(bit_code) >> 3)
+
+ #elif LCD_BPP == LCD_COLOR16
/*
* 16bpp color definitions
*/
# define CONSOLE_COLOR_BLACK 0x0000
+ # define CONSOLE_COLOR_RED 0xf800
+ # define CONSOLE_COLOR_GREEN 0x07e0
+ # define CONSOLE_COLOR_YELLOW 0xffe0
+ # define CONSOLE_COLOR_BLUE 0x001f
+ # define CONSOLE_COLOR_MAGENTA 0xf81f
+ # define CONSOLE_COLOR_CYAN 0x07ff
+ # define CONSOLE_COLOR_GREY 0xcccc
# define CONSOLE_COLOR_WHITE 0xffff /* Must remain last / highest */
-#elif LCD_BPP == LCD_COLOR24
-/*
- * 16bpp color definitions
- */
-# define CONSOLE_COLOR_BLACK 0x00000000
-# define CONSOLE_COLOR_RED 0x00ff0000
-# define CONSOLE_COLOR_GREEN 0x0000ff00
-# define CONSOLE_COLOR_YELLOW 0x00ffff00
-# define CONSOLE_COLOR_BLUE 0x000000ff
-# define CONSOLE_COLOR_MAGENTA 0x00ff00ff
-# define CONSOLE_COLOR_CYAN 0x0000ffff
-# define CONSOLE_COLOR_GREY 0x00cccccc
-# define CONSOLE_COLOR_WHITE 0x00ffffff /* Must remain last / highest */
+ #else
+ #error Invalid LCD_BPP setting
#endif /* color definitions */
/************************************************************************/
#include <config.h>
--/*
-- * All boards using a given driver must convert to self-init
-- * at the same time, so do it here. When all drivers are
-- * converted, this will go away.
-- */
- #ifdef CONFIG_SPL_BUILD
- #if defined(CONFIG_NAND_FSL_ELBC) || defined(CONFIG_NAND_FSL_IFC)
- #define CONFIG_SYS_NAND_SELF_INIT
- #endif
- #else
--#if defined(CONFIG_NAND_FSL_ELBC) || defined(CONFIG_NAND_ATMEL)\
- || defined(CONFIG_NAND_FSL_IFC)
- || defined(CONFIG_NAND_FSL_IFC) || defined(CONFIG_NAND_MXC)
--#define CONFIG_SYS_NAND_SELF_INIT
- #endif
--#endif
--
extern void nand_init(void);
#include <linux/compat.h>
#define ENV_OFFSET_SIZE 8
int get_nand_env_oob(nand_info_t *nand, unsigned long *result);
#endif
+int spl_nand_erase_one(int block, int page);
*
* Copyright 1994 - 2000 Neil Russell.
* (See License)
- *
+ * SPDX-License-Identifier: GPL-2.0
*
* History
* 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added
int (*recv) (struct eth_device *);
void (*halt) (struct eth_device *);
#ifdef CONFIG_MCAST_TFTP
- int (*mcast) (struct eth_device *, u32 ip, u8 set);
+ int (*mcast) (struct eth_device *, const u8 *enetaddr, u8 set);
#endif
int (*write_hwaddr) (struct eth_device *);
struct eth_device *next;
extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr);
-#ifdef CONFIG_RANDOM_MACADDR
-/*
- * The u-boot policy does not allow hardcoded ethernet addresses. Under the
- * following circumstances a random generated address is allowed:
- * - in emergency cases, where you need a working network connection to set
- * the ethernet address.
- * Eg. you want a rescue boot and don't have a serial port to access the
- * CLI to set environment variables.
- *
- * In these cases, we generate a random locally administered ethernet address.
- *
- * Args:
- * enetaddr - returns 6 byte hardware address
- */
-extern void eth_random_enetaddr(uchar *enetaddr);
-#endif
-
extern int usb_eth_initialize(bd_t *bi);
extern int eth_init(bd_t *bis); /* Initialize the device */
extern int eth_send(void *packet, int length); /* Send a packet */
} echo;
ulong gateway;
struct {
- ushort __unused;
+ ushort unused;
ushort mtu;
} frag;
uchar data[0];
enum proto_t {
BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP,
- TFTPSRV, TFTPPUT, LINKLOCAL
+ TFTPSRV, TFTPPUT, LINKLOCAL, BOOTME
};
/* from net/net.c */
net_loop_last_protocol = protocol;
#endif
}
+ #ifdef CONFIG_CMD_BOOTCE
+ void BootmeStart(void);
+ #endif
/*
* Check if autoload is enabled. If so, use either NFS or TFTP to download
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
}
+/**
+ * eth_random_addr - Generate software assigned random Ethernet address
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Generate a random Ethernet address (MAC) that is not multicast
+ * and has the local assigned bit set.
+ */
+static inline void eth_random_addr(uchar *addr)
+{
+ int i;
+ unsigned int seed = get_timer(0);
+
+ for (i = 0; i < 6; i++)
+ addr[i] = rand_r(&seed);
+
+ addr[0] &= 0xfe; /* clear multicast bit */
+ addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
+}
+
/* Convert an IP address to a string */
extern void ip_to_string(IPaddr_t x, char *s);
int at91emac_register(bd_t *bis, unsigned long iobase);
int au1x00_enet_initialize(bd_t*);
int ax88180_initialize(bd_t *bis);
+int bcm_sf2_eth_register(bd_t *bis, u8 dev_num);
int bfin_EMAC_initialize(bd_t *bis);
int calxedaxgmac_initialize(u32 id, ulong base_addr);
int cs8900_initialize(u8 dev_num, int base_addr);
int davinci_emac_initialize(void);
int dc21x4x_initialize(bd_t *bis);
-int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface);
+int designware_initialize(ulong base_addr, u32 interface);
int dm9000_initialize(bd_t *bis);
int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr);
int e1000_initialize(bd_t *bis);
int ftmac110_initialize(bd_t *bits);
int greth_initialize(bd_t *bis);
void gt6426x_eth_initialize(bd_t *bis);
-int inca_switch_initialize(bd_t *bis);
int ks8695_eth_initialize(void);
int ks8851_mll_initialize(u8 dev_num, int base_addr);
int lan91c96_initialize(u8 dev_num, int base_addr);
int mpc5xxx_fec_initialize(bd_t *bis);
int mpc82xx_scc_enet_initialize(bd_t *bis);
int mvgbe_initialize(bd_t *bis);
+int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr);
int natsemi_initialize(bd_t *bis);
int ne2k_register(void);
int npe_initialize(bd_t *bis);
int ns8382x_initialize(bd_t *bis);
int pcnet_initialize(bd_t *bis);
-int plb2800_eth_initialize(bd_t *bis);
int ppc_4xx_eth_initialize (bd_t *bis);
int rtl8139_initialize(bd_t *bis);
int rtl8169_initialize(bd_t *bis);
int skge_initialize(bd_t *bis);
int smc91111_initialize(u8 dev_num, int base_addr);
int smc911x_initialize(u8 dev_num, int base_addr);
-int sunxi_wemac_initialize(bd_t *bis);
+int sunxi_emac_initialize(bd_t *bis);
+int sunxi_gmac_initialize(bd_t *bis);
int tsi108_eth_initialize(bd_t *bis);
int uec_standard_init(bd_t *bis);
int uli526x_initialize(bd_t *bis);
int armada100_fec_register(unsigned long base_addr);
int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
unsigned long dma_addr);
+int xilinx_emaclite_of_init(const void *blob);
int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
int txpp, int rxpp);
int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
unsigned long ctrl_addr);
+int zynq_gem_of_init(const void *blob);
int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio);
/*
* As long as the Xilinx xps_ll_temac ethernet driver has not its own interface
int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int));
#endif
+ #ifdef CONFIG_DRIVER_TI_CPSW
+ enum {
+ CPSW_CTRL_VERSION_1 = 0, /* version1 devices */
+ CPSW_CTRL_VERSION_2 /* version2 devices */
+ };
+
+ struct cpsw_slave_data {
+ u32 slave_reg_ofs;
+ u32 sliver_reg_ofs;
+ int phy_id;
+ int phy_if;
+ };
+
+ struct cpsw_platform_data {
+ u32 mdio_base;
+ u32 cpsw_base;
+ int mdio_div;
+ int channels; /* number of cpdma channels (symmetric) */
+ u32 cpdma_reg_ofs; /* cpdma register offset */
+ int slaves; /* number of slave cpgmac ports */
+ u32 ale_reg_ofs; /* address lookup engine reg offset */
+ int ale_entries; /* ale table size */
+ u32 host_port_reg_ofs; /* cpdma host port registers */
+ u32 hw_stats_reg_ofs; /* cpsw hw stats counters */
+ u32 mac_control;
+ struct cpsw_slave_data *slave_data;
+ void (*control)(int enabled);
+ void (*phy_init)(char *name, int addr);
+ u32 gigabit_en; /* gigabit capable AND enabled */
+ u32 host_port_num;
+ u8 version;
+ };
+
+ int cpsw_register(struct cpsw_platform_data *data);
+ #endif /* CONFIG_DRIVER_TI_CPSW */
+
#endif /* _NETDEV_H_ */
#include <linux/compiler.h>
#include <asm/spl.h>
+
/* Boot type */
#define MMCSD_MODE_UNDEFINED 0
#define MMCSD_MODE_RAW 1
-#define MMCSD_MODE_FAT 2
+#define MMCSD_MODE_FS 2
+#define MMCSD_MODE_EMMCBOOT 3
struct spl_image_info {
const char *name;
void preloader_console_init(void);
u32 spl_boot_device(void);
u32 spl_boot_mode(void);
+void spl_set_header_raw_uboot(void);
void spl_parse_image_header(const struct image_header *header);
void spl_board_prepare_for_linux(void);
void __noreturn jump_to_image_linux(void *arg);
void spl_display_print(void);
/* NAND SPL functions */
- void spl_nand_load_image(void);
+ int spl_nand_load_image(void);
/* OneNAND SPL functions */
void spl_onenand_load_image(void);
/* Ethernet SPL functions */
void spl_net_load_image(const char *device);
+/* USB SPL functions */
+void spl_usb_load_image(void);
+
+/* SATA SPL functions */
+void spl_sata_load_image(void);
+
+/* SPL FAT image functions */
+int spl_load_image_fat(block_dev_desc_t *block_dev, int partition, const char *filename);
+int spl_load_image_fat_os(block_dev_desc_t *block_dev, int partition);
+
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image);
+
+/* SPL EXT image functions */
+int spl_load_image_ext(block_dev_desc_t *block_dev, int partition, const char *filename);
+int spl_load_image_ext_os(block_dev_desc_t *block_dev, int partition);
+
#ifdef CONFIG_SPL_BOARD_INIT
void spl_board_init(void);
#endif
# SPDX-License-Identifier: GPL-2.0+
#
-include $(TOPDIR)/config.mk
-
-# CFLAGS += -DDEBUG
-
-LIB = $(obj)libnet.o
-
-COBJS-$(CONFIG_CMD_BOOTCE) += bootme.o
-COBJS-$(CONFIG_CMD_NET) += arp.o
-COBJS-$(CONFIG_CMD_NET) += bootp.o
-COBJS-$(CONFIG_CMD_CDP) += cdp.o
-COBJS-$(CONFIG_CMD_DNS) += dns.o
-COBJS-$(CONFIG_CMD_NET) += eth.o
-COBJS-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
-COBJS-$(CONFIG_CMD_NET) += net.o
-COBJS-$(CONFIG_CMD_NFS) += nfs.o
-COBJS-$(CONFIG_CMD_PING) += ping.o
-COBJS-$(CONFIG_CMD_RARP) += rarp.o
-COBJS-$(CONFIG_CMD_SNTP) += sntp.o
-COBJS-$(CONFIG_CMD_NET) += tftp.o
-
-COBJS := $(sort $(COBJS-y))
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(call cmd_link_o_target, $(OBJS))
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+#ccflags-y += -DDEBUG
+
+obj-$(CONFIG_CMD_NET) += arp.o
++obj-$(CONFIG_CMD_BOOTCE) += bootme.o
+obj-$(CONFIG_CMD_NET) += bootp.o
+obj-$(CONFIG_CMD_CDP) += cdp.o
+obj-$(CONFIG_CMD_DNS) += dns.o
+obj-$(CONFIG_CMD_NET) += eth.o
+obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
+obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NFS) += nfs.o
+obj-$(CONFIG_CMD_PING) += ping.o
+obj-$(CONFIG_CMD_RARP) += rarp.o
+obj-$(CONFIG_CMD_SNTP) += sntp.o
+obj-$(CONFIG_CMD_NET) += tftp.o
#ifdef CONFIG_STATUS_LED
#include <status_led.h>
#endif
- #ifdef CONFIG_BOOTP_RANDOM_DELAY
+ #if defined(CONFIG_BOOTP_RANDOM_DELAY) || defined(CONFIG_BOOTP_RANDOM_ID)
#include "net_rand.h"
#endif
#define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
-#define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */
+/*
+ * The timeout for the initial BOOTP/DHCP request used to be described by a
+ * counter of fixed-length timeout periods. TIMEOUT_COUNT represents
+ * that counter
+ *
+ * Now that the timeout periods are variable (exponential backoff and retry)
+ * we convert the timeout count to the absolute time it would have take to
+ * execute that many retries, and keep sending retry packets until that time
+ * is reached.
+ */
#ifndef CONFIG_NET_RETRY_COUNT
# define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
#else
# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
#endif
+#define TIMEOUT_MS ((3 + (TIMEOUT_COUNT * 5)) * 1000)
#define PORT_BOOTPS 67 /* BOOTP server UDP port */
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
#define CONFIG_DHCP_MIN_EXT_LEN 64
#endif
-static ulong BootpID;
+#ifndef CONFIG_BOOTP_ID_CACHE_SIZE
+#define CONFIG_BOOTP_ID_CACHE_SIZE 4
+#endif
+
+ulong bootp_ids[CONFIG_BOOTP_ID_CACHE_SIZE];
+unsigned int bootp_num_ids;
int BootpTry;
+ulong bootp_start;
+ulong bootp_timeout;
#if defined(CONFIG_CMD_DHCP)
static dhcp_state_t dhcp_state = INIT;
#endif
#endif
+static void bootp_add_id(ulong id)
+{
+ if (bootp_num_ids >= ARRAY_SIZE(bootp_ids)) {
+ size_t size = sizeof(bootp_ids) - sizeof(id);
+
+ memmove(bootp_ids, &bootp_ids[1], size);
+ bootp_ids[bootp_num_ids - 1] = id;
+ } else {
+ bootp_ids[bootp_num_ids] = id;
+ bootp_num_ids++;
+ }
+}
+
+static bool bootp_match_id(ulong id)
+{
+ unsigned int i;
+
+ for (i = 0; i < bootp_num_ids; i++)
+ if (bootp_ids[i] == id)
+ return true;
+
+ return false;
+}
+
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
{
struct Bootp_t *bp = (struct Bootp_t *) pkt;
retval = -4;
else if (bp->bp_hlen != HWL_ETHER)
retval = -5;
- else if (NetReadLong((ulong *)&bp->bp_id) != BootpID)
+ else if (!bootp_match_id(NetReadLong((ulong *)&bp->bp_id)))
retval = -6;
debug("Filtering pkt = %d\n", retval);
if (tmp_ip != 0)
NetCopyIP(&NetServerIP, &bp->bp_siaddr);
memcpy(NetServerEther, ((struct ethernet_hdr *)NetRxPacket)->et_src, 6);
-#endif
- NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
if (strlen(bp->bp_file) > 0)
copy_filename(BootFile, bp->bp_file, sizeof(BootFile));
*/
if (*BootFile)
setenv("bootfile", BootFile);
+#endif
+ NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
}
static int truncate_sz(const char *name, int maxlen, int curlen)
static void
BootpTimeout(void)
{
- if (BootpTry >= TIMEOUT_COUNT) {
+ ulong time_taken = get_timer(bootp_start);
+
+ if (time_taken >= TIMEOUT_MS) {
#ifdef CONFIG_BOOTP_MAY_FAIL
- puts("\nRetry count exceeded\n");
+ puts("\nRetry time exceeded\n");
net_set_state(NETLOOP_FAIL);
#else
- puts("\nRetry count exceeded; starting again\n");
+ puts("\nRetry time exceeded; starting again\n");
NetStartAgain();
#endif
} else {
- NetSetTimeout(TIMEOUT, BootpTimeout);
+ bootp_timeout *= 2;
+ if (bootp_timeout > 2000)
+ bootp_timeout = 2000;
+ NetSetTimeout(bootp_timeout, BootpTimeout);
BootpRequest();
}
}
*e++ = 17;
*e++ = 0; /* type 0 - UUID */
- uuid_str_to_bin(uuid, e);
+ uuid_str_to_bin(uuid, e, UUID_STR_FORMAT_STD);
e += 16;
} else {
printf("Invalid pxeuuid: %s\n", uuid);
}
#endif
+void BootpReset(void)
+{
+ bootp_num_ids = 0;
+ BootpTry = 0;
+ bootp_start = get_timer(0);
+ bootp_timeout = 250;
+}
+
void
BootpRequest(void)
{
int extlen, pktlen, iplen;
int eth_hdr_size;
#ifdef CONFIG_BOOTP_RANDOM_DELAY
- ulong i, rand_ms;
+ ulong rand_ms;
#endif
+ ulong BootpID;
bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start");
#if defined(CONFIG_CMD_DHCP)
rand_ms = rand() >> 19;
printf("Random delay: %ld ms...\n", rand_ms);
- for (i = 0; i < rand_ms; i++)
- udelay(1000); /*Wait 1ms*/
+ mdelay(rand_ms);
#endif /* CONFIG_BOOTP_RANDOM_DELAY */
* Bootp ID is the lower 4 bytes of our ethernet address
* plus the current time in ms.
*/
+ #ifdef CONFIG_BOOTP_RANDOM_ID
+ BootpID = rand();
+ #else
BootpID = ((ulong)NetOurEther[2] << 24)
| ((ulong)NetOurEther[3] << 16)
| ((ulong)NetOurEther[4] << 8)
| (ulong)NetOurEther[5];
BootpID += get_timer(0);
- BootpID = htonl(BootpID);
+ BootpID = htonl(BootpID);
+ bootp_add_id(BootpID);
+ #endif
NetCopyLong(&bp->bp_id, &BootpID);
/*
iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
- NetSetTimeout(SELECT_TIMEOUT, BootpTimeout);
+ NetSetTimeout(bootp_timeout, BootpTimeout);
#if defined(CONFIG_CMD_DHCP)
dhcp_state = SELECTING;
htonl(BOOTP_VENDOR_MAGIC))
DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
- NetSetTimeout(TIMEOUT, BootpTimeout);
+ NetSetTimeout(5000, BootpTimeout);
DhcpSendRequestPkt(bp);
#ifdef CONFIG_SYS_BOOTFILE_PREFIX
}
/* Store net params from reply */
BootpCopyNetParams(bp);
dhcp_state = BOUND;
- printf("DHCP client bound to address %pI4\n",
- &NetOurIP);
+ printf("DHCP client bound to address %pI4 (%lu ms)\n",
+ &NetOurIP, get_timer(bootp_start));
bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP,
"bootp_stop");
*/
/* bootp.c */
- extern ulong BootpID; /* ID of cur BOOTP request */
extern char BootFile[128]; /* Boot file name */
extern int BootpTry;
/* Send a BOOTP request */
+extern void BootpReset(void);
extern void BootpRequest(void);
/****************** DHCP Support *********************/
#define DHCP_NAK 6
#define DHCP_RELEASE 7
-#define SELECT_TIMEOUT 3000UL /* Milliseconds to wait for offers */
-
/**********************************************************************/
#endif /* __BOOTP_H__ */
* Copyright 2000 Roland Borde
* Copyright 2000 Paolo Scaffardi
* Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ * SPDX-License-Identifier: GPL-2.0
*/
/*
static int NetTryCount;
+int __maybe_unused net_busy_flag;
+
/**********************************************************************/
static int on_bootfile(const char *name, const char *value, enum env_op op,
eth_init_state_only(bd);
restart:
+#ifdef CONFIG_USB_KEYBOARD
+ net_busy_flag = 0;
+#endif
net_set_state(NETLOOP_CONTINUE);
/*
#endif
#if defined(CONFIG_CMD_DHCP)
case DHCP:
- BootpTry = 0;
+ BootpReset();
NetOurIP = 0;
DhcpRequest(); /* Basically same as BOOTP */
break;
#endif
case BOOTP:
- BootpTry = 0;
+ BootpReset();
NetOurIP = 0;
BootpRequest();
break;
CDPStart();
break;
#endif
-#ifdef CONFIG_NETCONSOLE
+#if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD)
case NETCONS:
NcStart();
break;
case LINKLOCAL:
link_local_start();
break;
+ #endif
+ #if defined(CONFIG_CMD_BOOTCE)
+ case BOOTME:
+ BootmeStart();
+ break;
#endif
default:
break;
status_led_set(STATUS_LED_RED, STATUS_LED_ON);
#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
#endif /* CONFIG_MII, ... */
+#ifdef CONFIG_USB_KEYBOARD
+ net_busy_flag = 1;
+#endif
/*
* Main packet reception loop. Loop receiving packets until
* Check for a timeout, and run the timeout handler
* if we have one.
*/
- if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
+ if (timeHandler && ((get_timer(timeStart)) > timeDelta)) {
thand_f *x;
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
setenv_hex("filesize", NetBootFileXferSize);
setenv_hex("fileaddr", load_addr);
}
- if (protocol != NETCONS)
+ if (protocol != NETCONS) {
eth_halt();
- else
+ } else {
eth_halt_state_only();
+ }
eth_set_last_protocol(protocol);
}
done:
+#ifdef CONFIG_USB_KEYBOARD
+ net_busy_flag = 0;
+#endif
#ifdef CONFIG_CMD_TFTPPUT
/* Clear out the handlers */
net_set_udp_handler(NULL);
#endif
-#ifdef CONFIG_NETCONSOLE
+#if defined (CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD)
nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE,
src_ip,
ntohs(ip->udp_dst),
static int net_check_prereq(enum proto_t protocol)
{
switch (protocol) {
- /* Fall through */
#if defined(CONFIG_CMD_PING)
case PING:
if (NetPingIP == 0) {
#endif
/* Fall through */
+ case BOOTME:
case NETCONS:
case TFTPSRV:
if (NetOurIP == 0) {
# SPDX-License-Identifier: GPL-2.0+
#
-TOOLSUBDIRS = kernel-doc
-
-#
-# Include this after HOSTOS HOSTARCH check
-# so that we can act intelligently.
-#
-include $(TOPDIR)/config.mk
-
-#
-# toolchains targeting win32 generate .exe files
-#
-ifneq (,$(findstring WIN32 ,$(shell $(HOSTCC) -E -dM -xc /dev/null)))
-SFX = .exe
-else
-SFX =
-endif
-
# Enable all the config-independent tools
ifneq ($(HOST_TOOLS_ALL),)
CONFIG_LCD_LOGO = y
CONFIG_SHA1_CHECK_UB_IMG = y
endif
+subdir-$(HOST_TOOLS_ALL) += easylogo
+subdir-$(HOST_TOOLS_ALL) += gdb
+
# Merge all the different vars for envcrc into one
ENVCRC-$(CONFIG_ENV_IS_EMBEDDED) = y
ENVCRC-$(CONFIG_ENV_IS_IN_DATAFLASH) = y
ENVCRC-$(CONFIG_ENV_IS_IN_SPI_FLASH) = y
CONFIG_BUILD_ENVCRC ?= $(ENVCRC-y)
-# Generated executable files
-BIN_FILES-$(CONFIG_LCD_LOGO) += bmp_logo$(SFX)
-BIN_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo$(SFX)
-BIN_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc$(SFX)
-BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX)
-BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
-BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
-BIN_FILES-y += mkenvimage$(SFX)
-BIN_FILES-y += mkimage$(SFX)
-BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX)
-BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX)
-BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
-BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
-BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
-BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
-BIN_FILES-y += proftool(SFX)
-
-# Source files which exist outside the tools directory
-EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
-EXT_OBJ_FILES-y += common/image.o
-EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o
-EXT_OBJ_FILES-y += common/image-sig.o
-EXT_OBJ_FILES-y += lib/crc32.o
-EXT_OBJ_FILES-y += lib/md5.o
-EXT_OBJ_FILES-y += lib/sha1.o
-
-# Source files located in the tools directory
-OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o
-OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o
-NOPED_OBJ_FILES-y += default_image.o
-NOPED_OBJ_FILES-y += proftool.o
-OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o
-NOPED_OBJ_FILES-y += fit_image.o
-OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o
-OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o
-OBJ_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes.o
-NOPED_OBJ_FILES-y += aisimage.o
-NOPED_OBJ_FILES-y += kwbimage.o
-NOPED_OBJ_FILES-y += pblimage.o
-NOPED_OBJ_FILES-y += imximage.o
-NOPED_OBJ_FILES-y += image-host.o
-NOPED_OBJ_FILES-y += omapimage.o
-NOPED_OBJ_FILES-y += mkenvimage.o
-NOPED_OBJ_FILES-y += mkimage.o
-OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
-OBJ_FILES-$(CONFIG_MX23) += mxsboot.o
-OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
-OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
-NOPED_OBJ_FILES-y += os_support.o
-OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
-NOPED_OBJ_FILES-y += ublimage.o
-OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o
+hostprogs-$(CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER) += atmel_pmecc_params
-# Don't build by default
-#ifeq ($(ARCH),ppc)
-#BIN_FILES-y += mpc86x_clk$(SFX)
-#OBJ_FILES-y += mpc86x_clk.o
-#endif
+# TODO: CONFIG_CMD_LICENSE does not work
+hostprogs-$(CONFIG_CMD_LICENSE) += bin2header
+hostprogs-$(CONFIG_LCD_LOGO) += bmp_logo
+hostprogs-$(CONFIG_VIDEO_LOGO) += bmp_logo
+HOSTCFLAGS_bmp_logo.o := -pedantic
+
+hostprogs-$(CONFIG_BUILD_ENVCRC) += envcrc
+envcrc-objs := envcrc.o lib/crc32.o common/env_embedded.o lib/sha1.o
+
+hostprogs-$(CONFIG_CMD_NET) += gen_eth_addr
+HOSTCFLAGS_gen_eth_addr.o := -pedantic
+
+hostprogs-$(CONFIG_CMD_LOADS) += img2srec
+HOSTCFLAGS_img2srec.o := -pedantic
- hostprogs-y += dumpimage mkimage
+hostprogs-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes
+HOSTCFLAGS_xway-swap-bytes.o := -pedantic
+
+hostprogs-y += mkenvimage
+mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o
+
++#hostprogs-y += dumpimage mkimage
+hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
+
+FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
# Flattened device tree objects
-LIBFDT_OBJ_FILES-y += fdt.o
-LIBFDT_OBJ_FILES-y += fdt_ro.o
-LIBFDT_OBJ_FILES-y += fdt_rw.o
-LIBFDT_OBJ_FILES-y += fdt_strerror.o
-LIBFDT_OBJ_FILES-y += fdt_wip.o
+LIBFDT_OBJS := $(addprefix lib/libfdt/, \
+ fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o)
+RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
+ rsa-sign.o rsa-verify.o rsa-checksum.o)
+
+# common objs for dumpimage and mkimage
+dumpimage-mkimage-objs := aisimage.o \
+ atmelimage.o \
+ $(FIT_SIG_OBJS-y) \
+ common/bootm.o \
+ lib/crc32.o \
+ default_image.o \
+ lib/fdtdec_common.o \
+ lib/fdtdec.o \
+ fit_common.o \
+ fit_image.o \
+ gpimage.o \
+ gpimage-common.o \
+ common/image-fit.o \
+ image-host.o \
+ common/image.o \
+ imagetool.o \
+ imximage.o \
+ kwbimage.o \
+ lib/md5.o \
+ mxsimage.o \
+ omapimage.o \
+ os_support.o \
+ pblimage.o \
+ pbl_crc32.o \
+ socfpgaimage.o \
+ lib/sha1.o \
+ lib/sha256.o \
+ ublimage.o \
+ $(LIBFDT_OBJS) \
+ $(RSA_OBJS-y)
+
+dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
+mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
+fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
+fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
+
+# TODO(sjg@chromium.org): Is this correct on Mac OS?
+
+ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
+# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
+# the mxsimage support within tools/mxsimage.c .
+HOSTCFLAGS_mxsimage.o += -DCONFIG_MXS
+endif
+
+ifdef CONFIG_FIT_SIGNATURE
+# This affects include/image.h, but including the board config file
+# is tricky, so manually define this options here.
+HOST_EXTRACFLAGS += -DCONFIG_FIT_SIGNATURE
+endif
+
+# MXSImage needs LibSSL
+ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_FIT_SIGNATURE),)
+HOSTLOADLIBES_mkimage += -lssl -lcrypto
+endif
+
+HOSTLOADLIBES_dumpimage := $(HOSTLOADLIBES_mkimage)
+HOSTLOADLIBES_fit_info := $(HOSTLOADLIBES_mkimage)
+HOSTLOADLIBES_fit_check_sign := $(HOSTLOADLIBES_mkimage)
+
+hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl
+hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
+HOSTCFLAGS_mkexynosspl.o := -pedantic
-# RSA objects
-RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o
+ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o
+hostprogs-$(CONFIG_X86) += ifdtool
+
+hostprogs-$(CONFIG_MX23) += mxsboot
+hostprogs-$(CONFIG_MX28) += mxsboot
+HOSTCFLAGS_mxsboot.o := -pedantic
+
+hostprogs-$(CONFIG_SUNXI) += mksunxiboot
+
+hostprogs-$(CONFIG_NETCONSOLE) += ncb
+hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1
+
+ubsha1-objs := os_support.o ubsha1.o lib/sha1.o
+
+HOSTCFLAGS_ubsha1.o := -pedantic
+
+hostprogs-$(CONFIG_KIRKWOOD) += kwboot
+hostprogs-$(CONFIG_ARMADA_XP) += kwboot
+hostprogs-y += proftool
+hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela
+
+# We build some files with extra pedantic flags to try to minimize things
+# that won't build on some weird host compiler -- though there are lots of
+# exceptions for files that aren't complaint.
+HOSTCFLAGS_crc32.o := -pedantic
+HOSTCFLAGS_md5.o := -pedantic
+HOSTCFLAGS_sha1.o := -pedantic
+HOSTCFLAGS_sha256.o := -pedantic
+
+# Don't build by default
+#hostprogs-$(CONFIG_PPC) += mpc86x_clk
+#HOSTCFLAGS_mpc86x_clk.o := -pedantic
+
+quiet_cmd_wrap = WRAP $@
+cmd_wrap = echo "\#include <../$(patsubst $(obj)/%,%,$@)>" >$@
+
+$(obj)/lib/%.c $(obj)/common/%.c:
+ $(call cmd,wrap)
+
+clean-dirs := lib common
+
+always := $(hostprogs-y)
# Generated LCD/video logo
-LOGO_H = $(OBJTREE)/include/bmp_logo.h
-LOGO_DATA_H = $(OBJTREE)/include/bmp_logo_data.h
+LOGO_H = $(objtree)/include/bmp_logo.h
+LOGO_DATA_H = $(objtree)/include/bmp_logo_data.h
LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_H)
LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_DATA_H)
LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_H)
# Generic logo
ifeq ($(LOGO_BMP),)
-LOGO_BMP= logos/denx.bmp
+LOGO_BMP= $(srctree)/$(src)/logos/denx.bmp
# Use board logo and fallback to vendor
-ifneq ($(wildcard logos/$(BOARD).bmp),)
-LOGO_BMP= logos/$(BOARD).bmp
+ifneq ($(wildcard $(srctree)/$(src)/logos/$(BOARD).bmp),)
+LOGO_BMP= $(srctree)/$(src)/logos/$(BOARD).bmp
else
-ifneq ($(wildcard logos/$(VENDOR).bmp),)
-LOGO_BMP= logos/$(VENDOR).bmp
+ifneq ($(wildcard $(srctree)/$(src)/logos/$(VENDOR).bmp),)
+LOGO_BMP= $(srctree)/$(src)/logos/$(VENDOR).bmp
endif
endif
endif # !LOGO_BMP
-# now $(obj) is defined
-HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c))
-HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c))
-HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c))
-HOSTSRCS += $(addprefix $(SRCTREE)/lib/rsa/,$(RSA_OBJ_FILES-y:.o=.c))
-BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y)))
-LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y))
-RSA_OBJS := $(addprefix $(obj),$(RSA_OBJ_FILES-y))
-
-# We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host
-FIT_SIG_OBJ_FILES := image-sig.o
-FIT_SIG_OBJS := $(addprefix $(obj),$(FIT_SIG_OBJ_FILES))
-
-HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y))
-NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y))
-
#
# Use native tools and options
# Define __KERNEL_STRICT_NAMES to prevent typedef overlaps
+# Define _GNU_SOURCE to obtain the getline prototype from stdio.h
#
-HOSTCPPFLAGS = -include $(SRCTREE)/include/libfdt_env.h \
- -idirafter $(SRCTREE)/include \
- -idirafter $(OBJTREE)/include2 \
- -idirafter $(OBJTREE)/include \
- -I $(SRCTREE)/lib/libfdt \
- -I $(SRCTREE)/tools \
+HOST_EXTRACFLAGS += -include $(srctree)/include/libfdt_env.h \
+ $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \
+ -I$(srctree)/lib/libfdt \
+ -I$(srctree)/tools \
++ -include $(srctree)/include/linux/kconfig.h \
++ -Wno-variadic-macros \
-DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \
-DUSE_HOSTCC \
- -D__KERNEL_STRICT_NAMES
-
-
-all: $(obj).depend $(BINS) $(LOGO-y) subdirs
-
-$(obj)bin2header$(SFX): $(obj)bin2header.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)bmp_logo$(SFX): $(obj)bmp_logo.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)proftool(SFX): $(obj)proftool.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)envcrc$(SFX): $(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
-
-$(obj)gen_eth_addr$(SFX): $(obj)gen_eth_addr.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)img2srec$(SFX): $(obj)img2srec.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)xway-swap-bytes$(SFX): $(obj)xway-swap-bytes.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)mkenvimage$(SFX): $(obj)crc32.o $(obj)mkenvimage.o \
- $(obj)os_support.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)mkimage$(SFX): $(obj)aisimage.o \
- $(obj)crc32.o \
- $(obj)default_image.o \
- $(obj)fit_image.o \
- $(obj)image-fit.o \
- $(obj)image.o \
- $(obj)image-host.o \
- $(FIT_SIG_OBJS) \
- $(obj)imximage.o \
- $(obj)kwbimage.o \
- $(obj)pblimage.o \
- $(obj)md5.o \
- $(obj)mkimage.o \
- $(obj)os_support.o \
- $(obj)omapimage.o \
- $(obj)sha1.o \
- $(obj)ublimage.o \
- $(LIBFDT_OBJS) \
- $(RSA_OBJS)
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS)
- $(HOSTSTRIP) $@
-
-$(obj)mk$(BOARD)spl$(SFX): $(obj)mkexynosspl.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)mxsboot$(SFX): $(obj)mxsboot.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
-$(obj)ncb$(SFX): $(obj)ncb.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
+ -D__KERNEL_STRICT_NAMES \
+ -D_GNU_SOURCE
-$(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+__build: $(LOGO-y)
-$(obj)kwboot$(SFX): $(obj)kwboot.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
+$(LOGO_H): $(obj)/bmp_logo $(LOGO_BMP)
+ $(obj)/bmp_logo --gen-info $(LOGO_BMP) > $@
-# Some of the tool objects need to be accessed from outside the tools directory
-$(obj)%.o: $(SRCTREE)/common/%.c
- $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+$(LOGO_DATA_H): $(obj)/bmp_logo $(LOGO_BMP)
+ $(obj)/bmp_logo --gen-data $(LOGO_BMP) > $@
-$(obj)%.o: $(SRCTREE)/lib/%.c
- $(HOSTCC) -g $(HOSTCFLAGS) -c -o $@ $<
+# Let clean descend into subdirs
+subdir- += env
-$(obj)%.o: $(SRCTREE)/lib/libfdt/%.c
- $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+ifneq ($(CROSS_BUILD_TOOLS),)
+HOSTCC = $(CC)
-$(obj)%.o: $(SRCTREE)/lib/rsa/%.c
- $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+quiet_cmd_crosstools_strip = STRIP $^
+ cmd_crosstools_strip = $(STRIP) $^; touch $@
+$(obj)/.strip: $(call objectify,$(filter $(always),$(hostprogs-y)))
+ $(call cmd,crosstools_strip)
-subdirs:
-ifeq ($(TOOLSUBDIRS),)
- @:
-else
- @for dir in $(TOOLSUBDIRS) ; do \
- $(MAKE) \
- HOSTOS=$(HOSTOS) \
- HOSTARCH=$(HOSTARCH) \
- -C $$dir || exit 1 ; \
- done
+always += .strip
endif
-
-$(LOGO_H): $(obj)bmp_logo $(LOGO_BMP)
- $(obj)./bmp_logo --gen-info $(LOGO_BMP) > $@
-
-$(LOGO_DATA_H): $(obj)bmp_logo $(LOGO_BMP)
- $(obj)./bmp_logo --gen-data $(LOGO_BMP) > $@
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+clean-files += .strip