diff options
125 files changed, 28357 insertions, 1612 deletions
diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig index a4b1783be239..8f00d362cc15 100644 --- a/arch/arm/configs/imx6_defconfig +++ b/arch/arm/configs/imx6_defconfig @@ -1,7 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/arm 2.6.38 Kernel Configuration -# Tue Jan 17 18:55:30 2012 +# Linux/arm 3.0.15 Kernel Configuration # CONFIG_ARM=y CONFIG_HAVE_PWM=y @@ -11,6 +10,7 @@ CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_USES_GETTIMEOFFSET is not set CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y CONFIG_HAVE_PROC_CPU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y @@ -29,7 +29,6 @@ CONFIG_FIQ=y CONFIG_VECTORS_BASE=0xffff0000 # CONFIG_ARM_PATCH_PHYS_VIRT is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_CONSTRUCTORS=y CONFIG_HAVE_IRQ_WORK=y CONFIG_IRQ_WORK=y @@ -37,7 +36,6 @@ CONFIG_IRQ_WORK=y # General setup # CONFIG_EXPERIMENTAL=y -CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" CONFIG_LOCALVERSION="" @@ -48,11 +46,13 @@ CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_LZMA is not set # CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set CONFIG_HAVE_GENERIC_HARDIRQS=y @@ -61,11 +61,8 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y -# CONFIG_GENERIC_PENDING_IRQ is not set -# CONFIG_AUTO_IRQ_AFFINITY is not set -# CONFIG_IRQ_PER_CPU is not set +CONFIG_GENERIC_IRQ_SHOW=y # CONFIG_SPARSE_IRQ is not set # @@ -77,6 +74,7 @@ CONFIG_PREEMPT_RCU=y CONFIG_RCU_FANOUT=32 # CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -90,11 +88,9 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSCTL=y CONFIG_ANON_INODES=y CONFIG_EXPERT=y -CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y @@ -107,6 +103,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y +CONFIG_EMBEDDED=y CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_USE_VMALLOC=y @@ -197,7 +194,6 @@ CONFIG_FREEZER=y # System Type # CONFIG_MMU=y -# CONFIG_ARCH_AAEC2000 is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set @@ -212,7 +208,6 @@ CONFIG_MMU=y # CONFIG_ARCH_FOOTBRIDGE is not set CONFIG_ARCH_MXC=y # CONFIG_ARCH_MXS is not set -# CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_IOP13XX is not set @@ -229,7 +224,6 @@ CONFIG_ARCH_MXC=y # CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_MMP is not set # CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_NS9XXX is not set # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_NUC93X is not set # CONFIG_ARCH_TEGRA is not set @@ -242,19 +236,18 @@ CONFIG_ARCH_MXC=y # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5P6442 is not set # CONFIG_ARCH_S5PC100 is not set # CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_S5PV310 is not set +# CONFIG_ARCH_EXYNOS4 is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_TCC_926 is not set -# CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_U300 is not set # CONFIG_ARCH_U8500 is not set # CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set # CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set CONFIG_GPIO_PCA953X=y # CONFIG_KEYBOARD_GPIO_POLLED is not set CONFIG_IMX_HAVE_PLATFORM_DMA=y @@ -281,6 +274,7 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_OCOTP=y CONFIG_IMX_HAVE_PLATFORM_IMX_VIIM=y CONFIG_IMX_HAVE_PLATFORM_PERFMON=y CONFIG_IMX_HAVE_PLATFORM_LDB=y +CONFIG_IMX_HAVE_PLATFORM_IMX_PXP=y CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y CONFIG_IMX_HAVE_PLATFORM_VIV_GPU=y CONFIG_IMX_HAVE_PLATFORM_MXC_HDMI=y @@ -299,11 +293,11 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2=y # CONFIG_ARCH_MX2 is not set # CONFIG_ARCH_MX25 is not set # CONFIG_ARCH_MX3 is not set -# CONFIG_ARCH_MXC91231 is not set -# CONFIG_ARCH_MX5 is not set +# CONFIG_ARCH_MX503 is not set +# CONFIG_ARCH_MX51 is not set CONFIG_ARCH_MX6=y -CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_ARCH_MX6Q=y +CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_SOC_IMX6Q=y CONFIG_MACH_MX6Q_ARM2=y CONFIG_MACH_MX6Q_SABRELITE=y @@ -313,6 +307,7 @@ CONFIG_MACH_MX6Q_SABREAUTO=y # # MX6 Options: # +# CONFIG_IMX_PCIE is not set CONFIG_ISP1504_MXC=y # CONFIG_MXC_IRQ_PRIOR is not set CONFIG_MXC_PWM=y @@ -330,8 +325,8 @@ CONFIG_DMA_ZONE_SIZE=184 # # Processor Type # -CONFIG_CPU_32v6K=y CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y CONFIG_CPU_32v7=y CONFIG_CPU_ABRT_EV7=y CONFIG_CPU_PABRT_V7=y @@ -366,11 +361,12 @@ CONFIG_CPU_HAS_PMU=y # CONFIG_ARM_ERRATA_742231 is not set # CONFIG_PL310_ERRATA_588369 is not set # CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set CONFIG_ARM_ERRATA_743622=y CONFIG_ARM_ERRATA_751472=y # CONFIG_ARM_ERRATA_753970 is not set -# CONFIG_PL310_ERRATA_727915 is not set CONFIG_ARM_ERRATA_754322=y +# CONFIG_ARM_ERRATA_754327 is not set CONFIG_ARM_GIC=y # @@ -380,6 +376,7 @@ CONFIG_ARM_GIC=y # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set CONFIG_ARM_ERRATA_764369=y +# CONFIG_PL310_ERRATA_769419 is not set # # Kernel Features @@ -407,7 +404,9 @@ CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set CONFIG_HW_PERF_EVENTS=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -416,13 +415,15 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_HAVE_MEMBLOCK=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_COMPACTION is not set +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set +CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set # CONFIG_SECCOMP is not set @@ -432,9 +433,12 @@ CONFIG_ALIGNMENT_TRAP=y # # Boot options # +# CONFIG_USE_OF is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw rootfstype=jffs2 ip=off" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set # CONFIG_CMDLINE_FORCE is not set # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set @@ -444,9 +448,12 @@ CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw rootfstyp # # CPU Power Management # + +# +# CPU Frequency scaling +# CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y -# CONFIG_CPU_FREQ_DEBUG is not set CONFIG_CPU_FREQ_STAT=y # CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set @@ -485,20 +492,19 @@ CONFIG_HAVE_AOUT=y # # Power management options # -CONFIG_PM=y -CONFIG_PM_DEBUG=y -# CONFIG_PM_ADVANCED_DEBUG is not set -# CONFIG_PM_VERBOSE is not set -CONFIG_CAN_PM_TRACE=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_PM_SLEEP=y CONFIG_SUSPEND=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_SUSPEND_DEVICE_TIME_DEBUG=y CONFIG_SUSPEND_FREEZER=y -CONFIG_APM_EMULATION=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y CONFIG_PM_RUNTIME=y -CONFIG_PM_OPS=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_APM_EMULATION=y +CONFIG_PM_RUNTIME_CLK=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y @@ -516,7 +522,6 @@ CONFIG_XFRM=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y @@ -568,6 +573,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_DCB is not set # CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_RFS_ACCEL=y CONFIG_XPS=y # @@ -590,6 +596,7 @@ CONFIG_CAN_CALC_BITTIMING=y CONFIG_HAVE_CAN_FLEXCAN=y CONFIG_CAN_FLEXCAN=y # CONFIG_CAN_SJA1000 is not set +# CONFIG_CAN_C_CAN is not set # # CAN USB interfaces @@ -632,24 +639,26 @@ CONFIG_WEXT_CORE=y CONFIG_WEXT_PROC=y CONFIG_WEXT_SPY=y CONFIG_WEXT_PRIV=y -# CONFIG_CFG80211 is not set +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_LIB80211=y CONFIG_LIB80211_CRYPT_WEP=y CONFIG_LIB80211_CRYPT_CCMP=y CONFIG_LIB80211_CRYPT_TKIP=y # CONFIG_LIB80211_DEBUG is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# - -# -# Some wireless drivers require a rate control algorithm -# +# CONFIG_MAC80211 is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set # CONFIG_NET_9P is not set # CONFIG_CAIF is not set # CONFIG_CEPH_LIB is not set @@ -674,8 +683,6 @@ CONFIG_PROC_EVENTS=y CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_TESTS is not set -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -694,6 +701,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_SSFDC is not set # CONFIG_SM_FTL is not set # CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set # # RAM/ROM/Flash chip drivers @@ -742,13 +750,14 @@ CONFIG_MTD_NAND_ECC=y # CONFIG_MTD_NAND_ECC_SMC is not set CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set # CONFIG_MTD_SM_COMMON is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_NANDSIM is not set -# CONFIG_MTD_NAND_GPMI_NFC is not set +# CONFIG_MTD_NAND_GPMI_NAND is not set # CONFIG_MTD_NAND_PLATFORM is not set # CONFIG_MTD_ALAUDA is not set # CONFIG_MTD_ONENAND is not set @@ -761,10 +770,6 @@ CONFIG_MTD_UBI=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTD_UBI_BEB_RESERVE=1 # CONFIG_MTD_UBI_GLUEBI is not set - -# -# UBI debugging options -# # CONFIG_MTD_UBI_DEBUG is not set # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y @@ -779,8 +784,10 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set CONFIG_MISC_DEVICES=y # CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_APDS9802ALS is not set @@ -811,6 +818,8 @@ CONFIG_MXS_PERFMON=m # Texas Instruments shared transport line discipline # # CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -881,6 +890,7 @@ CONFIG_ATA_BMDMA=y # # PATA SFF controllers with BMDMA # +# CONFIG_PATA_ARASAN_CF is not set # # PIO-only SFF controllers @@ -913,7 +923,6 @@ CONFIG_PHYLIB=y # CONFIG_VITESSE_PHY is not set # CONFIG_SMSC_PHY is not set # CONFIG_BROADCOM_PHY is not set -# CONFIG_BCM63XX_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set # CONFIG_NATIONAL_PHY is not set @@ -945,12 +954,21 @@ CONFIG_SMSC911X=y # CONFIG_KS8851_MLL is not set CONFIG_FEC=y # CONFIG_FEC_1588 is not set +# CONFIG_FTMAC100 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set CONFIG_WLAN=y # CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_ATH_COMMON=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH6KL=m +# CONFIG_ATH6KL_DEBUG is not set CONFIG_HOSTAP=y # CONFIG_HOSTAP_FIRMWARE is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +# CONFIG_MWIFIEX is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -1004,7 +1022,9 @@ CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set # CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_LKKBD is not set CONFIG_KEYBOARD_GPIO=y @@ -1013,6 +1033,7 @@ CONFIG_KEYBOARD_GPIO=y # CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set # CONFIG_KEYBOARD_IMX is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_OPENCORES is not set @@ -1020,7 +1041,6 @@ CONFIG_KEYBOARD_GPIO=y # CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_MXC is not set -# CONFIG_KEYBOARD_MPR121 is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set @@ -1028,6 +1048,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_AD7877 is not set # CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set # CONFIG_TOUCHSCREEN_BU21013 is not set # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set # CONFIG_TOUCHSCREEN_DYNAPRO is not set @@ -1038,23 +1059,23 @@ CONFIG_TOUCHSCREEN_EGALAX=y # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set # CONFIG_TOUCHSCREEN_MCS5000 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_MK712 is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set -# CONFIG_TOUCHSCREEN_QT602240 is not set # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set # CONFIG_TOUCHSCREEN_TOUCHWIN is not set # CONFIG_TOUCHSCREEN_WM97XX is not set # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set # CONFIG_TOUCHSCREEN_TSC2007 is not set # CONFIG_TOUCHSCREEN_W90X900 is not set # CONFIG_TOUCHSCREEN_ST1232 is not set # CONFIG_TOUCHSCREEN_P1003 is not set # CONFIG_TOUCHSCREEN_TPS6507X is not set -# CONFIG_TOUCHSCREEN_MAX11801 is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_ATI_REMOTE is not set @@ -1069,7 +1090,7 @@ CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # CONFIG_INPUT_ADXL34X is not set # CONFIG_INPUT_CMA3000 is not set -# CONFIG_INPUT_ISL29023 is not set +CONFIG_INPUT_ISL29023=y # # Hardware I/O ports @@ -1090,9 +1111,14 @@ CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_DEVKMEM=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y # # Serial drivers @@ -1112,10 +1138,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_IFX6X60 is not set -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_XILINX_PS_UART is not set # CONFIG_TTY_PRINTK is not set CONFIG_FSL_OTP=y # CONFIG_HVC_DCC is not set @@ -1146,12 +1169,14 @@ CONFIG_I2C_HELPER_AUTO=y CONFIG_I2C_IMX=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers # +# CONFIG_I2C_DIOLAN_U2C is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_TAOS_EVM is not set # CONFIG_I2C_TINY_USB is not set @@ -1169,10 +1194,12 @@ CONFIG_SPI_MASTER=y # # SPI Master Controller Drivers # +# CONFIG_SPI_ALTERA is not set CONFIG_SPI_BITBANG=y # CONFIG_SPI_GPIO is not set CONFIG_SPI_IMX_VER_2_3=y CONFIG_SPI_IMX=y +# CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_DESIGNWARE is not set @@ -1191,12 +1218,20 @@ CONFIG_SPI_IMX=y # # PPS generators support # + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_GPIO_SYSFS is not set # -# Memory mapped GPIO expanders: +# Memory mapped GPIO drivers: # # CONFIG_GPIO_BASIC_MMIO is not set # CONFIG_GPIO_IT8761E is not set @@ -1231,9 +1266,117 @@ CONFIG_GPIOLIB=y # MODULbus GPIO expanders: # # CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_APM_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_BQ20Z75 is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +CONFIG_CHARGER_MAX8903=y +# CONFIG_CHARGER_GPIO is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX17135 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_SENSORS_MAG3110=y +# CONFIG_MXC_MMA8450 is not set +CONFIG_MXC_MMA8451=y CONFIG_THERMAL=y +# CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y CONFIG_WATCHDOG_NOWAYOUT=y @@ -1254,6 +1397,12 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set CONFIG_MFD_SUPPORT=y CONFIG_MFD_CORE=y # CONFIG_MFD_88PM860X is not set @@ -1263,8 +1412,10 @@ CONFIG_MFD_CORE=y # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_UCB1400_CORE is not set +# CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_TC3589X is not set @@ -1275,6 +1426,7 @@ CONFIG_MFD_CORE=y # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set @@ -1283,14 +1435,14 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_PMIC_DIALOG is not set -# CONFIG_MFD_MC13XXX is not set # CONFIG_MFD_MC_PMIC is not set # CONFIG_MFD_MC34708 is not set CONFIG_MFD_PFUZE=y +# CONFIG_MFD_MC13XXX is not set # CONFIG_ABX500_CORE is not set # CONFIG_EZX_PCAP is not set -# CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_MAX17135 is not set CONFIG_MFD_MXC_HDMI=y CONFIG_REGULATOR=y @@ -1312,13 +1464,14 @@ CONFIG_REGULATOR_PFUZE100=y # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_AD5398 is not set -# CONFIG_REGULATOR_TPS6524X is not set CONFIG_REGULATOR_ANATOP=y +# CONFIG_REGULATOR_TPS6524X is not set CONFIG_MEDIA_SUPPORT=y # # Multimedia core support # +# CONFIG_MEDIA_CONTROLLER is not set CONFIG_VIDEO_DEV=y CONFIG_VIDEO_V4L2_COMMON=y # CONFIG_DVB_CORE is not set @@ -1351,11 +1504,11 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set # -# Encoders/decoders and other helper chips +# Encoders, decoders, sensors and other helper chips # # -# Audio decoders +# Audio decoders, processors and mixers # # CONFIG_VIDEO_TVAUDIO is not set # CONFIG_VIDEO_TDA7432 is not set @@ -1365,7 +1518,6 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y # CONFIG_VIDEO_MSP3400 is not set # CONFIG_VIDEO_CS5345 is not set # CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_M52790 is not set # CONFIG_VIDEO_TLV320AIC23B is not set # CONFIG_VIDEO_WM8775 is not set # CONFIG_VIDEO_WM8739 is not set @@ -1384,12 +1536,8 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y # CONFIG_VIDEO_BT856 is not set # CONFIG_VIDEO_BT866 is not set # CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_TCM825X is not set # CONFIG_VIDEO_SAA7110 is not set # CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA717X is not set # CONFIG_VIDEO_SAA7191 is not set # CONFIG_VIDEO_TVP514X is not set # CONFIG_VIDEO_TVP5150 is not set @@ -1399,6 +1547,7 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y # # Video and audio decoders # +# CONFIG_VIDEO_SAA717X is not set # CONFIG_VIDEO_CX25840 is not set # @@ -1413,15 +1562,27 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y # CONFIG_VIDEO_SAA7185 is not set # CONFIG_VIDEO_ADV7170 is not set # CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_THS7303 is not set # CONFIG_VIDEO_ADV7343 is not set # CONFIG_VIDEO_AK881X is not set # +# Camera sensor devices +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set + +# # Video improvement chips # # CONFIG_VIDEO_UPD64031A is not set # CONFIG_VIDEO_UPD64083 is not set + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set # CONFIG_VIDEO_VIVI is not set CONFIG_VIDEO_MXC_CAMERA=m @@ -1448,6 +1609,7 @@ CONFIG_VIDEO_MXC_IPU_OUTPUT=y # CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_NOON010PC30 is not set # CONFIG_SOC_CAMERA is not set CONFIG_V4L_USB_DRIVERS=y CONFIG_USB_VIDEO_CLASS=m @@ -1462,9 +1624,11 @@ CONFIG_USB_GSPCA=m # CONFIG_USB_GSPCA_ETOMS is not set # CONFIG_USB_GSPCA_FINEPIX is not set # CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_KINECT is not set # CONFIG_USB_GSPCA_KONICA is not set # CONFIG_USB_GSPCA_MARS is not set # CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set # CONFIG_USB_GSPCA_OV519 is not set # CONFIG_USB_GSPCA_OV534 is not set # CONFIG_USB_GSPCA_OV534_9 is not set @@ -1491,6 +1655,7 @@ CONFIG_USB_GSPCA=m # CONFIG_USB_GSPCA_T613 is not set # CONFIG_USB_GSPCA_TV8532 is not set # CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set # CONFIG_USB_GSPCA_XIRLINK_CIT is not set # CONFIG_USB_GSPCA_ZC3XX is not set # CONFIG_VIDEO_PVRUSB2 is not set @@ -1540,7 +1705,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set # CONFIG_FB_BROADSHEET is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set @@ -1548,6 +1712,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_GENERIC is not set CONFIG_BACKLIGHT_PWM=y # CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set # # Display device support @@ -1626,6 +1791,7 @@ CONFIG_SND_USB=y CONFIG_SND_USB_AUDIO=y # CONFIG_SND_USB_UA101 is not set # CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set CONFIG_SND_SOC=y # CONFIG_SND_SOC_CACHE_LZO is not set CONFIG_SND_SOC_AC97_BUS=y @@ -1658,27 +1824,26 @@ CONFIG_USB_HID=y # # Special HID drivers # -# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=m -# CONFIG_HID_ACRUX_FF is not set +# CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=m CONFIG_HID_BELKIN=m -# CONFIG_HID_CANDO is not set CONFIG_HID_CHERRY=m CONFIG_HID_CHICONY=m # CONFIG_HID_PRODIKEYS is not set CONFIG_HID_CYPRESS=m # CONFIG_HID_DRAGONRISE is not set # CONFIG_HID_EMS_FF is not set -# CONFIG_HID_EGALAX is not set # CONFIG_HID_ELECOM is not set CONFIG_HID_EZKEY=m +# CONFIG_HID_KEYTOUCH is not set # CONFIG_HID_KYE is not set # CONFIG_HID_UCLOGIC is not set # CONFIG_HID_WALTOP is not set CONFIG_HID_GYRATION=m # CONFIG_HID_TWINHAN is not set # CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set CONFIG_HID_LOGITECH=m # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set @@ -1686,7 +1851,6 @@ CONFIG_HID_LOGITECH=m # CONFIG_LOGIWII_FF is not set # CONFIG_HID_MAGICMOUSE is not set CONFIG_HID_MICROSOFT=m -# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=m # CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set @@ -1697,12 +1861,13 @@ CONFIG_HID_PETALYNX=m # CONFIG_HID_PICOLCD is not set # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set +# CONFIG_HID_ROCCAT_ARVO is not set # CONFIG_HID_ROCCAT_KONE is not set # CONFIG_HID_ROCCAT_KONEPLUS is not set +# CONFIG_HID_ROCCAT_KOVAPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m -# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=m # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1771,6 +1936,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set @@ -1782,6 +1948,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set # CONFIG_USB_UAS is not set # CONFIG_USB_LIBUSUAL is not set @@ -1827,6 +1994,7 @@ CONFIG_USB_GADGET_SELECTED=y CONFIG_USB_GADGET_ARC=y CONFIG_USB_ARC=y # CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_FUSB300 is not set # CONFIG_USB_GADGET_R8A66597 is not set # CONFIG_USB_GADGET_PXA_U2O is not set # CONFIG_USB_GADGET_M66592 is not set @@ -1882,8 +2050,8 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_IO_ACCESSORS=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_ESDHC_IMX=y -# CONFIG_MMC_MXC is not set # CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set # CONFIG_MMC_USHC is not set # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y @@ -1892,6 +2060,7 @@ CONFIG_LEDS_CLASS=y # # LED drivers # +# CONFIG_LEDS_LM3530 is not set # CONFIG_LEDS_PCA9532 is not set # CONFIG_LEDS_GPIO is not set # CONFIG_LEDS_LP3944 is not set @@ -1949,10 +2118,13 @@ CONFIG_RTC_INTF_DEV_UIE_EMUL=y # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set # CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set # # SPI RTC drivers # +# CONFIG_RTC_DRV_M41T93 is not set # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set # CONFIG_RTC_DRV_DS1390 is not set @@ -1991,7 +2163,10 @@ CONFIG_DMADEVICES=y # # DMA Devices # +# CONFIG_DW_DMAC is not set # CONFIG_MXC_PXP is not set +CONFIG_MXC_PXP_V2=y +CONFIG_MXC_PXP_CLIENT_DEVICE=y # CONFIG_TIMB_DMA is not set CONFIG_IMX_SDMA=y # CONFIG_MXS_DMA is not set @@ -2007,6 +2182,7 @@ CONFIG_DMA_ENGINE=y # CONFIG_UIO is not set # CONFIG_STAGING is not set CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_MMIO=y # # MXC support drivers @@ -2163,6 +2339,7 @@ CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set CONFIG_MISC_FILESYSTEMS=y @@ -2199,6 +2376,7 @@ CONFIG_CRAMFS=y # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -2212,7 +2390,6 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -2285,6 +2462,7 @@ CONFIG_NLS_UTF8=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 @@ -2293,15 +2471,16 @@ CONFIG_FRAME_WARN=1024 # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set # CONFIG_DEBUG_KERNEL is not set # CONFIG_HARDLOCKUP_DETECTOR is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set -CONFIG_BKL=y # CONFIG_SPARSE_RCU_POINTER is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_VERBOSE=y # CONFIG_LKDTM is not set CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -2316,6 +2495,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_TEST_KSTRTOX is not set # CONFIG_STRICT_DEVMEM is not set CONFIG_ARM_UNWIND=y # CONFIG_DEBUG_USER is not set @@ -2439,7 +2619,6 @@ CONFIG_CRYPTO_HW=y # CONFIG_BITREVERSE=y CONFIG_RATIONAL=y -CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set @@ -2457,4 +2636,6 @@ CONFIG_GENERIC_ALLOCATOR=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index 83dfa5c33783..aa081b6ce0c1 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -57,6 +57,7 @@ config MACH_MX6Q_ARM2 select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2 select IMX_HAVE_PLATFORM_PERFMON select IMX_HAVE_PLATFORM_MXC_MLB + select IMX_HAVE_PLATFORM_IMX_PXP help Include support for i.MX 6Quad Armadillo2 platform. This includes specific configurations for the board and its peripherals. @@ -163,4 +164,8 @@ config MACH_MX6Q_SABREAUTO comment "MX6 Options:" +config IMX_PCIE + bool "PCI Express support" + select PCI + endif diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile index 6fc9646ba8d2..21f776ab598c 100644 --- a/arch/arm/mach-mx6/Makefile +++ b/arch/arm/mach-mx6/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_MACH_MX6Q_SABRESD) += board-mx6q_sabresd.o mx6q_sabresd_pmic_pfuze1 obj-$(CONFIG_MACH_MX6Q_SABREAUTO) += board-mx6q_sabreauto.o mx6q_sabreauto_pmic_pfuze100.o obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o +obj-$(CONFIG_IMX_PCIE) += pcie.o diff --git a/arch/arm/mach-mx6/board-mx6dl_arm2.h b/arch/arm/mach-mx6/board-mx6dl_arm2.h new file mode 100644 index 000000000000..9261a28fb6d1 --- /dev/null +++ b/arch/arm/mach-mx6/board-mx6dl_arm2.h @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <mach/iomux-mx6dl.h> + +static iomux_v3_cfg_t mx6dl_arm2_pads[] = { + + /* UART4 for debug */ + MX6DL_PAD_KEY_COL0__UART4_TXD, + MX6DL_PAD_KEY_ROW0__UART4_RXD, + /* USB HSIC ports use the same pin with ENET */ +#ifdef CONFIG_USB_EHCI_ARC_HSIC + /* USB H2 strobe/data pin */ + MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE, + MX6DL_PAD_RGMII_TXC__USBOH3_H2_DATA, + + /* USB H3 strobe/data pin */ + MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE, + MX6DL_PAD_RGMII_RX_CTL__USBOH3_H3_DATA, + /* ENET */ +#else + MX6DL_PAD_KEY_COL1__ENET_MDIO, + MX6DL_PAD_KEY_COL2__ENET_MDC, + MX6DL_PAD_RGMII_TXC__ENET_RGMII_TXC, + MX6DL_PAD_RGMII_TD0__ENET_RGMII_TD0, + MX6DL_PAD_RGMII_TD1__ENET_RGMII_TD1, + MX6DL_PAD_RGMII_TD2__ENET_RGMII_TD2, + MX6DL_PAD_RGMII_TD3__ENET_RGMII_TD3, + MX6DL_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, + MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK, + MX6DL_PAD_RGMII_RXC__ENET_RGMII_RXC, + MX6DL_PAD_RGMII_RD0__ENET_RGMII_RD0, + MX6DL_PAD_RGMII_RD1__ENET_RGMII_RD1, + MX6DL_PAD_RGMII_RD2__ENET_RGMII_RD2, + MX6DL_PAD_RGMII_RD3__ENET_RGMII_RD3, + MX6DL_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, +#ifdef CONFIG_FEC_1588 + MX6DL_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT, +#endif +#endif + /* MCLK for csi0 */ + MX6DL_PAD_GPIO_0__CCM_CLKO, + MX6DL_PAD_GPIO_3__CCM_CLKO2, + + /* SD1 */ + MX6DL_PAD_SD1_CLK__USDHC1_CLK, + MX6DL_PAD_SD1_CMD__USDHC1_CMD, + MX6DL_PAD_SD1_DAT0__USDHC1_DAT0, + MX6DL_PAD_SD1_DAT1__USDHC1_DAT1, + MX6DL_PAD_SD1_DAT2__USDHC1_DAT2, + MX6DL_PAD_SD1_DAT3__USDHC1_DAT3, + /* SD2 */ + MX6DL_PAD_SD2_CLK__USDHC2_CLK, + MX6DL_PAD_SD2_CMD__USDHC2_CMD, + MX6DL_PAD_SD2_DAT0__USDHC2_DAT0, + MX6DL_PAD_SD2_DAT1__USDHC2_DAT1, + MX6DL_PAD_SD2_DAT2__USDHC2_DAT2, + MX6DL_PAD_SD2_DAT3__USDHC2_DAT3, + /* SD3 */ + MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ, + MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ, + MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ, + MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ, + MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ, + MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ, + MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ, + MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ, + MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ, + MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ, + MX6DL_PAD_SD3_RST__USDHC3_RST, + /* SD3 VSelect */ + MX6DL_PAD_GPIO_18__USDHC3_VSELECT, + /* SD3_CD and SD3_WP */ + MX6DL_PAD_NANDF_CS0__GPIO_6_11, + MX6DL_PAD_NANDF_CS1__GPIO_6_14, + /* SD4 */ + MX6DL_PAD_SD4_CLK__USDHC4_CLK_50MHZ, + MX6DL_PAD_SD4_CMD__USDHC4_CMD_50MHZ, + MX6DL_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ, + MX6DL_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ, + MX6DL_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ, + MX6DL_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ, + MX6DL_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ, + MX6DL_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ, + MX6DL_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ, + MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ, + MX6DL_PAD_NANDF_ALE__USDHC4_RST, + /* eCSPI1 */ + MX6DL_PAD_EIM_EB2__ECSPI1_SS0, + MX6DL_PAD_EIM_D16__ECSPI1_SCLK, + MX6DL_PAD_EIM_D17__ECSPI1_MISO, + MX6DL_PAD_EIM_D18__ECSPI1_MOSI, + MX6DL_PAD_EIM_D19__ECSPI1_SS1, + MX6DL_PAD_EIM_EB2__GPIO_2_30, /*SS0*/ + MX6DL_PAD_EIM_D19__GPIO_3_19, /*SS1*/ + + /* ESAI */ + MX6DL_PAD_ENET_RXD0__ESAI1_HCKT, + MX6DL_PAD_ENET_CRS_DV__ESAI1_SCKT, + MX6DL_PAD_ENET_RXD1__ESAI1_FST, + MX6DL_PAD_ENET_TX_EN__ESAI1_TX3_RX2, + MX6DL_PAD_ENET_TXD1__ESAI1_TX2_RX3, + MX6DL_PAD_ENET_TXD0__ESAI1_TX4_RX1, + MX6DL_PAD_ENET_MDC__ESAI1_TX5_RX0, + MX6DL_PAD_NANDF_CS2__ESAI1_TX0, + MX6DL_PAD_NANDF_CS3__ESAI1_TX1, + + /* I2C1 */ + MX6DL_PAD_CSI0_DAT8__I2C1_SDA, + MX6DL_PAD_CSI0_DAT9__I2C1_SCL, + + /* I2C2 */ + MX6DL_PAD_KEY_COL3__I2C2_SCL, + MX6DL_PAD_KEY_ROW3__I2C2_SDA, + + /* DISPLAY */ + MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, + MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15, + MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN2, + MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN3, + MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0, + MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1, + MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2, + MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3, + MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4, + MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5, + MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6, + MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7, + MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8, + MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9, + MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10, + MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11, + MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12, + MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13, + MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14, + MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15, + MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16, + MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17, + MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18, + MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19, + MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20, + MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21, + MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, + MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, + + MX6DL_PAD_EIM_D24__GPIO_3_24, + + /* UART2 */ + MX6DL_PAD_EIM_D26__UART2_RXD, + MX6DL_PAD_EIM_D27__UART2_TXD, + MX6DL_PAD_EIM_D28__UART2_RTS, + MX6DL_PAD_EIM_D29__UART2_CTS, + + /* PWM1 */ + MX6DL_PAD_GPIO_9__PWM1_PWMO, + + /* DISP0 DET */ + MX6DL_PAD_EIM_D31__GPIO_3_31, + + /* DISP0 RESET */ + MX6DL_PAD_EIM_WAIT__GPIO_5_0, + + /* HDMI */ + MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE, + MX6DL_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0, + MX6DL_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1, + + /* USBOTG ID pin */ + MX6DL_PAD_GPIO_1__USBOTG_ID, + + /* MLB150 */ + MX6DL_PAD_GPIO_3__MLB_MLBCLK, + MX6DL_PAD_GPIO_6__MLB_MLBSIG, + MX6DL_PAD_GPIO_2__MLB_MLBDAT, +}; + +static iomux_v3_cfg_t mx6dl_arm2_i2c3_pads[] = { + MX6DL_PAD_GPIO_5__I2C3_SCL, + MX6DL_PAD_GPIO_16__I2C3_SDA, +}; + +static iomux_v3_cfg_t mx6dl_arm2_spdif_pads[] = { + /* SPDIF */ + MX6DL_PAD_GPIO_16__SPDIF_IN1, + MX6DL_PAD_GPIO_17__SPDIF_OUT1, +}; + +static iomux_v3_cfg_t mx6dl_arm2_can_pads[] = { + /* CAN1 */ + MX6DL_PAD_GPIO_7__CAN1_TXCAN, + MX6DL_PAD_KEY_ROW2__CAN1_RXCAN, + MX6DL_PAD_GPIO_17__GPIO_7_12, /* CAN1 STBY */ + MX6DL_PAD_GPIO_18__GPIO_7_13, /* CAN1 EN */ + + /* CAN2 */ + MX6DL_PAD_KEY_COL4__CAN2_TXCAN, + MX6DL_PAD_KEY_ROW4__CAN2_RXCAN, + MX6DL_PAD_CSI0_DAT6__GPIO_5_24, /* CAN2 EN */ +}; + +static iomux_v3_cfg_t mx6dl_arm2_esai_record_pads[] = { + MX6DL_PAD_ENET_RX_ER__ESAI1_HCKR, + MX6DL_PAD_ENET_MDIO__ESAI1_SCKR, + MX6DL_PAD_ENET_REF_CLK__ESAI1_FSR, +}; + +static iomux_v3_cfg_t mx6dl_arm2_csi0_sensor_pads[] = { + MX6DL_PAD_GPIO_0__CCM_CLKO, + /* ipu1 csi0 */ + MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12, + MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13, + MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14, + MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15, + MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16, + MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17, + MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18, + MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19, + MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, + MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, + MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, + /* camera reset */ + MX6DL_PAD_GPIO_19__GPIO_4_5, + /* camera powerdown */ + MX6DL_PAD_CSI0_DAT5__GPIO_5_23, +}; + +static iomux_v3_cfg_t mx6dl_arm2_csi0_tvin_pads[] = { + /* ipu1 csi0 */ + MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12, + MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13, + MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14, + MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15, + MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16, + MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17, + MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18, + MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19, + MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, + MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, + MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, + /* camera reset */ + MX6DL_PAD_CSI0_DAT7__GPIO_5_25, + /* camera powerdown */ + MX6DL_PAD_CSI0_DAT5__GPIO_5_23, +}; + +static iomux_v3_cfg_t mx6dl_arm2_mipi_sensor_pads[] = { + MX6DL_PAD_CSI0_MCLK__CCM_CLKO, +}; + +static iomux_v3_cfg_t mx6dl_arm2_audmux_pads[] = { + + /* AUDMUX */ + MX6DL_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, + MX6DL_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD, + MX6DL_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS, + MX6DL_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD, +}; + +#define MX6DL_USDHC_PAD_SETTING(id, speed) \ +mx6dl_sd##id##_##speed##mhz[] = { \ + MX6DL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \ + MX6DL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \ + MX6DL_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \ +} + +static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 50); +static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 100); +static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(3, 200); +static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(4, 50); +static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(4, 100); +static iomux_v3_cfg_t MX6DL_USDHC_PAD_SETTING(4, 200); + +/* The GPMI is conflicted with SD3, so init this in the driver. */ +static iomux_v3_cfg_t mx6dl_gpmi_nand[] __initdata = { + MX6DL_PAD_NANDF_CLE__RAWNAND_CLE, + MX6DL_PAD_NANDF_ALE__RAWNAND_ALE, + MX6DL_PAD_NANDF_CS0__RAWNAND_CE0N, + MX6DL_PAD_NANDF_CS1__RAWNAND_CE1N, + MX6DL_PAD_NANDF_CS2__RAWNAND_CE2N, + MX6DL_PAD_NANDF_CS3__RAWNAND_CE3N, + MX6DL_PAD_NANDF_RB0__RAWNAND_READY0, + MX6DL_PAD_SD4_DAT0__RAWNAND_DQS, + MX6DL_PAD_NANDF_D0__RAWNAND_D0, + MX6DL_PAD_NANDF_D1__RAWNAND_D1, + MX6DL_PAD_NANDF_D2__RAWNAND_D2, + MX6DL_PAD_NANDF_D3__RAWNAND_D3, + MX6DL_PAD_NANDF_D4__RAWNAND_D4, + MX6DL_PAD_NANDF_D5__RAWNAND_D5, + MX6DL_PAD_NANDF_D6__RAWNAND_D6, + MX6DL_PAD_NANDF_D7__RAWNAND_D7, + MX6DL_PAD_SD4_CMD__RAWNAND_RDN, + MX6DL_PAD_SD4_CLK__RAWNAND_WRN, + MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN, +}; diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index c3b46b7a551f..7d20f1cf8572 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -56,7 +56,6 @@ #include <mach/hardware.h> #include <mach/mxc_dvfs.h> #include <mach/memory.h> -#include <mach/iomux-mx6q.h> #include <mach/imx-uart.h> #include <mach/viv_gpu.h> #include <mach/ahci_sata.h> @@ -78,35 +77,37 @@ #include "cpu_op-mx6.h" #include "android.h" -#define MX6Q_ARM2_LDB_BACKLIGHT IMX_GPIO_NR(1, 9) -#define MX6Q_ARM2_ECSPI1_CS0 IMX_GPIO_NR(2, 30) -#define MX6Q_ARM2_ECSPI1_CS1 IMX_GPIO_NR(3, 19) -#define MX6Q_ARM2_DISP0_PWR IMX_GPIO_NR(3, 24) -#define MX6Q_ARM2_DISP0_I2C_EN IMX_GPIO_NR(3, 28) -#define MX6Q_ARM2_DISP0_DET_INT IMX_GPIO_NR(3, 31) -#define MX6Q_ARM2_DISP0_RESET IMX_GPIO_NR(5, 0) -#define MX6Q_ARM2_SD3_CD IMX_GPIO_NR(6, 11) -#define MX6Q_ARM2_SD3_WP IMX_GPIO_NR(6, 14) -#define MX6Q_ARM2_USB_OTG_PWR IMX_GPIO_NR(3, 22) -#define MX6Q_ARM2_MAX7310_1_BASE_ADDR IMX_GPIO_NR(8, 0) -#define MX6Q_ARM2_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8) -#define MX6Q_ARM2_CAP_TCH_INT IMX_GPIO_NR(3, 31) - -#define MX6Q_ARM2_IO_EXP_GPIO1(x) \ - (MX6Q_ARM2_MAX7310_1_BASE_ADDR + (x)) -#define MX6Q_ARM2_IO_EXP_GPIO2(x) \ - (MX6Q_ARM2_MAX7310_2_BASE_ADDR + (x)) - -#define MX6Q_ARM2_CAN1_STBY IMX_GPIO_NR(7, 12) -#define MX6Q_ARM2_CAN1_EN IMX_GPIO_NR(7, 13) -#define MX6Q_ARM2_CAN2_STBY MX6Q_ARM2_IO_EXP_GPIO2(1) -#define MX6Q_ARM2_CAN2_EN IMX_GPIO_NR(5, 24) - -#define MX6Q_ARM2_CSI0_RST IMX_GPIO_NR(4, 5) -#define MX6Q_ARM2_CSI0_PWN IMX_GPIO_NR(5, 23) -#define MX6Q_ARM2_CSI0_RST_TVIN IMX_GPIO_NR(5, 25) - -#define BMCR_PDOWN 0x0800 /* PHY Powerdown */ +#include "board-mx6q_arm2.h" +#include "board-mx6dl_arm2.h" + +/* GPIO PIN, sort by PORT/BIT */ +#define MX6_ARM2_LDB_BACKLIGHT IMX_GPIO_NR(1, 9) +#define MX6_ARM2_ECSPI1_CS0 IMX_GPIO_NR(2, 30) +#define MX6_ARM2_ECSPI1_CS1 IMX_GPIO_NR(3, 19) +#define MX6_ARM2_USB_OTG_PWR IMX_GPIO_NR(3, 22) +#define MX6_ARM2_DISP0_PWR IMX_GPIO_NR(3, 24) +#define MX6_ARM2_DISP0_I2C_EN IMX_GPIO_NR(3, 28) +#define MX6_ARM2_CAP_TCH_INT IMX_GPIO_NR(3, 31) +#define MX6_ARM2_DISP0_DET_INT IMX_GPIO_NR(3, 31) +#define MX6_ARM2_CSI0_RST IMX_GPIO_NR(4, 5) +#define MX6_ARM2_DISP0_RESET IMX_GPIO_NR(5, 0) +#define MX6_ARM2_CSI0_PWN IMX_GPIO_NR(5, 23) +#define MX6_ARM2_CAN2_EN IMX_GPIO_NR(5, 24) +#define MX6_ARM2_CSI0_RST_TVIN IMX_GPIO_NR(5, 25) +#define MX6_ARM2_SD3_CD IMX_GPIO_NR(6, 11) +#define MX6_ARM2_SD3_WP IMX_GPIO_NR(6, 14) +#define MX6_ARM2_CAN1_STBY IMX_GPIO_NR(7, 12) +#define MX6_ARM2_CAN1_EN IMX_GPIO_NR(7, 13) +#define MX6_ARM2_MAX7310_1_BASE_ADDR IMX_GPIO_NR(8, 0) +#define MX6_ARM2_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8) + +#define MX6_ARM2_IO_EXP_GPIO1(x) (MX6_ARM2_MAX7310_1_BASE_ADDR + (x)) +#define MX6_ARM2_IO_EXP_GPIO2(x) (MX6_ARM2_MAX7310_2_BASE_ADDR + (x)) + +#define MX6_ARM2_CAN2_STBY MX6_ARM2_IO_EXP_GPIO2(1) + + +#define BMCR_PDOWN 0x0800 /* PHY Powerdown */ void __init early_console_setup(unsigned long base, struct clk *clk); static struct clk *sata_clk; @@ -120,277 +121,6 @@ extern void (*put_cpu_regulator)(void); extern char *gp_reg_id; extern void mx6_cpu_regulator_init(void); -static iomux_v3_cfg_t mx6q_arm2_pads[] = { - - /* UART4 for debug */ - MX6Q_PAD_KEY_COL0__UART4_TXD, - MX6Q_PAD_KEY_ROW0__UART4_RXD, - /* USB HSIC ports use the same pin with ENET */ -#ifdef CONFIG_USB_EHCI_ARC_HSIC - /* USB H2 strobe/data pin */ - MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE, - MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA, - - /* USB H3 strobe/data pin */ - MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE, - MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA, - /* ENET */ -#else - MX6Q_PAD_KEY_COL1__ENET_MDIO, - MX6Q_PAD_KEY_COL2__ENET_MDC, - MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC, - MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0, - MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1, - MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2, - MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3, - MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, - MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, - MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC, - MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0, - MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1, - MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2, - MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3, - MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, -#endif - /* MCLK for csi0 */ - MX6Q_PAD_GPIO_0__CCM_CLKO, - MX6Q_PAD_GPIO_3__CCM_CLKO2, - - /* SD1 */ - MX6Q_PAD_SD1_CLK__USDHC1_CLK, - MX6Q_PAD_SD1_CMD__USDHC1_CMD, - MX6Q_PAD_SD1_DAT0__USDHC1_DAT0, - MX6Q_PAD_SD1_DAT1__USDHC1_DAT1, - MX6Q_PAD_SD1_DAT2__USDHC1_DAT2, - MX6Q_PAD_SD1_DAT3__USDHC1_DAT3, - /* SD2 */ - MX6Q_PAD_SD2_CLK__USDHC2_CLK, - MX6Q_PAD_SD2_CMD__USDHC2_CMD, - MX6Q_PAD_SD2_DAT0__USDHC2_DAT0, - MX6Q_PAD_SD2_DAT1__USDHC2_DAT1, - MX6Q_PAD_SD2_DAT2__USDHC2_DAT2, - MX6Q_PAD_SD2_DAT3__USDHC2_DAT3, - /* SD3 */ - MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ, - MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ, - MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ, - MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ, - MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ, - MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ, - MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ, - MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ, - MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ, - MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ, - MX6Q_PAD_SD3_RST__USDHC3_RST, - /* SD3 VSelect */ - MX6Q_PAD_GPIO_18__USDHC3_VSELECT, - /* SD3_CD and SD3_WP */ - MX6Q_PAD_NANDF_CS0__GPIO_6_11, - MX6Q_PAD_NANDF_CS1__GPIO_6_14, - /* SD4 */ - MX6Q_PAD_SD4_CLK__USDHC4_CLK_50MHZ, - MX6Q_PAD_SD4_CMD__USDHC4_CMD_50MHZ, - MX6Q_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ, - MX6Q_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ, - MX6Q_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ, - MX6Q_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ, - MX6Q_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ, - MX6Q_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ, - MX6Q_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ, - MX6Q_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ, - MX6Q_PAD_NANDF_ALE__USDHC4_RST, - /* eCSPI1 */ - MX6Q_PAD_EIM_EB2__ECSPI1_SS0, - MX6Q_PAD_EIM_D16__ECSPI1_SCLK, - MX6Q_PAD_EIM_D17__ECSPI1_MISO, - MX6Q_PAD_EIM_D18__ECSPI1_MOSI, - MX6Q_PAD_EIM_D19__ECSPI1_SS1, - MX6Q_PAD_EIM_EB2__GPIO_2_30, /*SS0*/ - MX6Q_PAD_EIM_D19__GPIO_3_19, /*SS1*/ - - /* ESAI */ - MX6Q_PAD_ENET_RXD0__ESAI1_HCKT, - MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT, - MX6Q_PAD_ENET_RXD1__ESAI1_FST, - MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2, - MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3, - MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1, - MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0, - MX6Q_PAD_NANDF_CS2__ESAI1_TX0, - MX6Q_PAD_NANDF_CS3__ESAI1_TX1, - - /* I2C1 */ - MX6Q_PAD_CSI0_DAT8__I2C1_SDA, - MX6Q_PAD_CSI0_DAT9__I2C1_SCL, - - /* I2C2 */ - MX6Q_PAD_KEY_COL3__I2C2_SCL, - MX6Q_PAD_KEY_ROW3__I2C2_SDA, - - /* DISPLAY */ - MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, - MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, - MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2, - MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3, - MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0, - MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1, - MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2, - MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3, - MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4, - MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5, - MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6, - MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7, - MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8, - MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9, - MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10, - MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11, - MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12, - MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13, - MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14, - MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15, - MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16, - MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17, - MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18, - MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19, - MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20, - MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21, - MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, - MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, - - MX6Q_PAD_EIM_D24__GPIO_3_24, - - /* UART2 */ - MX6Q_PAD_EIM_D26__UART2_RXD, - MX6Q_PAD_EIM_D27__UART2_TXD, - MX6Q_PAD_EIM_D28__UART2_RTS, - MX6Q_PAD_EIM_D29__UART2_CTS, - - /* PWM1 */ - MX6Q_PAD_GPIO_9__PWM1_PWMO, - - /* DISP0 DET */ - MX6Q_PAD_EIM_D31__GPIO_3_31, - - /* DISP0 RESET */ - MX6Q_PAD_EIM_WAIT__GPIO_5_0, - - /* HDMI */ - MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE, - MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0, - MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1, - - /* USBOTG ID pin */ - MX6Q_PAD_GPIO_1__USBOTG_ID, - - /* MLB150 */ - MX6Q_PAD_GPIO_3__MLB_MLBCLK, - MX6Q_PAD_GPIO_6__MLB_MLBSIG, - MX6Q_PAD_GPIO_2__MLB_MLBDAT, -}; - -static iomux_v3_cfg_t mx6q_arm2_i2c3_pads[] = { - MX6Q_PAD_GPIO_5__I2C3_SCL, - MX6Q_PAD_GPIO_16__I2C3_SDA, -}; - -static iomux_v3_cfg_t mx6q_arm2_spdif_pads[] = { - /* SPDIF */ - MX6Q_PAD_GPIO_16__SPDIF_IN1, - MX6Q_PAD_GPIO_17__SPDIF_OUT1, -}; - -static iomux_v3_cfg_t mx6q_arm2_can_pads[] = { - /* CAN1 */ - MX6Q_PAD_GPIO_7__CAN1_TXCAN, - MX6Q_PAD_KEY_ROW2__CAN1_RXCAN, - MX6Q_PAD_GPIO_17__GPIO_7_12, /* CAN1 STBY */ - MX6Q_PAD_GPIO_18__GPIO_7_13, /* CAN1 EN */ - - /* CAN2 */ - MX6Q_PAD_KEY_COL4__CAN2_TXCAN, - MX6Q_PAD_KEY_ROW4__CAN2_RXCAN, - MX6Q_PAD_CSI0_DAT6__GPIO_5_24, /* CAN2 EN */ -}; - -static iomux_v3_cfg_t mx6q_arm2_esai_record_pads[] = { - MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR, - MX6Q_PAD_ENET_MDIO__ESAI1_SCKR, - MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR, -}; - -static iomux_v3_cfg_t mx6q_arm2_csi0_sensor_pads[] = { - MX6Q_PAD_GPIO_0__CCM_CLKO, - /* ipu1 csi0 */ - MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, - MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, - MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, - MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, - MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, - MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, - MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, - MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, - MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, - MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, - MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, - /* camera reset */ - MX6Q_PAD_GPIO_19__GPIO_4_5, - /* camera powerdown */ - MX6Q_PAD_CSI0_DAT5__GPIO_5_23, -}; - -static iomux_v3_cfg_t mx6q_arm2_csi0_tvin_pads[] = { - /* ipu1 csi0 */ - MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, - MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, - MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, - MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, - MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, - MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, - MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, - MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, - MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, - MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, - MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, - /* camera reset */ - MX6Q_PAD_CSI0_DAT7__GPIO_5_25, - /* camera powerdown */ - MX6Q_PAD_CSI0_DAT5__GPIO_5_23, -}; - -static iomux_v3_cfg_t mx6q_arm2_mipi_sensor_pads[] = { - MX6Q_PAD_CSI0_MCLK__CCM_CLKO, -}; - -static iomux_v3_cfg_t mx6q_arm2_audmux_pads[] = { - - /* AUDMUX */ - MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, - MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD, - MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS, - MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD, -}; - -#define MX6Q_USDHC_PAD_SETTING(id, speed) \ -mx6q_sd##id##_##speed##mhz[] = { \ - MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \ - MX6Q_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \ - MX6Q_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \ -} - -static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 50); -static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 100); -static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 200); -static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 50); -static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 100); -static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 200); - enum sd_pad_mode { SD_PAD_MODE_LOW_SPEED, SD_PAD_MODE_MED_SPEED, @@ -401,27 +131,53 @@ static int plt_sd3_pad_change(int clock) { static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; + iomux_v3_cfg_t *sd3_pads_200mhz = NULL; + iomux_v3_cfg_t *sd3_pads_100mhz = NULL; + iomux_v3_cfg_t *sd3_pads_50mhz = NULL; + + u32 sd3_pads_200mhz_cnt; + u32 sd3_pads_100mhz_cnt; + u32 sd3_pads_50mhz_cnt; + + if (cpu_is_mx6q()) { + sd3_pads_200mhz = mx6q_sd3_200mhz; + sd3_pads_100mhz = mx6q_sd3_100mhz; + sd3_pads_50mhz = mx6q_sd3_50mhz; + + sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz); + sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz); + sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz); + } else if (cpu_is_mx6dl()) { + sd3_pads_200mhz = mx6dl_sd3_200mhz; + sd3_pads_100mhz = mx6dl_sd3_100mhz; + sd3_pads_50mhz = mx6dl_sd3_50mhz; + + sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz); + sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz); + sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz); + } + if (clock > 100000000) { if (pad_mode == SD_PAD_MODE_HIGH_SPEED) return 0; - + BUG_ON(!sd3_pads_200mhz); pad_mode = SD_PAD_MODE_HIGH_SPEED; - return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_200mhz, - ARRAY_SIZE(mx6q_sd3_200mhz)); + return mxc_iomux_v3_setup_multiple_pads(sd3_pads_200mhz, + sd3_pads_200mhz_cnt); } else if (clock > 52000000) { if (pad_mode == SD_PAD_MODE_MED_SPEED) return 0; - + BUG_ON(!sd3_pads_100mhz); pad_mode = SD_PAD_MODE_MED_SPEED; - return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_100mhz, - ARRAY_SIZE(mx6q_sd3_100mhz)); + return mxc_iomux_v3_setup_multiple_pads(sd3_pads_100mhz, + sd3_pads_100mhz_cnt); } else { if (pad_mode == SD_PAD_MODE_LOW_SPEED) return 0; - + BUG_ON(!sd3_pads_50mhz); pad_mode = SD_PAD_MODE_LOW_SPEED; - return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_50mhz, - ARRAY_SIZE(mx6q_sd3_50mhz)); + return mxc_iomux_v3_setup_multiple_pads(sd3_pads_50mhz, + sd3_pads_50mhz_cnt); } } @@ -429,103 +185,118 @@ static int plt_sd4_pad_change(int clock) { static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; + iomux_v3_cfg_t *sd4_pads_200mhz = NULL; + iomux_v3_cfg_t *sd4_pads_100mhz = NULL; + iomux_v3_cfg_t *sd4_pads_50mhz = NULL; + + u32 sd4_pads_200mhz_cnt; + u32 sd4_pads_100mhz_cnt; + u32 sd4_pads_50mhz_cnt; + + if (cpu_is_mx6q()) { + sd4_pads_200mhz = mx6q_sd4_200mhz; + sd4_pads_100mhz = mx6q_sd4_100mhz; + sd4_pads_50mhz = mx6q_sd4_50mhz; + + sd4_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd4_200mhz); + sd4_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz); + sd4_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz); + } else if (cpu_is_mx6dl()) { + sd4_pads_200mhz = mx6dl_sd4_200mhz; + sd4_pads_100mhz = mx6dl_sd4_100mhz; + sd4_pads_50mhz = mx6dl_sd4_50mhz; + + sd4_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd4_200mhz); + sd4_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd4_100mhz); + sd4_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd4_50mhz); + } + if (clock > 100000000) { if (pad_mode == SD_PAD_MODE_HIGH_SPEED) return 0; pad_mode = SD_PAD_MODE_HIGH_SPEED; - return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_200mhz, - ARRAY_SIZE(mx6q_sd4_200mhz)); + return mxc_iomux_v3_setup_multiple_pads(sd4_pads_200mhz, + sd4_pads_200mhz_cnt); } else if (clock > 52000000) { if (pad_mode == SD_PAD_MODE_MED_SPEED) return 0; pad_mode = SD_PAD_MODE_MED_SPEED; - return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_100mhz, - ARRAY_SIZE(mx6q_sd4_100mhz)); + return mxc_iomux_v3_setup_multiple_pads(sd4_pads_100mhz, + sd4_pads_100mhz_cnt); } else { if (pad_mode == SD_PAD_MODE_LOW_SPEED) return 0; pad_mode = SD_PAD_MODE_LOW_SPEED; - return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_50mhz, - ARRAY_SIZE(mx6q_sd4_50mhz)); + return mxc_iomux_v3_setup_multiple_pads(sd4_pads_50mhz, + sd4_pads_50mhz_cnt); } } -static const struct esdhc_platform_data mx6q_arm2_sd3_data __initconst = { - .cd_gpio = MX6Q_ARM2_SD3_CD, - .wp_gpio = MX6Q_ARM2_SD3_WP, - .support_18v = 1, - .support_8bit = 1, - .keep_power_at_suspend = 1, - .delay_line = 0, - .platform_pad_change = plt_sd3_pad_change, -}; - -/* No card detect signal for SD4 */ -static const struct esdhc_platform_data mx6q_arm2_sd4_data __initconst = { - .always_present = 1, - .support_8bit = 1, - .keep_power_at_suspend = 1, - .platform_pad_change = plt_sd4_pad_change, -}; - -/* The GPMI is conflicted with SD3, so init this in the driver. */ -static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = { - MX6Q_PAD_NANDF_CLE__RAWNAND_CLE, - MX6Q_PAD_NANDF_ALE__RAWNAND_ALE, - MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N, - MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N, - MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N, - MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N, - MX6Q_PAD_NANDF_RB0__RAWNAND_READY0, - MX6Q_PAD_SD4_DAT0__RAWNAND_DQS, - MX6Q_PAD_NANDF_D0__RAWNAND_D0, - MX6Q_PAD_NANDF_D1__RAWNAND_D1, - MX6Q_PAD_NANDF_D2__RAWNAND_D2, - MX6Q_PAD_NANDF_D3__RAWNAND_D3, - MX6Q_PAD_NANDF_D4__RAWNAND_D4, - MX6Q_PAD_NANDF_D5__RAWNAND_D5, - MX6Q_PAD_NANDF_D6__RAWNAND_D6, - MX6Q_PAD_NANDF_D7__RAWNAND_D7, - MX6Q_PAD_SD4_CMD__RAWNAND_RDN, - MX6Q_PAD_SD4_CLK__RAWNAND_WRN, - MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN, -}; - -static int gpmi_nfc_platform_init(void) +static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = { + .cd_gpio = MX6_ARM2_SD3_CD, + .wp_gpio = MX6_ARM2_SD3_WP, + .support_18v = 1, + .support_8bit = 1, + .keep_power_at_suspend = 1, + .delay_line = 0, + .platform_pad_change = plt_sd3_pad_change, +}; + +/* No card detect signal for SD4 on ARM2 board*/ +static const struct esdhc_platform_data mx6_arm2_sd4_data __initconst = { + .always_present = 1, + .support_8bit = 1, + .keep_power_at_suspend = 1, + .platform_pad_change = plt_sd4_pad_change, +}; + +static int __init gpmi_nand_platform_init(void) { - return mxc_iomux_v3_setup_multiple_pads(mx6q_gpmi_nand, - ARRAY_SIZE(mx6q_gpmi_nand)); + iomux_v3_cfg_t *nand_pads = NULL; + u32 nand_pads_cnt; + + if (cpu_is_mx6q()) { + nand_pads = mx6q_gpmi_nand; + nand_pads_cnt = ARRAY_SIZE(mx6dl_gpmi_nand); + } else if (cpu_is_mx6dl()) { + nand_pads = mx6dl_gpmi_nand; + nand_pads_cnt = ARRAY_SIZE(mx6dl_gpmi_nand); + + } + BUG_ON(!nand_pads); + return mxc_iomux_v3_setup_multiple_pads(nand_pads, nand_pads_cnt); } -static const struct gpmi_nfc_platform_data -mx6q_gpmi_nfc_platform_data __initconst = { - .platform_init = gpmi_nfc_platform_init, +static const struct gpmi_nand_platform_data +mx6_gpmi_nand_platform_data __initconst = { + .platform_init = gpmi_nand_platform_init, .min_prop_delay_in_ns = 5, .max_prop_delay_in_ns = 9, .max_chip_count = 1, + .enable_bbt = 1, }; static const struct anatop_thermal_platform_data - mx6q_arm2_anatop_thermal_data __initconst = { + mx6_arm2_anatop_thermal_data __initconst = { .name = "anatop_thermal", }; -static const struct imxuart_platform_data mx6q_uart1_data __initconst = { - .flags = IMXUART_HAVE_RTSCTS | IMXUART_USE_DCEDTE | IMXUART_SDMA, +static const struct imxuart_platform_data mx6_arm2_uart1_data __initconst = { + .flags = IMXUART_HAVE_RTSCTS | IMXUART_USE_DCEDTE | IMXUART_SDMA, .dma_req_rx = MX6Q_DMA_REQ_UART2_RX, .dma_req_tx = MX6Q_DMA_REQ_UART2_TX, }; -static inline void mx6q_arm2_init_uart(void) +static inline void mx6_arm2_init_uart(void) { imx6q_add_imx_uart(3, NULL); - imx6q_add_imx_uart(1, &mx6q_uart1_data); + imx6q_add_imx_uart(1, &mx6_arm2_uart1_data); } -static int mx6q_arm2_fec_phy_init(struct phy_device *phydev) +static int mx6_arm2_fec_phy_init(struct phy_device *phydev) { unsigned short val; @@ -552,7 +323,7 @@ static int mx6q_arm2_fec_phy_init(struct phy_device *phydev) return 0; } -static int mx6q_arm2_fec_power_hibernate(struct phy_device *phydev) +static int mx6_arm2_fec_power_hibernate(struct phy_device *phydev) { unsigned short val; @@ -567,52 +338,51 @@ static int mx6q_arm2_fec_power_hibernate(struct phy_device *phydev) } static struct fec_platform_data fec_data __initdata = { - .init = mx6q_arm2_fec_phy_init, - .power_hibernate = mx6q_arm2_fec_power_hibernate, - .phy = PHY_INTERFACE_MODE_RGMII, + .init = mx6_arm2_fec_phy_init, + .power_hibernate = mx6_arm2_fec_power_hibernate, + .phy = PHY_INTERFACE_MODE_RGMII, }; -static int mx6q_arm2_spi_cs[] = { - MX6Q_ARM2_ECSPI1_CS0, - MX6Q_ARM2_ECSPI1_CS1, +static int mx6_arm2_spi_cs[] = { + MX6_ARM2_ECSPI1_CS0, + MX6_ARM2_ECSPI1_CS1, }; -static const struct spi_imx_master mx6q_arm2_spi_data __initconst = { - .chipselect = mx6q_arm2_spi_cs, - .num_chipselect = ARRAY_SIZE(mx6q_arm2_spi_cs), +static const struct spi_imx_master mx6_arm2_spi_data __initconst = { + .chipselect = mx6_arm2_spi_cs, + .num_chipselect = ARRAY_SIZE(mx6_arm2_spi_cs), }; #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) static struct mtd_partition m25p32_partitions[] = { { - .name = "bootloader", - .offset = 0, - .size = 0x00040000, - }, - { - .name = "kernel", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, + .name = "bootloader", + .offset = 0, + .size = 0x00040000, + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, }, }; static struct flash_platform_data m25p32_spi_flash_data = { - .name = "m25p32", - .parts = m25p32_partitions, - .nr_parts = ARRAY_SIZE(m25p32_partitions), - .type = "m25p32", + .name = "m25p32", + .parts = m25p32_partitions, + .nr_parts = ARRAY_SIZE(m25p32_partitions), + .type = "m25p32", }; #endif static struct spi_board_info m25p32_spi0_board_info[] __initdata = { #if defined(CONFIG_MTD_M25P80) { - /* The modalias must be the same as spi device driver name */ - .modalias = "m25p80", - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 1, - .platform_data = &m25p32_spi_flash_data, + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &m25p32_spi_flash_data, }, #endif }; @@ -627,9 +397,7 @@ static int max7310_1_setup(struct i2c_client *client, unsigned gpio_base, unsigned ngpio, void *context) { - int max7310_gpio_value[] = { - 0, 1, 0, 1, 0, 0, 0, 0, - }; + int max7310_gpio_value[] = { 0, 1, 0, 1, 0, 0, 0, 0 }; int n; @@ -647,7 +415,7 @@ static int max7310_1_setup(struct i2c_client *client, } static struct pca953x_platform_data max7310_platdata = { - .gpio_base = MX6Q_ARM2_MAX7310_1_BASE_ADDR, + .gpio_base = MX6_ARM2_MAX7310_1_BASE_ADDR, .invert = 0, .setup = max7310_1_setup, }; @@ -656,9 +424,7 @@ static int max7310_u48_setup(struct i2c_client *client, unsigned gpio_base, unsigned ngpio, void *context) { - int max7310_gpio_value[] = { - 1, 1, 1, 1, 0, 1, 0, 0, - }; + int max7310_gpio_value[] = { 1, 1, 1, 1, 0, 1, 0, 0 }; int n; @@ -676,7 +442,7 @@ static int max7310_u48_setup(struct i2c_client *client, } static struct pca953x_platform_data max7310_u48_platdata = { - .gpio_base = MX6Q_ARM2_MAX7310_2_BASE_ADDR, + .gpio_base = MX6_ARM2_MAX7310_2_BASE_ADDR, .invert = 0, .setup = max7310_u48_setup, }; @@ -684,46 +450,59 @@ static struct pca953x_platform_data max7310_u48_platdata = { static void ddc_dvi_init(void) { /* enable DVI I2C */ - gpio_set_value(MX6Q_ARM2_DISP0_I2C_EN, 1); + gpio_set_value(MX6_ARM2_DISP0_I2C_EN, 1); /* DISP0 Detect */ - gpio_request(MX6Q_ARM2_DISP0_DET_INT, "disp0-detect"); - gpio_direction_input(MX6Q_ARM2_DISP0_DET_INT); + gpio_request(MX6_ARM2_DISP0_DET_INT, "disp0-detect"); + gpio_direction_input(MX6_ARM2_DISP0_DET_INT); } static int ddc_dvi_update(void) { /* DVI cable state */ - if (gpio_get_value(MX6Q_ARM2_DISP0_DET_INT) == 1) + if (gpio_get_value(MX6_ARM2_DISP0_DET_INT) == 1) return 1; - else - return 0; + return 0; } static struct fsl_mxc_dvi_platform_data sabr_ddc_dvi_data = { - .ipu_id = 0, - .disp_id = 0, - .init = ddc_dvi_init, - .update = ddc_dvi_update, + .ipu_id = 0, + .disp_id = 0, + .init = ddc_dvi_init, + .update = ddc_dvi_update, }; -static void mx6q_csi0_io_init(void) +static void mx6_csi0_io_init(void) { if (0 == sgtl5000_en) { - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_csi0_sensor_pads, - ARRAY_SIZE(mx6q_arm2_csi0_sensor_pads)); + iomux_v3_cfg_t *sensor_pads = NULL; + u32 sensor_pads_cnt; + + if (cpu_is_mx6q()) { + sensor_pads = mx6q_arm2_csi0_sensor_pads; + sensor_pads_cnt = \ + ARRAY_SIZE(mx6q_arm2_csi0_sensor_pads); + } else if (cpu_is_mx6dl()) { + sensor_pads = mx6dl_arm2_csi0_sensor_pads; + sensor_pads_cnt = \ + ARRAY_SIZE(mx6dl_arm2_csi0_sensor_pads); + } + + BUG_ON(!sensor_pads); + mxc_iomux_v3_setup_multiple_pads(sensor_pads, sensor_pads_cnt); } /* Camera reset */ - gpio_request(MX6Q_ARM2_CSI0_RST, "cam-reset"); - gpio_direction_output(MX6Q_ARM2_CSI0_RST, 1); + gpio_request(MX6_ARM2_CSI0_RST, "cam-reset"); + gpio_direction_output(MX6_ARM2_CSI0_RST, 1); /* Camera power down */ - gpio_request(MX6Q_ARM2_CSI0_PWN, "cam-pwdn"); - gpio_direction_output(MX6Q_ARM2_CSI0_PWN, 1); + gpio_request(MX6_ARM2_CSI0_PWN, "cam-pwdn"); + gpio_direction_output(MX6_ARM2_CSI0_PWN, 1); msleep(1); - gpio_set_value(MX6Q_ARM2_CSI0_PWN, 0); + gpio_set_value(MX6_ARM2_CSI0_PWN, 0); - /* For MX6Q GPR1 bit19 and bit20 meaning: + /* For MX6Q: + * GPR1 bit19 and bit20 meaning: * Bit19: 0 - Enable mipi to IPU1 CSI0 * virtual channel is fixed to 0 * 1 - Enable parallel interface to IPU1 CSI0 @@ -734,79 +513,114 @@ static void mx6q_csi0_io_init(void) * virtual channel is fixed to 1 * IPU2 CSI0 directly connect to mipi csi2, * virtual channel is fixed to 2 + * + * For MX6DL: + * GPR1 bit 21 and GPR13 bit 0-5, RM has detail information */ - mxc_iomux_set_gpr_register(1, 19, 1, 1); + if (cpu_is_mx6q()) + mxc_iomux_set_gpr_register(1, 19, 1, 1); + else if (cpu_is_mx6dl()) + mxc_iomux_set_gpr_register(13, 0, 3, 4); } static struct fsl_mxc_camera_platform_data camera_data = { - .analog_regulator = "DA9052_LDO7", - .core_regulator = "DA9052_LDO9", - .mclk = 24000000, - .csi = 0, - .io_init = mx6q_csi0_io_init, + .analog_regulator = "DA9052_LDO7", + .core_regulator = "DA9052_LDO9", + .mclk = 24000000, + .csi = 0, + .io_init = mx6_csi0_io_init, }; -static void mx6q_csi0_tvin_io_init(void) +static void mx6_csi0_tvin_io_init(void) { if (0 == sgtl5000_en) { - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_csi0_tvin_pads, - ARRAY_SIZE(mx6q_arm2_csi0_tvin_pads)); + iomux_v3_cfg_t *tvin_pads = NULL; + u32 tvin_pads_cnt; + + if (cpu_is_mx6q()) { + tvin_pads = mx6q_arm2_csi0_tvin_pads; + tvin_pads_cnt = \ + ARRAY_SIZE(mx6q_arm2_csi0_tvin_pads); + } else if (cpu_is_mx6dl()) { + tvin_pads = mx6dl_arm2_csi0_tvin_pads; + tvin_pads_cnt = \ + ARRAY_SIZE(mx6dl_arm2_csi0_tvin_pads); + } + + BUG_ON(!tvin_pads); + mxc_iomux_v3_setup_multiple_pads(tvin_pads, tvin_pads_cnt); } /* Tvin reset */ - gpio_request(MX6Q_ARM2_CSI0_RST_TVIN, "tvin-reset"); - gpio_direction_output(MX6Q_ARM2_CSI0_RST_TVIN, 1); + gpio_request(MX6_ARM2_CSI0_RST_TVIN, "tvin-reset"); + gpio_direction_output(MX6_ARM2_CSI0_RST_TVIN, 1); /* Tvin power down */ - gpio_request(MX6Q_ARM2_CSI0_PWN, "cam-pwdn"); - gpio_direction_output(MX6Q_ARM2_CSI0_PWN, 0); + gpio_request(MX6_ARM2_CSI0_PWN, "cam-pwdn"); + gpio_direction_output(MX6_ARM2_CSI0_PWN, 0); msleep(1); - gpio_set_value(MX6Q_ARM2_CSI0_PWN, 1); + gpio_set_value(MX6_ARM2_CSI0_PWN, 1); - mxc_iomux_set_gpr_register(1, 19, 1, 1); + if (cpu_is_mx6q()) + mxc_iomux_set_gpr_register(1, 19, 1, 1); + else if (cpu_is_mx6dl()) + mxc_iomux_set_gpr_register(13, 0, 3, 4); } static struct fsl_mxc_tvin_platform_data tvin_data = { - .io_init = mx6q_csi0_tvin_io_init, + .io_init = mx6_csi0_tvin_io_init, .cvbs = false, }; -static void mx6q_mipi_sensor_io_init(void) +static void mx6_mipi_sensor_io_init(void) { - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_mipi_sensor_pads, - ARRAY_SIZE(mx6q_arm2_mipi_sensor_pads)); + iomux_v3_cfg_t *mipi_sensor_pads = NULL; + u32 mipi_sensor_pads_cnt; - mxc_iomux_set_gpr_register(1, 19, 1, 0); + if (cpu_is_mx6q()) { + mipi_sensor_pads = mx6q_arm2_mipi_sensor_pads; + mipi_sensor_pads_cnt = ARRAY_SIZE(mx6q_arm2_mipi_sensor_pads); + } else if (cpu_is_mx6dl()) { + mipi_sensor_pads = mx6dl_arm2_mipi_sensor_pads; + mipi_sensor_pads_cnt = ARRAY_SIZE(mx6dl_arm2_mipi_sensor_pads); + + } + BUG_ON(!mipi_sensor_pads); + mxc_iomux_v3_setup_multiple_pads(mipi_sensor_pads, + mipi_sensor_pads_cnt); + + if (cpu_is_mx6q()) + mxc_iomux_set_gpr_register(1, 19, 1, 0); + if (cpu_is_mx6dl()) + mxc_iomux_set_gpr_register(13, 0, 3, 0); } static struct fsl_mxc_camera_platform_data ov5640_mipi_data = { - .mclk = 24000000, - .csi = 0, - .io_init = mx6q_mipi_sensor_io_init, + .mclk = 24000000, + .csi = 0, + .io_init = mx6_mipi_sensor_io_init, }; static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { { I2C_BOARD_INFO("cs42888", 0x48), - }, - { + }, { I2C_BOARD_INFO("ov5640", 0x3c), .platform_data = (void *)&camera_data, - }, - { + }, { I2C_BOARD_INFO("adv7180", 0x21), .platform_data = (void *)&tvin_data, }, }; -static struct imxi2c_platform_data mx6q_arm2_i2c0_data = { +static struct imxi2c_platform_data mx6_arm2_i2c0_data = { .bitrate = 100000, }; -static struct imxi2c_platform_data mx6q_arm2_i2c1_data = { +static struct imxi2c_platform_data mx6_arm2_i2c1_data = { .bitrate = 100000, }; -static struct imxi2c_platform_data mx6q_arm2_i2c2_data = { +static struct imxi2c_platform_data mx6_arm2_i2c2_data = { .bitrate = 400000, }; @@ -814,19 +628,16 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { { I2C_BOARD_INFO("max7310", 0x1F), .platform_data = &max7310_platdata, - }, - { + }, { I2C_BOARD_INFO("max7310", 0x1B), .platform_data = &max7310_u48_platdata, - }, - { + }, { I2C_BOARD_INFO("mxc_dvi", 0x50), .platform_data = &sabr_ddc_dvi_data, - .irq = gpio_to_irq(MX6Q_ARM2_DISP0_DET_INT), - }, - { + .irq = gpio_to_irq(MX6_ARM2_DISP0_DET_INT), + }, { I2C_BOARD_INFO("egalax_ts", 0x4), - .irq = gpio_to_irq(MX6Q_ARM2_CAP_TCH_INT), + .irq = gpio_to_irq(MX6_ARM2_CAP_TCH_INT), }, }; @@ -834,47 +645,44 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { { I2C_BOARD_INFO("egalax_ts", 0x4), - .irq = gpio_to_irq(MX6Q_ARM2_CAP_TCH_INT), - }, - { + .irq = gpio_to_irq(MX6_ARM2_CAP_TCH_INT), + }, { I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50), - }, - { + }, { I2C_BOARD_INFO("ov5640_mipi", 0x3c), .platform_data = (void *)&ov5640_mipi_data, - }, - { + }, { I2C_BOARD_INFO("sgtl5000", 0x0a), }, }; -static void imx6q_arm2_usbotg_vbus(bool on) +static void imx6_arm2_usbotg_vbus(bool on) { if (on) - gpio_set_value(MX6Q_ARM2_USB_OTG_PWR, 1); + gpio_set_value(MX6_ARM2_USB_OTG_PWR, 1); else - gpio_set_value(MX6Q_ARM2_USB_OTG_PWR, 0); + gpio_set_value(MX6_ARM2_USB_OTG_PWR, 0); } -static void __init imx6q_arm2_init_usb(void) +static void __init mx6_arm2_init_usb(void) { int ret = 0; imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR); + /* disable external charger detect, * or it will affect signal quality at dp. */ - ret = gpio_request(MX6Q_ARM2_USB_OTG_PWR, "usb-pwr"); + ret = gpio_request(MX6_ARM2_USB_OTG_PWR, "usb-pwr"); if (ret) { - printk(KERN_ERR"failed to get GPIO MX6Q_ARM2_USB_OTG_PWR:" - " %d\n", ret); + pr_err("failed to get GPIO MX6_ARM2_USB_OTG_PWR:%d\n", ret); return; } - gpio_direction_output(MX6Q_ARM2_USB_OTG_PWR, 0); + gpio_direction_output(MX6_ARM2_USB_OTG_PWR, 0); mxc_iomux_set_gpr_register(1, 13, 1, 1); - mx6_set_otghost_vbus_func(imx6q_arm2_usbotg_vbus); + mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus); mx6_usb_dr_init(); mx6_usb_h1_init(); #ifdef CONFIG_USB_EHCI_ARC_HSIC @@ -883,20 +691,20 @@ static void __init imx6q_arm2_init_usb(void) #endif } -static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = { +static struct viv_gpu_platform_data imx6_gpu_pdata __initdata = { .reserved_mem_size = SZ_128M, }; /* HW Initialization, if return 0, initialization is successful. */ -static int mx6q_arm2_sata_init(struct device *dev, void __iomem *addr) +static int mx6_arm2_sata_init(struct device *dev, void __iomem *addr) { u32 tmpdata; int ret = 0; struct clk *clk; /* Enable SATA PWR CTRL_0 of MAX7310 */ - gpio_request(MX6Q_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); - gpio_direction_output(MX6Q_ARM2_MAX7310_1_BASE_ADDR, 1); + gpio_request(MX6_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); + gpio_direction_output(MX6_ARM2_MAX7310_1_BASE_ADDR, 1); sata_clk = clk_get(dev, "imx_sata_clk"); if (IS_ERR(sata_clk)) { @@ -949,41 +757,41 @@ release_sata_clk: put_sata_clk: clk_put(sata_clk); /* Disable SATA PWR CTRL_0 of MAX7310 */ - gpio_request(MX6Q_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); - gpio_direction_output(MX6Q_ARM2_MAX7310_1_BASE_ADDR, 0); + gpio_request(MX6_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); + gpio_direction_output(MX6_ARM2_MAX7310_1_BASE_ADDR, 0); return ret; } -static void mx6q_arm2_sata_exit(struct device *dev) +static void mx6_arm2_sata_exit(struct device *dev) { clk_disable(sata_clk); clk_put(sata_clk); /* Disable SATA PWR CTRL_0 of MAX7310 */ - gpio_request(MX6Q_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); - gpio_direction_output(MX6Q_ARM2_MAX7310_1_BASE_ADDR, 0); + gpio_request(MX6_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); + gpio_direction_output(MX6_ARM2_MAX7310_1_BASE_ADDR, 0); } -static struct ahci_platform_data mx6q_arm2_sata_data = { - .init = mx6q_arm2_sata_init, - .exit = mx6q_arm2_sata_exit, +static struct ahci_platform_data mx6_arm2_sata_data = { + .init = mx6_arm2_sata_init, + .exit = mx6_arm2_sata_exit, }; static struct imx_asrc_platform_data imx_asrc_data = { - .channel_bits = 4, - .clk_map_ver = 2, + .channel_bits = 4, + .clk_map_ver = 2, }; -static void mx6q_sabreauto_reset_mipi_dsi(void) +static void mx6_arm2_reset_mipi_dsi(void) { - gpio_set_value(MX6Q_ARM2_DISP0_PWR, 1); - gpio_set_value(MX6Q_ARM2_DISP0_RESET, 1); + gpio_set_value(MX6_ARM2_DISP0_PWR, 1); + gpio_set_value(MX6_ARM2_DISP0_RESET, 1); udelay(10); - gpio_set_value(MX6Q_ARM2_DISP0_RESET, 0); + gpio_set_value(MX6_ARM2_DISP0_RESET, 0); udelay(50); - gpio_set_value(MX6Q_ARM2_DISP0_RESET, 1); + gpio_set_value(MX6_ARM2_DISP0_RESET, 1); /* * it needs to delay 120ms minimum for reset complete @@ -992,102 +800,101 @@ static void mx6q_sabreauto_reset_mipi_dsi(void) } static struct mipi_dsi_platform_data mipi_dsi_pdata = { - .ipu_id = 1, - .disp_id = 1, - .lcd_panel = "TRULY-WVGA", - .reset = mx6q_sabreauto_reset_mipi_dsi, + .ipu_id = 1, + .disp_id = 1, + .lcd_panel = "TRULY-WVGA", + .reset = mx6_arm2_reset_mipi_dsi, }; static struct ipuv3_fb_platform_data sabr_fb_data[] = { { /*fb0*/ - .disp_dev = "ldb", - .interface_pix_fmt = IPU_PIX_FMT_RGB666, - .mode_str = "LDB-XGA", - .default_bpp = 32, - .int_clk = false, + .disp_dev = "ldb", + .interface_pix_fmt = IPU_PIX_FMT_RGB666, + .mode_str = "LDB-XGA", + .default_bpp = 32, + .int_clk = false, }, { - .disp_dev = "mipi_dsi", - .interface_pix_fmt = IPU_PIX_FMT_RGB24, - .mode_str = "TRULY-WVGA", - .default_bpp = 24, - .int_clk = false, + .disp_dev = "mipi_dsi", + .interface_pix_fmt = IPU_PIX_FMT_RGB24, + .mode_str = "TRULY-WVGA", + .default_bpp = 24, + .int_clk = false, }, { - .disp_dev = "ldb", - .interface_pix_fmt = IPU_PIX_FMT_RGB666, - .mode_str = "LDB-XGA", - .default_bpp = 32, - .int_clk = false, + .disp_dev = "ldb", + .interface_pix_fmt = IPU_PIX_FMT_RGB666, + .mode_str = "LDB-XGA", + .default_bpp = 32, + .int_clk = false, }, { - .disp_dev = "lcd", - .interface_pix_fmt = IPU_PIX_FMT_RGB565, - .mode_str = "CLAA-WVGA", - .default_bpp = 16, - .int_clk = false, + .disp_dev = "lcd", + .interface_pix_fmt = IPU_PIX_FMT_RGB565, + .mode_str = "CLAA-WVGA", + .default_bpp = 16, + .int_clk = false, } }; static void hdmi_init(int ipu_id, int disp_id) { int hdmi_mux_setting; + int max_ipu_id = cpu_is_mx6q() ? 1 : 0; - if ((ipu_id > 1) || (ipu_id < 0)) { - printk(KERN_ERR"Invalid IPU select for HDMI: %d. Set to 0\n", - ipu_id); + if ((ipu_id > max_ipu_id) || (ipu_id < 0)) { + pr_err("Invalid IPU select for HDMI: %d. Set to 0\n", ipu_id); ipu_id = 0; } if ((disp_id > 1) || (disp_id < 0)) { - printk(KERN_ERR"Invalid DI select for HDMI: %d. Set to 0\n", - disp_id); + pr_err("Invalid DI select for HDMI: %d. Set to 0\n", disp_id); disp_id = 0; } /* Configure the connection between IPU1/2 and HDMI */ - hdmi_mux_setting = 2*ipu_id + disp_id; + hdmi_mux_setting = 2 * ipu_id + disp_id; /* GPR3, bits 2-3 = HDMI_MUX_CTL */ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting); } static struct fsl_mxc_hdmi_platform_data hdmi_data = { - .init = hdmi_init, + .init = hdmi_init, }; static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = { - .ipu_id = 1, - .disp_id = 0, + .ipu_id = 0, + .disp_id = 0, }; static struct fsl_mxc_lcd_platform_data lcdif_data = { - .ipu_id = 0, - .disp_id = 0, - .default_ifmt = IPU_PIX_FMT_RGB565, + .ipu_id = 0, + .disp_id = 0, + .default_ifmt = IPU_PIX_FMT_RGB565, }; static struct fsl_mxc_ldb_platform_data ldb_data = { - .ipu_id = 0, - .disp_id = 1, - .ext_ref = 1, - .mode = LDB_SEP0, - .sec_ipu_id = 1, - .sec_disp_id = 0, + .ipu_id = 0, + .disp_id = 1, + .ext_ref = 1, + .mode = LDB_SEP0, + .sec_ipu_id = 1, + .sec_disp_id = 0, }; static struct imx_ipuv3_platform_data ipu_data[] = { { - .rev = 4, - .csi_clk[0] = "ccm_clk0", + .rev = 4, + .csi_clk[0] = "ccm_clk0", }, { - .rev = 4, - .csi_clk[0] = "ccm_clk0", + .rev = 4, + .csi_clk[0] = "ccm_clk0", }, }; static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data = { - .pwm_id = 0, - .max_brightness = 255, - .dft_brightness = 128, - .pwm_period_ns = 50000, + .pwm_id = 0, + .max_brightness = 255, + .dft_brightness = 128, + .pwm_period_ns = 50000, }; static struct android_pmem_platform_data android_pmem_data = { @@ -1100,50 +907,50 @@ static struct android_pmem_platform_data android_pmem_gpu_data = { .size = SZ_32M, }; -static struct gpio mx6q_flexcan_gpios[] = { - { MX6Q_ARM2_CAN1_EN, GPIOF_OUT_INIT_LOW, "flexcan1-en" }, - { MX6Q_ARM2_CAN1_STBY, GPIOF_OUT_INIT_LOW, "flexcan1-stby" }, - { MX6Q_ARM2_CAN2_EN, GPIOF_OUT_INIT_LOW, "flexcan2-en" }, +static struct gpio mx6_flexcan_gpios[] = { + { MX6_ARM2_CAN1_EN, GPIOF_OUT_INIT_LOW, "flexcan1-en" }, + { MX6_ARM2_CAN1_STBY, GPIOF_OUT_INIT_LOW, "flexcan1-stby" }, + { MX6_ARM2_CAN2_EN, GPIOF_OUT_INIT_LOW, "flexcan2-en" }, }; -static void mx6q_flexcan0_switch(int enable) +static void mx6_flexcan0_switch(int enable) { if (enable) { - gpio_set_value(MX6Q_ARM2_CAN1_EN, 1); - gpio_set_value(MX6Q_ARM2_CAN1_STBY, 1); + gpio_set_value(MX6_ARM2_CAN1_EN, 1); + gpio_set_value(MX6_ARM2_CAN1_STBY, 1); } else { - gpio_set_value(MX6Q_ARM2_CAN1_EN, 0); - gpio_set_value(MX6Q_ARM2_CAN1_STBY, 0); + gpio_set_value(MX6_ARM2_CAN1_EN, 0); + gpio_set_value(MX6_ARM2_CAN1_STBY, 0); } } -static void mx6q_flexcan1_switch(int enable) +static void mx6_flexcan1_switch(int enable) { if (enable) { - gpio_set_value(MX6Q_ARM2_CAN2_EN, 1); - gpio_set_value_cansleep(MX6Q_ARM2_CAN2_STBY, 1); + gpio_set_value(MX6_ARM2_CAN2_EN, 1); + gpio_set_value_cansleep(MX6_ARM2_CAN2_STBY, 1); } else { - gpio_set_value(MX6Q_ARM2_CAN2_EN, 0); - gpio_set_value_cansleep(MX6Q_ARM2_CAN2_STBY, 0); + gpio_set_value(MX6_ARM2_CAN2_EN, 0); + gpio_set_value_cansleep(MX6_ARM2_CAN2_STBY, 0); } } static const struct flexcan_platform_data - mx6q_arm2_flexcan_pdata[] __initconst = { + mx6_arm2_flexcan_pdata[] __initconst = { { - .transceiver_switch = mx6q_flexcan0_switch, + .transceiver_switch = mx6_flexcan0_switch, }, { - .transceiver_switch = mx6q_flexcan1_switch, + .transceiver_switch = mx6_flexcan1_switch, } }; static struct mipi_csi2_platform_data mipi_csi2_pdata = { - .ipu_id = 0, - .csi_id = 0, - .v_channel = 0, - .lanes = 2, - .dphy_clk = "mipi_pllref_clk", - .pixel_clk = "emi_clk", + .ipu_id = 0, + .csi_id = 0, + .v_channel = 0, + .lanes = 2, + .dphy_clk = "mipi_pllref_clk", + .pixel_clk = "emi_clk", }; static void arm2_suspend_enter(void) @@ -1155,22 +962,22 @@ static void arm2_suspend_exit(void) { /* resmue resore */ } -static const struct pm_platform_data mx6q_arm2_pm_data __initconst = { - .name = "imx_pm", - .suspend_enter = arm2_suspend_enter, - .suspend_exit = arm2_suspend_exit, +static const struct pm_platform_data mx6_arm2_pm_data __initconst = { + .name = "imx_pm", + .suspend_enter = arm2_suspend_enter, + .suspend_exit = arm2_suspend_exit, }; static struct mxc_audio_platform_data sab_audio_data = { - .sysclk = 16934400, + .sysclk = 16934400, }; static struct platform_device sab_audio_device = { - .name = "imx-cs42888", + .name = "imx-cs42888", }; static struct imx_esai_platform_data sab_esai_pdata = { - .flags = IMX_ESAI_NET, + .flags = IMX_ESAI_NET, }; static struct regulator_consumer_supply arm2_vmmc_consumers[] = { @@ -1185,16 +992,16 @@ static struct regulator_init_data arm2_vmmc_init = { }; static struct fixed_voltage_config arm2_vmmc_reg_config = { - .supply_name = "vmmc", - .microvolts = 3300000, - .gpio = -1, - .init_data = &arm2_vmmc_init, + .supply_name = "vmmc", + .microvolts = 3300000, + .gpio = -1, + .init_data = &arm2_vmmc_init, }; static struct platform_device arm2_vmmc_reg_devices = { - .name = "reg-fixed-voltage", - .id = 0, - .dev = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { .platform_data = &arm2_vmmc_reg_config, }, }; @@ -1202,43 +1009,43 @@ static struct platform_device arm2_vmmc_reg_devices = { #ifdef CONFIG_SND_SOC_CS42888 static struct regulator_consumer_supply cs42888_arm2_consumer_va = { - .supply = "VA", - .dev_name = "0-0048", + .supply = "VA", + .dev_name = "0-0048", }; static struct regulator_consumer_supply cs42888_arm2_consumer_vd = { - .supply = "VD", - .dev_name = "0-0048", + .supply = "VD", + .dev_name = "0-0048", }; static struct regulator_consumer_supply cs42888_arm2_consumer_vls = { - .supply = "VLS", - .dev_name = "0-0048", + .supply = "VLS", + .dev_name = "0-0048", }; static struct regulator_consumer_supply cs42888_arm2_consumer_vlc = { - .supply = "VLC", - .dev_name = "0-0048", + .supply = "VLC", + .dev_name = "0-0048", }; static struct regulator_init_data cs42888_arm2_va_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &cs42888_arm2_consumer_va, + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_va, }; static struct regulator_init_data cs42888_arm2_vd_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &cs42888_arm2_consumer_vd, + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_vd, }; static struct regulator_init_data cs42888_arm2_vls_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &cs42888_arm2_consumer_vls, + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_vls, }; static struct regulator_init_data cs42888_arm2_vlc_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &cs42888_arm2_consumer_vlc, + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_vlc, }; static struct fixed_voltage_config cs42888_arm2_va_reg_config = { @@ -1306,33 +1113,33 @@ static struct platform_device cs42888_arm2_vlc_reg_devices = { #ifdef CONFIG_SND_SOC_SGTL5000 static struct regulator_consumer_supply sgtl5000_arm2_consumer_vdda = { - .supply = "VDDA", - .dev_name = "1-000a", + .supply = "VDDA", + .dev_name = "1-000a", }; static struct regulator_consumer_supply sgtl5000_arm2_consumer_vddio = { - .supply = "VDDIO", - .dev_name = "1-000a", + .supply = "VDDIO", + .dev_name = "1-000a", }; static struct regulator_consumer_supply sgtl5000_arm2_consumer_vddd = { - .supply = "VDDD", - .dev_name = "1-000a", + .supply = "VDDD", + .dev_name = "1-000a", }; static struct regulator_init_data sgtl5000_arm2_vdda_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &sgtl5000_arm2_consumer_vdda, + .num_consumer_supplies = 1, + .consumer_supplies = &sgtl5000_arm2_consumer_vdda, }; static struct regulator_init_data sgtl5000_arm2_vddio_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &sgtl5000_arm2_consumer_vddio, + .num_consumer_supplies = 1, + .consumer_supplies = &sgtl5000_arm2_consumer_vddio, }; static struct regulator_init_data sgtl5000_arm2_vddd_reg_initdata = { - .num_consumer_supplies = 1, - .consumer_supplies = &sgtl5000_arm2_consumer_vddd, + .num_consumer_supplies = 1, + .consumer_supplies = &sgtl5000_arm2_consumer_vddd, }; static struct fixed_voltage_config sgtl5000_arm2_vdda_reg_config = { @@ -1408,7 +1215,7 @@ static struct platform_device mx6_arm2_audio_device = { .name = "imx-sgtl5000", }; -static int __init imx6q_init_audio(void) +static int __init mx6_arm2_init_audio(void) { struct clk *pll3_pfd, *esai_clk; mxc_register_device(&sab_audio_device, &sab_audio_data); @@ -1426,10 +1233,10 @@ static int __init imx6q_init_audio(void) clk_set_rate(esai_clk, 101647058); #ifdef CONFIG_SND_SOC_CS42888 - platform_device_register(&cs42888_arm2_va_reg_devices); - platform_device_register(&cs42888_arm2_vd_reg_devices); - platform_device_register(&cs42888_arm2_vls_reg_devices); - platform_device_register(&cs42888_arm2_vlc_reg_devices); + platform_device_register(&cs42888_arm2_va_reg_devices); + platform_device_register(&cs42888_arm2_vd_reg_devices); + platform_device_register(&cs42888_arm2_vls_reg_devices); + platform_device_register(&cs42888_arm2_vlc_reg_devices); #endif if (sgtl5000_en) { @@ -1438,8 +1245,17 @@ static int __init imx6q_init_audio(void) &mx6_arm2_audio_data); imx6q_add_imx_ssi(1, &mx6_arm2_ssi_pdata); - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_audmux_pads, - ARRAY_SIZE(mx6q_arm2_audmux_pads)); + /* + * AUDMUX3 and CSI0_Camera use the same pin + * MX6x_PAD_CSI0_DAT5 + */ + if (cpu_is_mx6q()) { + mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_audmux_pads, + ARRAY_SIZE(mx6q_arm2_audmux_pads)); + } else if (cpu_is_mx6dl()) { + mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_audmux_pads, + ARRAY_SIZE(mx6dl_arm2_audmux_pads)); + } #ifdef CONFIG_SND_SOC_SGTL5000 platform_device_register(&sgtl5000_arm2_vdda_reg_devices); @@ -1459,36 +1275,36 @@ static int __init early_use_esai_record(char *p) early_param("esai_record", early_use_esai_record); -static struct mxc_mlb_platform_data mx6q_arm2_mlb150_data = { - .reg_nvcc = NULL, - .mlb_clk = "mlb150_clk", - .mlb_pll_clk = "pll6", +static struct mxc_mlb_platform_data mx6_arm2_mlb150_data = { + .reg_nvcc = NULL, + .mlb_clk = "mlb150_clk", + .mlb_pll_clk = "pll6", }; static struct mxc_dvfs_platform_data arm2_dvfscore_data = { - .reg_id = "cpu_vddgp", - .clk1_id = "cpu_clk", - .clk2_id = "gpc_dvfs_clk", - .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, - .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET, - .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET, - .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET, - .prediv_mask = 0x1F800, - .prediv_offset = 11, - .prediv_val = 3, - .div3ck_mask = 0xE0000000, - .div3ck_offset = 29, - .div3ck_val = 2, - .emac_val = 0x08, - .upthr_val = 25, - .dnthr_val = 9, - .pncthr_val = 33, - .upcnt_val = 10, - .dncnt_val = 10, - .delay_time = 80, -}; - -static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + .reg_id = "cpu_vddgp", + .clk1_id = "cpu_clk", + .clk2_id = "gpc_dvfs_clk", + .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, + .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET, + .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET, + .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET, + .prediv_mask = 0x1F800, + .prediv_offset = 11, + .prediv_val = 3, + .div3ck_mask = 0xE0000000, + .div3ck_offset = 29, + .div3ck_val = 2, + .emac_val = 0x08, + .upthr_val = 25, + .dnthr_val = 9, + .pncthr_val = 33, + .upcnt_val = 10, + .dncnt_val = 10, + .delay_time = 80, +}; + +static void __init mx6_arm2_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) { char *str; @@ -1545,8 +1361,8 @@ static int spdif_clk_set_rate(struct clk *clk, unsigned long rate) } static struct mxc_spdif_platform_data mxc_spdif_data = { - .spdif_tx = 1, /* enable tx */ - .spdif_rx = 1, /* enable rx */ + .spdif_tx = 1, /* enable tx */ + .spdif_rx = 1, /* enable rx */ /* * spdif0_clk will be 454.7MHz divided by ccm dividers. * @@ -1554,58 +1370,133 @@ static struct mxc_spdif_platform_data mxc_spdif_data = { * 48KHz: 454.7MHz / 4 (ccm) / 37 (spdif) = 48,004 Hz ~ 0.01% error * 32KHz: 454.7MHz / 6 (ccm) / 37 (spdif) = 32,003 Hz ~ 0.01% error */ - .spdif_clk_44100 = 1, /* tx clk from spdif0_clk_root */ - .spdif_clk_48000 = 1, /* tx clk from spdif0_clk_root */ - .spdif_div_44100 = 23, - .spdif_div_48000 = 37, - .spdif_div_32000 = 37, - .spdif_rx_clk = 0, /* rx clk from spdif stream */ - .spdif_clk_set_rate = spdif_clk_set_rate, - .spdif_clk = NULL, /* spdif bus clk */ + .spdif_clk_44100 = 1, /* tx clk from spdif0_clk_root */ + .spdif_clk_48000 = 1, /* tx clk from spdif0_clk_root */ + .spdif_div_44100 = 23, + .spdif_div_48000 = 37, + .spdif_div_32000 = 37, + .spdif_rx_clk = 0, /* rx clk from spdif stream */ + .spdif_clk_set_rate = spdif_clk_set_rate, + .spdif_clk = NULL, /* spdif bus clk */ }; /*! * Board specific initialization. */ -static void __init mx6_board_init(void) +static void __init mx6_arm2_init(void) { int i; int ret; - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_pads, - ARRAY_SIZE(mx6q_arm2_pads)); + iomux_v3_cfg_t *common_pads = NULL; + iomux_v3_cfg_t *esai_rec_pads = NULL; + iomux_v3_cfg_t *spdif_pads = NULL; + iomux_v3_cfg_t *flexcan_pads = NULL; + iomux_v3_cfg_t *i2c3_pads = NULL; + + int common_pads_cnt; + int esai_rec_pads_cnt; + int spdif_pads_cnt; + int flexcan_pads_cnt; + int i2c3_pads_cnt; - if (esai_record) - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_esai_record_pads, - ARRAY_SIZE(mx6q_arm2_esai_record_pads)); /* - * S/PDIF in and i2c3 are mutually exclusive because both - * use GPIO_16. + * common pads: pads are non-shared with others on this board + * feature_pds: pads are shared with others on this board + */ + + if (cpu_is_mx6q()) { + common_pads = mx6q_arm2_pads; + esai_rec_pads = mx6q_arm2_esai_record_pads; + spdif_pads = mx6q_arm2_spdif_pads; + flexcan_pads = mx6q_arm2_can_pads; + i2c3_pads = mx6q_arm2_i2c3_pads; + + common_pads_cnt = ARRAY_SIZE(mx6q_arm2_pads); + esai_rec_pads_cnt = ARRAY_SIZE(mx6q_arm2_esai_record_pads); + spdif_pads_cnt = ARRAY_SIZE(mx6q_arm2_spdif_pads); + flexcan_pads_cnt = ARRAY_SIZE(mx6q_arm2_can_pads); + i2c3_pads_cnt = ARRAY_SIZE(mx6q_arm2_i2c3_pads); + } else if (cpu_is_mx6dl()) { + common_pads = mx6dl_arm2_pads; + esai_rec_pads = mx6dl_arm2_esai_record_pads; + spdif_pads = mx6dl_arm2_spdif_pads; + flexcan_pads = mx6dl_arm2_can_pads; + i2c3_pads = mx6dl_arm2_i2c3_pads; + + common_pads_cnt = ARRAY_SIZE(mx6dl_arm2_pads); + esai_rec_pads_cnt = ARRAY_SIZE(mx6dl_arm2_esai_record_pads); + spdif_pads_cnt = ARRAY_SIZE(mx6dl_arm2_spdif_pads); + flexcan_pads_cnt = ARRAY_SIZE(mx6dl_arm2_can_pads); + i2c3_pads_cnt = ARRAY_SIZE(mx6dl_arm2_i2c3_pads); + } + + BUG_ON(!common_pads); + mxc_iomux_v3_setup_multiple_pads(common_pads, common_pads_cnt); + + if (esai_record) { + BUG_ON(!esai_rec_pads); + mxc_iomux_v3_setup_multiple_pads(esai_rec_pads, + esai_rec_pads_cnt); + } + + /* + * IEEE-1588 ts_clk, S/PDIF in and i2c3 are mutually exclusive + * because all of them use GPIO_16. * S/PDIF out and can1 stby are mutually exclusive because both * use GPIO_17. */ +#ifndef CONFIG_FEC_1588 if (spdif_en) { - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_spdif_pads, - ARRAY_SIZE(mx6q_arm2_spdif_pads)); + BUG_ON(!spdif_pads); + mxc_iomux_v3_setup_multiple_pads(spdif_pads, spdif_pads_cnt); } else { - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_i2c3_pads, - ARRAY_SIZE(mx6q_arm2_i2c3_pads)); - if (flexcan_en) - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_can_pads, - ARRAY_SIZE(mx6q_arm2_can_pads)); + BUG_ON(!i2c3_pads); + mxc_iomux_v3_setup_multiple_pads(i2c3_pads, i2c3_pads_cnt); } +#else + /* Set GPIO_16 input for IEEE-1588 ts_clk and RMII reference clock + * For MX6 GPR1 bit21 meaning: + * Bit21: 0 - GPIO_16 pad output + * 1 - GPIO_16 pad input + */ + mxc_iomux_set_gpr_register(1, 21, 1, 1); +#endif + + if (!spdif_en && flexcan_en) { + BUG_ON(!flexcan_pads); + mxc_iomux_v3_setup_multiple_pads(flexcan_pads, + flexcan_pads_cnt); + } + + /* + * the following is the common devices support on the shared ARM2 boards + * Since i.MX6DQ/DL share the same memory/Register layout, we don't + * need to diff the i.MX6DQ or i.MX6DL here. We can simply use the + * mx6q_add_features() for the shared devices. For which only exist + * on each indivual SOC, we can use cpu_is_mx6q/6dl() to diff it. + */ gp_reg_id = arm2_dvfscore_data.reg_id; - mx6q_arm2_init_uart(); + mx6_arm2_init_uart(); imx6q_add_mipi_csi2(&mipi_csi2_pdata); imx6q_add_mxc_hdmi_core(&hdmi_core_data); imx6q_add_ipuv3(0, &ipu_data[0]); - imx6q_add_ipuv3(1, &ipu_data[1]); - - for (i = 0; i < ARRAY_SIZE(sabr_fb_data); i++) - imx6q_add_ipuv3fb(i, &sabr_fb_data[i]); + if (cpu_is_mx6q()) + imx6q_add_ipuv3(1, &ipu_data[1]); + + if (cpu_is_mx6dl()) { + mipi_dsi_pdata.ipu_id = 0; + mipi_dsi_pdata.disp_id = 1; + ldb_data.ipu_id = 0; + ldb_data.disp_id = 0; + for (i = 0; i < ARRAY_SIZE(sabr_fb_data) / 2; i++) + imx6q_add_ipuv3fb(i, &sabr_fb_data[i]); + } else + for (i = 0; i < ARRAY_SIZE(sabr_fb_data); i++) + imx6q_add_ipuv3fb(i, &sabr_fb_data[i]); imx6q_add_mipi_dsi(&mipi_dsi_pdata); imx6q_add_lcdif(&lcdif_data); @@ -1615,37 +1506,38 @@ static void __init mx6_board_init(void) imx6q_add_imx_snvs_rtc(); - imx6q_add_imx_i2c(0, &mx6q_arm2_i2c0_data); - imx6q_add_imx_i2c(1, &mx6q_arm2_i2c1_data); + imx6q_add_imx_i2c(0, &mx6_arm2_i2c0_data); + imx6q_add_imx_i2c(1, &mx6_arm2_i2c1_data); i2c_register_board_info(0, mxc_i2c0_board_info, ARRAY_SIZE(mxc_i2c0_board_info)); i2c_register_board_info(1, mxc_i2c1_board_info, ARRAY_SIZE(mxc_i2c1_board_info)); if (!spdif_en) { - imx6q_add_imx_i2c(2, &mx6q_arm2_i2c2_data); + imx6q_add_imx_i2c(2, &mx6_arm2_i2c2_data); i2c_register_board_info(2, mxc_i2c2_board_info, ARRAY_SIZE(mxc_i2c2_board_info)); } /* SPI */ - imx6q_add_ecspi(0, &mx6q_arm2_spi_data); + imx6q_add_ecspi(0, &mx6_arm2_spi_data); spi_device_init(); imx6q_add_mxc_hdmi(&hdmi_data); - imx6q_add_anatop_thermal_imx(1, &mx6q_arm2_anatop_thermal_data); + imx6q_add_anatop_thermal_imx(1, &mx6_arm2_anatop_thermal_data); if (!esai_record) imx6_init_fec(fec_data); - imx6q_add_pm_imx(0, &mx6q_arm2_pm_data); - imx6q_add_sdhci_usdhc_imx(3, &mx6q_arm2_sd4_data); - imx6q_add_sdhci_usdhc_imx(2, &mx6q_arm2_sd3_data); - imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata); - imx6q_arm2_init_usb(); - imx6q_add_ahci(0, &mx6q_arm2_sata_data); + imx6q_add_pm_imx(0, &mx6_arm2_pm_data); + imx6q_add_sdhci_usdhc_imx(3, &mx6_arm2_sd4_data); + imx6q_add_sdhci_usdhc_imx(2, &mx6_arm2_sd3_data); + imx_add_viv_gpu(&imx6_gpu_data, &imx6_gpu_pdata); + if (cpu_is_mx6q()) + imx6q_add_ahci(0, &mx6_arm2_sata_data); imx6q_add_vpu(); - imx6q_init_audio(); + mx6_arm2_init_usb(); + mx6_arm2_init_audio(); platform_device_register(&arm2_vmmc_reg_devices); mx6_cpu_regulator_init(); @@ -1654,23 +1546,23 @@ static void __init mx6_board_init(void) imx6q_add_asrc(&imx_asrc_data); /* DISP0 Reset - Assert for i2c disabled mode */ - gpio_request(MX6Q_ARM2_DISP0_RESET, "disp0-reset"); - gpio_direction_output(MX6Q_ARM2_DISP0_RESET, 0); + gpio_request(MX6_ARM2_DISP0_RESET, "disp0-reset"); + gpio_direction_output(MX6_ARM2_DISP0_RESET, 0); /* DISP0 I2C enable */ - gpio_request(MX6Q_ARM2_DISP0_I2C_EN, "disp0-i2c"); - gpio_direction_output(MX6Q_ARM2_DISP0_I2C_EN, 0); + gpio_request(MX6_ARM2_DISP0_I2C_EN, "disp0-i2c"); + gpio_direction_output(MX6_ARM2_DISP0_I2C_EN, 0); - gpio_request(MX6Q_ARM2_DISP0_PWR, "disp0-pwr"); - gpio_direction_output(MX6Q_ARM2_DISP0_PWR, 1); + gpio_request(MX6_ARM2_DISP0_PWR, "disp0-pwr"); + gpio_direction_output(MX6_ARM2_DISP0_PWR, 1); - gpio_request(MX6Q_ARM2_LDB_BACKLIGHT, "ldb-backlight"); - gpio_direction_output(MX6Q_ARM2_LDB_BACKLIGHT, 1); + gpio_request(MX6_ARM2_LDB_BACKLIGHT, "ldb-backlight"); + gpio_direction_output(MX6_ARM2_LDB_BACKLIGHT, 1); imx6q_add_otp(); imx6q_add_viim(); imx6q_add_imx2_wdt(0, NULL); imx6q_add_dma(); - imx6q_add_gpmi(&mx6q_gpmi_nfc_platform_data); + imx6q_add_gpmi(&mx6_gpmi_nand_platform_data); imx6q_add_dvfs_core(&arm2_dvfscore_data); @@ -1688,13 +1580,13 @@ static void __init mx6_board_init(void) imx6q_add_spdif_dai(); imx6q_add_spdif_audio_device(); } else if (flexcan_en) { - ret = gpio_request_array(mx6q_flexcan_gpios, - ARRAY_SIZE(mx6q_flexcan_gpios)); + ret = gpio_request_array(mx6_flexcan_gpios, + ARRAY_SIZE(mx6_flexcan_gpios)); if (ret) { pr_err("failed to request flexcan-gpios: %d\n", ret); } else { - imx6q_add_flexcan0(&mx6q_arm2_flexcan_pdata[0]); - imx6q_add_flexcan1(&mx6q_arm2_flexcan_pdata[1]); + imx6q_add_flexcan0(&mx6_arm2_flexcan_pdata[0]); + imx6q_add_flexcan1(&mx6_arm2_flexcan_pdata[1]); } } @@ -1703,7 +1595,12 @@ static void __init mx6_board_init(void) imx6q_add_perfmon(0); imx6q_add_perfmon(1); imx6q_add_perfmon(2); - imx6q_add_mlb150(&mx6q_arm2_mlb150_data); + imx6q_add_mlb150(&mx6_arm2_mlb150_data); + + if (cpu_is_mx6dl()) { + imx6dl_add_imx_pxp(); + imx6dl_add_imx_pxp_client(); + } } extern void __iomem *twd_base; @@ -1724,16 +1621,16 @@ static struct sys_timer mxc_timer = { .init = mx6_timer_init, }; -static void __init mx6q_reserve(void) +static void __init mx6_arm2_reserve(void) { phys_addr_t phys; - if (imx6q_gpu_pdata.reserved_mem_size) { - phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size, - SZ_4K, SZ_2G); - memblock_free(phys, imx6q_gpu_pdata.reserved_mem_size); - memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size); - imx6q_gpu_pdata.reserved_mem_base = phys; + if (imx6_gpu_pdata.reserved_mem_size) { + phys = memblock_alloc_base( + imx6_gpu_pdata.reserved_mem_size, SZ_4K, SZ_2G); + memblock_free(phys, imx6_gpu_pdata.reserved_mem_size); + memblock_remove(phys, imx6_gpu_pdata.reserved_mem_size); + imx6_gpu_pdata.reserved_mem_base = phys; } if (android_pmem_data.size) { @@ -1751,16 +1648,12 @@ static void __init mx6q_reserve(void) } } -/* - * initialize __mach_desc_MX6Q_ARM2 data structure. - */ -MACHINE_START(MX6Q_ARM2, "Freescale i.MX 6Quad Armadillo2 Board") - /* Maintainer: Freescale Semiconductor, Inc. */ - .boot_params = MX6_PHYS_OFFSET + 0x100, - .fixup = fixup_mxc_board, - .map_io = mx6_map_io, - .init_irq = mx6_init_irq, - .init_machine = mx6_board_init, - .timer = &mxc_timer, - .reserve = mx6q_reserve, +MACHINE_START(MX6Q_ARM2, "Freescale i.MX 6Quad/Solo/DualLite Armadillo2 Board") + .boot_params = MX6_PHYS_OFFSET + 0x100, + .fixup = mx6_arm2_fixup, + .map_io = mx6_map_io, + .init_irq = mx6_init_irq, + .init_machine = mx6_arm2_init, + .timer = &mxc_timer, + .reserve = mx6_arm2_reserve, MACHINE_END diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.h b/arch/arm/mach-mx6/board-mx6q_arm2.h new file mode 100644 index 000000000000..8c3277d869e1 --- /dev/null +++ b/arch/arm/mach-mx6/board-mx6q_arm2.h @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <mach/iomux-mx6q.h> + +static iomux_v3_cfg_t mx6q_arm2_pads[] = { + + /* UART4 for debug */ + MX6Q_PAD_KEY_COL0__UART4_TXD, + MX6Q_PAD_KEY_ROW0__UART4_RXD, + /* USB HSIC ports use the same pin with ENET */ +#ifdef CONFIG_USB_EHCI_ARC_HSIC + /* USB H2 strobe/data pin */ + MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE, + MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA, + + /* USB H3 strobe/data pin */ + MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE, + MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA, + /* ENET */ +#else + MX6Q_PAD_KEY_COL1__ENET_MDIO, + MX6Q_PAD_KEY_COL2__ENET_MDC, + MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC, + MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0, + MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1, + MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2, + MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3, + MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, + MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, + MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC, + MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0, + MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1, + MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2, + MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3, + MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, +#ifdef CONFIG_FEC_1588 + MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT, +#endif +#endif + /* MCLK for csi0 */ + MX6Q_PAD_GPIO_0__CCM_CLKO, + MX6Q_PAD_GPIO_3__CCM_CLKO2, + + /* SD1 */ + MX6Q_PAD_SD1_CLK__USDHC1_CLK, + MX6Q_PAD_SD1_CMD__USDHC1_CMD, + MX6Q_PAD_SD1_DAT0__USDHC1_DAT0, + MX6Q_PAD_SD1_DAT1__USDHC1_DAT1, + MX6Q_PAD_SD1_DAT2__USDHC1_DAT2, + MX6Q_PAD_SD1_DAT3__USDHC1_DAT3, + /* SD2 */ + MX6Q_PAD_SD2_CLK__USDHC2_CLK, + MX6Q_PAD_SD2_CMD__USDHC2_CMD, + MX6Q_PAD_SD2_DAT0__USDHC2_DAT0, + MX6Q_PAD_SD2_DAT1__USDHC2_DAT1, + MX6Q_PAD_SD2_DAT2__USDHC2_DAT2, + MX6Q_PAD_SD2_DAT3__USDHC2_DAT3, + /* SD3 */ + MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ, + MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ, + MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ, + MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ, + MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ, + MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ, + MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ, + MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ, + MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ, + MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ, + MX6Q_PAD_SD3_RST__USDHC3_RST, + /* SD3 VSelect */ + MX6Q_PAD_GPIO_18__USDHC3_VSELECT, + /* SD3_CD and SD3_WP */ + MX6Q_PAD_NANDF_CS0__GPIO_6_11, + MX6Q_PAD_NANDF_CS1__GPIO_6_14, + /* SD4 */ + MX6Q_PAD_SD4_CLK__USDHC4_CLK_50MHZ, + MX6Q_PAD_SD4_CMD__USDHC4_CMD_50MHZ, + MX6Q_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ, + MX6Q_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ, + MX6Q_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ, + MX6Q_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ, + MX6Q_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ, + MX6Q_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ, + MX6Q_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ, + MX6Q_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ, + MX6Q_PAD_NANDF_ALE__USDHC4_RST, + /* eCSPI1 */ + MX6Q_PAD_EIM_EB2__ECSPI1_SS0, + MX6Q_PAD_EIM_D16__ECSPI1_SCLK, + MX6Q_PAD_EIM_D17__ECSPI1_MISO, + MX6Q_PAD_EIM_D18__ECSPI1_MOSI, + MX6Q_PAD_EIM_D19__ECSPI1_SS1, + MX6Q_PAD_EIM_EB2__GPIO_2_30, /*SS0*/ + MX6Q_PAD_EIM_D19__GPIO_3_19, /*SS1*/ + + /* ESAI */ + MX6Q_PAD_ENET_RXD0__ESAI1_HCKT, + MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT, + MX6Q_PAD_ENET_RXD1__ESAI1_FST, + MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2, + MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3, + MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1, + MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0, + MX6Q_PAD_NANDF_CS2__ESAI1_TX0, + MX6Q_PAD_NANDF_CS3__ESAI1_TX1, + + /* I2C1 */ + MX6Q_PAD_CSI0_DAT8__I2C1_SDA, + MX6Q_PAD_CSI0_DAT9__I2C1_SCL, + + /* I2C2 */ + MX6Q_PAD_KEY_COL3__I2C2_SCL, + MX6Q_PAD_KEY_ROW3__I2C2_SDA, + + /* DISPLAY */ + MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, + MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, + MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2, + MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3, + MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0, + MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1, + MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2, + MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3, + MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4, + MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5, + MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6, + MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7, + MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8, + MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9, + MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10, + MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11, + MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12, + MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13, + MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14, + MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15, + MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16, + MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17, + MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18, + MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19, + MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20, + MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21, + MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, + MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, + + MX6Q_PAD_EIM_D24__GPIO_3_24, + + /* UART2 */ + MX6Q_PAD_EIM_D26__UART2_RXD, + MX6Q_PAD_EIM_D27__UART2_TXD, + MX6Q_PAD_EIM_D28__UART2_RTS, + MX6Q_PAD_EIM_D29__UART2_CTS, + + /* PWM1 */ + MX6Q_PAD_GPIO_9__PWM1_PWMO, + + /* DISP0 DET */ + MX6Q_PAD_EIM_D31__GPIO_3_31, + + /* DISP0 RESET */ + MX6Q_PAD_EIM_WAIT__GPIO_5_0, + + /* HDMI */ + MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE, + MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0, + MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1, + + /* USBOTG ID pin */ + MX6Q_PAD_GPIO_1__USBOTG_ID, + + /* MLB150 */ + MX6Q_PAD_GPIO_3__MLB_MLBCLK, + MX6Q_PAD_GPIO_6__MLB_MLBSIG, + MX6Q_PAD_GPIO_2__MLB_MLBDAT, +}; + +static iomux_v3_cfg_t mx6q_arm2_i2c3_pads[] = { + MX6Q_PAD_GPIO_5__I2C3_SCL, + MX6Q_PAD_GPIO_16__I2C3_SDA, +}; + +static iomux_v3_cfg_t mx6q_arm2_spdif_pads[] = { + /* SPDIF */ + MX6Q_PAD_GPIO_16__SPDIF_IN1, + MX6Q_PAD_GPIO_17__SPDIF_OUT1, +}; + +static iomux_v3_cfg_t mx6q_arm2_can_pads[] = { + /* CAN1 */ + MX6Q_PAD_GPIO_7__CAN1_TXCAN, + MX6Q_PAD_KEY_ROW2__CAN1_RXCAN, + MX6Q_PAD_GPIO_17__GPIO_7_12, /* CAN1 STBY */ + MX6Q_PAD_GPIO_18__GPIO_7_13, /* CAN1 EN */ + + /* CAN2 */ + MX6Q_PAD_KEY_COL4__CAN2_TXCAN, + MX6Q_PAD_KEY_ROW4__CAN2_RXCAN, + MX6Q_PAD_CSI0_DAT6__GPIO_5_24, /* CAN2 EN */ +}; + +static iomux_v3_cfg_t mx6q_arm2_esai_record_pads[] = { + MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR, + MX6Q_PAD_ENET_MDIO__ESAI1_SCKR, + MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR, +}; + +static iomux_v3_cfg_t mx6q_arm2_csi0_sensor_pads[] = { + MX6Q_PAD_GPIO_0__CCM_CLKO, + /* ipu1 csi0 */ + MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, + MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, + MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, + MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, + MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, + MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, + MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, + MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, + MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, + MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, + MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, + /* camera reset */ + MX6Q_PAD_GPIO_19__GPIO_4_5, + /* camera powerdown */ + MX6Q_PAD_CSI0_DAT5__GPIO_5_23, +}; + +static iomux_v3_cfg_t mx6q_arm2_csi0_tvin_pads[] = { + /* ipu1 csi0 */ + MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, + MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, + MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, + MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, + MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, + MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, + MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, + MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, + MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, + MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, + MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, + /* camera reset */ + MX6Q_PAD_CSI0_DAT7__GPIO_5_25, + /* camera powerdown */ + MX6Q_PAD_CSI0_DAT5__GPIO_5_23, +}; + +static iomux_v3_cfg_t mx6q_arm2_mipi_sensor_pads[] = { + MX6Q_PAD_CSI0_MCLK__CCM_CLKO, +}; + +static iomux_v3_cfg_t mx6q_arm2_audmux_pads[] = { + + /* AUDMUX */ + MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, + MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD, + MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS, + MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD, +}; + +#define MX6Q_USDHC_PAD_SETTING(id, speed) \ +mx6q_sd##id##_##speed##mhz[] = { \ + MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \ + MX6Q_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \ +} + +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 50); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 100); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 200); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 50); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 100); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 200); + + +/* The GPMI is conflicted with SD3, so init this in the driver. */ +static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = { + MX6Q_PAD_NANDF_CLE__RAWNAND_CLE, + MX6Q_PAD_NANDF_ALE__RAWNAND_ALE, + MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N, + MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N, + MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N, + MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N, + MX6Q_PAD_NANDF_RB0__RAWNAND_READY0, + MX6Q_PAD_SD4_DAT0__RAWNAND_DQS, + MX6Q_PAD_NANDF_D0__RAWNAND_D0, + MX6Q_PAD_NANDF_D1__RAWNAND_D1, + MX6Q_PAD_NANDF_D2__RAWNAND_D2, + MX6Q_PAD_NANDF_D3__RAWNAND_D3, + MX6Q_PAD_NANDF_D4__RAWNAND_D4, + MX6Q_PAD_NANDF_D5__RAWNAND_D5, + MX6Q_PAD_NANDF_D6__RAWNAND_D6, + MX6Q_PAD_NANDF_D7__RAWNAND_D7, + MX6Q_PAD_SD4_CMD__RAWNAND_RDN, + MX6Q_PAD_SD4_CLK__RAWNAND_WRN, + MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN, +}; diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c index 5938b9a7ddf3..8b582d566539 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c @@ -498,15 +498,15 @@ static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = { MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN, }; -static int gpmi_nfc_platform_init(void) +static int gpmi_nand_platform_init(void) { return mxc_iomux_v3_setup_multiple_pads(mx6q_gpmi_nand, ARRAY_SIZE(mx6q_gpmi_nand)); } -static const struct gpmi_nfc_platform_data -mx6q_gpmi_nfc_platform_data __initconst = { - .platform_init = gpmi_nfc_platform_init, +static const struct gpmi_nand_platform_data +mx6q_gpmi_nand_platform_data __initconst = { + .platform_init = gpmi_nand_platform_init, .min_prop_delay_in_ns = 5, .max_prop_delay_in_ns = 9, .max_chip_count = 1, @@ -1349,31 +1349,10 @@ static inline void __init mx6q_csi0_io_init(void) mxc_iomux_set_gpr_register(1, 19, 1, 1); } -static int spdif_clk_set_rate(struct clk *clk, unsigned long rate) -{ - unsigned long rate_actual; - rate_actual = clk_round_rate(clk, rate); - clk_set_rate(clk, rate_actual); - return 0; -} - static struct mxc_spdif_platform_data mxc_spdif_data = { .spdif_tx = 0, /* disable tx */ .spdif_rx = 1, /* enable rx */ - /* - * spdif0_clk will be 454.7MHz divided by ccm dividers. - * - * 44.1KHz: 454.7MHz / 7 (ccm) / 23 (spdif) = 44,128 Hz ~ 0.06% error - * 48KHz: 454.7MHz / 4 (ccm) / 37 (spdif) = 48,004 Hz ~ 0.01% error - * 32KHz: 454.7MHz / 6 (ccm) / 37 (spdif) = 32,003 Hz ~ 0.01% error - */ - .spdif_clk_44100 = 1, /* tx clk from spdif0_clk_root */ - .spdif_clk_48000 = 1, /* tx clk from spdif0_clk_root */ - .spdif_div_44100 = 23, - .spdif_div_48000 = 37, - .spdif_div_32000 = 37, .spdif_rx_clk = 0, /* rx clk from spdif stream */ - .spdif_clk_set_rate = spdif_clk_set_rate, .spdif_clk = NULL, /* spdif bus clk */ }; @@ -1498,7 +1477,7 @@ static void __init mx6_board_init(void) imx6q_add_viim(); imx6q_add_imx2_wdt(0, NULL); imx6q_add_dma(); - imx6q_add_gpmi(&mx6q_gpmi_nfc_platform_data); + imx6q_add_gpmi(&mx6q_gpmi_nand_platform_data); imx6q_add_dvfs_core(&sabreauto_dvfscore_data); diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index 877609ebad63..66e93e414bc8 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -101,6 +101,7 @@ #define MX6Q_SABRESD_eCOMPASS_INT IMX_GPIO_NR(3, 16) #define MX6Q_SABRESD_ALS_INT IMX_GPIO_NR(3, 9) #define MX6Q_SABRESD_MPCIE_3V3_EN IMX_GPIO_NR(1, 6) + #define MX6Q_SABRESD_CHARGE_FLT_1_B IMX_GPIO_NR(5, 2) #define MX6Q_SABRESD_CHARGE_CHG_1_B IMX_GPIO_NR(3, 23) #define MX6Q_SABRESD_CHARGE_FLT_2_B IMX_GPIO_NR(3, 14) @@ -1249,6 +1250,7 @@ static void __init mx6_sabresd_board_init(void) mxc_register_device(&mxc_android_pmem_gpu_device, &android_pmem_gpu_data); imx6q_add_device_buttons(); + /* enable sensor 3v3 and 1v8 */ gpio_request(MX6Q_SABRESD_SENSOR_EN, "sensor-en"); gpio_direction_output(MX6Q_SABRESD_SENSOR_EN, 1); diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 403664a62168..578118103299 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -344,9 +344,6 @@ static int pfd_set_rate(struct clk *clk, unsigned long rate) __raw_writel(frac << clk->enable_shift, (int)clk->enable_reg + 4); - tmp = (u64)clk_get_rate(clk->parent) * 18; - do_div(tmp, frac); - if (apbh_dma_clk.usecount == 0) apbh_dma_clk.disable(&apbh_dma_clk); return 0; @@ -1746,7 +1743,6 @@ static struct clk vdoa_clk = { static unsigned long _clk_gpt_get_rate(struct clk *clk) { - u32 reg; unsigned long rate; if (mx6q_revision() == IMX_CHIP_REVISION_1_0) @@ -3489,7 +3485,7 @@ static int _clk_enet_enable(struct clk *clk) /* Enable ENET ref clock */ reg = __raw_readl(PLL8_ENET_BASE_ADDR); reg &= ~ANADIG_PLL_BYPASS; - reg &= ~ANADIG_PLL_ENABLE; + reg |= ANADIG_PLL_ENABLE; __raw_writel(reg, PLL8_ENET_BASE_ADDR); _clk_enable(clk); @@ -3505,7 +3501,7 @@ static void _clk_enet_disable(struct clk *clk) /* Enable ENET ref clock */ reg = __raw_readl(PLL8_ENET_BASE_ADDR); reg |= ANADIG_PLL_BYPASS; - reg |= ANADIG_PLL_ENABLE; + reg &= ~ANADIG_PLL_ENABLE; __raw_writel(reg, PLL8_ENET_BASE_ADDR); } @@ -4338,10 +4334,13 @@ static int _clk_gpu2d_core_set_parent(struct clk *clk, struct clk *parent) u32 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK; - mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk, - &pll2_pfd_352M, &pll2_pfd_400M, NULL, NULL); - reg |= (mux << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET); - __raw_writel(reg, MXC_CCM_CBCMR); + /*on mx6dl, 2d core clock sources from 3d shader core clock*/ + if (!cpu_is_mx6dl()) { + mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk, + &pll2_pfd_352M, &pll2_pfd_400M, NULL, NULL); + reg |= (mux << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + } return 0; } @@ -4478,11 +4477,11 @@ static struct clk gpu3d_shader_clk = { }; /* set the parent by the ipcg table */ -static struct clk gpmi_nfc_clk[] = { +static struct clk gpmi_nand_clk[] = { { /* gpmi_io_clk */ __INIT_CLK_DEBUG(gpmi_io_clk) .parent = &enfc_clk, - .secondary = &gpmi_nfc_clk[1], + .secondary = &gpmi_nand_clk[1], .enable = _clk_enable, .enable_reg = MXC_CCM_CCGR4, .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, @@ -4491,7 +4490,7 @@ static struct clk gpmi_nfc_clk[] = { { /* gpmi_apb_clk */ __INIT_CLK_DEBUG(gpmi_apb_clk) .parent = &usdhc3_clk, - .secondary = &gpmi_nfc_clk[2], + .secondary = &gpmi_nand_clk[2], .enable = _clk_enable, .enable_reg = MXC_CCM_CCGR4, .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET, @@ -4500,7 +4499,7 @@ static struct clk gpmi_nfc_clk[] = { { /* bch_clk */ __INIT_CLK_DEBUG(gpmi_bch_clk) .parent = &usdhc4_clk, - .secondary = &gpmi_nfc_clk[3], + .secondary = &gpmi_nand_clk[3], .enable = _clk_enable, .enable_reg = MXC_CCM_CCGR4, .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, @@ -4509,7 +4508,7 @@ static struct clk gpmi_nfc_clk[] = { { /* bch_apb_clk */ __INIT_CLK_DEBUG(gpmi_bch_apb_clk) .parent = &usdhc3_clk, - .secondary = &gpmi_nfc_clk[4], + .secondary = &gpmi_nand_clk[4], .enable = _clk_enable, .enable_reg = MXC_CCM_CCGR4, .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, @@ -4565,7 +4564,48 @@ static int _clk_pcie_enable(struct clk *clk) { unsigned int reg; - /* Enable SATA ref clock */ + /* Clear Power Down and Enable PLLs */ + reg = __raw_readl(PLL8_ENET_BASE_ADDR); + reg &= ~ANADIG_PLL_ENET_POWER_DOWN; + __raw_writel(reg, PLL8_ENET_BASE_ADDR); + + reg = __raw_readl(PLL8_ENET_BASE_ADDR); + reg |= ANADIG_PLL_ENET_EN; + __raw_writel(reg, PLL8_ENET_BASE_ADDR); + + /* Waiting for the PLL is locked */ + if (!WAIT(ANADIG_PLL_ENET_LOCK & __raw_readl(PLL8_ENET_BASE_ADDR), + SPIN_DELAY)) + panic("pll8 lock failed\n"); + + /* Disable the bypass */ + reg = __raw_readl(PLL8_ENET_BASE_ADDR); + reg &= ~ANADIG_PLL_ENET_BYPASS; + __raw_writel(reg, PLL8_ENET_BASE_ADDR); + + /* + * Enable SATA ref clock. + * PCIe needs both sides to have the same source of refernce clock, + * The SATA reference clock is taken out on clk out + */ + reg = __raw_readl(PLL8_ENET_BASE_ADDR); + reg |= ANADIG_PLL_ENET_EN_SATA; + __raw_writel(reg, PLL8_ENET_BASE_ADDR); + + /* Activate LVDS CLK1 (the MiniPCIe slot clock input) */ + reg = __raw_readl(ANADIG_MISC1_REG); + reg &= ~ANATOP_LVDS_CLK1_IBEN_MASK; + __raw_writel(reg, ANADIG_MISC1_REG); + + reg = __raw_readl(ANADIG_MISC1_REG); + reg |= ANATOP_LVDS_CLK1_SRC_SATA; + __raw_writel(reg, ANADIG_MISC1_REG); + + reg = __raw_readl(ANADIG_MISC1_REG); + reg |= ANATOP_LVDS_CLK1_OBEN_MASK; + __raw_writel(reg, ANADIG_MISC1_REG); + + /* Enable PCIE ref clock */ reg = __raw_readl(PLL8_ENET_BASE_ADDR); reg |= ANADIG_PLL_ENET_EN_PCIE; __raw_writel(reg, PLL8_ENET_BASE_ADDR); @@ -5044,11 +5084,11 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_core_clk[0]), _REGISTER_CLOCK(NULL, "gpu3d_shader_clk", gpu3d_shader_clk), _REGISTER_CLOCK(NULL, "gpt", gpt_clk[0]), - _REGISTER_CLOCK("imx6q-gpmi-nfc.0", NULL, gpmi_nfc_clk[0]), - _REGISTER_CLOCK(NULL, "gpmi-apb", gpmi_nfc_clk[1]), - _REGISTER_CLOCK(NULL, "bch", gpmi_nfc_clk[2]), - _REGISTER_CLOCK(NULL, "bch-apb", gpmi_nfc_clk[3]), - _REGISTER_CLOCK(NULL, "pl301_mx6qperl-bch", gpmi_nfc_clk[4]), + _REGISTER_CLOCK("imx6q-gpmi-nand.0", NULL, gpmi_nand_clk[0]), + _REGISTER_CLOCK(NULL, "gpmi-apb", gpmi_nand_clk[1]), + _REGISTER_CLOCK(NULL, "bch", gpmi_nand_clk[2]), + _REGISTER_CLOCK(NULL, "bch-apb", gpmi_nand_clk[3]), + _REGISTER_CLOCK(NULL, "pl301_mx6qperl-bch", gpmi_nand_clk[4]), _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk[0]), _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm_clk[1]), _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm_clk[2]), @@ -5070,6 +5110,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, NULL, aips_tz1_clk), _REGISTER_CLOCK(NULL, "clko_clk", clko_clk), _REGISTER_CLOCK(NULL, "clko2_clk", clko2_clk), + _REGISTER_CLOCK(NULL, "pxp_axi", ipu2_clk), _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk), _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk), _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk), @@ -5083,7 +5124,8 @@ static void clk_tree_init(void) reg = __raw_readl(MMDC_MDMISC_OFFSET); if ((reg & MMDC_MDMISC_DDR_TYPE_MASK) == - (0x1 << MMDC_MDMISC_DDR_TYPE_OFFSET)) { + (0x1 << MMDC_MDMISC_DDR_TYPE_OFFSET) || + cpu_is_mx6dl()) { clk_set_parent(&periph_clk, &pll2_pfd_400M); printk(KERN_INFO "Set periph_clk's parent to pll2_pfd_400M!\n"); } @@ -5116,7 +5158,7 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_tree_init(); - if (pll2_pfd_400M.usecount == 0) + if (pll2_pfd_400M.usecount == 0 && cpu_is_mx6q()) pll2_pfd_400M.disable(&pll2_pfd_400M); pll2_pfd_352M.disable(&pll2_pfd_352M); pll2_pfd_594M.disable(&pll2_pfd_594M); @@ -5158,6 +5200,13 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_set_rate(&gpu3d_shader_clk, 594000000); clk_set_parent(&gpu3d_core_clk[0], &mmdc_ch0_axi_clk[0]); clk_set_rate(&gpu3d_core_clk[0], 528000000); + if (cpu_is_mx6dl()) { + /*on mx6dl, 2d core clock sources from 3d shader core clock*/ + clk_set_parent(&gpu2d_core_clk[0], &gpu3d_shader_clk); + /* on mx6dl gpu2d_axi_clk source from mmdc0 directly */ + clk_set_parent(&gpu2d_axi_clk, &mmdc_ch0_axi_clk[0]); + gpu2d_axi_clk.secondary = NULL; + } /* PCLK camera - J5 */ clk_set_parent(&clko2_clk, &osc_clk); @@ -5216,6 +5265,10 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, /* S/PDIF */ clk_set_parent(&spdif0_clk[0], &pll3_pfd_454M); + /* pxp & epdc */ + clk_set_parent(&ipu2_clk, &pll2_pfd_400M); + clk_set_rate(&ipu2_clk, 200000000); + if (mx6q_revision() == IMX_CHIP_REVISION_1_0) { gpt_clk[0].parent = &ipg_perclk; gpt_clk[0].get_rate = NULL; diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c index 40ee552c6b04..781e9063fac0 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.c +++ b/arch/arm/mach-mx6/cpu_op-mx6.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -23,26 +23,22 @@ extern void (*set_num_cpu_op)(int num); extern u32 arm_max_freq; static int num_cpu_op; -/* working point(wp): 0 - 1GHzMHz; 1 - 800MHz, 3 - 400MHz, 4 - 160MHz */ +/* working point(wp): 0 - 1GHzMHz; 1 - 800MHz, 2 - 624MHz 3 - 400MHz, 4 - 200MHz */ static struct cpu_op mx6_cpu_op_1G[] = { { .pll_rate = 996000000, .cpu_rate = 996000000, - .pdf = 0, - .mfi = 10, - .mfd = 11, - .mfn = 5, .cpu_podf = 0, .cpu_voltage = 1225000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, - .pdf = 0, - .mfi = 8, - .mfd = 2, - .mfn = 1, .cpu_podf = 0, .cpu_voltage = 1100000,}, + { + .pll_rate = 624000000, + .cpu_rate = 624000000, + .cpu_voltage = 11000000,}, { .pll_rate = 792000000, .cpu_rate = 396000000, @@ -59,10 +55,6 @@ static struct cpu_op mx6_cpu_op[] = { { .pll_rate = 792000000, .cpu_rate = 792000000, - .pdf = 0, - .mfi = 8, - .mfd = 2, - .mfn = 1, .cpu_podf = 0, .cpu_voltage = 1100000,}, { @@ -77,6 +69,48 @@ static struct cpu_op mx6_cpu_op[] = { .cpu_voltage = 850000,}, }; +/* working point(wp): 0 - 1GHzMHz; 1 - 800MHz, 3 - 400MHz, 4 - 200MHz */ +static struct cpu_op mx6dl_cpu_op_1G[] = { + { + .pll_rate = 996000000, + .cpu_rate = 996000000, + .cpu_podf = 0, + .cpu_voltage = 1225000,}, + { + .pll_rate = 792000000, + .cpu_rate = 792000000, + .cpu_podf = 0, + .cpu_voltage = 1100000,}, + { + .pll_rate = 792000000, + .cpu_rate = 396000000, + .cpu_podf = 1, + .cpu_voltage = 1000000,}, + { + .pll_rate = 792000000, + .cpu_rate = 198000000, + .cpu_podf = 3, + .cpu_voltage = 1000000,}, +}; + +static struct cpu_op mx6dl_cpu_op[] = { + { + .pll_rate = 792000000, + .cpu_rate = 792000000, + .cpu_podf = 0, + .cpu_voltage = 1100000,}, + { + .pll_rate = 792000000, + .cpu_rate = 396000000, + .cpu_podf = 1, + .cpu_voltage = 1000000,}, + { + .pll_rate = 792000000, + .cpu_rate = 198000000, + .cpu_podf = 3, + .cpu_voltage = 1000000,}, +}; + static struct dvfs_op dvfs_core_setpoint_1G[] = { {33, 14, 33, 10, 128, 0x10}, /* 1GHz*/ {30, 12, 33, 100, 200, 0x10}, /* 800MHz */ @@ -101,12 +135,22 @@ static struct dvfs_op *mx6_get_dvfs_core_table(int *wp) struct cpu_op *mx6_get_cpu_op(int *op) { - if (arm_max_freq == CPU_AT_1GHz) { - *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op_1G); - return mx6_cpu_op_1G; + if (cpu_is_mx6dl()) { + if (arm_max_freq == CPU_AT_1GHz) { + *op = num_cpu_op = ARRAY_SIZE(mx6dl_cpu_op_1G); + return mx6dl_cpu_op_1G; + } else { + *op = num_cpu_op = ARRAY_SIZE(mx6dl_cpu_op); + return mx6dl_cpu_op; + } } else { - *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op); - return mx6_cpu_op; + if (arm_max_freq == CPU_AT_1GHz) { + *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op_1G); + return mx6_cpu_op_1G; + } else { + *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op); + return mx6_cpu_op; + } } } diff --git a/arch/arm/mach-mx6/crm_regs.h b/arch/arm/mach-mx6/crm_regs.h index 0e29ea83f1df..6dbdeafa0dba 100644 --- a/arch/arm/mach-mx6/crm_regs.h +++ b/arch/arm/mach-mx6/crm_regs.h @@ -47,6 +47,10 @@ #define PFD_480_BASE_ADDR (MXC_PLL_BASE + 0xF0) #define PFD_528_BASE_ADDR (MXC_PLL_BASE + 0x100) #define ANADIG_REG_CORE (MXC_PLL_BASE + 0x140) +#define ANADIG_MISC1_REG (MXC_PLL_BASE + 0x160) +#define ANATOP_LVDS_CLK1_SRC_SATA 0xB +#define ANATOP_LVDS_CLK1_OBEN_MASK 0x400 +#define ANATOP_LVDS_CLK1_IBEN_MASK 0x1000 #define ANA_MISC2_BASE_ADDR (MXC_PLL_BASE + 0x170) #define PLL_SETREG_OFFSET 0x4 diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h index ce6b50dc641f..ab245158cfb7 100644 --- a/arch/arm/mach-mx6/devices-imx6q.h +++ b/arch/arm/mach-mx6/devices-imx6q.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -198,3 +198,13 @@ extern const struct imx_mxc_mlb_data imx6q_mxc_mlb150_data __initconst; #define imx6q_add_mlb150(pdata) \ imx_add_mlb(pdata) +extern const struct imx_pxp_data imx6dl_pxp_data __initconst; +#define imx6dl_add_imx_pxp() \ + imx_add_imx_pxp(&imx6dl_pxp_data) + +#define imx6dl_add_imx_pxp_client() \ + imx_add_imx_pxp_client() + +extern const struct imx_epdc_data imx6dl_epdc_data __initconst; +#define imx6dl_add_imx_epdc(pdata) \ + imx_add_imx_epdc(&imx6dl_epdc_data, pdata) diff --git a/arch/arm/mach-mx6/mm.c b/arch/arm/mach-mx6/mm.c index fa1c78be532f..e4daaf1fb415 100644 --- a/arch/arm/mach-mx6/mm.c +++ b/arch/arm/mach-mx6/mm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,6 +57,19 @@ static struct map_desc mx6_io_desc[] __initdata = { .type = MT_DEVICE}, }; +static void mx6_set_cpu_type(void) +{ + u32 cpu_type = readl(IO_ADDRESS(ANATOP_BASE_ADDR + 0x260)); + + cpu_type >>= 16; + if (cpu_type == 0x63) + mxc_set_cpu_type(MXC_CPU_MX6Q); + else if (cpu_type == 0x61) + mxc_set_cpu_type(MXC_CPU_MX6DL); + else + pr_err("Unknown CPU type: %x\n", cpu_type); +} + /*! * This function initializes the memory map. It is called during the * system startup to create static physical to virtual memory map for @@ -67,6 +80,7 @@ void __init mx6_map_io(void) iotable_init(mx6_io_desc, ARRAY_SIZE(mx6_io_desc)); mxc_iomux_v3_init(IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR)); mxc_arch_reset_init(IO_ADDRESS(MX6Q_WDOG1_BASE_ADDR)); + mx6_set_cpu_type(); } #ifdef CONFIG_CACHE_L2X0 int mxc_init_l2x0(void) diff --git a/arch/arm/mach-mx6/pcie.c b/arch/arm/mach-mx6/pcie.c new file mode 100644 index 000000000000..9959bbceaa4d --- /dev/null +++ b/arch/arm/mach-mx6/pcie.c @@ -0,0 +1,484 @@ +/* + * arch/arm/mach-mx6/pcie.c + * + * PCIe host controller driver for IMX6 SOCs + * + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * Bits taken from arch/arm/mach-dove/pcie.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio.h> + +#include <asm/sizes.h> + +#include "crm_regs.h" + +/* Register Definitions */ +#define PRT_LOG_R_BaseAddress 0x700 + +/* Register DB_R0 */ +/* Debug Register 0 */ +#define DB_R0 (PRT_LOG_R_BaseAddress + 0x28) +#define DB_R0_RegisterSize 32 +#define DB_R0_RegisterResetValue 0x0 +#define DB_R0_RegisterResetMask 0xFFFFFFFF +/* End of Register Definition for DB_R0 */ + +/* Register DB_R1 */ +/* Debug Register 1 */ +#define DB_R1 (PRT_LOG_R_BaseAddress + 0x2c) +#define DB_R1_RegisterSize 32 +#define DB_R1_RegisterResetValue 0x0 +#define DB_R1_RegisterResetMask 0xFFFFFFFF +/* End of Register Definition for DB_R1 */ + +#define ATU_R_BaseAddress 0x900 +#define ATU_VIEWPORT_R (ATU_R_BaseAddress + 0x0) +#define ATU_REGION_CTRL1_R (ATU_R_BaseAddress + 0x4) +#define ATU_REGION_CTRL2_R (ATU_R_BaseAddress + 0x8) +#define ATU_REGION_LOWBASE_R (ATU_R_BaseAddress + 0xC) +#define ATU_REGION_UPBASE_R (ATU_R_BaseAddress + 0x10) +#define ATU_REGION_LIMIT_ADDR_R (ATU_R_BaseAddress + 0x14) +#define ATU_REGION_LOW_TRGT_ADDR_R (ATU_R_BaseAddress + 0x18) +#define ATU_REGION_UP_TRGT_ADDR_R (ATU_R_BaseAddress + 0x1C) + +/* GPR1: iomuxc_gpr1_pcie_ref_clk_en(iomuxc_gpr1[16]) */ +#define iomuxc_gpr1_pcie_ref_clk_en (1 << 16) +/* GPR1: iomuxc_gpr1_test_powerdown(iomuxc_gpr1_18) */ +#define iomuxc_gpr1_test_powerdown (1 << 18) + +/* GPR12: iomuxc_gpr12_los_level(iomuxc_gpr12[8:4]) */ +#define iomuxc_gpr12_los_level (0x1F << 4) +/* GPR12: iomuxc_gpr12_app_ltssm_enable(iomuxc_gpr12[10]) */ +#define iomuxc_gpr12_app_ltssm_enable (1 << 10) +/* GPR12: iomuxc_gpr12_device_type(iomuxc_gpr12[15:12]) */ +#define iomuxc_gpr12_device_type (0xF << 12) + +/* GPR8: iomuxc_gpr8_tx_deemph_gen1(iomuxc_gpr8[5:0]) */ +#define iomuxc_gpr8_tx_deemph_gen1 (0x3F << 0) +/* GPR8: iomuxc_gpr8_tx_deemph_gen2_3p5db(iomuxc_gpr8[11:6]) */ +#define iomuxc_gpr8_tx_deemph_gen2_3p5db (0x3F << 6) +/* GPR8: iomuxc_gpr8_tx_deemph_gen2_6db(iomuxc_gpr8[17:12]) */ +#define iomuxc_gpr8_tx_deemph_gen2_6db (0x3F << 12) +/* GPR8: iomuxc_gpr8_tx_swing_full(iomuxc_gpr8[24:18]) */ +#define iomuxc_gpr8_tx_swing_full (0x7F << 18) +/* GPR8: iomuxc_gpr8_tx_swing_low(iomuxc_gpr8[31:25]) */ +#define iomuxc_gpr8_tx_swing_low (0x7F << 25) + +/* End of Register Definitions */ + +#define PCIE_DBI_BASE_ADDR (PCIE_ARB_END_ADDR - SZ_16K + 1) + +#define PCIE_CONF_BUS(b) (((b) & 0xFF) << 16) +#define PCIE_CONF_DEV(d) (((d) & 0x1F) << 11) +#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8) + +enum { + MemRdWr = 0, + MemRdLk = 1, + IORdWr = 2, + CfgRdWr0 = 4, + CfgRdWr1 = 5 +}; + +struct imx_pcie_port { + u8 index; + u8 root_bus_nr; + void __iomem *base; + void __iomem *dbi_base; + spinlock_t conf_lock; + + char io_space_name[16]; + char mem_space_name[16]; + + struct resource res[2]; +}; + +static struct imx_pcie_port imx_pcie_port[1]; +static int num_pcie_ports; + +/* IMX PCIE GPR configure routines */ +static inline void imx_pcie_clrset(u32 mask, u32 val, void __iomem *addr) +{ + writel(((readl(addr) & ~mask) | (val & mask)), addr); +} + +static struct imx_pcie_port *bus_to_port(int bus) +{ + int i; + + for (i = num_pcie_ports - 1; i >= 0; i--) { + int rbus = imx_pcie_port[i].root_bus_nr; + if (rbus != -1 && rbus <= bus) + break; + } + + return i >= 0 ? imx_pcie_port + i : NULL; +} + +static int __init imx_pcie_setup(int nr, struct pci_sys_data *sys) +{ + struct imx_pcie_port *pp; + + if (nr >= num_pcie_ports) + return 0; + + pp = &imx_pcie_port[nr]; + pp->root_bus_nr = sys->busnr; + + /* + * IORESOURCE_IO + */ + snprintf(pp->io_space_name, sizeof(pp->io_space_name), + "PCIe %d I/O", pp->index); + pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0; + pp->res[0].name = pp->io_space_name; + if (pp->index == 0) { + pp->res[0].start = PCIE_ARB_BASE_ADDR; + pp->res[0].end = pp->res[0].start + SZ_64K - 1; + } + pp->res[0].flags = IORESOURCE_IO; + if (request_resource(&ioport_resource, &pp->res[0])) + panic("Request PCIe IO resource failed\n"); + sys->resource[0] = &pp->res[0]; + + /* + * IORESOURCE_MEM + */ + snprintf(pp->mem_space_name, sizeof(pp->mem_space_name), + "PCIe %d MEM", pp->index); + pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0; + pp->res[1].name = pp->mem_space_name; + if (pp->index == 0) { + pp->res[1].start = PCIE_ARB_BASE_ADDR + SZ_64K; + pp->res[1].end = pp->res[1].start + SZ_16M - SZ_128K - 1; + } + pp->res[1].flags = IORESOURCE_MEM; + if (request_resource(&iomem_resource, &pp->res[1])) + panic("Request PCIe Memory resource failed\n"); + sys->resource[1] = &pp->res[1]; + + sys->resource[2] = NULL; + + return 1; +} + +static void __init imx_pcie_preinit(void) +{ + pcibios_setup("debug"); +} + +static int imx_pcie_link_up(void __iomem *dbi_base) +{ + /* Check the pcie link up or link down */ + u32 rc, iterations = 0x100000; + + do { + /* link is debug bit 36 debug 1 start in bit 32 */ + rc = readl(dbi_base + DB_R1) & (0x1 << (36-32)) ; + iterations--; + if ((iterations % 0x100000) == 0) + pr_info("link up failed!\n"); + } while (!rc && iterations); + + if (!rc) + return 0; + return 1; +} + +static int pcie_valid_config(struct imx_pcie_port *pp, int bus_num, int dev) +{ + /*If there is no link, then there is no device*/ + if (bus_num != pp->root_bus_nr) { + if (!imx_pcie_link_up(pp->dbi_base)) + return 0; + } + + /* + * Don't go out when trying to access nonexisting devices + * on the local bus. + * We have only one slot on the root port. + */ + if (bus_num == pp->root_bus_nr && dev > 0) + return 0; + + return 1; +} + +static void imx_pcie_regions_setup(void __iomem *dbi_base) +{ + /* + * i.MX6 defines 16MB in the AXI address map for PCIe. + * + * That address space excepted the pcie registers is + * split and defined into different regions by iATU, + * with sizes and offsets as follows: + * + * 0x0100_0000 --- 0x0100_FFFF 64KB IORESOURCE_IO + * 0x0101_0000 --- 0x01FE_FFFF 16MB - 128KB IORESOURCE_MEM + * 0x01FF_0000 --- 0x01FF_FFFF 64KB Cfg + Registers + */ + + /* CMD reg:I/O space, MEM space, and Bus Master Enable */ + writel(readl(dbi_base + PCI_COMMAND) + | PCI_COMMAND_IO + | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER, + dbi_base + PCI_COMMAND); + /* + * region0 outbound used to access target cfg + */ + writel(0, dbi_base + ATU_VIEWPORT_R); + writel(PCIE_ARB_END_ADDR - SZ_64K + 1, dbi_base + ATU_REGION_LOWBASE_R); + writel(0, dbi_base + ATU_REGION_UPBASE_R); + writel(PCIE_ARB_END_ADDR, dbi_base + ATU_REGION_LIMIT_ADDR_R); + writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); + writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); + writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R); + writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); + + /* + * region1 outbound used to as IORESOURCE_IO + */ + writel(1, dbi_base + ATU_VIEWPORT_R); + writel(0, dbi_base + ATU_REGION_LOWBASE_R); + writel(0, dbi_base + ATU_REGION_UPBASE_R); + writel(SZ_64K - 1, dbi_base + ATU_REGION_LIMIT_ADDR_R); + writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); + writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); + writel(IORdWr, dbi_base + ATU_REGION_CTRL1_R); + writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); + + /* + * region2 outbound used to as IORESOURCE_MEM + */ + writel(2, dbi_base + ATU_VIEWPORT_R); + writel(0, dbi_base + ATU_REGION_LOWBASE_R); + writel(0, dbi_base + ATU_REGION_UPBASE_R); + writel(SZ_16M - SZ_128K - 1, dbi_base + ATU_REGION_LIMIT_ADDR_R); + writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); + writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); + writel(MemRdWr, dbi_base + ATU_REGION_CTRL1_R); + writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); +} + +static int imx_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, + int size, u32 *val) +{ + struct imx_pcie_port *pp = bus_to_port(bus->number); + unsigned long flags; + u32 va_address; + + if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) { + *val = 0xFFFFFFFF; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + + spin_lock_irqsave(&pp->conf_lock, flags); + + va_address = (u32)pp->base + + PCIE_CONF_BUS(bus->number) + + PCIE_CONF_DEV(PCI_SLOT(devfn)) + + PCIE_CONF_FUNC(PCI_FUNC(devfn)) + + (where & ~0x3); + + *val = readl(va_address); + + if (size == 1) + *val = (*val >> (8 * (where & 3))) & 0xFF; + else if (size == 2) + *val = (*val >> (8 * (where & 3))) & 0xFFFF; + + spin_unlock_irqrestore(&pp->conf_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static int imx_pcie_wr_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 val) +{ + struct imx_pcie_port *pp = bus_to_port(bus->number); + unsigned long flags; + u32 va_address = 0, mask = 0, tmp = 0; + int ret = PCIBIOS_SUCCESSFUL; + + if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + spin_lock_irqsave(&pp->conf_lock, flags); + + va_address = (u32)pp->base + + PCIE_CONF_BUS(bus->number) + + PCIE_CONF_DEV(PCI_SLOT(devfn)) + + PCIE_CONF_FUNC(PCI_FUNC(devfn)) + + (where & ~0x3); + + if (size == 4) { + writel(val, va_address); + goto exit; + } + + if (size == 2) + mask = ~(0xFFFF << ((where & 0x3) * 8)); + else if (size == 1) + mask = ~(0xFF << ((where & 0x3) * 8)); + else + ret = PCIBIOS_BAD_REGISTER_NUMBER; + + tmp = readl(va_address) & mask; + tmp |= val << ((where & 0x3) * 8); + writel(tmp, va_address); +exit: + spin_unlock_irqrestore(&pp->conf_lock, flags); + + return ret; +} + +static struct pci_ops imx_pcie_ops = { + .read = imx_pcie_rd_conf, + .write = imx_pcie_wr_conf, +}; + +static struct pci_bus __init * +imx_pcie_scan_bus(int nr, struct pci_sys_data *sys) +{ + struct pci_bus *bus; + + if (nr < num_pcie_ports) { + bus = pci_scan_bus(sys->busnr, &imx_pcie_ops, sys); + } else { + bus = NULL; + BUG(); + } + + return bus; +} + +static int __init imx_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return MXC_INT_PCIE_0; +} + +static struct hw_pci imx_pci __initdata = { + .nr_controllers = 1, + .swizzle = pci_std_swizzle, + .setup = imx_pcie_setup, + .preinit = imx_pcie_preinit, + .scan = imx_pcie_scan_bus, + .map_irq = imx_pcie_map_irq, +}; + +static void imx_pcie_enable_controller(void) +{ + struct clk *pcie_clk; + + imx_pcie_clrset(iomuxc_gpr1_test_powerdown, 0 << 18, IOMUXC_GPR1); + + /* enable the clks */ + pcie_clk = clk_get(NULL, "pcie_clk"); + if (IS_ERR(pcie_clk)) + pr_err("no pcie clock.\n"); + + if (clk_enable(pcie_clk)) { + pr_err("can't enable pcie clock.\n"); + clk_put(pcie_clk); + } +} + +static void card_reset(void) +{ + /* Add one reset to the pcie external device */ +} + +static void __init add_pcie_port(void __iomem *base, void __iomem *dbi_base) +{ + if (imx_pcie_link_up(dbi_base)) { + struct imx_pcie_port *pp = &imx_pcie_port[num_pcie_ports++]; + + pr_info("IMX PCIe port: link up.\n"); + + pp->index = 0; + pp->root_bus_nr = -1; + pp->base = base; + pp->dbi_base = dbi_base; + spin_lock_init(&pp->conf_lock); + memset(pp->res, 0, sizeof(pp->res)); + } else + pr_info("IMX PCIe port: link down!\n"); +} + +static int __init imx_pcie_init(void) +{ + void __iomem *base, *dbi_base; + + base = ioremap_nocache(PCIE_ARB_END_ADDR - SZ_64K + 1, SZ_32K); + if (!base) { + pr_err("error with ioremap in function %s\n", __func__); + return -EIO; + } + + dbi_base = ioremap_nocache(PCIE_DBI_BASE_ADDR, SZ_16K); + if (!dbi_base) { + pr_err("error with ioremap in function %s\n", __func__); + iounmap(base); + return -EIO; + } + + /* FIXME the field name should be aligned to RM */ + imx_pcie_clrset(iomuxc_gpr12_app_ltssm_enable, 0 << 10, IOMUXC_GPR12); + + /* configure constant input signal to the pcie ctrl and phy */ + imx_pcie_clrset(iomuxc_gpr12_device_type, PCI_EXP_TYPE_ROOT_PORT << 12, + IOMUXC_GPR12); + imx_pcie_clrset(iomuxc_gpr12_los_level, 9 << 4, IOMUXC_GPR12); + imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen1, 21 << 0, IOMUXC_GPR8); + imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_3p5db, 21 << 6, IOMUXC_GPR8); + imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_6db, 32 << 12, IOMUXC_GPR8); + imx_pcie_clrset(iomuxc_gpr8_tx_swing_full, 115 << 18, IOMUXC_GPR8); + imx_pcie_clrset(iomuxc_gpr8_tx_swing_low, 115 << 25, IOMUXC_GPR8); + + /* Enable the pwr, clks and so on */ + imx_pcie_enable_controller(); + + imx_pcie_clrset(iomuxc_gpr1_pcie_ref_clk_en, 1 << 16, IOMUXC_GPR1); + + /* togle the external card's reset */ + card_reset() ; + + usleep_range(3000, 4000); + imx_pcie_regions_setup(dbi_base); + usleep_range(3000, 4000); + + /* start link up */ + imx_pcie_clrset(iomuxc_gpr12_app_ltssm_enable, 1 << 10, IOMUXC_GPR12); + + /* add the pcie port */ + add_pcie_port(base, dbi_base); + + pci_common_init(&imx_pci); + pr_info("pcie init successful\n"); + return 0; +} +subsys_initcall(imx_pcie_init); diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index efc838e08078..185be00db482 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -243,7 +243,7 @@ static int __mxs_reset_block(void __iomem *hwreg, int just_enable) return 0; } -int mxs_reset_block(void __iomem *hwreg, int just_enable) +static int _mxs_reset_block(void __iomem *hwreg, int just_enable) { int try = 10; int r; @@ -256,4 +256,9 @@ int mxs_reset_block(void __iomem *hwreg, int just_enable) } return r; } + +int mxs_reset_block(void __iomem *hwreg) +{ + return _mxs_reset_block(hwreg, false); +} EXPORT_SYMBOL(mxs_reset_block); diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c index 4c7c21dd2f56..21cf3d80699a 100644 --- a/arch/arm/mach-mx6/usb_dr.c +++ b/arch/arm/mach-mx6/usb_dr.c @@ -395,6 +395,19 @@ static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata) #ifdef CONFIG_USB_GADGET_ARC /* Beginning of device related operation for DR port */ +static void _gadget_discharge_dp(bool enable) +{ + void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR); + if (enable) { + __raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_SET); + __raw_writel(BF_USBPHY_DEBUG_HSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_SET); + } else { + __raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_CLR); + __raw_writel(BF_USBPHY_DEBUG_HSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_CLR); + } + +} + static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE); @@ -489,6 +502,7 @@ void __init mx6_usb_dr_init(void) dr_utmi_config.platform_resume = NULL; dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend; dr_utmi_config.is_wakeup_event = _is_device_wakeup; + dr_utmi_config.gadget_discharge_dp = _gadget_discharge_dp; dr_utmi_config.wakeup_pdata = &dr_wakeup_config; dr_utmi_config.wakeup_handler = device_wakeup_handler; pdev = imx6q_add_fsl_usb2_udc(&dr_utmi_config); diff --git a/arch/arm/mach-mx6/usb_h2.c b/arch/arm/mach-mx6/usb_h2.c index edbad95a82ad..4e78ad3a0cf9 100644 --- a/arch/arm/mach-mx6/usb_h2.c +++ b/arch/arm/mach-mx6/usb_h2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include <mach/arc_otg.h> #include <mach/hardware.h> #include <mach/iomux-mx6q.h> +#include <mach/iomux-mx6dl.h> #include "devices-imx6q.h" #include "regs-anadig.h" #include "usb.h" @@ -43,11 +44,17 @@ static struct fsl_usb2_platform_data usbh2_config; static void usbh2_internal_phy_clock_gate(bool on) { if (on) { + /* must turn on the 480M clock, otherwise + * there will be a 10ms delay before host + * controller send out resume signal*/ USB_H2_CTRL |= UCTRL_UTMI_ON_CLOCK; USB_UH2_HSIC_CTRL |= HSIC_CLK_ON; } else { USB_UH2_HSIC_CTRL &= ~HSIC_CLK_ON; - USB_H2_CTRL &= ~UCTRL_UTMI_ON_CLOCK; + /* can't turn off this clock, otherwise + * there will be a 10ms delay before host + * controller send out resume signal*/ + /*USB_H2_CTRL &= ~UCTRL_UTMI_ON_CLOCK*/; } } @@ -113,6 +120,10 @@ void mx6_set_host2_vbus_func(driver_vbus_func driver_vbus) static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable) { pr_debug("host2, %s, enable is %d\n", __func__, enable); + /* for HSIC, no disconnect nor connect + * we need to disable the WKDS, WKCN */ + UH2_PORTSC1 &= ~(PORTSC_WKDC | PORTSC_WKCN); + if (enable) { USB_H2_CTRL |= (UCTRL_OWIE); } else { @@ -169,7 +180,19 @@ static void hsic_start(void) { pr_debug("%s\n", __func__); /* strobe 47K pull up */ - mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE_START); + if (cpu_is_mx6q()) + mxc_iomux_v3_setup_pad( + MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE_START); + else if (cpu_is_mx6dl()) + mxc_iomux_v3_setup_pad( + MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE_START); +} + +static void hsic_device_connected(void) +{ + pr_debug("%s\n", __func__); + if (!(USB_UH2_HSIC_CTRL & HSIC_DEV_CONN)) + USB_UH2_HSIC_CTRL |= HSIC_DEV_CONN; } static struct fsl_usb2_platform_data usbh2_config = { @@ -186,6 +209,7 @@ static struct fsl_usb2_platform_data usbh2_config = { .wakeup_handler = h2_wakeup_handler, .transceiver = "hsic_xcvr", .hsic_post_ops = hsic_start, + .hsic_device_connected = hsic_device_connected, }; static struct fsl_usb2_wakeup_platform_data usbh2_wakeup_config = { @@ -211,4 +235,8 @@ void __init mx6_usb_h2_init(void) */ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS, anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET); + /* must change the clkgate delay to 2 or 3 to avoid + * 24M OSCI clock not stable issue */ + __raw_writel(BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(3), + anatop_base_addr + HW_ANADIG_ANA_MISC0); } diff --git a/arch/arm/mach-mx6/usb_h3.c b/arch/arm/mach-mx6/usb_h3.c index 43c2b1208eed..46ffc74cce3a 100644 --- a/arch/arm/mach-mx6/usb_h3.c +++ b/arch/arm/mach-mx6/usb_h3.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include <mach/arc_otg.h> #include <mach/hardware.h> #include <mach/iomux-mx6q.h> +#include <mach/iomux-mx6dl.h> #include "devices-imx6q.h" #include "regs-anadig.h" #include "usb.h" @@ -43,11 +44,17 @@ static struct fsl_usb2_platform_data usbh3_config; static void usbh3_internal_phy_clock_gate(bool on) { if (on) { + /* must turn on the 480M clock, otherwise + * there will be a 10ms delay before host + * controller send out resume signal*/ USB_H3_CTRL |= UCTRL_UTMI_ON_CLOCK; USB_UH3_HSIC_CTRL |= HSIC_CLK_ON; } else { USB_UH3_HSIC_CTRL &= ~HSIC_CLK_ON; - USB_H3_CTRL &= ~UCTRL_UTMI_ON_CLOCK; + /* can't turn off this clock, otherwise + * there will be a 10ms delay before host + * controller send out resume signal*/ + /*USB_H3_CTRL &= ~UCTRL_UTMI_ON_CLOCK;*/ } } @@ -114,6 +121,10 @@ void mx6_set_host3_vbus_func(driver_vbus_func driver_vbus) static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable) { pr_debug("host3, %s, enable is %d\n", __func__, enable); + /* for HSIC, no disconnect nor connect + * we need to disable the WKDS, WKCN */ + UH3_PORTSC1 &= ~(PORTSC_WKDC | PORTSC_WKCN); + if (enable) { USB_H3_CTRL |= (UCTRL_OWIE); } else { @@ -170,7 +181,19 @@ static void hsic_start(void) { pr_debug("%s", __func__); /* strobe 47K pull up */ - mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE_START); + if (cpu_is_mx6q()) + mxc_iomux_v3_setup_pad( + MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE_START); + else if (cpu_is_mx6dl()) + mxc_iomux_v3_setup_pad( + MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE_START); +} + +static void hsic_device_connected(void) +{ + pr_debug("%s\n", __func__); + if (!(USB_UH3_HSIC_CTRL & HSIC_DEV_CONN)) + USB_UH3_HSIC_CTRL |= HSIC_DEV_CONN; } static struct fsl_usb2_platform_data usbh3_config = { @@ -187,6 +210,7 @@ static struct fsl_usb2_platform_data usbh3_config = { .wakeup_handler = usbh3_wakeup_handler, .transceiver = "hsic_xcvr", .hsic_post_ops = hsic_start, + .hsic_device_connected = hsic_device_connected, }; static struct fsl_usb2_wakeup_platform_data usbh3_wakeup_config = { @@ -213,4 +237,8 @@ void __init mx6_usb_h3_init(void) */ __raw_writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS, anatop_base_addr + HW_ANADIG_USB1_PLL_480_CTRL_SET); + /* must change the clkgate delay to 2 or 3 to avoid + * 24M OSCI clock not stable issue */ + __raw_writel(BF_ANADIG_ANA_MISC0_CLKGATE_DELAY(3), + anatop_base_addr + HW_ANADIG_ANA_MISC0); } diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c index c7270196718d..8933cacb8cb3 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux-v2.c @@ -189,7 +189,7 @@ static int mxc_audmux_v2_init(void) int ret; #if defined(CONFIG_ARCH_MX6) - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { audmux_base = MX6_IO_ADDRESS(MX6Q_AUDMUX_BASE_ADDR); ret = 0; } diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c index 9b8715244e29..9f99aa481526 100755 --- a/arch/arm/plat-mxc/devices/platform-imx-dma.c +++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c @@ -259,7 +259,7 @@ static int __init imxXX_add_imx_dma(void) } else #endif #if defined(CONFIG_SOC_IMX6Q) - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { int to_version = 1; imx6q_imx_sdma_data.pdata.to_version = to_version; if (to_version == 1) diff --git a/arch/arm/plat-mxc/devices/platform-imx-gpmi-nfc.c b/arch/arm/plat-mxc/devices/platform-imx-gpmi-nfc.c index bc0c6ab47fd8..a1e297d5c35d 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-gpmi-nfc.c +++ b/arch/arm/plat-mxc/devices/platform-imx-gpmi-nfc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -17,9 +17,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include <linux/mtd/gpmi-nand.h> #include <asm/sizes.h> #include <mach/hardware.h> -#include <mach/gpmi-nfc.h> #include <mach/devices-common.h> #ifdef CONFIG_SOC_IMX50 @@ -67,42 +67,42 @@ imx_add_gpmi(const struct gpmi_nfc_platform_data *platform_data) #ifdef CONFIG_SOC_IMX6Q struct platform_device *__init -imx_add_gpmi(const struct gpmi_nfc_platform_data *platform_data) +imx_add_gpmi(const struct gpmi_nand_platform_data *platform_data) { struct resource res[] = { { /* GPMI */ - .name = GPMI_NFC_GPMI_REGS_ADDR_RES_NAME, + .name = GPMI_NAND_GPMI_REGS_ADDR_RES_NAME, .flags = IORESOURCE_MEM, .start = MX6Q_GPMI_BASE_ADDR, .end = MX6Q_GPMI_BASE_ADDR + SZ_8K - 1, }, { - .name = GPMI_NFC_GPMI_INTERRUPT_RES_NAME, + .name = GPMI_NAND_GPMI_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = MXC_INT_RAWNAND_GPMI, .end = MXC_INT_RAWNAND_GPMI, }, { /* BCH */ - .name = GPMI_NFC_BCH_REGS_ADDR_RES_NAME, + .name = GPMI_NAND_BCH_REGS_ADDR_RES_NAME, .flags = IORESOURCE_MEM, .start = MX6Q_BCH_BASE_ADDR, .end = MX6Q_BCH_BASE_ADDR + SZ_8K - 1, }, { - .name = GPMI_NFC_BCH_INTERRUPT_RES_NAME, + .name = GPMI_NAND_BCH_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = MXC_INT_RAWNAND_BCH, .end = MXC_INT_RAWNAND_BCH, }, { /* DMA */ - .name = GPMI_NFC_DMA_CHANNELS_RES_NAME, + .name = GPMI_NAND_DMA_CHANNELS_RES_NAME, .flags = IORESOURCE_DMA, .start = MX6Q_DMA_CHANNEL_AHB_APBH_GPMI0, .end = MX6Q_DMA_CHANNEL_AHB_APBH_GPMI7, }, { - .name = GPMI_NFC_DMA_INTERRUPT_RES_NAME, + .name = GPMI_NAND_DMA_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = MXC_INT_APBHDMA_DMA, .end = MXC_INT_APBHDMA_DMA, }, }; - return imx_add_platform_device_dmamask("imx6q-gpmi-nfc", 0, + return imx_add_platform_device_dmamask("imx6q-gpmi-nand", 0, res, ARRAY_SIZE(res), platform_data, sizeof(*platform_data), DMA_BIT_MASK(32)); } diff --git a/arch/arm/plat-mxc/devices/platform-imx-perfmon.c b/arch/arm/plat-mxc/devices/platform-imx-perfmon.c index 25d1bf582de2..56e262b39f11 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-perfmon.c +++ b/arch/arm/plat-mxc/devices/platform-imx-perfmon.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -86,8 +86,11 @@ static void platform_perfmon_init(void) if (init) return; - /* GPR11 bit[16] is the clock enable bit for perfmon */ - mxc_iomux_set_gpr_register(11, 16, 1, 1); + if (mx6q_revision() == IMX_CHIP_REVISION_1_0 || cpu_is_mx6dl()) + /* GPR11 bit[16] must be set for TO1.0(6q & 6dl), it's a bug */ + mxc_iomux_set_gpr_register(11, 16, 1, 1); + + mxc_iomux_set_gpr_register(11, 0, 1, 1); init = true; } @@ -96,8 +99,7 @@ static void platform_perfmon_exit(void) if (!init) return; - /* GPR11 bit[16] is the clock enable bit for perfmon */ - mxc_iomux_set_gpr_register(11, 16, 1, 0); + mxc_iomux_set_gpr_register(11, 0, 1, 0); init = false; } diff --git a/arch/arm/plat-mxc/devices/platform-imx-pxp.c b/arch/arm/plat-mxc/devices/platform-imx-pxp.c index 51030c57ca83..3ae3e4880e1d 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-pxp.c +++ b/arch/arm/plat-mxc/devices/platform-imx-pxp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -22,7 +22,7 @@ #include <mach/hardware.h> #include <mach/devices-common.h> -#define imx5_pxp_data_entry_single(soc, size) \ +#define imx_pxp_data_entry_single(soc, size) \ { \ .iobase = soc ## _EPXP_BASE_ADDR, \ .irq = soc ## _INT_EPXP, \ @@ -31,7 +31,12 @@ #ifdef CONFIG_SOC_IMX50 const struct imx_pxp_data imx50_pxp_data __initconst = - imx5_pxp_data_entry_single(MX50, SZ_4K); + imx_pxp_data_entry_single(MX50, SZ_4K); +#endif + +#ifdef CONFIG_SOC_IMX6Q +const struct imx_pxp_data imx6dl_pxp_data __initconst = + imx_pxp_data_entry_single(MX6DL, SZ_16K); #endif struct platform_device *__init imx_add_imx_pxp( diff --git a/arch/arm/plat-mxc/devices/platform-imx_vpu.c b/arch/arm/plat-mxc/devices/platform-imx_vpu.c index ed30bc7882b8..c36439138778 100755 --- a/arch/arm/plat-mxc/devices/platform-imx_vpu.c +++ b/arch/arm/plat-mxc/devices/platform-imx_vpu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * Jason Chen <jason.chen@freescale.com> * * This program is free software; you can redistribute it and/or modify it under @@ -167,6 +167,9 @@ struct platform_device *__init imx_add_vpu( pdata.iram_enable = data->iram_enable; pdata.iram_size = data->iram_size; + if (cpu_is_mx6dl()) + pdata.iram_enable = false; + return imx_add_platform_device("mxc_vpu", -1, res, ARRAY_SIZE(res), &pdata, sizeof(pdata)); } diff --git a/arch/arm/plat-mxc/devices/platform-viv_gpu.c b/arch/arm/plat-mxc/devices/platform-viv_gpu.c index b11efe0de1cf..dad9d5a2df3b 100644 --- a/arch/arm/plat-mxc/devices/platform-viv_gpu.c +++ b/arch/arm/plat-mxc/devices/platform-viv_gpu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -36,6 +36,7 @@ struct platform_device *__init imx_add_viv_gpu( const struct imx_viv_gpu_data *data, const struct viv_gpu_platform_data *pdata) { + u32 res_count = 0; struct resource res[] = { { .name = "iobase_3d", @@ -70,8 +71,15 @@ struct platform_device *__init imx_add_viv_gpu( }, }; + if (cpu_is_mx6q()) + res_count = ARRAY_SIZE(res); + else if (cpu_is_mx6dl()) + /* No openVG on i.mx6 Solo/DL */ + res_count = ARRAY_SIZE(res) - 2; + BUG_ON(!res_count); + return imx_add_platform_device_dmamask("galcore", 0, - res, ARRAY_SIZE(res), + res, res_count, pdata, sizeof(*pdata), DMA_BIT_MASK(32)); } diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c index cacd3cca7dd5..d52f7b6eb039 100755 --- a/arch/arm/plat-mxc/dvfs_core.c +++ b/arch/arm/plat-mxc/dvfs_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -427,7 +427,7 @@ static int set_cpu_freq(int op) { int ret = 0; - if (cpu_is_mx6q()) + if (cpu_is_mx6q() || cpu_is_mx6dl()) ret = mx6_set_cpu_freq(op); else ret = mx5_set_cpu_freq(op); @@ -476,7 +476,7 @@ static int start_dvfs(void) /* GPCIRQ=1, select ARM IRQ */ reg |= MXC_GPCCNTR_GPCIRQ_ARM; /* ADU=1, select ARM domain */ - if (!cpu_is_mx6q()) + if (!(cpu_is_mx6q() || cpu_is_mx6dl())) reg |= MXC_GPCCNTR_ADU; __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset); @@ -509,7 +509,7 @@ static int start_dvfs(void) __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR); /* Enable DVFS */ - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { unsigned long cpu_wfi = 0; int num_cpus = num_possible_cpus(); reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_EMAC); @@ -947,7 +947,7 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev) printk(KERN_ERR "%s: failed to get cpu clock\n", __func__); return PTR_ERR(cpu_clk); } - if (!cpu_is_mx6q()) { + if (!(cpu_is_mx6q() || cpu_is_mx6dl())) { dvfs_clk = clk_get(NULL, dvfs_data->clk2_id); if (IS_ERR(dvfs_clk)) { printk(KERN_ERR "%s: failed to get dvfs clock\n", __func__); diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 40f9799ed0d3..f84aa75cdbba 100755 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -345,7 +345,8 @@ int mxc_gpio_init(struct mxc_gpio_port *port, int cnt) BUG_ON(gpiochip_add(&port[i].chip) < 0); if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || - cpu_is_mx51() || cpu_is_mx53() || cpu_is_mx6q()) { + cpu_is_mx51() || cpu_is_mx53() || cpu_is_mx6q() || + cpu_is_mx6dl()) { /* setup one handler for each entry */ irq_set_chained_handler(port[i].irq, mx3_gpio_irq_handler); diff --git a/arch/arm/plat-mxc/include/mach/arc_otg.h b/arch/arm/plat-mxc/include/mach/arc_otg.h index b5bd8c31a4b2..bdb6b252b356 100755 --- a/arch/arm/plat-mxc/include/mach/arc_otg.h +++ b/arch/arm/plat-mxc/include/mach/arc_otg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -248,6 +248,8 @@ extern void __iomem *imx_otg_base; #define PORTSC_PTW (1 << 28) /* UTMI width */ #define PORTSC_HSIC_MODE (1 << 25) /* Only for HSIC */ #define PORTSC_PHCD (1 << 23) /* Low Power Suspend */ +#define PORTSC_WKDC (1 << 21) /* wakeup on discnt*/ +#define PORTSC_WKCN (1 << 20) /* wakeup on connect*/ #define PORTSC_PORT_POWER (1 << 12) /* port power */ #define PORTSC_LS_MASK (3 << 10) /* Line State mask */ #define PORTSC_LS_SE0 (0 << 10) /* SE0 */ diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index a8d1982b1b08..62489695af0f 100755 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -87,4 +87,5 @@ extern int mx53_revision(void); extern int mx50_revision(void); extern int mx53_display_revision(void); extern unsigned long mx6_timer_rate(void); +extern int mxs_reset_block(void __iomem *); #endif diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index 8538d5b658c2..2f5f04c39638 100755 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -621,10 +621,10 @@ struct platform_device *__init imx_add_fsl_usb2_wakeup( const struct imx_fsl_usb2_wakeup_data *data, const struct fsl_usb2_wakeup_platform_data *pdata); -/* gpmi-nfc */ -#include <mach/gpmi-nfc.h> +/* gpmi-nand*/ +#include <linux/mtd/gpmi-nand.h> struct platform_device *__init imx_add_gpmi( - const struct gpmi_nfc_platform_data *data); + const struct gpmi_nand_platform_data *data); struct imx_rngb_data { resource_size_t iobase; diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h index 321ced11c71d..ee3b962eeb4d 100644 --- a/arch/arm/plat-mxc/include/mach/dma.h +++ b/arch/arm/plat-mxc/include/mach/dma.h @@ -71,6 +71,11 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan) return !strcmp(dev_name(chan->device->dev), "ipu-core"); } +static inline int imx_dma_is_pxp(struct dma_chan *chan) +{ + return !strcmp(dev_name(chan->device->dev), "imx-pxp"); +} + static inline int imx_dma_is_general_purpose(struct dma_chan *chan) { return !strcmp(dev_name(chan->device->dev), "imx-sdma") || diff --git a/arch/arm/plat-mxc/include/mach/fsl_usb.h b/arch/arm/plat-mxc/include/mach/fsl_usb.h index c471064a5fda..0b47a7d5bcaa 100755 --- a/arch/arm/plat-mxc/include/mach/fsl_usb.h +++ b/arch/arm/plat-mxc/include/mach/fsl_usb.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -98,7 +98,7 @@ static inline void fsl_platform_set_ahb_burst(struct usb_hcd *hcd) } /* Increase TX fifo threshold for in Hostx */ - if (cpu_is_mx6q()) { + if (cpu_is_mx6()) { temp = readl(hcd->regs + FSL_SOC_USB_TXFILLTUNING); /* Change TX FIFO threshold to be 0x08 */ writel((temp & (~(0x3f << 16))) | (0x08 << 16), diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index ef964551b0ea..e1c523443ca8 100755 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011 Freescale Semiconductor, Inc. + * Copyright 2004-2012 Freescale Semiconductor, Inc. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * * This program is free software; you can redistribute it and/or @@ -138,4 +138,9 @@ .type = _type, \ } +/* macro to get at IO space when running virtually */ +#define PCIBIOS_MIN_IO 0x00000000 +#define PCIBIOS_MIN_MEM 0x00000000 +#define pcibios_assign_all_busses() 0 + #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h new file mode 100644 index 000000000000..b32cc00859ba --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h @@ -0,0 +1,3797 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Auto Generate file, please don't edit it + * + */ + +#ifndef __MACH_IOMUX_MX6DL_H__ +#define __MACH_IOMUX_MX6DL_H__ + +#include <mach/iomux-v3.h> + +#define MX6DL_HIGH_DRV PAD_CTL_DSE_120ohm +#define MX6DL_DISP_PAD_CLT MX6DL_HIGH_DRV + +#define MX6DL_CCM_CLK0_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define MX6DL_MLB150_PAD_CTRL (PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) \ + +#define MX6DL_UART_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 | PAD_CTL_HYS) + +#define MX6DL_USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define MX6DL_USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define MX6DL_USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define MX6DL_ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + + +#define MX6DL_I2C_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 | \ + PAD_CTL_HYS | PAD_CTL_ODE) + +#define MX6DL_ESAI_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + +#define MX6DL_USB_HSIC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + +#define MX6DL_ECSPI_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + +#define MX6DL_GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) +#define MX6DL_GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | PAD_CTL_SRE_FAST) +#define MX6DL_GPMI_PAD_CTRL2 (MX6DL_GPMI_PAD_CTRL0 | MX6DL_GPMI_PAD_CTRL1) +#define MX6DL_SPDIF_OUT_PAD_CTRL (PAD_CTL_DSE_120ohm | PAD_CTL_SRE_FAST) + +#define MX6DL_PAD_CSI0_DAT10__IPU1_CSI0_D_10 \ + IOMUX_PAD(0x0360, 0x004C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC \ + IOMUX_PAD(0x0360, 0x004C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__ECSPI2_MISO \ + IOMUX_PAD(0x0360, 0x004C, 2, 0x07F8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__UART1_TXD \ + IOMUX_PAD(0x0360, 0x004C, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__UART1_RXD \ + IOMUX_PAD(0x0360, 0x004C, 3, 0x08FC, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 \ + IOMUX_PAD(0x0360, 0x004C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__GPIO_5_28 \ + IOMUX_PAD(0x0360, 0x004C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__MMDC_MMDC_DEBUG_33 \ + IOMUX_PAD(0x0360, 0x004C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT10__SIMBA_TRACE_7 \ + IOMUX_PAD(0x0360, 0x004C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT11__IPU1_CSI0_D_11 \ + IOMUX_PAD(0x0364, 0x0050, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS \ + IOMUX_PAD(0x0364, 0x0050, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__ECSPI2_SS0 \ + IOMUX_PAD(0x0364, 0x0050, 2, 0x0800, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__UART1_TXD \ + IOMUX_PAD(0x0364, 0x0050, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__UART1_RXD \ + IOMUX_PAD(0x0364, 0x0050, 3, 0x08FC, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 \ + IOMUX_PAD(0x0364, 0x0050, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__GPIO_5_29 \ + IOMUX_PAD(0x0364, 0x0050, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__MMDC_MMDC_DEBUG_34 \ + IOMUX_PAD(0x0364, 0x0050, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT11__SIMBA_TRACE_8 \ + IOMUX_PAD(0x0364, 0x0050, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_D_12 \ + IOMUX_PAD(0x0368, 0x0054, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__WEIM_WEIM_D_8 \ + IOMUX_PAD(0x0368, 0x0054, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__PCIE_CTRL_DIAG_STATUS_BUS_MUX_16 \ + IOMUX_PAD(0x0368, 0x0054, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__UART4_TXD \ + IOMUX_PAD(0x0368, 0x0054, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__UART4_RXD \ + IOMUX_PAD(0x0368, 0x0054, 3, 0x0914, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 \ + IOMUX_PAD(0x0368, 0x0054, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__GPIO_5_30 \ + IOMUX_PAD(0x0368, 0x0054, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__MMDC_MMDC_DEBUG_35 \ + IOMUX_PAD(0x0368, 0x0054, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT12__SIMBA_TRACE_9 \ + IOMUX_PAD(0x0368, 0x0054, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_D_13 \ + IOMUX_PAD(0x036C, 0x0058, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__WEIM_WEIM_D_9 \ + IOMUX_PAD(0x036C, 0x0058, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__PCIE_CTRL_DIAG_STATUS_BUS_MUX_17 \ + IOMUX_PAD(0x036C, 0x0058, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__UART4_TXD \ + IOMUX_PAD(0x036C, 0x0058, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__UART4_RXD \ + IOMUX_PAD(0x036C, 0x0058, 3, 0x0914, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 \ + IOMUX_PAD(0x036C, 0x0058, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__GPIO_5_31 \ + IOMUX_PAD(0x036C, 0x0058, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__MMDC_MMDC_DEBUG_36 \ + IOMUX_PAD(0x036C, 0x0058, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT13__SIMBA_TRACE_10 \ + IOMUX_PAD(0x036C, 0x0058, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_D_14 \ + IOMUX_PAD(0x0370, 0x005C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__WEIM_WEIM_D_10 \ + IOMUX_PAD(0x0370, 0x005C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__PCIE_CTRL_DIAG_STATUS_BUS_MUX_18 \ + IOMUX_PAD(0x0370, 0x005C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__UART5_TXD \ + IOMUX_PAD(0x0370, 0x005C, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__UART5_RXD \ + IOMUX_PAD(0x0370, 0x005C, 3, 0x091C, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 \ + IOMUX_PAD(0x0370, 0x005C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__GPIO_6_0 \ + IOMUX_PAD(0x0370, 0x005C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__MMDC_MMDC_DEBUG_37 \ + IOMUX_PAD(0x0370, 0x005C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT14__SIMBA_TRACE_11 \ + IOMUX_PAD(0x0370, 0x005C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_D_15 \ + IOMUX_PAD(0x0374, 0x0060, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__WEIM_WEIM_D_11 \ + IOMUX_PAD(0x0374, 0x0060, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__PCIE_CTRL_DIAG_STATUS_BUS_MUX_19 \ + IOMUX_PAD(0x0374, 0x0060, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__UART5_TXD \ + IOMUX_PAD(0x0374, 0x0060, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__UART5_RXD \ + IOMUX_PAD(0x0374, 0x0060, 3, 0x091C, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 \ + IOMUX_PAD(0x0374, 0x0060, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__GPIO_6_1 \ + IOMUX_PAD(0x0374, 0x0060, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__MMDC_MMDC_DEBUG_38 \ + IOMUX_PAD(0x0374, 0x0060, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT15__SIMBA_TRACE_12 \ + IOMUX_PAD(0x0374, 0x0060, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_D_16 \ + IOMUX_PAD(0x0378, 0x0064, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__WEIM_WEIM_D_12 \ + IOMUX_PAD(0x0378, 0x0064, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__PCIE_CTRL_DIAG_STATUS_BUS_MUX_20 \ + IOMUX_PAD(0x0378, 0x0064, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__UART4_CTS \ + IOMUX_PAD(0x0378, 0x0064, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__UART4_RTS \ + IOMUX_PAD(0x0378, 0x0064, 3, 0x0910, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 \ + IOMUX_PAD(0x0378, 0x0064, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__GPIO_6_2 \ + IOMUX_PAD(0x0378, 0x0064, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__MMDC_MMDC_DEBUG_39 \ + IOMUX_PAD(0x0378, 0x0064, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT16__SIMBA_TRACE_13 \ + IOMUX_PAD(0x0378, 0x0064, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_D_17 \ + IOMUX_PAD(0x037C, 0x0068, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__WEIM_WEIM_D_13 \ + IOMUX_PAD(0x037C, 0x0068, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__PCIE_CTRL_DIAG_STATUS_BUS_MUX_21 \ + IOMUX_PAD(0x037C, 0x0068, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__UART4_CTS \ + IOMUX_PAD(0x037C, 0x0068, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__UART4_RTS \ + IOMUX_PAD(0x037C, 0x0068, 3, 0x0910, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 \ + IOMUX_PAD(0x037C, 0x0068, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__GPIO_6_3 \ + IOMUX_PAD(0x037C, 0x0068, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__MMDC_MMDC_DEBUG_40 \ + IOMUX_PAD(0x037C, 0x0068, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT17__SIMBA_TRACE_14 \ + IOMUX_PAD(0x037C, 0x0068, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_D_18 \ + IOMUX_PAD(0x0380, 0x006C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__WEIM_WEIM_D_14 \ + IOMUX_PAD(0x0380, 0x006C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__PCIE_CTRL_DIAG_STATUS_BUS_MUX_22 \ + IOMUX_PAD(0x0380, 0x006C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__UART5_CTS \ + IOMUX_PAD(0x0380, 0x006C, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__UART5_RTS \ + IOMUX_PAD(0x0380, 0x006C, 3, 0x0918, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 \ + IOMUX_PAD(0x0380, 0x006C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__GPIO_6_4 \ + IOMUX_PAD(0x0380, 0x006C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__MMDC_MMDC_DEBUG_41 \ + IOMUX_PAD(0x0380, 0x006C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT18__SIMBA_TRACE_15 \ + IOMUX_PAD(0x0380, 0x006C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_D_19 \ + IOMUX_PAD(0x0384, 0x0070, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__WEIM_WEIM_D_15 \ + IOMUX_PAD(0x0384, 0x0070, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__PCIE_CTRL_DIAG_STATUS_BUS_MUX_23 \ + IOMUX_PAD(0x0384, 0x0070, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__UART5_CTS \ + IOMUX_PAD(0x0384, 0x0070, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__UART5_RTS \ + IOMUX_PAD(0x0384, 0x0070, 3, 0x0918, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 \ + IOMUX_PAD(0x0384, 0x0070, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__GPIO_6_5 \ + IOMUX_PAD(0x0384, 0x0070, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__MMDC_MMDC_DEBUG_42 \ + IOMUX_PAD(0x0384, 0x0070, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT19__ANATOP_ANATOP_TESTO_9 \ + IOMUX_PAD(0x0384, 0x0070, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT4__IPU1_CSI0_D_4 \ + IOMUX_PAD(0x0388, 0x0074, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__WEIM_WEIM_D_2 \ + IOMUX_PAD(0x0388, 0x0074, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__ECSPI1_SCLK \ + IOMUX_PAD(0x0388, 0x0074, 2, 0x07D8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__KPP_COL_5 \ + IOMUX_PAD(0x0388, 0x0074, 3, 0x08C0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC \ + IOMUX_PAD(0x0388, 0x0074, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__GPIO_5_22 \ + IOMUX_PAD(0x0388, 0x0074, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__MMDC_MMDC_DEBUG_43 \ + IOMUX_PAD(0x0388, 0x0074, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT4__SIMBA_TRACE_1 \ + IOMUX_PAD(0x0388, 0x0074, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT5__IPU1_CSI0_D_5 \ + IOMUX_PAD(0x038C, 0x0078, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__WEIM_WEIM_D_3 \ + IOMUX_PAD(0x038C, 0x0078, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__ECSPI1_MOSI \ + IOMUX_PAD(0x038C, 0x0078, 2, 0x07E0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__KPP_ROW_5 \ + IOMUX_PAD(0x038C, 0x0078, 3, 0x08CC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD \ + IOMUX_PAD(0x038C, 0x0078, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__GPIO_5_23 \ + IOMUX_PAD(0x038C, 0x0078, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44 \ + IOMUX_PAD(0x038C, 0x0078, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT5__SIMBA_TRACE_2 \ + IOMUX_PAD(0x038C, 0x0078, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT6__IPU1_CSI0_D_6 \ + IOMUX_PAD(0x0390, 0x007C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__WEIM_WEIM_D_4 \ + IOMUX_PAD(0x0390, 0x007C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__ECSPI1_MISO \ + IOMUX_PAD(0x0390, 0x007C, 2, 0x07DC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__KPP_COL_6 \ + IOMUX_PAD(0x0390, 0x007C, 3, 0x08C4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS \ + IOMUX_PAD(0x0390, 0x007C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__GPIO_5_24 \ + IOMUX_PAD(0x0390, 0x007C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__MMDC_MMDC_DEBUG_45 \ + IOMUX_PAD(0x0390, 0x007C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT6__SIMBA_TRACE_3 \ + IOMUX_PAD(0x0390, 0x007C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT7__IPU1_CSI0_D_7 \ + IOMUX_PAD(0x0394, 0x0080, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__WEIM_WEIM_D_5 \ + IOMUX_PAD(0x0394, 0x0080, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__ECSPI1_SS0 \ + IOMUX_PAD(0x0394, 0x0080, 2, 0x07E4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__KPP_ROW_6 \ + IOMUX_PAD(0x0394, 0x0080, 3, 0x08D0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD \ + IOMUX_PAD(0x0394, 0x0080, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__GPIO_5_25 \ + IOMUX_PAD(0x0394, 0x0080, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__MMDC_MMDC_DEBUG_46 \ + IOMUX_PAD(0x0394, 0x0080, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT7__SIMBA_TRACE_4 \ + IOMUX_PAD(0x0394, 0x0080, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT8__IPU1_CSI0_D_8 \ + IOMUX_PAD(0x0398, 0x0084, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__WEIM_WEIM_D_6 \ + IOMUX_PAD(0x0398, 0x0084, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__ECSPI2_SCLK \ + IOMUX_PAD(0x0398, 0x0084, 2, 0x07F4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__KPP_COL_7 \ + IOMUX_PAD(0x0398, 0x0084, 3, 0x08C8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__I2C1_SDA \ + IOMUX_PAD(0x0398, 0x0084, 4 | IOMUX_CONFIG_SION, 0x086C, 0, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__GPIO_5_26 \ + IOMUX_PAD(0x0398, 0x0084, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__MMDC_MMDC_DEBUG_47 \ + IOMUX_PAD(0x0398, 0x0084, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT8__SIMBA_TRACE_5 \ + IOMUX_PAD(0x0398, 0x0084, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DAT9__IPU1_CSI0_D_9 \ + IOMUX_PAD(0x039C, 0x0088, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__WEIM_WEIM_D_7 \ + IOMUX_PAD(0x039C, 0x0088, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__ECSPI2_MOSI \ + IOMUX_PAD(0x039C, 0x0088, 2, 0x07FC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__KPP_ROW_7 \ + IOMUX_PAD(0x039C, 0x0088, 3, 0x08D4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__I2C1_SCL \ + IOMUX_PAD(0x039C, 0x0088, 4 | IOMUX_CONFIG_SION, 0x0868, 0, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__GPIO_5_27 \ + IOMUX_PAD(0x039C, 0x0088, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__MMDC_MMDC_DEBUG_48 \ + IOMUX_PAD(0x039C, 0x0088, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DAT9__SIMBA_TRACE_6 \ + IOMUX_PAD(0x039C, 0x0088, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN \ + IOMUX_PAD(0x03A0, 0x008C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DATA_EN__WEIM_WEIM_D_0 \ + IOMUX_PAD(0x03A0, 0x008C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DATA_EN__PCIE_CTRL_DIAG_STATUS_BUS_MUX_14 \ + IOMUX_PAD(0x03A0, 0x008C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 \ + IOMUX_PAD(0x03A0, 0x008C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DATA_EN__GPIO_5_20 \ + IOMUX_PAD(0x03A0, 0x008C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DATA_EN__MMDC_MMDC_DEBUG_31 \ + IOMUX_PAD(0x03A0, 0x008C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_DATA_EN__SIMBA_TRCLK \ + IOMUX_PAD(0x03A0, 0x008C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC \ + IOMUX_PAD(0x03A4, 0x0090, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_MCLK__PCIE_CTRL_DIAG_STATUS_BUS_MUX_13 \ + IOMUX_PAD(0x03A4, 0x0090, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_MCLK__CCM_CLKO \ + IOMUX_PAD(0x03A4, 0x0090, 3, 0x0000, 0, MX6DL_CCM_CLK0_PAD_CTRL) +#define MX6DL_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 \ + IOMUX_PAD(0x03A4, 0x0090, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_MCLK__GPIO_5_19 \ + IOMUX_PAD(0x03A4, 0x0090, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_MCLK__MMDC_MMDC_DEBUG_30 \ + IOMUX_PAD(0x03A4, 0x0090, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_MCLK__SIMBA_TRCTL \ + IOMUX_PAD(0x03A4, 0x0090, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK \ + IOMUX_PAD(0x03A8, 0x0094, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_PIXCLK__PCIE_CTRL_DIAG_STATUS_BUS_MUX_12 \ + IOMUX_PAD(0x03A8, 0x0094, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 \ + IOMUX_PAD(0x03A8, 0x0094, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_PIXCLK__GPIO_5_18 \ + IOMUX_PAD(0x03A8, 0x0094, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_PIXCLK__MMDC_MMDC_DEBUG_29 \ + IOMUX_PAD(0x03A8, 0x0094, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_PIXCLK__SIMBA_EVENTO \ + IOMUX_PAD(0x03A8, 0x0094, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC \ + IOMUX_PAD(0x03AC, 0x0098, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_VSYNC__WEIM_WEIM_D_1 \ + IOMUX_PAD(0x03AC, 0x0098, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_VSYNC__PCIE_CTRL_DIAG_STATUS_BUS_MUX_15 \ + IOMUX_PAD(0x03AC, 0x0098, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 \ + IOMUX_PAD(0x03AC, 0x0098, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_VSYNC__GPIO_5_21 \ + IOMUX_PAD(0x03AC, 0x0098, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_VSYNC__MMDC_MMDC_DEBUG_32 \ + IOMUX_PAD(0x03AC, 0x0098, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_CSI0_VSYNC__SIMBA_TRACE_0 \ + IOMUX_PAD(0x03AC, 0x0098, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK \ + IOMUX_PAD(0x03B0, 0x009C, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DI0_DISP_CLK__LCDIF_CLK \ + IOMUX_PAD(0x03B0, 0x009C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_DISP_CLK__MIPI_CORE_DPHY_TEST_OUT_28 \ + IOMUX_PAD(0x03B0, 0x009C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 \ + IOMUX_PAD(0x03B0, 0x009C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_DISP_CLK__GPIO_4_16 \ + IOMUX_PAD(0x03B0, 0x009C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_DISP_CLK__MMDC_MMDC_DEBUG_0 \ + IOMUX_PAD(0x03B0, 0x009C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_DISP_CLK__TPSMP_HDATA_DIR \ + IOMUX_PAD(0x03B0, 0x009C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_DISP_CLK__LCDIF_WR_RWN \ + IOMUX_PAD(0x03B0, 0x009C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15 \ + IOMUX_PAD(0x03B4, 0x00A0, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DI0_PIN15__LCDIF_ENABLE \ + IOMUX_PAD(0x03B4, 0x00A0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__AUDMUX_AUD6_TXC \ + IOMUX_PAD(0x03B4, 0x00A0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__MIPI_CORE_DPHY_TEST_OUT_29 \ + IOMUX_PAD(0x03B4, 0x00A0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 \ + IOMUX_PAD(0x03B4, 0x00A0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__GPIO_4_17 \ + IOMUX_PAD(0x03B4, 0x00A0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__MMDC_MMDC_DEBUG_1 \ + IOMUX_PAD(0x03B4, 0x00A0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__PL301_SIM_MX6DL_PER1_HSIZE_0 \ + IOMUX_PAD(0x03B4, 0x00A0, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN15__LCDIF_RD_E \ + IOMUX_PAD(0x03B4, 0x00A0, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN2 \ + IOMUX_PAD(0x03B8, 0x00A4, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DI0_PIN2__LCDIF_HSYNC \ + IOMUX_PAD(0x03B8, 0x00A4, 1, 0x08D8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__AUDMUX_AUD6_TXD \ + IOMUX_PAD(0x03B8, 0x00A4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__MIPI_CORE_DPHY_TEST_OUT_30 \ + IOMUX_PAD(0x03B8, 0x00A4, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 \ + IOMUX_PAD(0x03B8, 0x00A4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__GPIO_4_18 \ + IOMUX_PAD(0x03B8, 0x00A4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__MMDC_MMDC_DEBUG_2 \ + IOMUX_PAD(0x03B8, 0x00A4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__PL301_SIM_MX6DL_PER1_HADDR_9 \ + IOMUX_PAD(0x03B8, 0x00A4, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN2__LCDIF_RS \ + IOMUX_PAD(0x03B8, 0x00A4, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN3 \ + IOMUX_PAD(0x03BC, 0x00A8, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DI0_PIN3__LCDIF_VSYNC \ + IOMUX_PAD(0x03BC, 0x00A8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS \ + IOMUX_PAD(0x03BC, 0x00A8, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__MIPI_CORE_DPHY_TEST_OUT_31 \ + IOMUX_PAD(0x03BC, 0x00A8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 \ + IOMUX_PAD(0x03BC, 0x00A8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__GPIO_4_19 \ + IOMUX_PAD(0x03BC, 0x00A8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__MMDC_MMDC_DEBUG_3 \ + IOMUX_PAD(0x03BC, 0x00A8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__PL301_SIM_MX6DL_PER1_HADDR_10 \ + IOMUX_PAD(0x03BC, 0x00A8, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN3__LCDIF_CS \ + IOMUX_PAD(0x03BC, 0x00A8, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DI0_PIN4__IPU1_DI0_PIN4 \ + IOMUX_PAD(0x03C0, 0x00AC, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DI0_PIN4__LCDIF_BUSY \ + IOMUX_PAD(0x03C0, 0x00AC, 1, 0x08D8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__AUDMUX_AUD6_RXD \ + IOMUX_PAD(0x03C0, 0x00AC, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__USDHC1_WP \ + IOMUX_PAD(0x03C0, 0x00AC, 3, 0x092C, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__SDMA_DEBUG_YIELD \ + IOMUX_PAD(0x03C0, 0x00AC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__GPIO_4_20 \ + IOMUX_PAD(0x03C0, 0x00AC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__MMDC_MMDC_DEBUG_4 \ + IOMUX_PAD(0x03C0, 0x00AC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__PL301_SIM_MX6DL_PER1_HADDR_11 \ + IOMUX_PAD(0x03C0, 0x00AC, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DI0_PIN4__LCDIF_RESET \ + IOMUX_PAD(0x03C0, 0x00AC, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0 \ + IOMUX_PAD(0x03C4, 0x00B0, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT0__LCDIF_DAT_0 \ + IOMUX_PAD(0x03C4, 0x00B0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT0__ECSPI3_SCLK \ + IOMUX_PAD(0x03C4, 0x00B0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT0__USDHC1_USDHC_DEBUG_0 \ + IOMUX_PAD(0x03C4, 0x00B0, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN \ + IOMUX_PAD(0x03C4, 0x00B0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT0__GPIO_4_21 \ + IOMUX_PAD(0x03C4, 0x00B0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT0__MMDC_MMDC_DEBUG_5 \ + IOMUX_PAD(0x03C4, 0x00B0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT0__PL301_SIM_MX6DL_PER1_HSIZE_1 \ + IOMUX_PAD(0x03C4, 0x00B0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1 \ + IOMUX_PAD(0x03C8, 0x00B4, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT1__LCDIF_DAT_1 \ + IOMUX_PAD(0x03C8, 0x00B4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT1__ECSPI3_MOSI \ + IOMUX_PAD(0x03C8, 0x00B4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT1__USDHC1_USDHC_DEBUG_1 \ + IOMUX_PAD(0x03C8, 0x00B4, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL \ + IOMUX_PAD(0x03C8, 0x00B4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT1__GPIO_4_22 \ + IOMUX_PAD(0x03C8, 0x00B4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT1__MMDC_MMDC_DEBUG_6 \ + IOMUX_PAD(0x03C8, 0x00B4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT1__PL301_SIM_MX6DL_PER1_HADDR_12 \ + IOMUX_PAD(0x03C8, 0x00B4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10 \ + IOMUX_PAD(0x03CC, 0x00B8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT10__LCDIF_DAT_10 \ + IOMUX_PAD(0x03CC, 0x00B8, 1, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT10__USDHC1_USDHC_DEBUG_6 \ + IOMUX_PAD(0x03CC, 0x00B8, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 \ + IOMUX_PAD(0x03CC, 0x00B8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT10__GPIO_4_31 \ + IOMUX_PAD(0x03CC, 0x00B8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT10__MMDC_MMDC_DEBUG_15 \ + IOMUX_PAD(0x03CC, 0x00B8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT10__PL301_SIM_MX6DL_PER1_HADDR_21 \ + IOMUX_PAD(0x03CC, 0x00B8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11 \ + IOMUX_PAD(0x03D0, 0x00BC, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT11__LCDIF_DAT_11 \ + IOMUX_PAD(0x03D0, 0x00BC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT11__USDHC1_USDHC_DEBUG_7 \ + IOMUX_PAD(0x03D0, 0x00BC, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 \ + IOMUX_PAD(0x03D0, 0x00BC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT11__GPIO_5_5 \ + IOMUX_PAD(0x03D0, 0x00BC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT11__MMDC_MMDC_DEBUG_16 \ + IOMUX_PAD(0x03D0, 0x00BC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT11__PL301_SIM_MX6DL_PER1_HADDR_22 \ + IOMUX_PAD(0x03D0, 0x00BC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12 \ + IOMUX_PAD(0x03D4, 0x00C0, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT12__LCDIF_DAT_12 \ + IOMUX_PAD(0x03D4, 0x00C0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 \ + IOMUX_PAD(0x03D4, 0x00C0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT12__GPIO_5_6 \ + IOMUX_PAD(0x03D4, 0x00C0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT12__MMDC_MMDC_DEBUG_17 \ + IOMUX_PAD(0x03D4, 0x00C0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT12__PL301_SIM_MX6DL_PER1_HADDR_23 \ + IOMUX_PAD(0x03D4, 0x00C0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13 \ + IOMUX_PAD(0x03D8, 0x00C4, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT13__LCDIF_DAT_13 \ + IOMUX_PAD(0x03D8, 0x00C4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS \ + IOMUX_PAD(0x03D8, 0x00C4, 3, 0x07BC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 \ + IOMUX_PAD(0x03D8, 0x00C4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT13__GPIO_5_7 \ + IOMUX_PAD(0x03D8, 0x00C4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT13__MMDC_MMDC_DEBUG_18 \ + IOMUX_PAD(0x03D8, 0x00C4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT13__PL301_SIM_MX6DL_PER1_HADDR_24 \ + IOMUX_PAD(0x03D8, 0x00C4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14 \ + IOMUX_PAD(0x03DC, 0x00C8, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT14__LCDIF_DAT_14 \ + IOMUX_PAD(0x03DC, 0x00C8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC \ + IOMUX_PAD(0x03DC, 0x00C8, 3, 0x07B8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 \ + IOMUX_PAD(0x03DC, 0x00C8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT14__GPIO_5_8 \ + IOMUX_PAD(0x03DC, 0x00C8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT14__MMDC_MMDC_DEBUG_19 \ + IOMUX_PAD(0x03DC, 0x00C8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT14__PL301_SIM_MX6DL_PER1_HSIZE_2 \ + IOMUX_PAD(0x03DC, 0x00C8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15 \ + IOMUX_PAD(0x03E0, 0x00CC, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT15__LCDIF_DAT_15 \ + IOMUX_PAD(0x03E0, 0x00CC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT15__ECSPI1_SS1 \ + IOMUX_PAD(0x03E0, 0x00CC, 2, 0x07E8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT15__ECSPI2_SS1 \ + IOMUX_PAD(0x03E0, 0x00CC, 3, 0x0804, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 \ + IOMUX_PAD(0x03E0, 0x00CC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT15__GPIO_5_9 \ + IOMUX_PAD(0x03E0, 0x00CC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT15__MMDC_MMDC_DEBUG_20 \ + IOMUX_PAD(0x03E0, 0x00CC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT15__PL301_SIM_MX6DL_PER1_HADDR_25 \ + IOMUX_PAD(0x03E0, 0x00CC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16 \ + IOMUX_PAD(0x03E4, 0x00D0, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT16__LCDIF_DAT_16 \ + IOMUX_PAD(0x03E4, 0x00D0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT16__ECSPI2_MOSI \ + IOMUX_PAD(0x03E4, 0x00D0, 2, 0x07FC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC \ + IOMUX_PAD(0x03E4, 0x00D0, 3, 0x07C0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT16__SDMA_SDMA_EXT_EVENT_0 \ + IOMUX_PAD(0x03E4, 0x00D0, 4, 0x08E8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT16__GPIO_5_10 \ + IOMUX_PAD(0x03E4, 0x00D0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT16__MMDC_MMDC_DEBUG_21 \ + IOMUX_PAD(0x03E4, 0x00D0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT16__PL301_SIM_MX6DL_PER1_HADDR_26 \ + IOMUX_PAD(0x03E4, 0x00D0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17 \ + IOMUX_PAD(0x03E8, 0x00D4, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT17__LCDIF_DAT_17 \ + IOMUX_PAD(0x03E8, 0x00D4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT17__ECSPI2_MISO \ + IOMUX_PAD(0x03E8, 0x00D4, 2, 0x07F8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD \ + IOMUX_PAD(0x03E8, 0x00D4, 3, 0x07B4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT17__SDMA_SDMA_EXT_EVENT_1 \ + IOMUX_PAD(0x03E8, 0x00D4, 4, 0x08EC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT17__GPIO_5_11 \ + IOMUX_PAD(0x03E8, 0x00D4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT17__MMDC_MMDC_DEBUG_22 \ + IOMUX_PAD(0x03E8, 0x00D4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT17__PL301_SIM_MX6DL_PER1_HADDR_27 \ + IOMUX_PAD(0x03E8, 0x00D4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18 \ + IOMUX_PAD(0x03EC, 0x00D8, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT18__LCDIF_DAT_18 \ + IOMUX_PAD(0x03EC, 0x00D8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT18__ECSPI2_SS0 \ + IOMUX_PAD(0x03EC, 0x00D8, 2, 0x0800, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS \ + IOMUX_PAD(0x03EC, 0x00D8, 3, 0x07C4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS \ + IOMUX_PAD(0x03EC, 0x00D8, 4, 0x07A4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT18__GPIO_5_12 \ + IOMUX_PAD(0x03EC, 0x00D8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT18__MMDC_MMDC_DEBUG_23 \ + IOMUX_PAD(0x03EC, 0x00D8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT18__WEIM_WEIM_CS_2 \ + IOMUX_PAD(0x03EC, 0x00D8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19 \ + IOMUX_PAD(0x03F0, 0x00DC, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT19__LCDIF_DAT_19 \ + IOMUX_PAD(0x03F0, 0x00DC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT19__ECSPI2_SCLK \ + IOMUX_PAD(0x03F0, 0x00DC, 2, 0x07F4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD \ + IOMUX_PAD(0x03F0, 0x00DC, 3, 0x07B0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC \ + IOMUX_PAD(0x03F0, 0x00DC, 4, 0x07A0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT19__GPIO_5_13 \ + IOMUX_PAD(0x03F0, 0x00DC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT19__MMDC_MMDC_DEBUG_24 \ + IOMUX_PAD(0x03F0, 0x00DC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT19__WEIM_WEIM_CS_3 \ + IOMUX_PAD(0x03F0, 0x00DC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2 \ + IOMUX_PAD(0x03F4, 0x00E0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__LCDIF_DAT_2 \ + IOMUX_PAD(0x03F4, 0x00E0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__ECSPI3_MISO \ + IOMUX_PAD(0x03F4, 0x00E0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__USDHC1_USDHC_DEBUG_2 \ + IOMUX_PAD(0x03F4, 0x00E0, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__SDMA_DEBUG_MODE \ + IOMUX_PAD(0x03F4, 0x00E0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__GPIO_4_23 \ + IOMUX_PAD(0x03F4, 0x00E0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__MMDC_MMDC_DEBUG_7 \ + IOMUX_PAD(0x03F4, 0x00E0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT2__PL301_SIM_MX6DL_PER1_HADDR_13 \ + IOMUX_PAD(0x03F4, 0x00E0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20 \ + IOMUX_PAD(0x03F8, 0x00E4, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT20__LCDIF_DAT_20 \ + IOMUX_PAD(0x03F8, 0x00E4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT20__ECSPI1_SCLK \ + IOMUX_PAD(0x03F8, 0x00E4, 2, 0x07D8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC \ + IOMUX_PAD(0x03F8, 0x00E4, 3, 0x07A8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 \ + IOMUX_PAD(0x03F8, 0x00E4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT20__GPIO_5_14 \ + IOMUX_PAD(0x03F8, 0x00E4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT20__MMDC_MMDC_DEBUG_25 \ + IOMUX_PAD(0x03F8, 0x00E4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT20__PL301_SIM_MX6DL_PER1_HADDR_28 \ + IOMUX_PAD(0x03F8, 0x00E4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21 \ + IOMUX_PAD(0x03FC, 0x00E8, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT21__LCDIF_DAT_21 \ + IOMUX_PAD(0x03FC, 0x00E8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT21__ECSPI1_MOSI \ + IOMUX_PAD(0x03FC, 0x00E8, 2, 0x07E0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD \ + IOMUX_PAD(0x03FC, 0x00E8, 3, 0x079C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 \ + IOMUX_PAD(0x03FC, 0x00E8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT21__GPIO_5_15 \ + IOMUX_PAD(0x03FC, 0x00E8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT21__MMDC_MMDC_DEBUG_26 \ + IOMUX_PAD(0x03FC, 0x00E8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT21__PL301_SIM_MX6DL_PER1_HADDR_29 \ + IOMUX_PAD(0x03FC, 0x00E8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22 \ + IOMUX_PAD(0x0400, 0x00EC, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT22__LCDIF_DAT_22 \ + IOMUX_PAD(0x0400, 0x00EC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT22__ECSPI1_MISO \ + IOMUX_PAD(0x0400, 0x00EC, 2, 0x07DC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS \ + IOMUX_PAD(0x0400, 0x00EC, 3, 0x07AC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 \ + IOMUX_PAD(0x0400, 0x00EC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT22__GPIO_5_16 \ + IOMUX_PAD(0x0400, 0x00EC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT22__MMDC_MMDC_DEBUG_27 \ + IOMUX_PAD(0x0400, 0x00EC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT22__PL301_SIM_MX6DL_PER1_HADDR_30 \ + IOMUX_PAD(0x0400, 0x00EC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23 \ + IOMUX_PAD(0x0404, 0x00F0, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT23__LCDIF_DAT_23 \ + IOMUX_PAD(0x0404, 0x00F0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT23__ECSPI1_SS0 \ + IOMUX_PAD(0x0404, 0x00F0, 2, 0x07E4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD \ + IOMUX_PAD(0x0404, 0x00F0, 3, 0x0798, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 \ + IOMUX_PAD(0x0404, 0x00F0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT23__GPIO_5_17 \ + IOMUX_PAD(0x0404, 0x00F0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT23__MMDC_MMDC_DEBUG_28 \ + IOMUX_PAD(0x0404, 0x00F0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT23__PL301_SIM_MX6DL_PER1_HADDR_31 \ + IOMUX_PAD(0x0404, 0x00F0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3 \ + IOMUX_PAD(0x0408, 0x00F4, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT3__LCDIF_DAT_3 \ + IOMUX_PAD(0x0408, 0x00F4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT3__ECSPI3_SS0 \ + IOMUX_PAD(0x0408, 0x00F4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT3__USDHC1_USDHC_DEBUG_3 \ + IOMUX_PAD(0x0408, 0x00F4, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR \ + IOMUX_PAD(0x0408, 0x00F4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT3__GPIO_4_24 \ + IOMUX_PAD(0x0408, 0x00F4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT3__MMDC_MMDC_DEBUG_8 \ + IOMUX_PAD(0x0408, 0x00F4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT3__PL301_SIM_MX6DL_PER1_HADDR_14 \ + IOMUX_PAD(0x0408, 0x00F4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4 \ + IOMUX_PAD(0x040C, 0x00F8, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT4__LCDIF_DAT_4 \ + IOMUX_PAD(0x040C, 0x00F8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT4__ECSPI3_SS1 \ + IOMUX_PAD(0x040C, 0x00F8, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT4__USDHC1_USDHC_DEBUG_4 \ + IOMUX_PAD(0x040C, 0x00F8, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB \ + IOMUX_PAD(0x040C, 0x00F8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT4__GPIO_4_25 \ + IOMUX_PAD(0x040C, 0x00F8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT4__MMDC_MMDC_DEBUG_9 \ + IOMUX_PAD(0x040C, 0x00F8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT4__PL301_SIM_MX6DL_PER1_HADDR_15 \ + IOMUX_PAD(0x040C, 0x00F8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5 \ + IOMUX_PAD(0x0410, 0x00FC, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT5__LCDIF_DAT_5 \ + IOMUX_PAD(0x0410, 0x00FC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT5__ECSPI3_SS2 \ + IOMUX_PAD(0x0410, 0x00FC, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT5__AUDMUX_AUD6_RXFS \ + IOMUX_PAD(0x0410, 0x00FC, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS \ + IOMUX_PAD(0x0410, 0x00FC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT5__GPIO_4_26 \ + IOMUX_PAD(0x0410, 0x00FC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT5__MMDC_MMDC_DEBUG_10 \ + IOMUX_PAD(0x0410, 0x00FC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT5__PL301_SIM_MX6DL_PER1_HADDR_16 \ + IOMUX_PAD(0x0410, 0x00FC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6 \ + IOMUX_PAD(0x0414, 0x0100, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT6__LCDIF_DAT_6 \ + IOMUX_PAD(0x0414, 0x0100, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT6__ECSPI3_SS3 \ + IOMUX_PAD(0x0414, 0x0100, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT6__AUDMUX_AUD6_RXC \ + IOMUX_PAD(0x0414, 0x0100, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE \ + IOMUX_PAD(0x0414, 0x0100, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT6__GPIO_4_27 \ + IOMUX_PAD(0x0414, 0x0100, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT6__MMDC_MMDC_DEBUG_11 \ + IOMUX_PAD(0x0414, 0x0100, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT6__PL301_SIM_MX6DL_PER1_HADDR_17 \ + IOMUX_PAD(0x0414, 0x0100, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7 \ + IOMUX_PAD(0x0418, 0x0104, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT7__LCDIF_DAT_7 \ + IOMUX_PAD(0x0418, 0x0104, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT7__ECSPI3_RDY \ + IOMUX_PAD(0x0418, 0x0104, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT7__USDHC1_USDHC_DEBUG_5 \ + IOMUX_PAD(0x0418, 0x0104, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 \ + IOMUX_PAD(0x0418, 0x0104, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT7__GPIO_4_28 \ + IOMUX_PAD(0x0418, 0x0104, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT7__MMDC_MMDC_DEBUG_12 \ + IOMUX_PAD(0x0418, 0x0104, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT7__PL301_SIM_MX6DL_PER1_HADDR_18 \ + IOMUX_PAD(0x0418, 0x0104, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8 \ + IOMUX_PAD(0x041C, 0x0108, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT8__LCDIF_DAT_8 \ + IOMUX_PAD(0x041C, 0x0108, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT8__PWM1_PWMO \ + IOMUX_PAD(0x041C, 0x0108, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT8__WDOG1_WDOG_B \ + IOMUX_PAD(0x041C, 0x0108, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 \ + IOMUX_PAD(0x041C, 0x0108, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT8__GPIO_4_29 \ + IOMUX_PAD(0x041C, 0x0108, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT8__MMDC_MMDC_DEBUG_13 \ + IOMUX_PAD(0x041C, 0x0108, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT8__PL301_SIM_MX6DL_PER1_HADDR_19 \ + IOMUX_PAD(0x041C, 0x0108, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9 \ + IOMUX_PAD(0x0420, 0x010C, 0, 0x0000, 0, MX6DL_DISP_PAD_CLT) +#define MX6DL_PAD_DISP0_DAT9__LCDIF_DAT_9 \ + IOMUX_PAD(0x0420, 0x010C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT9__PWM2_PWMO \ + IOMUX_PAD(0x0420, 0x010C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT9__WDOG2_WDOG_B \ + IOMUX_PAD(0x0420, 0x010C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 \ + IOMUX_PAD(0x0420, 0x010C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT9__GPIO_4_30 \ + IOMUX_PAD(0x0420, 0x010C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT9__MMDC_MMDC_DEBUG_14 \ + IOMUX_PAD(0x0420, 0x010C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_DISP0_DAT9__PL301_SIM_MX6DL_PER1_HADDR_20 \ + IOMUX_PAD(0x0420, 0x010C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A0__MMDC_DRAM_A_0 \ + IOMUX_PAD(0x0424, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A1__MMDC_DRAM_A_1 \ + IOMUX_PAD(0x0428, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A10__MMDC_DRAM_A_10 \ + IOMUX_PAD(0x042C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A11__MMDC_DRAM_A_11 \ + IOMUX_PAD(0x0430, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A12__MMDC_DRAM_A_12 \ + IOMUX_PAD(0x0434, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A13__MMDC_DRAM_A_13 \ + IOMUX_PAD(0x0438, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A14__MMDC_DRAM_A_14 \ + IOMUX_PAD(0x043C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A15__MMDC_DRAM_A_15 \ + IOMUX_PAD(0x0440, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A2__MMDC_DRAM_A_2 \ + IOMUX_PAD(0x0444, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A3__MMDC_DRAM_A_3 \ + IOMUX_PAD(0x0448, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A4__MMDC_DRAM_A_4 \ + IOMUX_PAD(0x044C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A5__MMDC_DRAM_A_5 \ + IOMUX_PAD(0x0450, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A6__MMDC_DRAM_A_6 \ + IOMUX_PAD(0x0454, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A7__MMDC_DRAM_A_7 \ + IOMUX_PAD(0x0458, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A8__MMDC_DRAM_A_8 \ + IOMUX_PAD(0x045C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_A9__MMDC_DRAM_A_9 \ + IOMUX_PAD(0x0460, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_CAS__MMDC_DRAM_CAS \ + IOMUX_PAD(0x0464, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_CS0__MMDC_DRAM_CS_0 \ + IOMUX_PAD(0x0468, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_CS1__MMDC_DRAM_CS_1 \ + IOMUX_PAD(0x046C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D0__MMDC_DRAM_D_0 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D1__MMDC_DRAM_D_1 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D10__MMDC_DRAM_D_10 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D11__MMDC_DRAM_D_11 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D12__MMDC_DRAM_D_12 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D13__MMDC_DRAM_D_13 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D14__MMDC_DRAM_D_14 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D15__MMDC_DRAM_D_15 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D16__MMDC_DRAM_D_16 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D17__MMDC_DRAM_D_17 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D18__MMDC_DRAM_D_18 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D19__MMDC_DRAM_D_19 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D2__MMDC_DRAM_D_2 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D20__MMDC_DRAM_D_20 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D21__MMDC_DRAM_D_21 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D22__MMDC_DRAM_D_22 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D23__MMDC_DRAM_D_23 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D24__MMDC_DRAM_D_24 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D25__MMDC_DRAM_D_25 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D26__MMDC_DRAM_D_26 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D27__MMDC_DRAM_D_27 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D28__MMDC_DRAM_D_28 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D29__MMDC_DRAM_D_29 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D3__MMDC_DRAM_D_3 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D30__MMDC_DRAM_D_30 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D31__MMDC_DRAM_D_31 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D32__MMDC_DRAM_D_32 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D33__MMDC_DRAM_D_33 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D34__MMDC_DRAM_D_34 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D35__MMDC_DRAM_D_35 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D36__MMDC_DRAM_D_36 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D37__MMDC_DRAM_D_37 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D38__MMDC_DRAM_D_38 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D39__MMDC_DRAM_D_39 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D4__MMDC_DRAM_D_4 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D40__MMDC_DRAM_D_40 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D41__MMDC_DRAM_D_41 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D42__MMDC_DRAM_D_42 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D43__MMDC_DRAM_D_43 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D44__MMDC_DRAM_D_44 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D45__MMDC_DRAM_D_45 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D46__MMDC_DRAM_D_46 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D47__MMDC_DRAM_D_47 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D48__MMDC_DRAM_D_48 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D49__MMDC_DRAM_D_49 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D5__MMDC_DRAM_D_5 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D50__MMDC_DRAM_D_50 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D51__MMDC_DRAM_D_51 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D52__MMDC_DRAM_D_52 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D53__MMDC_DRAM_D_53 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D54__MMDC_DRAM_D_54 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D55__MMDC_DRAM_D_55 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D56__MMDC_DRAM_D_56 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D57__MMDC_DRAM_D_57 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D58__MMDC_DRAM_D_58 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D59__MMDC_DRAM_D_59 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D6__MMDC_DRAM_D_6 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D60__MMDC_DRAM_D_60 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D61__MMDC_DRAM_D_61 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D62__MMDC_DRAM_D_62 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D63__MMDC_DRAM_D_63 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D7__MMDC_DRAM_D_7 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D8__MMDC_DRAM_D_8 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_D9__MMDC_DRAM_D_9 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM0__MMDC_DRAM_DQM_0 \ + IOMUX_PAD(0x0470, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM1__MMDC_DRAM_DQM_1 \ + IOMUX_PAD(0x0474, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM2__MMDC_DRAM_DQM_2 \ + IOMUX_PAD(0x0478, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM3__MMDC_DRAM_DQM_3 \ + IOMUX_PAD(0x047C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM4__MMDC_DRAM_DQM_4 \ + IOMUX_PAD(0x0480, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM5__MMDC_DRAM_DQM_5 \ + IOMUX_PAD(0x0484, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM6__MMDC_DRAM_DQM_6 \ + IOMUX_PAD(0x0488, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_DQM7__MMDC_DRAM_DQM_7 \ + IOMUX_PAD(0x048C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_RAS__MMDC_DRAM_RAS \ + IOMUX_PAD(0x0490, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_RESET__MMDC_DRAM_RESET \ + IOMUX_PAD(0x0494, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDBA0__MMDC_DRAM_SDBA_0 \ + IOMUX_PAD(0x0498, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDBA1__MMDC_DRAM_SDBA_1 \ + IOMUX_PAD(0x049C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDBA2__MMDC_DRAM_SDBA_2 \ + IOMUX_PAD(0x04A0, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDCKE0__MMDC_DRAM_SDCKE_0 \ + IOMUX_PAD(0x04A4, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDCKE1__MMDC_DRAM_SDCKE_1 \ + IOMUX_PAD(0x04A8, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDCLK_0__MMDC_DRAM_SDCLK0 \ + IOMUX_PAD(0x04AC, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDCLK_1__MMDC_DRAM_SDCLK1 \ + IOMUX_PAD(0x04B0, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDODT0__MMDC_DRAM_ODT_0 \ + IOMUX_PAD(0x04B4, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDODT1__MMDC_DRAM_ODT_1 \ + IOMUX_PAD(0x04B8, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS0__MMDC_DRAM_SDQS_0 \ + IOMUX_PAD(0x04BC, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS1__MMDC_DRAM_SDQS_1 \ + IOMUX_PAD(0x04C0, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS2__MMDC_DRAM_SDQS_2 \ + IOMUX_PAD(0x04C4, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS3__MMDC_DRAM_SDQS_3 \ + IOMUX_PAD(0x04C8, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS4__MMDC_DRAM_SDQS_4 \ + IOMUX_PAD(0x04CC, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS5__MMDC_DRAM_SDQS_5 \ + IOMUX_PAD(0x04D0, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS6__MMDC_DRAM_SDQS_6 \ + IOMUX_PAD(0x04D4, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDQS7__MMDC_DRAM_SDQS_7 \ + IOMUX_PAD(0x04D8, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_DRAM_SDWE__MMDC_DRAM_SDWE \ + IOMUX_PAD(0x04DC, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A16__WEIM_WEIM_A_16 \ + IOMUX_PAD(0x04E0, 0x0110, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__IPU1_DI1_DISP_CLK \ + IOMUX_PAD(0x04E0, 0x0110, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__IPU1_CSI1_PIXCLK \ + IOMUX_PAD(0x04E0, 0x0110, 2, 0x08B8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__MIPI_CORE_DPHY_TEST_OUT_23 \ + IOMUX_PAD(0x04E0, 0x0110, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__GPIO_2_22 \ + IOMUX_PAD(0x04E0, 0x0110, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__TPSMP_HDATA_6 \ + IOMUX_PAD(0x04E0, 0x0110, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__SRC_BT_CFG_16 \ + IOMUX_PAD(0x04E0, 0x0110, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A16__EPDC_SDDO_0 \ + IOMUX_PAD(0x04E0, 0x0110, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A17__WEIM_WEIM_A_17 \ + IOMUX_PAD(0x04E4, 0x0114, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__IPU1_DISP1_DAT_12 \ + IOMUX_PAD(0x04E4, 0x0114, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__IPU1_CSI1_D_12 \ + IOMUX_PAD(0x04E4, 0x0114, 2, 0x0890, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__MIPI_CORE_DPHY_TEST_OUT_22 \ + IOMUX_PAD(0x04E4, 0x0114, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__GPIO_2_21 \ + IOMUX_PAD(0x04E4, 0x0114, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__TPSMP_HDATA_5 \ + IOMUX_PAD(0x04E4, 0x0114, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__SRC_BT_CFG_17 \ + IOMUX_PAD(0x04E4, 0x0114, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A17__EPDC_PWRSTAT \ + IOMUX_PAD(0x04E4, 0x0114, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A18__WEIM_WEIM_A_18 \ + IOMUX_PAD(0x04E8, 0x0118, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__IPU1_DISP1_DAT_13 \ + IOMUX_PAD(0x04E8, 0x0118, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__IPU1_CSI1_D_13 \ + IOMUX_PAD(0x04E8, 0x0118, 2, 0x0894, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__MIPI_CORE_DPHY_TEST_OUT_21 \ + IOMUX_PAD(0x04E8, 0x0118, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__GPIO_2_20 \ + IOMUX_PAD(0x04E8, 0x0118, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__TPSMP_HDATA_4 \ + IOMUX_PAD(0x04E8, 0x0118, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__SRC_BT_CFG_18 \ + IOMUX_PAD(0x04E8, 0x0118, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A18__EPDC_PWRCTRL_0 \ + IOMUX_PAD(0x04E8, 0x0118, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A19__WEIM_WEIM_A_19 \ + IOMUX_PAD(0x04EC, 0x011C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__IPU1_DISP1_DAT_14 \ + IOMUX_PAD(0x04EC, 0x011C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__IPU1_CSI1_D_14 \ + IOMUX_PAD(0x04EC, 0x011C, 2, 0x0898, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__MIPI_CORE_DPHY_TEST_OUT_20 \ + IOMUX_PAD(0x04EC, 0x011C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__GPIO_2_19 \ + IOMUX_PAD(0x04EC, 0x011C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__TPSMP_HDATA_3 \ + IOMUX_PAD(0x04EC, 0x011C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__SRC_BT_CFG_19 \ + IOMUX_PAD(0x04EC, 0x011C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A19__EPDC_PWRCTRL_1 \ + IOMUX_PAD(0x04EC, 0x011C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A20__WEIM_WEIM_A_20 \ + IOMUX_PAD(0x04F0, 0x0120, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__IPU1_DISP1_DAT_15 \ + IOMUX_PAD(0x04F0, 0x0120, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__IPU1_CSI1_D_15 \ + IOMUX_PAD(0x04F0, 0x0120, 2, 0x089C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__MIPI_CORE_DPHY_TEST_OUT_19 \ + IOMUX_PAD(0x04F0, 0x0120, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__GPIO_2_18 \ + IOMUX_PAD(0x04F0, 0x0120, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__TPSMP_HDATA_2 \ + IOMUX_PAD(0x04F0, 0x0120, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__SRC_BT_CFG_20 \ + IOMUX_PAD(0x04F0, 0x0120, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A20__EPDC_PWRCTRL_2 \ + IOMUX_PAD(0x04F0, 0x0120, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A21__WEIM_WEIM_A_21 \ + IOMUX_PAD(0x04F4, 0x0124, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__IPU1_DISP1_DAT_16 \ + IOMUX_PAD(0x04F4, 0x0124, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__IPU1_CSI1_D_16 \ + IOMUX_PAD(0x04F4, 0x0124, 2, 0x08A0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__MIPI_CORE_DPHY_TEST_OUT_18 \ + IOMUX_PAD(0x04F4, 0x0124, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__GPIO_2_17 \ + IOMUX_PAD(0x04F4, 0x0124, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__TPSMP_HDATA_1 \ + IOMUX_PAD(0x04F4, 0x0124, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__SRC_BT_CFG_21 \ + IOMUX_PAD(0x04F4, 0x0124, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A21__EPDC_GDCLK \ + IOMUX_PAD(0x04F4, 0x0124, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A22__WEIM_WEIM_A_22 \ + IOMUX_PAD(0x04F8, 0x0128, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A22__IPU1_DISP1_DAT_17 \ + IOMUX_PAD(0x04F8, 0x0128, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A22__IPU1_CSI1_D_17 \ + IOMUX_PAD(0x04F8, 0x0128, 2, 0x08A4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A22__GPIO_2_16 \ + IOMUX_PAD(0x04F8, 0x0128, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A22__TPSMP_HDATA_0 \ + IOMUX_PAD(0x04F8, 0x0128, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A22__SRC_BT_CFG_22 \ + IOMUX_PAD(0x04F8, 0x0128, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A22__EPDC_GDSP \ + IOMUX_PAD(0x04F8, 0x0128, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A23__WEIM_WEIM_A_23 \ + IOMUX_PAD(0x04FC, 0x012C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__IPU1_DISP1_DAT_18 \ + IOMUX_PAD(0x04FC, 0x012C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__IPU1_CSI1_D_18 \ + IOMUX_PAD(0x04FC, 0x012C, 2, 0x08A8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__IPU1_SISG_3 \ + IOMUX_PAD(0x04FC, 0x012C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__GPIO_6_6 \ + IOMUX_PAD(0x04FC, 0x012C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__PL301_SIM_MX6DL_PER1_HPROT_3 \ + IOMUX_PAD(0x04FC, 0x012C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__SRC_BT_CFG_23 \ + IOMUX_PAD(0x04FC, 0x012C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A23__EPDC_GDOE \ + IOMUX_PAD(0x04FC, 0x012C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A24__WEIM_WEIM_A_24 \ + IOMUX_PAD(0x0500, 0x0130, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__IPU1_DISP1_DAT_19 \ + IOMUX_PAD(0x0500, 0x0130, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__IPU1_CSI1_D_19 \ + IOMUX_PAD(0x0500, 0x0130, 2, 0x08AC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__IPU1_SISG_2 \ + IOMUX_PAD(0x0500, 0x0130, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__GPIO_5_4 \ + IOMUX_PAD(0x0500, 0x0130, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__PL301_SIM_MX6DL_PER1_HPROT_2 \ + IOMUX_PAD(0x0500, 0x0130, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__SRC_BT_CFG_24 \ + IOMUX_PAD(0x0500, 0x0130, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A24__EPDC_GDRL \ + IOMUX_PAD(0x0500, 0x0130, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_A25__WEIM_WEIM_A_25 \ + IOMUX_PAD(0x0504, 0x0134, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__ECSPI4_SS1 \ + IOMUX_PAD(0x0504, 0x0134, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__ECSPI2_RDY \ + IOMUX_PAD(0x0504, 0x0134, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__IPU1_DI1_PIN12 \ + IOMUX_PAD(0x0504, 0x0134, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__IPU1_DI0_D1_CS \ + IOMUX_PAD(0x0504, 0x0134, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__GPIO_5_2 \ + IOMUX_PAD(0x0504, 0x0134, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE \ + IOMUX_PAD(0x0504, 0x0134, 6, 0x085C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__PL301_SIM_MX6DL_PER1_HBURST_0 \ + IOMUX_PAD(0x0504, 0x0134, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__EPDC_SDDO_15 \ + IOMUX_PAD(0x0504, 0x0134, 8, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_A25__WEIM_ACLK_FREERUN \ + IOMUX_PAD(0x0504, 0x0134, 9, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_BCLK__WEIM_WEIM_BCLK \ + IOMUX_PAD(0x0508, 0x0138, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_BCLK__IPU1_DI1_PIN16 \ + IOMUX_PAD(0x0508, 0x0138, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_BCLK__GPIO_6_31 \ + IOMUX_PAD(0x0508, 0x0138, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_BCLK__TPSMP_HDATA_31 \ + IOMUX_PAD(0x0508, 0x0138, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_BCLK__EPDC_SDCE_9 \ + IOMUX_PAD(0x0508, 0x0138, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_CS0__WEIM_WEIM_CS_0 \ + IOMUX_PAD(0x050C, 0x013C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS0__IPU1_DI1_PIN5 \ + IOMUX_PAD(0x050C, 0x013C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS0__ECSPI2_SCLK \ + IOMUX_PAD(0x050C, 0x013C, 2, 0x07F4, 2, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS0__MIPI_CORE_DPHY_TEST_OUT_24 \ + IOMUX_PAD(0x050C, 0x013C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS0__GPIO_2_23 \ + IOMUX_PAD(0x050C, 0x013C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS0__TPSMP_HDATA_7 \ + IOMUX_PAD(0x050C, 0x013C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS0__EPDC_SDDO_6 \ + IOMUX_PAD(0x050C, 0x013C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_CS1__WEIM_WEIM_CS_1 \ + IOMUX_PAD(0x0510, 0x0140, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS1__IPU1_DI1_PIN6 \ + IOMUX_PAD(0x0510, 0x0140, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS1__ECSPI2_MOSI \ + IOMUX_PAD(0x0510, 0x0140, 2, 0x07FC, 2, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS1__MIPI_CORE_DPHY_TEST_OUT_25 \ + IOMUX_PAD(0x0510, 0x0140, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS1__GPIO_2_24 \ + IOMUX_PAD(0x0510, 0x0140, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS1__TPSMP_HDATA_8 \ + IOMUX_PAD(0x0510, 0x0140, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_CS1__EPDC_SDDO_8 \ + IOMUX_PAD(0x0510, 0x0140, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D16__WEIM_WEIM_D_16 \ + IOMUX_PAD(0x0514, 0x0144, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__ECSPI1_SCLK \ + IOMUX_PAD(0x0514, 0x0144, 1, 0x07D8, 2, MX6DL_ECSPI_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__IPU1_DI0_PIN5 \ + IOMUX_PAD(0x0514, 0x0144, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__IPU1_CSI1_D_18 \ + IOMUX_PAD(0x0514, 0x0144, 3, 0x08A8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__HDMI_TX_DDC_SDA \ + IOMUX_PAD(0x0514, 0x0144, 4, 0x0864, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__GPIO_3_16 \ + IOMUX_PAD(0x0514, 0x0144, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__I2C2_SDA \ + IOMUX_PAD(0x0514, 0x0144, 6 | IOMUX_CONFIG_SION, 0x0874, 0, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__TPSMP_HTRANS_0 \ + IOMUX_PAD(0x0514, 0x0144, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D16__EPDC_SDDO_10 \ + IOMUX_PAD(0x0514, 0x0144, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D17__WEIM_WEIM_D_17 \ + IOMUX_PAD(0x0518, 0x0148, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__ECSPI1_MISO \ + IOMUX_PAD(0x0518, 0x0148, 1, 0x07DC, 2, MX6DL_ECSPI_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__IPU1_DI0_PIN6 \ + IOMUX_PAD(0x0518, 0x0148, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__IPU1_CSI1_PIXCLK \ + IOMUX_PAD(0x0518, 0x0148, 3, 0x08B8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__DCIC1_DCIC_OUT \ + IOMUX_PAD(0x0518, 0x0148, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__GPIO_3_17 \ + IOMUX_PAD(0x0518, 0x0148, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__I2C3_SCL \ + IOMUX_PAD(0x0518, 0x0148, 6 | IOMUX_CONFIG_SION, 0x0878, 0, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__PL301_SIM_MX6DL_PER1_HBURST_1 \ + IOMUX_PAD(0x0518, 0x0148, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D17__EPDC_VCOM_0 \ + IOMUX_PAD(0x0518, 0x0148, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D18__WEIM_WEIM_D_18 \ + IOMUX_PAD(0x051C, 0x014C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__ECSPI1_MOSI \ + IOMUX_PAD(0x051C, 0x014C, 1, 0x07E0, 2, MX6DL_ECSPI_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__IPU1_DI0_PIN7 \ + IOMUX_PAD(0x051C, 0x014C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__IPU1_CSI1_D_17 \ + IOMUX_PAD(0x051C, 0x014C, 3, 0x08A4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__IPU1_DI1_D0_CS \ + IOMUX_PAD(0x051C, 0x014C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__GPIO_3_18 \ + IOMUX_PAD(0x051C, 0x014C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__I2C3_SDA \ + IOMUX_PAD(0x051C, 0x014C, 6 | IOMUX_CONFIG_SION, 0x087C, 0, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__PL301_SIM_MX6DL_PER1_HBURST_2 \ + IOMUX_PAD(0x051C, 0x014C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D18__EPDC_VCOM_1 \ + IOMUX_PAD(0x051C, 0x014C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D19__WEIM_WEIM_D_19 \ + IOMUX_PAD(0x0520, 0x0150, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__ECSPI1_SS1 \ + IOMUX_PAD(0x0520, 0x0150, 1, 0x07E8, 1, MX6DL_ECSPI_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__IPU1_DI0_PIN8 \ + IOMUX_PAD(0x0520, 0x0150, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__IPU1_CSI1_D_16 \ + IOMUX_PAD(0x0520, 0x0150, 3, 0x08A0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__UART1_CTS \ + IOMUX_PAD(0x0520, 0x0150, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__UART1_RTS \ + IOMUX_PAD(0x0520, 0x0150, 4, 0x08F8, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__GPIO_3_19 \ + IOMUX_PAD(0x0520, 0x0150, 5, 0x0000, 0, MX6DL_ECSPI_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__EPIT1_EPITO \ + IOMUX_PAD(0x0520, 0x0150, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__PL301_SIM_MX6DL_PER1_HRESP \ + IOMUX_PAD(0x0520, 0x0150, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D19__EPDC_SDDO_12 \ + IOMUX_PAD(0x0520, 0x0150, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D20__WEIM_WEIM_D_20 \ + IOMUX_PAD(0x0524, 0x0154, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__ECSPI4_SS0 \ + IOMUX_PAD(0x0524, 0x0154, 1, 0x0808, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__IPU1_DI0_PIN16 \ + IOMUX_PAD(0x0524, 0x0154, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__IPU1_CSI1_D_15 \ + IOMUX_PAD(0x0524, 0x0154, 3, 0x089C, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__UART1_CTS \ + IOMUX_PAD(0x0524, 0x0154, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__UART1_RTS \ + IOMUX_PAD(0x0524, 0x0154, 4, 0x08F8, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__GPIO_3_20 \ + IOMUX_PAD(0x0524, 0x0154, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__EPIT2_EPITO \ + IOMUX_PAD(0x0524, 0x0154, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D20__TPSMP_HTRANS_1 \ + IOMUX_PAD(0x0524, 0x0154, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D21__WEIM_WEIM_D_21 \ + IOMUX_PAD(0x0528, 0x0158, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__ECSPI4_SCLK \ + IOMUX_PAD(0x0528, 0x0158, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__IPU1_DI0_PIN17 \ + IOMUX_PAD(0x0528, 0x0158, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__IPU1_CSI1_D_11 \ + IOMUX_PAD(0x0528, 0x0158, 3, 0x088C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__USBOH3_USBOTG_OC \ + IOMUX_PAD(0x0528, 0x0158, 4, 0x0920, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__GPIO_3_21 \ + IOMUX_PAD(0x0528, 0x0158, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__I2C1_SCL \ + IOMUX_PAD(0x0528, 0x0158, 6 | IOMUX_CONFIG_SION, 0x0868, 1, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_EIM_D21__SPDIF_IN1 \ + IOMUX_PAD(0x0528, 0x0158, 7, 0x08F0, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D22__WEIM_WEIM_D_22 \ + IOMUX_PAD(0x052C, 0x015C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__ECSPI4_MISO \ + IOMUX_PAD(0x052C, 0x015C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__IPU1_DI0_PIN1 \ + IOMUX_PAD(0x052C, 0x015C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__IPU1_CSI1_D_10 \ + IOMUX_PAD(0x052C, 0x015C, 3, 0x0888, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__USBOH3_USBOTG_PWR \ + IOMUX_PAD(0x052C, 0x015C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__GPIO_3_22 \ + IOMUX_PAD(0x052C, 0x015C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__SPDIF_OUT1 \ + IOMUX_PAD(0x052C, 0x015C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__PL301_SIM_MX6DL_PER1_HWRITE \ + IOMUX_PAD(0x052C, 0x015C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D22__EPDC_SDCE_6 \ + IOMUX_PAD(0x052C, 0x015C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D23__WEIM_WEIM_D_23 \ + IOMUX_PAD(0x0530, 0x0160, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__IPU1_DI0_D0_CS \ + IOMUX_PAD(0x0530, 0x0160, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__UART3_CTS \ + IOMUX_PAD(0x0530, 0x0160, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__UART3_RTS \ + IOMUX_PAD(0x0530, 0x0160, 2, 0x0908, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__UART1_DCD \ + IOMUX_PAD(0x0530, 0x0160, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__IPU1_CSI1_DATA_EN \ + IOMUX_PAD(0x0530, 0x0160, 4, 0x08B0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__GPIO_3_23 \ + IOMUX_PAD(0x0530, 0x0160, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__IPU1_DI1_PIN2 \ + IOMUX_PAD(0x0530, 0x0160, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__IPU1_DI1_PIN14 \ + IOMUX_PAD(0x0530, 0x0160, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D23__EPDC_SDDO_11 \ + IOMUX_PAD(0x0530, 0x0160, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D24__WEIM_WEIM_D_24 \ + IOMUX_PAD(0x0534, 0x0164, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__ECSPI4_SS2 \ + IOMUX_PAD(0x0534, 0x0164, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__UART3_TXD \ + IOMUX_PAD(0x0534, 0x0164, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__UART3_RXD \ + IOMUX_PAD(0x0534, 0x0164, 2, 0x090C, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__ECSPI1_SS2 \ + IOMUX_PAD(0x0534, 0x0164, 3, 0x07EC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__ECSPI2_SS2 \ + IOMUX_PAD(0x0534, 0x0164, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__GPIO_3_24 \ + IOMUX_PAD(0x0534, 0x0164, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__AUDMUX_AUD5_RXFS \ + IOMUX_PAD(0x0534, 0x0164, 6, 0x07BC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__UART1_DTR \ + IOMUX_PAD(0x0534, 0x0164, 7, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D24__EPDC_SDCE_7 \ + IOMUX_PAD(0x0534, 0x0164, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D25__WEIM_WEIM_D_25 \ + IOMUX_PAD(0x0538, 0x0168, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__ECSPI4_SS3 \ + IOMUX_PAD(0x0538, 0x0168, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__UART3_TXD \ + IOMUX_PAD(0x0538, 0x0168, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__UART3_RXD \ + IOMUX_PAD(0x0538, 0x0168, 2, 0x090C, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__ECSPI1_SS3 \ + IOMUX_PAD(0x0538, 0x0168, 3, 0x07F0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__ECSPI2_SS3 \ + IOMUX_PAD(0x0538, 0x0168, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__GPIO_3_25 \ + IOMUX_PAD(0x0538, 0x0168, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__AUDMUX_AUD5_RXC \ + IOMUX_PAD(0x0538, 0x0168, 6, 0x07B8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__UART1_DSR \ + IOMUX_PAD(0x0538, 0x0168, 7, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D25__EPDC_SDCE_8 \ + IOMUX_PAD(0x0538, 0x0168, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D26__WEIM_WEIM_D_26 \ + IOMUX_PAD(0x053C, 0x016C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__IPU1_DI1_PIN11 \ + IOMUX_PAD(0x053C, 0x016C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__IPU1_CSI0_D_1 \ + IOMUX_PAD(0x053C, 0x016C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__IPU1_CSI1_D_14 \ + IOMUX_PAD(0x053C, 0x016C, 3, 0x0898, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__UART2_TXD \ + IOMUX_PAD(0x053C, 0x016C, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__UART2_RXD \ + IOMUX_PAD(0x053C, 0x016C, 4, 0x0904, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__GPIO_3_26 \ + IOMUX_PAD(0x053C, 0x016C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__IPU1_SISG_2 \ + IOMUX_PAD(0x053C, 0x016C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__IPU1_DISP1_DAT_22 \ + IOMUX_PAD(0x053C, 0x016C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D26__EPDC_SDOED \ + IOMUX_PAD(0x053C, 0x016C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D27__WEIM_WEIM_D_27 \ + IOMUX_PAD(0x0540, 0x0170, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__IPU1_DI1_PIN13 \ + IOMUX_PAD(0x0540, 0x0170, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__IPU1_CSI0_D_0 \ + IOMUX_PAD(0x0540, 0x0170, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__IPU1_CSI1_D_13 \ + IOMUX_PAD(0x0540, 0x0170, 3, 0x0894, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__UART2_TXD \ + IOMUX_PAD(0x0540, 0x0170, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__UART2_RXD \ + IOMUX_PAD(0x0540, 0x0170, 4, 0x0904, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__GPIO_3_27 \ + IOMUX_PAD(0x0540, 0x0170, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__IPU1_SISG_3 \ + IOMUX_PAD(0x0540, 0x0170, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__IPU1_DISP1_DAT_23 \ + IOMUX_PAD(0x0540, 0x0170, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D27__EPDC_SDOE \ + IOMUX_PAD(0x0540, 0x0170, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D28__WEIM_WEIM_D_28 \ + IOMUX_PAD(0x0544, 0x0174, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__I2C1_SDA \ + IOMUX_PAD(0x0544, 0x0174, 1 | IOMUX_CONFIG_SION, 0x086C, 1, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__ECSPI4_MOSI \ + IOMUX_PAD(0x0544, 0x0174, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__IPU1_CSI1_D_12 \ + IOMUX_PAD(0x0544, 0x0174, 3, 0x0890, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__UART2_CTS \ + IOMUX_PAD(0x0544, 0x0174, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__UART2_RTS \ + IOMUX_PAD(0x0544, 0x0174, 4, 0x0900, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__GPIO_3_28 \ + IOMUX_PAD(0x0544, 0x0174, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__IPU1_EXT_TRIG \ + IOMUX_PAD(0x0544, 0x0174, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__IPU1_DI0_PIN13 \ + IOMUX_PAD(0x0544, 0x0174, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D28__EPDC_PWRCTRL_3 \ + IOMUX_PAD(0x0544, 0x0174, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D29__WEIM_WEIM_D_29 \ + IOMUX_PAD(0x0548, 0x0178, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__IPU1_DI1_PIN15 \ + IOMUX_PAD(0x0548, 0x0178, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__ECSPI4_SS0 \ + IOMUX_PAD(0x0548, 0x0178, 2, 0x0808, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__UART2_CTS \ + IOMUX_PAD(0x0548, 0x0178, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__UART2_RTS \ + IOMUX_PAD(0x0548, 0x0178, 4, 0x0900, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__GPIO_3_29 \ + IOMUX_PAD(0x0548, 0x0178, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__IPU1_CSI1_VSYNC \ + IOMUX_PAD(0x0548, 0x0178, 6, 0x08BC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__IPU1_DI0_PIN14 \ + IOMUX_PAD(0x0548, 0x0178, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D29__EPDC_PWRWAKE \ + IOMUX_PAD(0x0548, 0x0178, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D30__WEIM_WEIM_D_30 \ + IOMUX_PAD(0x054C, 0x017C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__IPU1_DISP1_DAT_21 \ + IOMUX_PAD(0x054C, 0x017C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__IPU1_DI0_PIN11 \ + IOMUX_PAD(0x054C, 0x017C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__IPU1_CSI0_D_3 \ + IOMUX_PAD(0x054C, 0x017C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__UART3_CTS \ + IOMUX_PAD(0x054C, 0x017C, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__UART3_RTS \ + IOMUX_PAD(0x054C, 0x017C, 4, 0x0908, 1, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__GPIO_3_30 \ + IOMUX_PAD(0x054C, 0x017C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__USBOH3_USBH1_OC \ + IOMUX_PAD(0x054C, 0x017C, 6, 0x0924, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__PL301_SIM_MX6DL_PER1_HPROT_0 \ + IOMUX_PAD(0x054C, 0x017C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D30__EPDC_SDOEZ \ + IOMUX_PAD(0x054C, 0x017C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_D31__WEIM_WEIM_D_31 \ + IOMUX_PAD(0x0550, 0x0180, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__IPU1_DISP1_DAT_20 \ + IOMUX_PAD(0x0550, 0x0180, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__IPU1_DI0_PIN12 \ + IOMUX_PAD(0x0550, 0x0180, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__IPU1_CSI0_D_2 \ + IOMUX_PAD(0x0550, 0x0180, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__UART3_CTS \ + IOMUX_PAD(0x0550, 0x0180, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__UART3_RTS \ + IOMUX_PAD(0x0550, 0x0180, 4, 0x0908, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__GPIO_3_31 \ + IOMUX_PAD(0x0550, 0x0180, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__USBOH3_USBH1_PWR \ + IOMUX_PAD(0x0550, 0x0180, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__PL301_SIM_MX6DL_PER1_HPROT_1 \ + IOMUX_PAD(0x0550, 0x0180, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__EPDC_SDCLK \ + IOMUX_PAD(0x0550, 0x0180, 8, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_D31__WEIM_ACLK_FREERUN \ + IOMUX_PAD(0x0550, 0x0180, 9, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA0__WEIM_WEIM_DA_A_0 \ + IOMUX_PAD(0x0554, 0x0184, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__IPU1_DISP1_DAT_9 \ + IOMUX_PAD(0x0554, 0x0184, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__IPU1_CSI1_D_9 \ + IOMUX_PAD(0x0554, 0x0184, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__MIPI_CORE_DPHY_TEST_OUT_2 \ + IOMUX_PAD(0x0554, 0x0184, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__GPIO_3_0 \ + IOMUX_PAD(0x0554, 0x0184, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__TPSMP_HDATA_14 \ + IOMUX_PAD(0x0554, 0x0184, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__SRC_BT_CFG_0 \ + IOMUX_PAD(0x0554, 0x0184, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA0__EPDC_SDCLKN \ + IOMUX_PAD(0x0554, 0x0184, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA1__WEIM_WEIM_DA_A_1 \ + IOMUX_PAD(0x0558, 0x0188, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__IPU1_DISP1_DAT_8 \ + IOMUX_PAD(0x0558, 0x0188, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__IPU1_CSI1_D_8 \ + IOMUX_PAD(0x0558, 0x0188, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__MIPI_CORE_DPHY_TEST_OUT_3 \ + IOMUX_PAD(0x0558, 0x0188, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__ANATOP_USBPHY1_TSTI_TX_LS_MODE \ + IOMUX_PAD(0x0558, 0x0188, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__GPIO_3_1 \ + IOMUX_PAD(0x0558, 0x0188, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__TPSMP_HDATA_15 \ + IOMUX_PAD(0x0558, 0x0188, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__SRC_BT_CFG_1 \ + IOMUX_PAD(0x0558, 0x0188, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA1__EPDC_SDLE \ + IOMUX_PAD(0x0558, 0x0188, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA10__WEIM_WEIM_DA_A_10 \ + IOMUX_PAD(0x055C, 0x018C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__IPU1_DI1_PIN15 \ + IOMUX_PAD(0x055C, 0x018C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__IPU1_CSI1_DATA_EN \ + IOMUX_PAD(0x055C, 0x018C, 2, 0x08B0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__MIPI_CORE_DPHY_TEST_OUT_12 \ + IOMUX_PAD(0x055C, 0x018C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__GPIO_3_10 \ + IOMUX_PAD(0x055C, 0x018C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__TPSMP_HDATA_24 \ + IOMUX_PAD(0x055C, 0x018C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__SRC_BT_CFG_10 \ + IOMUX_PAD(0x055C, 0x018C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA10__EPDC_SDDO_1 \ + IOMUX_PAD(0x055C, 0x018C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA11__WEIM_WEIM_DA_A_11 \ + IOMUX_PAD(0x0560, 0x0190, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__IPU1_DI1_PIN2 \ + IOMUX_PAD(0x0560, 0x0190, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__IPU1_CSI1_HSYNC \ + IOMUX_PAD(0x0560, 0x0190, 2, 0x08B4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__MIPI_CORE_DPHY_TEST_OUT_13 \ + IOMUX_PAD(0x0560, 0x0190, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__SDMA_DEBUG_EVT_CHN_LINES_6 \ + IOMUX_PAD(0x0560, 0x0190, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__GPIO_3_11 \ + IOMUX_PAD(0x0560, 0x0190, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__TPSMP_HDATA_25 \ + IOMUX_PAD(0x0560, 0x0190, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__SRC_BT_CFG_11 \ + IOMUX_PAD(0x0560, 0x0190, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA11__EPDC_SDDO_3 \ + IOMUX_PAD(0x0560, 0x0190, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA12__WEIM_WEIM_DA_A_12 \ + IOMUX_PAD(0x0564, 0x0194, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__IPU1_DI1_PIN3 \ + IOMUX_PAD(0x0564, 0x0194, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__IPU1_CSI1_VSYNC \ + IOMUX_PAD(0x0564, 0x0194, 2, 0x08BC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__MIPI_CORE_DPHY_TEST_OUT_14 \ + IOMUX_PAD(0x0564, 0x0194, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__SDMA_DEBUG_EVT_CHN_LINES_3 \ + IOMUX_PAD(0x0564, 0x0194, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__GPIO_3_12 \ + IOMUX_PAD(0x0564, 0x0194, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__TPSMP_HDATA_26 \ + IOMUX_PAD(0x0564, 0x0194, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__SRC_BT_CFG_12 \ + IOMUX_PAD(0x0564, 0x0194, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA12__EPDC_SDDO_2 \ + IOMUX_PAD(0x0564, 0x0194, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA13__WEIM_WEIM_DA_A_13 \ + IOMUX_PAD(0x0568, 0x0198, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__IPU1_DI1_D0_CS \ + IOMUX_PAD(0x0568, 0x0198, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__CCM_DI1_EXT_CLK \ + IOMUX_PAD(0x0568, 0x0198, 2, 0x07D0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__MIPI_CORE_DPHY_TEST_OUT_15 \ + IOMUX_PAD(0x0568, 0x0198, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__SDMA_DEBUG_EVT_CHN_LINES_4 \ + IOMUX_PAD(0x0568, 0x0198, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__GPIO_3_13 \ + IOMUX_PAD(0x0568, 0x0198, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__TPSMP_HDATA_27 \ + IOMUX_PAD(0x0568, 0x0198, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__SRC_BT_CFG_13 \ + IOMUX_PAD(0x0568, 0x0198, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA13__EPDC_SDDO_13 \ + IOMUX_PAD(0x0568, 0x0198, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA14__WEIM_WEIM_DA_A_14 \ + IOMUX_PAD(0x056C, 0x019C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__IPU1_DI1_D1_CS \ + IOMUX_PAD(0x056C, 0x019C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__CCM_DI0_EXT_CLK \ + IOMUX_PAD(0x056C, 0x019C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__MIPI_CORE_DPHY_TEST_OUT_16 \ + IOMUX_PAD(0x056C, 0x019C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__SDMA_DEBUG_EVT_CHN_LINES_5 \ + IOMUX_PAD(0x056C, 0x019C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__GPIO_3_14 \ + IOMUX_PAD(0x056C, 0x019C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__TPSMP_HDATA_28 \ + IOMUX_PAD(0x056C, 0x019C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__SRC_BT_CFG_14 \ + IOMUX_PAD(0x056C, 0x019C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA14__EPDC_SDDO_14 \ + IOMUX_PAD(0x056C, 0x019C, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA15__WEIM_WEIM_DA_A_15 \ + IOMUX_PAD(0x0570, 0x01A0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__IPU1_DI1_PIN1 \ + IOMUX_PAD(0x0570, 0x01A0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__IPU1_DI1_PIN4 \ + IOMUX_PAD(0x0570, 0x01A0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__MIPI_CORE_DPHY_TEST_OUT_17 \ + IOMUX_PAD(0x0570, 0x01A0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__GPIO_3_15 \ + IOMUX_PAD(0x0570, 0x01A0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__TPSMP_HDATA_29 \ + IOMUX_PAD(0x0570, 0x01A0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__SRC_BT_CFG_15 \ + IOMUX_PAD(0x0570, 0x01A0, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA15__EPDC_SDDO_9 \ + IOMUX_PAD(0x0570, 0x01A0, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA2__WEIM_WEIM_DA_A_2 \ + IOMUX_PAD(0x0574, 0x01A4, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__IPU1_DISP1_DAT_7 \ + IOMUX_PAD(0x0574, 0x01A4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__IPU1_CSI1_D_7 \ + IOMUX_PAD(0x0574, 0x01A4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__MIPI_CORE_DPHY_TEST_OUT_4 \ + IOMUX_PAD(0x0574, 0x01A4, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__ANATOP_USBPHY1_TSTI_TX_HS_MODE \ + IOMUX_PAD(0x0574, 0x01A4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__GPIO_3_2 \ + IOMUX_PAD(0x0574, 0x01A4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__TPSMP_HDATA_16 \ + IOMUX_PAD(0x0574, 0x01A4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__SRC_BT_CFG_2 \ + IOMUX_PAD(0x0574, 0x01A4, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA2__EPDC_BDR_0 \ + IOMUX_PAD(0x0574, 0x01A4, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA3__WEIM_WEIM_DA_A_3 \ + IOMUX_PAD(0x0578, 0x01A8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__IPU1_DISP1_DAT_6 \ + IOMUX_PAD(0x0578, 0x01A8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__IPU1_CSI1_D_6 \ + IOMUX_PAD(0x0578, 0x01A8, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__MIPI_CORE_DPHY_TEST_OUT_5 \ + IOMUX_PAD(0x0578, 0x01A8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__ANATOP_USBPHY1_TSTI_TX_HIZ \ + IOMUX_PAD(0x0578, 0x01A8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__GPIO_3_3 \ + IOMUX_PAD(0x0578, 0x01A8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__TPSMP_HDATA_17 \ + IOMUX_PAD(0x0578, 0x01A8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__SRC_BT_CFG_3 \ + IOMUX_PAD(0x0578, 0x01A8, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA3__EPDC_BDR_1 \ + IOMUX_PAD(0x0578, 0x01A8, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA4__WEIM_WEIM_DA_A_4 \ + IOMUX_PAD(0x057C, 0x01AC, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__IPU1_DISP1_DAT_5 \ + IOMUX_PAD(0x057C, 0x01AC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__IPU1_CSI1_D_5 \ + IOMUX_PAD(0x057C, 0x01AC, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__MIPI_CORE_DPHY_TEST_OUT_6 \ + IOMUX_PAD(0x057C, 0x01AC, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__ANATOP_USBPHY1_TSTI_TX_EN \ + IOMUX_PAD(0x057C, 0x01AC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__GPIO_3_4 \ + IOMUX_PAD(0x057C, 0x01AC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__TPSMP_HDATA_18 \ + IOMUX_PAD(0x057C, 0x01AC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__SRC_BT_CFG_4 \ + IOMUX_PAD(0x057C, 0x01AC, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA4__EPDC_SDCE_0 \ + IOMUX_PAD(0x057C, 0x01AC, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA5__WEIM_WEIM_DA_A_5 \ + IOMUX_PAD(0x0580, 0x01B0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__IPU1_DISP1_DAT_4 \ + IOMUX_PAD(0x0580, 0x01B0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__IPU1_CSI1_D_4 \ + IOMUX_PAD(0x0580, 0x01B0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__MIPI_CORE_DPHY_TEST_OUT_7 \ + IOMUX_PAD(0x0580, 0x01B0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__ANATOP_USBPHY1_TSTI_TX_DP \ + IOMUX_PAD(0x0580, 0x01B0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__GPIO_3_5 \ + IOMUX_PAD(0x0580, 0x01B0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__TPSMP_HDATA_19 \ + IOMUX_PAD(0x0580, 0x01B0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__SRC_BT_CFG_5 \ + IOMUX_PAD(0x0580, 0x01B0, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA5__EPDC_SDCE_1 \ + IOMUX_PAD(0x0580, 0x01B0, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA6__WEIM_WEIM_DA_A_6 \ + IOMUX_PAD(0x0584, 0x01B4, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__IPU1_DISP1_DAT_3 \ + IOMUX_PAD(0x0584, 0x01B4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__IPU1_CSI1_D_3 \ + IOMUX_PAD(0x0584, 0x01B4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__MIPI_CORE_DPHY_TEST_OUT_8 \ + IOMUX_PAD(0x0584, 0x01B4, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__ANATOP_USBPHY1_TSTI_TX_DN \ + IOMUX_PAD(0x0584, 0x01B4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__GPIO_3_6 \ + IOMUX_PAD(0x0584, 0x01B4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__TPSMP_HDATA_20 \ + IOMUX_PAD(0x0584, 0x01B4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__SRC_BT_CFG_6 \ + IOMUX_PAD(0x0584, 0x01B4, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA6__EPDC_SDCE_2 \ + IOMUX_PAD(0x0584, 0x01B4, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA7__WEIM_WEIM_DA_A_7 \ + IOMUX_PAD(0x0588, 0x01B8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__IPU1_DISP1_DAT_2 \ + IOMUX_PAD(0x0588, 0x01B8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__IPU1_CSI1_D_2 \ + IOMUX_PAD(0x0588, 0x01B8, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__MIPI_CORE_DPHY_TEST_OUT_9 \ + IOMUX_PAD(0x0588, 0x01B8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__GPIO_3_7 \ + IOMUX_PAD(0x0588, 0x01B8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__TPSMP_HDATA_21 \ + IOMUX_PAD(0x0588, 0x01B8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__SRC_BT_CFG_7 \ + IOMUX_PAD(0x0588, 0x01B8, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA7__EPDC_SDCE_3 \ + IOMUX_PAD(0x0588, 0x01B8, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA8__WEIM_WEIM_DA_A_8 \ + IOMUX_PAD(0x058C, 0x01BC, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__IPU1_DISP1_DAT_1 \ + IOMUX_PAD(0x058C, 0x01BC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__IPU1_CSI1_D_1 \ + IOMUX_PAD(0x058C, 0x01BC, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__MIPI_CORE_DPHY_TEST_OUT_10 \ + IOMUX_PAD(0x058C, 0x01BC, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__GPIO_3_8 \ + IOMUX_PAD(0x058C, 0x01BC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__TPSMP_HDATA_22 \ + IOMUX_PAD(0x058C, 0x01BC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__SRC_BT_CFG_8 \ + IOMUX_PAD(0x058C, 0x01BC, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA8__EPDC_SDCE_4 \ + IOMUX_PAD(0x058C, 0x01BC, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_DA9__WEIM_WEIM_DA_A_9 \ + IOMUX_PAD(0x0590, 0x01C0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__IPU1_DISP1_DAT_0 \ + IOMUX_PAD(0x0590, 0x01C0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__IPU1_CSI1_D_0 \ + IOMUX_PAD(0x0590, 0x01C0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__MIPI_CORE_DPHY_TEST_OUT_11 \ + IOMUX_PAD(0x0590, 0x01C0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__GPIO_3_9 \ + IOMUX_PAD(0x0590, 0x01C0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__TPSMP_HDATA_23 \ + IOMUX_PAD(0x0590, 0x01C0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__SRC_BT_CFG_9 \ + IOMUX_PAD(0x0590, 0x01C0, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_DA9__EPDC_SDCE_5 \ + IOMUX_PAD(0x0590, 0x01C0, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_EB0__WEIM_WEIM_EB_0 \ + IOMUX_PAD(0x0594, 0x01C4, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__IPU1_DISP1_DAT_11 \ + IOMUX_PAD(0x0594, 0x01C4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__IPU1_CSI1_D_11 \ + IOMUX_PAD(0x0594, 0x01C4, 2, 0x088C, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__MIPI_CORE_DPHY_TEST_OUT_0 \ + IOMUX_PAD(0x0594, 0x01C4, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__CCM_PMIC_RDY \ + IOMUX_PAD(0x0594, 0x01C4, 4, 0x07D4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__GPIO_2_28 \ + IOMUX_PAD(0x0594, 0x01C4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__TPSMP_HDATA_12 \ + IOMUX_PAD(0x0594, 0x01C4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__SRC_BT_CFG_27 \ + IOMUX_PAD(0x0594, 0x01C4, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB0__EPDC_PWRCOM \ + IOMUX_PAD(0x0594, 0x01C4, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_EB1__WEIM_WEIM_EB_1 \ + IOMUX_PAD(0x0598, 0x01C8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__IPU1_DISP1_DAT_10 \ + IOMUX_PAD(0x0598, 0x01C8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__IPU1_CSI1_D_10 \ + IOMUX_PAD(0x0598, 0x01C8, 2, 0x0888, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__MIPI_CORE_DPHY_TEST_OUT_1 \ + IOMUX_PAD(0x0598, 0x01C8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__GPIO_2_29 \ + IOMUX_PAD(0x0598, 0x01C8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__TPSMP_HDATA_13 \ + IOMUX_PAD(0x0598, 0x01C8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__SRC_BT_CFG_28 \ + IOMUX_PAD(0x0598, 0x01C8, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB1__EPDC_SDSHR \ + IOMUX_PAD(0x0598, 0x01C8, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_EB2__WEIM_WEIM_EB_2 \ + IOMUX_PAD(0x059C, 0x01CC, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__ECSPI1_SS0 \ + IOMUX_PAD(0x059C, 0x01CC, 1, 0x07E4, 2, MX6DL_ECSPI_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__CCM_DI1_EXT_CLK \ + IOMUX_PAD(0x059C, 0x01CC, 2, 0x07D0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__IPU1_CSI1_D_19 \ + IOMUX_PAD(0x059C, 0x01CC, 3, 0x08AC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__HDMI_TX_DDC_SCL \ + IOMUX_PAD(0x059C, 0x01CC, 4, 0x0860, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__GPIO_2_30 \ + IOMUX_PAD(0x059C, 0x01CC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__I2C2_SCL \ + IOMUX_PAD(0x059C, 0x01CC, 6 | IOMUX_CONFIG_SION, 0x0870, 0, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__SRC_BT_CFG_30 \ + IOMUX_PAD(0x059C, 0x01CC, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB2__EPDC_SDDO_5 \ + IOMUX_PAD(0x059C, 0x01CC, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_EB3__WEIM_WEIM_EB_3 \ + IOMUX_PAD(0x05A0, 0x01D0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__ECSPI4_RDY \ + IOMUX_PAD(0x05A0, 0x01D0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__UART3_CTS \ + IOMUX_PAD(0x05A0, 0x01D0, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__UART3_RTS \ + IOMUX_PAD(0x05A0, 0x01D0, 2, 0x0908, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__UART1_RI \ + IOMUX_PAD(0x05A0, 0x01D0, 3, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__IPU1_CSI1_HSYNC \ + IOMUX_PAD(0x05A0, 0x01D0, 4, 0x08B4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__GPIO_2_31 \ + IOMUX_PAD(0x05A0, 0x01D0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__IPU1_DI1_PIN3 \ + IOMUX_PAD(0x05A0, 0x01D0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__SRC_BT_CFG_31 \ + IOMUX_PAD(0x05A0, 0x01D0, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__EPDC_SDCE_0 \ + IOMUX_PAD(0x05A0, 0x01D0, 8, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_EB3__WEIM_ACLK_FREERUN \ + IOMUX_PAD(0x05A0, 0x01D0, 9, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_LBA__WEIM_WEIM_LBA \ + IOMUX_PAD(0x05A4, 0x01D4, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_LBA__IPU1_DI1_PIN17 \ + IOMUX_PAD(0x05A4, 0x01D4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_LBA__ECSPI2_SS1 \ + IOMUX_PAD(0x05A4, 0x01D4, 2, 0x0804, 1, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_LBA__GPIO_2_27 \ + IOMUX_PAD(0x05A4, 0x01D4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_LBA__TPSMP_HDATA_11 \ + IOMUX_PAD(0x05A4, 0x01D4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_LBA__SRC_BT_CFG_26 \ + IOMUX_PAD(0x05A4, 0x01D4, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_LBA__EPDC_SDDO_4 \ + IOMUX_PAD(0x05A4, 0x01D4, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_OE__WEIM_WEIM_OE \ + IOMUX_PAD(0x05A8, 0x01D8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_OE__IPU1_DI1_PIN7 \ + IOMUX_PAD(0x05A8, 0x01D8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_OE__ECSPI2_MISO \ + IOMUX_PAD(0x05A8, 0x01D8, 2, 0x07F8, 2, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_OE__MIPI_CORE_DPHY_TEST_OUT_26 \ + IOMUX_PAD(0x05A8, 0x01D8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_OE__GPIO_2_25 \ + IOMUX_PAD(0x05A8, 0x01D8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_OE__TPSMP_HDATA_9 \ + IOMUX_PAD(0x05A8, 0x01D8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_OE__EPDC_PWRIRQ \ + IOMUX_PAD(0x05A8, 0x01D8, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_RW__WEIM_WEIM_RW \ + IOMUX_PAD(0x05AC, 0x01DC, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__IPU1_DI1_PIN8 \ + IOMUX_PAD(0x05AC, 0x01DC, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__ECSPI2_SS0 \ + IOMUX_PAD(0x05AC, 0x01DC, 2, 0x0800, 2, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__MIPI_CORE_DPHY_TEST_OUT_27 \ + IOMUX_PAD(0x05AC, 0x01DC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__GPIO_2_26 \ + IOMUX_PAD(0x05AC, 0x01DC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__TPSMP_HDATA_10 \ + IOMUX_PAD(0x05AC, 0x01DC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__SRC_BT_CFG_29 \ + IOMUX_PAD(0x05AC, 0x01DC, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_RW__EPDC_SDDO_7 \ + IOMUX_PAD(0x05AC, 0x01DC, 8, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_EIM_WAIT__WEIM_WEIM_WAIT \ + IOMUX_PAD(0x05B0, 0x01E0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_WAIT__WEIM_WEIM_DTACK_B \ + IOMUX_PAD(0x05B0, 0x01E0, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_WAIT__GPIO_5_0 \ + IOMUX_PAD(0x05B0, 0x01E0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_WAIT__TPSMP_HDATA_30 \ + IOMUX_PAD(0x05B0, 0x01E0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_EIM_WAIT__SRC_BT_CFG_25 \ + IOMUX_PAD(0x05B0, 0x01E0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_CRS_DV__ENET_RX_EN \ + IOMUX_PAD(0x05B4, 0x01E4, 1, 0x0828, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_CRS_DV__ESAI1_SCKT \ + IOMUX_PAD(0x05B4, 0x01E4, 2, 0x0840, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_CRS_DV__SPDIF_SPDIF_EXTCLK \ + IOMUX_PAD(0x05B4, 0x01E4, 3, 0x08F4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_CRS_DV__GPIO_1_25 \ + IOMUX_PAD(0x05B4, 0x01E4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_CRS_DV__PHY_TDO \ + IOMUX_PAD(0x05B4, 0x01E4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_CRS_DV__ANATOP_USBPHY1_TSTO_RX_FS_RXD \ + IOMUX_PAD(0x05B4, 0x01E4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_MDC__MLB_MLBDAT \ + IOMUX_PAD(0x05B8, 0x01E8, 0, 0x08E0, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDC__ENET_MDC \ + IOMUX_PAD(0x05B8, 0x01E8, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_ENET_MDC__ESAI1_TX5_RX0 \ + IOMUX_PAD(0x05B8, 0x01E8, 2, 0x0858, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_MDC__ENET_1588_EVENT1_IN \ + IOMUX_PAD(0x05B8, 0x01E8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDC__GPIO_1_31 \ + IOMUX_PAD(0x05B8, 0x01E8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDC__ANATOP_USBPHY2_TSTO_RX_DISCON_DET \ + IOMUX_PAD(0x05B8, 0x01E8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_MDIO__ENET_MDIO \ + IOMUX_PAD(0x05BC, 0x01EC, 1, 0x0810, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_ENET_MDIO__ESAI1_SCKR \ + IOMUX_PAD(0x05BC, 0x01EC, 2, 0x083C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDIO__SDMA_DEBUG_BUS_DEVICE_3 \ + IOMUX_PAD(0x05BC, 0x01EC, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT \ + IOMUX_PAD(0x05BC, 0x01EC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDIO__GPIO_1_22 \ + IOMUX_PAD(0x05BC, 0x01EC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_MDIO__SPDIF_PLOCK \ + IOMUX_PAD(0x05BC, 0x01EC, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK \ + IOMUX_PAD(0x05C0, 0x01F0, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_ENET_REF_CLK__ESAI1_FSR \ + IOMUX_PAD(0x05C0, 0x01F0, 2, 0x082C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 \ + IOMUX_PAD(0x05C0, 0x01F0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_REF_CLK__GPIO_1_23 \ + IOMUX_PAD(0x05C0, 0x01F0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_REF_CLK__SPDIF_SRCLK \ + IOMUX_PAD(0x05C0, 0x01F0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_REF_CLK__ANATOP_USBPHY1_TSTO_RX_SQUELCH \ + IOMUX_PAD(0x05C0, 0x01F0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_RX_ER__ANATOP_USBOTG_ID \ + IOMUX_PAD(0x05C4, 0x01F4, 0, 0x0790, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__ENET_RX_ER \ + IOMUX_PAD(0x05C4, 0x01F4, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__ESAI1_HCKR \ + IOMUX_PAD(0x05C4, 0x01F4, 2, 0x0834, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__SPDIF_IN1 \ + IOMUX_PAD(0x05C4, 0x01F4, 3, 0x08F0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT \ + IOMUX_PAD(0x05C4, 0x01F4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__GPIO_1_24 \ + IOMUX_PAD(0x05C4, 0x01F4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__PHY_TDI \ + IOMUX_PAD(0x05C4, 0x01F4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RX_ER__ANATOP_USBPHY1_TSTO_RX_HS_RXD \ + IOMUX_PAD(0x05C4, 0x01F4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_RXD0__OSC32K_32K_OUT \ + IOMUX_PAD(0x05C8, 0x01F8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD0__ENET_RDATA_0 \ + IOMUX_PAD(0x05C8, 0x01F8, 1, 0x0818, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD0__ESAI1_HCKT \ + IOMUX_PAD(0x05C8, 0x01F8, 2, 0x0838, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD0__SPDIF_OUT1 \ + IOMUX_PAD(0x05C8, 0x01F8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD0__GPIO_1_27 \ + IOMUX_PAD(0x05C8, 0x01F8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD0__PHY_TMS \ + IOMUX_PAD(0x05C8, 0x01F8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD0__ANATOP_USBPHY1_TSTO_PLL_CLK20DIV \ + IOMUX_PAD(0x05C8, 0x01F8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_RXD1__MLB_MLBSIG \ + IOMUX_PAD(0x05CC, 0x01FC, 0, 0x08E4, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD1__ENET_RDATA_1 \ + IOMUX_PAD(0x05CC, 0x01FC, 1, 0x081C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD1__ESAI1_FST \ + IOMUX_PAD(0x05CC, 0x01FC, 2, 0x0830, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT \ + IOMUX_PAD(0x05CC, 0x01FC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD1__GPIO_1_26 \ + IOMUX_PAD(0x05CC, 0x01FC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD1__PHY_TCK \ + IOMUX_PAD(0x05CC, 0x01FC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_RXD1__ANATOP_USBPHY1_TSTO_RX_DISCON_DET \ + IOMUX_PAD(0x05CC, 0x01FC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_TX_EN__ENET_TX_EN \ + IOMUX_PAD(0x05D0, 0x0200, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TX_EN__ESAI1_TX3_RX2 \ + IOMUX_PAD(0x05D0, 0x0200, 2, 0x0850, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_TX_EN__GPIO_1_28 \ + IOMUX_PAD(0x05D0, 0x0200, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TX_EN__ANATOP_USBPHY2_TSTO_RX_SQUELCH \ + IOMUX_PAD(0x05D0, 0x0200, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TX_EN__I2C4_SCL \ + IOMUX_PAD(0x05D0, 0x0200, 9 | IOMUX_CONFIG_SION, 0x0880, 0, MX6DL_I2C_PAD_CTRL) + +#define MX6DL_PAD_ENET_TXD0__ENET_TDATA_0 \ + IOMUX_PAD(0x05D4, 0x0204, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD0__ESAI1_TX4_RX1 \ + IOMUX_PAD(0x05D4, 0x0204, 2, 0x0854, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD0__GPIO_1_30 \ + IOMUX_PAD(0x05D4, 0x0204, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD0__ANATOP_USBPHY2_TSTO_RX_FS_RXD \ + IOMUX_PAD(0x05D4, 0x0204, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_ENET_TXD1__MLB_MLBCLK \ + IOMUX_PAD(0x05D8, 0x0208, 0, 0x08DC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD1__ENET_TDATA_1 \ + IOMUX_PAD(0x05D8, 0x0208, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD1__ESAI1_TX2_RX3 \ + IOMUX_PAD(0x05D8, 0x0208, 2, 0x084C, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD1__ENET_1588_EVENT0_IN \ + IOMUX_PAD(0x05D8, 0x0208, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD1__GPIO_1_29 \ + IOMUX_PAD(0x05D8, 0x0208, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD1__ANATOP_USBPHY2_TSTO_RX_HS_RXD \ + IOMUX_PAD(0x05D8, 0x0208, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_ENET_TXD1__I2C4_SDA \ + IOMUX_PAD(0x05D8, 0x0208, 9 | IOMUX_CONFIG_SION, 0x0884, 0, MX6DL_I2C_PAD_CTRL) + +#define MX6DL_PAD_GPIO_0__CCM_CLKO \ + IOMUX_PAD(0x05DC, 0x020C, 0, 0x0000, 0, MX6DL_CCM_CLK0_PAD_CTRL) +#define MX6DL_PAD_GPIO_0__KPP_COL_5 \ + IOMUX_PAD(0x05DC, 0x020C, 2, 0x08C0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_0__ASRC_ASRC_EXT_CLK \ + IOMUX_PAD(0x05DC, 0x020C, 3, 0x0794, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_0__EPIT1_EPITO \ + IOMUX_PAD(0x05DC, 0x020C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_0__GPIO_1_0 \ + IOMUX_PAD(0x05DC, 0x020C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_0__USBOH3_USBH1_PWR \ + IOMUX_PAD(0x05DC, 0x020C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_0__SNVS_HP_WRAPPER_SNVS_VIO_5 \ + IOMUX_PAD(0x05DC, 0x020C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_1__ESAI1_SCKR \ + IOMUX_PAD(0x05E0, 0x0210, 0, 0x083C, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__WDOG2_WDOG_B \ + IOMUX_PAD(0x05E0, 0x0210, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__KPP_ROW_5 \ + IOMUX_PAD(0x05E0, 0x0210, 2, 0x08CC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__USBOTG_ID \ + IOMUX_PAD(0x05E0, 0x0210, 3, 0x0790, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__PWM2_PWMO \ + IOMUX_PAD(0x05E0, 0x0210, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__GPIO_1_1 \ + IOMUX_PAD(0x05E0, 0x0210, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__USDHC1_CD \ + IOMUX_PAD(0x05E0, 0x0210, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_1__SRC_TESTER_ACK \ + IOMUX_PAD(0x05E0, 0x0210, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_16__ESAI1_TX3_RX2 \ + IOMUX_PAD(0x05E4, 0x0214, 0, 0x0850, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__ENET_1588_EVENT2_IN \ + IOMUX_PAD(0x05E4, 0x0214, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT \ + IOMUX_PAD(0x05E4, 0x0214, 0x12, 0x080C, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__USDHC1_LCTL \ + IOMUX_PAD(0x05E4, 0x0214, 3, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__SPDIF_IN1 \ + IOMUX_PAD(0x05E4, 0x0214, 4, 0x08F0, 2, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__GPIO_7_11 \ + IOMUX_PAD(0x05E4, 0x0214, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__I2C3_SDA \ + IOMUX_PAD(0x05E4, 0x0214, 6 | IOMUX_CONFIG_SION, 0x087C, 1, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_GPIO_16__SJC_DE_B \ + IOMUX_PAD(0x05E4, 0x0214, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_17__ESAI1_TX0 \ + IOMUX_PAD(0x05E8, 0x0218, 0, 0x0844, 0, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_GPIO_17__ENET_1588_EVENT3_IN \ + IOMUX_PAD(0x05E8, 0x0218, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_17__CCM_PMIC_RDY \ + IOMUX_PAD(0x05E8, 0x0218, 2, 0x07D4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_17__SDMA_SDMA_EXT_EVENT_0 \ + IOMUX_PAD(0x05E8, 0x0218, 3, 0x08E8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_17__SPDIF_OUT1 \ + IOMUX_PAD(0x05E8, 0x0218, 4, 0x0000, 0, MX6DL_SPDIF_OUT_PAD_CTRL) +#define MX6DL_PAD_GPIO_17__GPIO_7_12 \ + IOMUX_PAD(0x05E8, 0x0218, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_17__SJC_JTAG_ACT \ + IOMUX_PAD(0x05E8, 0x0218, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_18__ESAI1_TX1 \ + IOMUX_PAD(0x05EC, 0x021C, 0, 0x0848, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__ENET_RX_CLK \ + IOMUX_PAD(0x05EC, 0x021C, 1, 0x0814, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__USDHC3_VSELECT \ + IOMUX_PAD(0x05EC, 0x021C, 2, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__SDMA_SDMA_EXT_EVENT_1 \ + IOMUX_PAD(0x05EC, 0x021C, 3, 0x08EC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__ASRC_ASRC_EXT_CLK \ + IOMUX_PAD(0x05EC, 0x021C, 4, 0x0794, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__GPIO_7_13 \ + IOMUX_PAD(0x05EC, 0x021C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__SNVS_HP_WRAPPER_SNVS_VIO_5_CTL \ + IOMUX_PAD(0x05EC, 0x021C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_18__SRC_SYSTEM_RST \ + IOMUX_PAD(0x05EC, 0x021C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_19__KPP_COL_5 \ + IOMUX_PAD(0x05F0, 0x0220, 0, 0x08C0, 2, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__ENET_1588_EVENT0_OUT \ + IOMUX_PAD(0x05F0, 0x0220, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__SPDIF_OUT1 \ + IOMUX_PAD(0x05F0, 0x0220, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__CCM_CLKO \ + IOMUX_PAD(0x05F0, 0x0220, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__ECSPI1_RDY \ + IOMUX_PAD(0x05F0, 0x0220, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__GPIO_4_5 \ + IOMUX_PAD(0x05F0, 0x0220, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__ENET_TX_ER \ + IOMUX_PAD(0x05F0, 0x0220, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_19__SRC_INT_BOOT \ + IOMUX_PAD(0x05F0, 0x0220, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_2__ESAI1_FST \ + IOMUX_PAD(0x05F4, 0x0224, 0, 0x0830, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 \ + IOMUX_PAD(0x05F4, 0x0224, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__KPP_ROW_6 \ + IOMUX_PAD(0x05F4, 0x0224, 2, 0x08D0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__CCM_CCM_OUT_1 \ + IOMUX_PAD(0x05F4, 0x0224, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 \ + IOMUX_PAD(0x05F4, 0x0224, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__GPIO_1_2 \ + IOMUX_PAD(0x05F4, 0x0224, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__USDHC2_WP \ + IOMUX_PAD(0x05F4, 0x0224, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_2__MLB_MLBDAT \ + IOMUX_PAD(0x05F4, 0x0224, 7, 0x08E0, 1, MX6DL_MLB150_PAD_CTRL) + +#define MX6DL_PAD_GPIO_3__ESAI1_HCKR \ + IOMUX_PAD(0x05F8, 0x0228, 0, 0x0834, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 \ + IOMUX_PAD(0x05F8, 0x0228, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__I2C3_SCL \ + IOMUX_PAD(0x05F8, 0x0228, 2 | IOMUX_CONFIG_SION, 0x0878, 1, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__ANATOP_ANATOP_24M_OUT \ + IOMUX_PAD(0x05F8, 0x0228, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__CCM_CLKO2 \ + IOMUX_PAD(0x05F8, 0x0228, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__GPIO_1_3 \ + IOMUX_PAD(0x05F8, 0x0228, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__USBOH3_USBH1_OC \ + IOMUX_PAD(0x05F8, 0x0228, 6, 0x0924, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_3__MLB_MLBCLK \ + IOMUX_PAD(0x05F8, 0x0228, 7, 0x08DC, 1, MX6DL_MLB150_PAD_CTRL) + +#define MX6DL_PAD_GPIO_4__ESAI1_HCKT \ + IOMUX_PAD(0x05FC, 0x022C, 0, 0x0838, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 \ + IOMUX_PAD(0x05FC, 0x022C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__KPP_COL_7 \ + IOMUX_PAD(0x05FC, 0x022C, 2, 0x08C8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__CCM_CCM_OUT_2 \ + IOMUX_PAD(0x05FC, 0x022C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 \ + IOMUX_PAD(0x05FC, 0x022C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__GPIO_1_4 \ + IOMUX_PAD(0x05FC, 0x022C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__USDHC2_CD \ + IOMUX_PAD(0x05FC, 0x022C, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_4__OCOTP_CTRL_WRAPPER_FUSE_LATCHED \ + IOMUX_PAD(0x05FC, 0x022C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_5__ESAI1_TX2_RX3 \ + IOMUX_PAD(0x0600, 0x0230, 0, 0x084C, 1, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 \ + IOMUX_PAD(0x0600, 0x0230, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__KPP_ROW_7 \ + IOMUX_PAD(0x0600, 0x0230, 2, 0x08D4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__CCM_CLKO \ + IOMUX_PAD(0x0600, 0x0230, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 \ + IOMUX_PAD(0x0600, 0x0230, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__GPIO_1_5 \ + IOMUX_PAD(0x0600, 0x0230, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__I2C3_SCL \ + IOMUX_PAD(0x0600, 0x0230, 6 | IOMUX_CONFIG_SION, 0x0878, 2, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_GPIO_5__SIMBA_EVENTI \ + IOMUX_PAD(0x0600, 0x0230, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_GPIO_6__ESAI1_SCKT \ + IOMUX_PAD(0x0604, 0x0234, 0, 0x0840, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ + IOMUX_PAD(0x0604, 0x0234, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__I2C3_SDA \ + IOMUX_PAD(0x0604, 0x0234, 2 | IOMUX_CONFIG_SION, 0x087C, 2, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__CCM_CCM_OUT_0 \ + IOMUX_PAD(0x0604, 0x0234, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__CSU_CSU_INT_DEB \ + IOMUX_PAD(0x0604, 0x0234, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__GPIO_1_6 \ + IOMUX_PAD(0x0604, 0x0234, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__USDHC2_LCTL \ + IOMUX_PAD(0x0604, 0x0234, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__MLB_MLBSIG \ + IOMUX_PAD(0x0604, 0x0234, 7, 0x08E4, 1, MX6DL_MLB150_PAD_CTRL) + +#define MX6DL_PAD_GPIO_7__ESAI1_TX4_RX1 \ + IOMUX_PAD(0x0608, 0x0238, 0, 0x0854, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__EPIT1_EPITO \ + IOMUX_PAD(0x0608, 0x0238, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__CAN1_TXCAN \ + IOMUX_PAD(0x0608, 0x0238, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__UART2_TXD \ + IOMUX_PAD(0x0608, 0x0238, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__UART2_RXD \ + IOMUX_PAD(0x0608, 0x0238, 4, 0x0904, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__GPIO_1_7 \ + IOMUX_PAD(0x0608, 0x0238, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__SPDIF_PLOCK \ + IOMUX_PAD(0x0608, 0x0238, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__USBOH3_OTGUSB_HOST_MODE \ + IOMUX_PAD(0x0608, 0x0238, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_7__I2C4_SCL \ + IOMUX_PAD(0x0608, 0x0238, 8 | IOMUX_CONFIG_SION, 0x0880, 1, MX6DL_I2C_PAD_CTRL) + +#define MX6DL_PAD_GPIO_8__ESAI1_TX5_RX0 \ + IOMUX_PAD(0x060C, 0x023C, 0, 0x0858, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__ANATOP_ANATOP_32K_OUT \ + IOMUX_PAD(0x060C, 0x023C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__EPIT2_EPITO \ + IOMUX_PAD(0x060C, 0x023C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__CAN1_RXCAN \ + IOMUX_PAD(0x060C, 0x023C, 3, 0x07C8, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__UART2_TXD \ + IOMUX_PAD(0x060C, 0x023C, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__UART2_RXD \ + IOMUX_PAD(0x060C, 0x023C, 4, 0x0904, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__GPIO_1_8 \ + IOMUX_PAD(0x060C, 0x023C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__SPDIF_SRCLK \ + IOMUX_PAD(0x060C, 0x023C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__USBOH3_OTGUSB_PWRCTL_WAKEUP \ + IOMUX_PAD(0x060C, 0x023C, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_8__I2C4_SDA \ + IOMUX_PAD(0x060C, 0x023C, 8 | IOMUX_CONFIG_SION, 0x0884, 1, MX6DL_I2C_PAD_CTRL) + +#define MX6DL_PAD_GPIO_9__ESAI1_FSR \ + IOMUX_PAD(0x0610, 0x0240, 0, 0x082C, 1, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__WDOG1_WDOG_B \ + IOMUX_PAD(0x0610, 0x0240, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__KPP_COL_6 \ + IOMUX_PAD(0x0610, 0x0240, 2, 0x08C4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__CCM_REF_EN_B \ + IOMUX_PAD(0x0610, 0x0240, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__PWM1_PWMO \ + IOMUX_PAD(0x0610, 0x0240, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__GPIO_1_9 \ + IOMUX_PAD(0x0610, 0x0240, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__USDHC1_WP \ + IOMUX_PAD(0x0610, 0x0240, 6, 0x092C, 1, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_GPIO_9__SRC_EARLY_RST \ + IOMUX_PAD(0x0610, 0x0240, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_JTAG_MOD__SJC_MOD \ + IOMUX_PAD(0x0614, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_JTAG_TCK__SJC_TCK \ + IOMUX_PAD(0x0618, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_JTAG_TDI__SJC_TDI \ + IOMUX_PAD(0x061C, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_JTAG_TDO__SJC_TDO \ + IOMUX_PAD(0x0620, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_JTAG_TMS__SJC_TMS \ + IOMUX_PAD(0x0624, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_JTAG_TRSTB__SJC_TRSTB \ + IOMUX_PAD(0x0628, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_COL0__ECSPI1_SCLK \ + IOMUX_PAD(0x062C, 0x0244, 0, 0x07D8, 3, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__ENET_RDATA_3 \ + IOMUX_PAD(0x062C, 0x0244, 1, 0x0824, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__AUDMUX_AUD5_TXC \ + IOMUX_PAD(0x062C, 0x0244, 2, 0x07C0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__KPP_COL_0 \ + IOMUX_PAD(0x062C, 0x0244, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__UART4_TXD \ + IOMUX_PAD(0x062C, 0x0244, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__UART4_RXD \ + IOMUX_PAD(0x062C, 0x0244, 4, 0x0914, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__GPIO_4_6 \ + IOMUX_PAD(0x062C, 0x0244, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__DCIC1_DCIC_OUT \ + IOMUX_PAD(0x062C, 0x0244, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL0__SRC_ANY_PU_RST \ + IOMUX_PAD(0x062C, 0x0244, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_COL1__ECSPI1_MISO \ + IOMUX_PAD(0x0630, 0x0248, 0, 0x07DC, 3, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__ENET_MDIO \ + IOMUX_PAD(0x0630, 0x0248, 1, 0x0810, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__AUDMUX_AUD5_TXFS \ + IOMUX_PAD(0x0630, 0x0248, 2, 0x07C4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__KPP_COL_1 \ + IOMUX_PAD(0x0630, 0x0248, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__UART5_TXD \ + IOMUX_PAD(0x0630, 0x0248, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__UART5_RXD \ + IOMUX_PAD(0x0630, 0x0248, 4, 0x091C, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__GPIO_4_8 \ + IOMUX_PAD(0x0630, 0x0248, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__USDHC1_VSELECT \ + IOMUX_PAD(0x0630, 0x0248, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_KEY_COL1__PL301_SIM_MX6DL_PER1_HADDR_1 \ + IOMUX_PAD(0x0630, 0x0248, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_COL2__ECSPI1_SS1 \ + IOMUX_PAD(0x0634, 0x024C, 0, 0x07E8, 2, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__ENET_RDATA_2 \ + IOMUX_PAD(0x0634, 0x024C, 1, 0x0820, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__CAN1_TXCAN \ + IOMUX_PAD(0x0634, 0x024C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__KPP_COL_2 \ + IOMUX_PAD(0x0634, 0x024C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__ENET_MDC \ + IOMUX_PAD(0x0634, 0x024C, 4, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__GPIO_4_10 \ + IOMUX_PAD(0x0634, 0x024C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__USBOH3_H1USB_PWRCTL_WAKEUP \ + IOMUX_PAD(0x0634, 0x024C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL2__PL301_SIM_MX6DL_PER1_HADDR_3 \ + IOMUX_PAD(0x0634, 0x024C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_COL3__ECSPI1_SS3 \ + IOMUX_PAD(0x0638, 0x0250, 0, 0x07F0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__ENET_CRS \ + IOMUX_PAD(0x0638, 0x0250, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL \ + IOMUX_PAD(0x0638, 0x0250, 2, 0x0860, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__KPP_COL_3 \ + IOMUX_PAD(0x0638, 0x0250, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__I2C2_SCL \ + IOMUX_PAD(0x0638, 0x0250, 4 | IOMUX_CONFIG_SION, 0x0870, 1, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__GPIO_4_12 \ + IOMUX_PAD(0x0638, 0x0250, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__SPDIF_IN1 \ + IOMUX_PAD(0x0638, 0x0250, 6, 0x08F0, 3, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL3__PL301_SIM_MX6DL_PER1_HADDR_5 \ + IOMUX_PAD(0x0638, 0x0250, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_COL4__CAN2_TXCAN \ + IOMUX_PAD(0x063C, 0x0254, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__IPU1_SISG_4 \ + IOMUX_PAD(0x063C, 0x0254, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__USBOH3_USBOTG_OC \ + IOMUX_PAD(0x063C, 0x0254, 2, 0x0920, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__KPP_COL_4 \ + IOMUX_PAD(0x063C, 0x0254, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__UART5_CTS \ + IOMUX_PAD(0x063C, 0x0254, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__UART5_RTS \ + IOMUX_PAD(0x063C, 0x0254, 4, 0x0918, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__GPIO_4_14 \ + IOMUX_PAD(0x063C, 0x0254, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__MMDC_MMDC_DEBUG_49 \ + IOMUX_PAD(0x063C, 0x0254, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_COL4__PL301_SIM_MX6DL_PER1_HADDR_7 \ + IOMUX_PAD(0x063C, 0x0254, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_ROW0__ECSPI1_MOSI \ + IOMUX_PAD(0x0640, 0x0258, 0, 0x07E0, 3, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__ENET_TDATA_3 \ + IOMUX_PAD(0x0640, 0x0258, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__AUDMUX_AUD5_TXD \ + IOMUX_PAD(0x0640, 0x0258, 2, 0x07B4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__KPP_ROW_0 \ + IOMUX_PAD(0x0640, 0x0258, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__UART4_TXD \ + IOMUX_PAD(0x0640, 0x0258, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__UART4_RXD \ + IOMUX_PAD(0x0640, 0x0258, 4, 0x0914, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__GPIO_4_7 \ + IOMUX_PAD(0x0640, 0x0258, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__DCIC2_DCIC_OUT \ + IOMUX_PAD(0x0640, 0x0258, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW0__PL301_SIM_MX6DL_PER1_HADDR_0 \ + IOMUX_PAD(0x0640, 0x0258, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_ROW1__ECSPI1_SS0 \ + IOMUX_PAD(0x0644, 0x025C, 0, 0x07E4, 3, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__ENET_COL \ + IOMUX_PAD(0x0644, 0x025C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__AUDMUX_AUD5_RXD \ + IOMUX_PAD(0x0644, 0x025C, 2, 0x07B0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__KPP_ROW_1 \ + IOMUX_PAD(0x0644, 0x025C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__UART5_TXD \ + IOMUX_PAD(0x0644, 0x025C, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__UART5_RXD \ + IOMUX_PAD(0x0644, 0x025C, 4, 0x091C, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__GPIO_4_9 \ + IOMUX_PAD(0x0644, 0x025C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__USDHC2_VSELECT \ + IOMUX_PAD(0x0644, 0x025C, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW1__PL301_SIM_MX6DL_PER1_HADDR_2 \ + IOMUX_PAD(0x0644, 0x025C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_ROW2__ECSPI1_SS2 \ + IOMUX_PAD(0x0648, 0x0260, 0, 0x07EC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__ENET_TDATA_2 \ + IOMUX_PAD(0x0648, 0x0260, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__CAN1_RXCAN \ + IOMUX_PAD(0x0648, 0x0260, 2, 0x07C8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__KPP_ROW_2 \ + IOMUX_PAD(0x0648, 0x0260, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__USDHC2_VSELECT \ + IOMUX_PAD(0x0648, 0x0260, 4, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__GPIO_4_11 \ + IOMUX_PAD(0x0648, 0x0260, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE \ + IOMUX_PAD(0x0648, 0x0260, 6, 0x085C, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW2__PL301_SIM_MX6DL_PER1_HADDR_4 \ + IOMUX_PAD(0x0648, 0x0260, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_ROW3__OSC32K_32K_OUT \ + IOMUX_PAD(0x064C, 0x0264, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK \ + IOMUX_PAD(0x064C, 0x0264, 1, 0x0794, 2, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA \ + IOMUX_PAD(0x064C, 0x0264, 2, 0x0864, 1, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__KPP_ROW_3 \ + IOMUX_PAD(0x064C, 0x0264, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__I2C2_SDA \ + IOMUX_PAD(0x064C, 0x0264, 4 | IOMUX_CONFIG_SION, 0x0874, 1, MX6DL_I2C_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__GPIO_4_13 \ + IOMUX_PAD(0x064C, 0x0264, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__USDHC1_VSELECT \ + IOMUX_PAD(0x064C, 0x0264, 6, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW3__PL301_SIM_MX6DL_PER1_HADDR_6 \ + IOMUX_PAD(0x064C, 0x0264, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_KEY_ROW4__CAN2_RXCAN \ + IOMUX_PAD(0x0650, 0x0268, 0, 0x07CC, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__IPU1_SISG_5 \ + IOMUX_PAD(0x0650, 0x0268, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__USBOH3_USBOTG_PWR \ + IOMUX_PAD(0x0650, 0x0268, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__KPP_ROW_4 \ + IOMUX_PAD(0x0650, 0x0268, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__UART5_CTS \ + IOMUX_PAD(0x0650, 0x0268, 4, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__UART5_RTS \ + IOMUX_PAD(0x0650, 0x0268, 4, 0x0918, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__GPIO_4_15 \ + IOMUX_PAD(0x0650, 0x0268, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__MMDC_MMDC_DEBUG_50 \ + IOMUX_PAD(0x0650, 0x0268, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_KEY_ROW4__PL301_SIM_MX6DL_PER1_HADDR_8 \ + IOMUX_PAD(0x0650, 0x0268, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_ALE__RAWNAND_ALE \ + IOMUX_PAD(0x0654, 0x026C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__USDHC4_RST \ + IOMUX_PAD(0x0654, 0x026C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__PCIE_CTRL_DIAG_STATUS_BUS_MUX_0 \ + IOMUX_PAD(0x0654, 0x026C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__USBOH3_UH3_DFD_OUT_12 \ + IOMUX_PAD(0x0654, 0x026C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__USBOH3_UH2_DFD_OUT_12 \ + IOMUX_PAD(0x0654, 0x026C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__GPIO_6_8 \ + IOMUX_PAD(0x0654, 0x026C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__MIPI_CORE_DPHY_TEST_IN_24 \ + IOMUX_PAD(0x0654, 0x026C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_ALE__USDHC3_CLKI \ + IOMUX_PAD(0x0654, 0x026C, 8, 0x0934, 0, MX6DL_USDHC_PAD_CTRL) + +#define MX6DL_PAD_NANDF_CLE__RAWNAND_CLE \ + IOMUX_PAD(0x0658, 0x0270, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_CLE__PCIE_CTRL_DIAG_STATUS_BUS_MUX_31 \ + IOMUX_PAD(0x0658, 0x0270, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CLE__USBOH3_UH3_DFD_OUT_11 \ + IOMUX_PAD(0x0658, 0x0270, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CLE__USBOH3_UH2_DFD_OUT_11 \ + IOMUX_PAD(0x0658, 0x0270, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CLE__GPIO_6_7 \ + IOMUX_PAD(0x0658, 0x0270, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CLE__MIPI_CORE_DPHY_TEST_IN_23 \ + IOMUX_PAD(0x0658, 0x0270, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CLE__USDHC3_CLKO \ + IOMUX_PAD(0x0658, 0x0270, 8, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) + +#define MX6DL_PAD_NANDF_CS0__RAWNAND_CE0N \ + IOMUX_PAD(0x065C, 0x0274, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_CS0__USBOH3_UH3_DFD_OUT_15 \ + IOMUX_PAD(0x065C, 0x0274, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS0__USBOH3_UH2_DFD_OUT_15 \ + IOMUX_PAD(0x065C, 0x0274, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS0__GPIO_6_11 \ + IOMUX_PAD(0x065C, 0x0274, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS0__USDHC1_CLKO \ + IOMUX_PAD(0x065C, 0x0274, 8, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) + +#define MX6DL_PAD_NANDF_CS1__RAWNAND_CE1N \ + IOMUX_PAD(0x0660, 0x0278, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_CS1__USDHC4_VSELECT \ + IOMUX_PAD(0x0660, 0x0278, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS1__USDHC3_VSELECT \ + IOMUX_PAD(0x0660, 0x0278, 2, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS1__PCIE_CTRL_DIAG_STATUS_BUS_MUX_3 \ + IOMUX_PAD(0x0660, 0x0278, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS1__GPIO_6_14 \ + IOMUX_PAD(0x0660, 0x0278, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS1__PL301_SIM_MX6DL_PER1_HREADYOUT \ + IOMUX_PAD(0x0660, 0x0278, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS1__USDHC1_CLKI \ + IOMUX_PAD(0x0660, 0x0278, 8, 0x0928, 0, MX6DL_USDHC_PAD_CTRL) + +#define MX6DL_PAD_NANDF_CS2__RAWNAND_CE2N \ + IOMUX_PAD(0x0664, 0x027C, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_CS2__IPU1_SISG_0 \ + IOMUX_PAD(0x0664, 0x027C, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS2__ESAI1_TX0 \ + IOMUX_PAD(0x0664, 0x027C, 2, 0x0844, 1, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS2__WEIM_WEIM_CRE \ + IOMUX_PAD(0x0664, 0x027C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS2__CCM_CLKO2 \ + IOMUX_PAD(0x0664, 0x027C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS2__GPIO_6_15 \ + IOMUX_PAD(0x0664, 0x027C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS2__USDHC2_CLKO \ + IOMUX_PAD(0x0664, 0x027C, 8, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) + +#define MX6DL_PAD_NANDF_CS3__RAWNAND_CE3N \ + IOMUX_PAD(0x0668, 0x0280, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_CS3__IPU1_SISG_1 \ + IOMUX_PAD(0x0668, 0x0280, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__ESAI1_TX1 \ + IOMUX_PAD(0x0668, 0x0280, 2, 0x0848, 1, MX6DL_ESAI_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__WEIM_WEIM_A_26 \ + IOMUX_PAD(0x0668, 0x0280, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__PCIE_CTRL_DIAG_STATUS_BUS_MUX_4 \ + IOMUX_PAD(0x0668, 0x0280, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__GPIO_6_16 \ + IOMUX_PAD(0x0668, 0x0280, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__TPSMP_CLK \ + IOMUX_PAD(0x0668, 0x0280, 7, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__USDHC2_CLKI \ + IOMUX_PAD(0x0668, 0x0280, 8, 0x0930, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_CS3__I2C4_SDA \ + IOMUX_PAD(0x0668, 0x0280, 9 | IOMUX_CONFIG_SION, 0x0884, 2, MX6DL_I2C_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D0__RAWNAND_D0 \ + IOMUX_PAD(0x066C, 0x0284, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D0__USDHC1_DAT4 \ + IOMUX_PAD(0x066C, 0x0284, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D0__GPU3D_GPU_DEBUG_OUT_0 \ + IOMUX_PAD(0x066C, 0x0284, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D0__USBOH3_UH2_DFD_OUT_16 \ + IOMUX_PAD(0x066C, 0x0284, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D0__USBOH3_UH3_DFD_OUT_16 \ + IOMUX_PAD(0x066C, 0x0284, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D0__GPIO_2_0 \ + IOMUX_PAD(0x066C, 0x0284, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D0__IPU1_IPU_DIAG_BUS_0 \ + IOMUX_PAD(0x066C, 0x0284, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D1__RAWNAND_D1 \ + IOMUX_PAD(0x0670, 0x0288, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D1__USDHC1_DAT5 \ + IOMUX_PAD(0x0670, 0x0288, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D1__GPU3D_GPU_DEBUG_OUT_1 \ + IOMUX_PAD(0x0670, 0x0288, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D1__USBOH3_UH2_DFD_OUT_17 \ + IOMUX_PAD(0x0670, 0x0288, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D1__USBOH3_UH3_DFD_OUT_17 \ + IOMUX_PAD(0x0670, 0x0288, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D1__GPIO_2_1 \ + IOMUX_PAD(0x0670, 0x0288, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D1__IPU1_IPU_DIAG_BUS_1 \ + IOMUX_PAD(0x0670, 0x0288, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D2__RAWNAND_D2 \ + IOMUX_PAD(0x0674, 0x028C, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D2__USDHC1_DAT6 \ + IOMUX_PAD(0x0674, 0x028C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D2__GPU3D_GPU_DEBUG_OUT_2 \ + IOMUX_PAD(0x0674, 0x028C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D2__USBOH3_UH2_DFD_OUT_18 \ + IOMUX_PAD(0x0674, 0x028C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D2__USBOH3_UH3_DFD_OUT_18 \ + IOMUX_PAD(0x0674, 0x028C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D2__GPIO_2_2 \ + IOMUX_PAD(0x0674, 0x028C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D2__IPU1_IPU_DIAG_BUS_2 \ + IOMUX_PAD(0x0674, 0x028C, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D3__RAWNAND_D3 \ + IOMUX_PAD(0x0678, 0x0290, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D3__USDHC1_DAT7 \ + IOMUX_PAD(0x0678, 0x0290, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D3__GPU3D_GPU_DEBUG_OUT_3 \ + IOMUX_PAD(0x0678, 0x0290, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D3__USBOH3_UH2_DFD_OUT_19 \ + IOMUX_PAD(0x0678, 0x0290, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D3__USBOH3_UH3_DFD_OUT_19 \ + IOMUX_PAD(0x0678, 0x0290, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D3__GPIO_2_3 \ + IOMUX_PAD(0x0678, 0x0290, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D3__IPU1_IPU_DIAG_BUS_3 \ + IOMUX_PAD(0x0678, 0x0290, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D4__RAWNAND_D4 \ + IOMUX_PAD(0x067C, 0x0294, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D4__USDHC2_DAT4 \ + IOMUX_PAD(0x067C, 0x0294, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D4__GPU3D_GPU_DEBUG_OUT_4 \ + IOMUX_PAD(0x067C, 0x0294, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D4__USBOH3_UH2_DFD_OUT_20 \ + IOMUX_PAD(0x067C, 0x0294, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D4__USBOH3_UH3_DFD_OUT_20 \ + IOMUX_PAD(0x067C, 0x0294, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D4__GPIO_2_4 \ + IOMUX_PAD(0x067C, 0x0294, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D4__IPU1_IPU_DIAG_BUS_4 \ + IOMUX_PAD(0x067C, 0x0294, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D5__RAWNAND_D5 \ + IOMUX_PAD(0x0680, 0x0298, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D5__USDHC2_DAT5 \ + IOMUX_PAD(0x0680, 0x0298, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D5__GPU3D_GPU_DEBUG_OUT_5 \ + IOMUX_PAD(0x0680, 0x0298, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D5__USBOH3_UH2_DFD_OUT_21 \ + IOMUX_PAD(0x0680, 0x0298, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D5__USBOH3_UH3_DFD_OUT_21 \ + IOMUX_PAD(0x0680, 0x0298, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D5__GPIO_2_5 \ + IOMUX_PAD(0x0680, 0x0298, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D5__IPU1_IPU_DIAG_BUS_5 \ + IOMUX_PAD(0x0680, 0x0298, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D6__RAWNAND_D6 \ + IOMUX_PAD(0x0684, 0x029C, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D6__USDHC2_DAT6 \ + IOMUX_PAD(0x0684, 0x029C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D6__GPU3D_GPU_DEBUG_OUT_6 \ + IOMUX_PAD(0x0684, 0x029C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D6__USBOH3_UH2_DFD_OUT_22 \ + IOMUX_PAD(0x0684, 0x029C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D6__USBOH3_UH3_DFD_OUT_22 \ + IOMUX_PAD(0x0684, 0x029C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D6__GPIO_2_6 \ + IOMUX_PAD(0x0684, 0x029C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D6__IPU1_IPU_DIAG_BUS_6 \ + IOMUX_PAD(0x0684, 0x029C, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_D7__RAWNAND_D7 \ + IOMUX_PAD(0x0688, 0x02A0, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_D7__USDHC2_DAT7 \ + IOMUX_PAD(0x0688, 0x02A0, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_D7__GPU3D_GPU_DEBUG_OUT_7 \ + IOMUX_PAD(0x0688, 0x02A0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D7__USBOH3_UH2_DFD_OUT_23 \ + IOMUX_PAD(0x0688, 0x02A0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D7__USBOH3_UH3_DFD_OUT_23 \ + IOMUX_PAD(0x0688, 0x02A0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D7__GPIO_2_7 \ + IOMUX_PAD(0x0688, 0x02A0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_D7__IPU1_IPU_DIAG_BUS_7 \ + IOMUX_PAD(0x0688, 0x02A0, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_NANDF_RB0__RAWNAND_READY0 \ + IOMUX_PAD(0x068C, 0x02A4, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL0) +#define MX6DL_PAD_NANDF_RB0__PCIE_CTRL_DIAG_STATUS_BUS_MUX_2 \ + IOMUX_PAD(0x068C, 0x02A4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_RB0__USBOH3_UH3_DFD_OUT_14 \ + IOMUX_PAD(0x068C, 0x02A4, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_RB0__USBOH3_UH2_DFD_OUT_14 \ + IOMUX_PAD(0x068C, 0x02A4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_RB0__GPIO_6_10 \ + IOMUX_PAD(0x068C, 0x02A4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_RB0__MIPI_CORE_DPHY_TEST_OUT_33 \ + IOMUX_PAD(0x068C, 0x02A4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_RB0__USDHC4_CLKI \ + IOMUX_PAD(0x068C, 0x02A4, 8, 0x0938, 0, MX6DL_USDHC_PAD_CTRL) + +#define MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN \ + IOMUX_PAD(0x0690, 0x02A8, 0, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_NANDF_WP_B__PCIE_CTRL_DIAG_STATUS_BUS_MUX_1 \ + IOMUX_PAD(0x0690, 0x02A8, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_WP_B__USBOH3_UH3_DFD_OUT_13 \ + IOMUX_PAD(0x0690, 0x02A8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_WP_B__USBOH3_UH2_DFD_OUT_13 \ + IOMUX_PAD(0x0690, 0x02A8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_WP_B__GPIO_6_9 \ + IOMUX_PAD(0x0690, 0x02A8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_WP_B__MIPI_CORE_DPHY_TEST_OUT_32 \ + IOMUX_PAD(0x0690, 0x02A8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_NANDF_WP_B__USDHC4_CLKO \ + IOMUX_PAD(0x0690, 0x02A8, 8, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_NANDF_WP_B__I2C4_SCL \ + IOMUX_PAD(0x0690, 0x02A8, 9 | IOMUX_CONFIG_SION, 0x0880, 2, MX6DL_I2C_PAD_CTRL) + +#define MX6DL_PAD_PMIC_ON_REQ__SNVS_LP_WRAPPER_SNVS_WAKEUP_ALARM \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_PMIC_STBY_REQ__CCM_PMIC_VSTBY_REQ \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_POR_B__SRC_POR_B \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RESET_IN_B__SRC_RESET_B \ + IOMUX_PAD(NO_PAD_I, NO_MUX_I, 0, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_RD0__MIPI_HSI_CTRL_RX_READY \ + IOMUX_PAD(0x0694, 0x02AC, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD0__ENET_RGMII_RD0 \ + IOMUX_PAD(0x0694, 0x02AC, 1, 0x0818, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD0__GPIO_6_25 \ + IOMUX_PAD(0x0694, 0x02AC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD0__MIPI_CORE_DPHY_TEST_IN_6 \ + IOMUX_PAD(0x0694, 0x02AC, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FLAG \ + IOMUX_PAD(0x0698, 0x02B0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD1__ENET_RGMII_RD1 \ + IOMUX_PAD(0x0698, 0x02B0, 1, 0x081C, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD1__GPIO_6_27 \ + IOMUX_PAD(0x0698, 0x02B0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD1__MIPI_CORE_DPHY_TEST_IN_8 \ + IOMUX_PAD(0x0698, 0x02B0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD1__SJC_FAIL \ + IOMUX_PAD(0x0698, 0x02B0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_RD2__MIPI_HSI_CTRL_TX_DATA \ + IOMUX_PAD(0x069C, 0x02B4, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD2__ENET_RGMII_RD2 \ + IOMUX_PAD(0x069C, 0x02B4, 1, 0x0820, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD2__GPIO_6_28 \ + IOMUX_PAD(0x069C, 0x02B4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD2__MIPI_CORE_DPHY_TEST_IN_9 \ + IOMUX_PAD(0x069C, 0x02B4, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_RD3__MIPI_HSI_CTRL_TX_WAKE \ + IOMUX_PAD(0x06A0, 0x02B8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD3__ENET_RGMII_RD3 \ + IOMUX_PAD(0x06A0, 0x02B8, 1, 0x0824, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD3__GPIO_6_29 \ + IOMUX_PAD(0x06A0, 0x02B8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RD3__MIPI_CORE_DPHY_TEST_IN_10 \ + IOMUX_PAD(0x06A0, 0x02B8, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_RX_CTL__USBOH3_H3_DATA \ + IOMUX_PAD(0x06A4, 0x02BC, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USB_HSIC_PAD_CTRL) +#define MX6DL_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL \ + IOMUX_PAD(0x06A4, 0x02BC, 1, 0x0828, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_RX_CTL__GPIO_6_24 \ + IOMUX_PAD(0x06A4, 0x02BC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RX_CTL__MIPI_CORE_DPHY_TEST_IN_5 \ + IOMUX_PAD(0x06A4, 0x02BC, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE \ + IOMUX_PAD(0x06A8, 0x02C0, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USB_HSIC_PAD_CTRL) +#define MX6DL_PAD_RGMII_RXC__USBOH3_H3_STROBE_START \ + IOMUX_PAD(0x06A8, 0x02C0, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USB_HSIC_PAD_CTRL | PAD_CTL_PUS_47K_UP) +#define MX6DL_PAD_RGMII_RXC__ENET_RGMII_RXC \ + IOMUX_PAD(0x06A8, 0x02C0, 1, 0x0814, 1, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_RXC__GPIO_6_30 \ + IOMUX_PAD(0x06A8, 0x02C0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_RXC__MIPI_CORE_DPHY_TEST_IN_11 \ + IOMUX_PAD(0x06A8, 0x02C0, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_TD0__MIPI_HSI_CTRL_TX_READY \ + IOMUX_PAD(0x06AC, 0x02C4, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD0__ENET_RGMII_TD0 \ + IOMUX_PAD(0x06AC, 0x02C4, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD0__GPIO_6_20 \ + IOMUX_PAD(0x06AC, 0x02C4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD0__MIPI_CORE_DPHY_TEST_IN_1 \ + IOMUX_PAD(0x06AC, 0x02C4, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_TD1__MIPI_HSI_CTRL_RX_FLAG \ + IOMUX_PAD(0x06B0, 0x02C8, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD1__ENET_RGMII_TD1 \ + IOMUX_PAD(0x06B0, 0x02C8, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD1__GPIO_6_21 \ + IOMUX_PAD(0x06B0, 0x02C8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD1__MIPI_CORE_DPHY_TEST_IN_2 \ + IOMUX_PAD(0x06B0, 0x02C8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD1__CCM_PLL3_BYP \ + IOMUX_PAD(0x06B0, 0x02C8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_TD2__MIPI_HSI_CTRL_RX_DATA \ + IOMUX_PAD(0x06B4, 0x02CC, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD2__ENET_RGMII_TD2 \ + IOMUX_PAD(0x06B4, 0x02CC, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD2__GPIO_6_22 \ + IOMUX_PAD(0x06B4, 0x02CC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD2__MIPI_CORE_DPHY_TEST_IN_3 \ + IOMUX_PAD(0x06B4, 0x02CC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD2__CCM_PLL2_BYP \ + IOMUX_PAD(0x06B4, 0x02CC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_TD3__MIPI_HSI_CTRL_RX_WAKE \ + IOMUX_PAD(0x06B8, 0x02D0, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD3__ENET_RGMII_TD3 \ + IOMUX_PAD(0x06B8, 0x02D0, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD3__GPIO_6_23 \ + IOMUX_PAD(0x06B8, 0x02D0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TD3__MIPI_CORE_DPHY_TEST_IN_4 \ + IOMUX_PAD(0x06B8, 0x02D0, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE \ + IOMUX_PAD(0x06BC, 0x02D4, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USB_HSIC_PAD_CTRL) +#define MX6DL_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE_START \ + IOMUX_PAD(0x06BC, 0x02D4, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USB_HSIC_PAD_CTRL | PAD_CTL_PUS_47K_UP) +#define MX6DL_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL \ + IOMUX_PAD(0x06BC, 0x02D4, 1, 0x0000, 0, MX6DL_ENET_PAD_CTRL) +#define MX6DL_PAD_RGMII_TX_CTL__GPIO_6_26 \ + IOMUX_PAD(0x06BC, 0x02D4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TX_CTL__MIPI_CORE_DPHY_TEST_IN_7 \ + IOMUX_PAD(0x06BC, 0x02D4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TX_CTL__ENET_ANATOP_ETHERNET_REF_OUT \ + IOMUX_PAD(0x06BC, 0x02D4, 7, 0x080C, 1, NO_PAD_CTRL) + +#define MX6DL_PAD_RGMII_TXC__USBOH3_H2_DATA \ + IOMUX_PAD(0x06C0, 0x02D8, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USB_HSIC_PAD_CTRL) +#define MX6DL_PAD_RGMII_TXC__ENET_RGMII_TXC \ + IOMUX_PAD(0x06C0, 0x02D8, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK \ + IOMUX_PAD(0x06C0, 0x02D8, 2, 0x08F4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TXC__GPIO_6_19 \ + IOMUX_PAD(0x06C0, 0x02D8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TXC__MIPI_CORE_DPHY_TEST_IN_0 \ + IOMUX_PAD(0x06C0, 0x02D8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_RGMII_TXC__ANATOP_ANATOP_24M_OUT \ + IOMUX_PAD(0x06C0, 0x02D8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD1_CLK__USDHC1_CLK \ + IOMUX_PAD(0x06C4, 0x02DC, 0, 0x0928, 1, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD1_CLK__OSC32K_32K_OUT \ + IOMUX_PAD(0x06C4, 0x02DC, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_CLK__GPT_CLKIN \ + IOMUX_PAD(0x06C4, 0x02DC, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_CLK__GPIO_1_20 \ + IOMUX_PAD(0x06C4, 0x02DC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_CLK__PHY_DTB_0 \ + IOMUX_PAD(0x06C4, 0x02DC, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD1_CMD__USDHC1_CMD \ + IOMUX_PAD(0x06C8, 0x02E0, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD1_CMD__PWM4_PWMO \ + IOMUX_PAD(0x06C8, 0x02E0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_CMD__GPT_CMPOUT1 \ + IOMUX_PAD(0x06C8, 0x02E0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_CMD__GPIO_1_18 \ + IOMUX_PAD(0x06C8, 0x02E0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_CMD__ANATOP_ANATOP_TESTO_5 \ + IOMUX_PAD(0x06C8, 0x02E0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD1_DAT0__USDHC1_DAT0 \ + IOMUX_PAD(0x06CC, 0x02E4, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT0__CAAM_WRAPPER_RNG_OSC_OBS \ + IOMUX_PAD(0x06CC, 0x02E4, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT0__GPT_CAPIN1 \ + IOMUX_PAD(0x06CC, 0x02E4, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT0__PCIE_CTRL_DIAG_STATUS_BUS_MUX_8 \ + IOMUX_PAD(0x06CC, 0x02E4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT0__GPIO_1_16 \ + IOMUX_PAD(0x06CC, 0x02E4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1 \ + IOMUX_PAD(0x06CC, 0x02E4, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT0__ANATOP_ANATOP_TESTO_7 \ + IOMUX_PAD(0x06CC, 0x02E4, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD1_DAT1__USDHC1_DAT1 \ + IOMUX_PAD(0x06D0, 0x02E8, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT1__PWM3_PWMO \ + IOMUX_PAD(0x06D0, 0x02E8, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT1__GPT_CAPIN2 \ + IOMUX_PAD(0x06D0, 0x02E8, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT1__PCIE_CTRL_DIAG_STATUS_BUS_MUX_7 \ + IOMUX_PAD(0x06D0, 0x02E8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT1__GPIO_1_17 \ + IOMUX_PAD(0x06D0, 0x02E8, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0 \ + IOMUX_PAD(0x06D0, 0x02E8, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT1__ANATOP_ANATOP_TESTO_8 \ + IOMUX_PAD(0x06D0, 0x02E8, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD1_DAT2__USDHC1_DAT2 \ + IOMUX_PAD(0x06D4, 0x02EC, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT2__GPT_CMPOUT2 \ + IOMUX_PAD(0x06D4, 0x02EC, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT2__PWM2_PWMO \ + IOMUX_PAD(0x06D4, 0x02EC, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT2__WDOG1_WDOG_B \ + IOMUX_PAD(0x06D4, 0x02EC, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT2__GPIO_1_19 \ + IOMUX_PAD(0x06D4, 0x02EC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT2__WDOG1_WDOG_RST_B_DEB \ + IOMUX_PAD(0x06D4, 0x02EC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT2__ANATOP_ANATOP_TESTO_4 \ + IOMUX_PAD(0x06D4, 0x02EC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD1_DAT3__USDHC1_DAT3 \ + IOMUX_PAD(0x06D8, 0x02F0, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT3__GPT_CMPOUT3 \ + IOMUX_PAD(0x06D8, 0x02F0, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT3__PWM1_PWMO \ + IOMUX_PAD(0x06D8, 0x02F0, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT3__WDOG2_WDOG_B \ + IOMUX_PAD(0x06D8, 0x02F0, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT3__GPIO_1_21 \ + IOMUX_PAD(0x06D8, 0x02F0, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT3__WDOG2_WDOG_RST_B_DEB \ + IOMUX_PAD(0x06D8, 0x02F0, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD1_DAT3__ANATOP_ANATOP_TESTO_6 \ + IOMUX_PAD(0x06D8, 0x02F0, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD2_CLK__USDHC2_CLK \ + IOMUX_PAD(0x06DC, 0x02F4, 0, 0x0930, 1, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD2_CLK__KPP_COL_5 \ + IOMUX_PAD(0x06DC, 0x02F4, 2, 0x08C0, 3, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CLK__AUDMUX_AUD4_RXFS \ + IOMUX_PAD(0x06DC, 0x02F4, 3, 0x07A4, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CLK__PCIE_CTRL_DIAG_STATUS_BUS_MUX_9 \ + IOMUX_PAD(0x06DC, 0x02F4, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CLK__GPIO_1_10 \ + IOMUX_PAD(0x06DC, 0x02F4, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CLK__PHY_DTB_1 \ + IOMUX_PAD(0x06DC, 0x02F4, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD2_CMD__USDHC2_CMD \ + IOMUX_PAD(0x06E0, 0x02F8, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD2_CMD__KPP_ROW_5 \ + IOMUX_PAD(0x06E0, 0x02F8, 2, 0x08CC, 2, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CMD__AUDMUX_AUD4_RXC \ + IOMUX_PAD(0x06E0, 0x02F8, 3, 0x07A0, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CMD__PCIE_CTRL_DIAG_STATUS_BUS_MUX_10 \ + IOMUX_PAD(0x06E0, 0x02F8, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_CMD__GPIO_1_11 \ + IOMUX_PAD(0x06E0, 0x02F8, 5, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD2_DAT0__USDHC2_DAT0 \ + IOMUX_PAD(0x06E4, 0x02FC, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT0__AUDMUX_AUD4_RXD \ + IOMUX_PAD(0x06E4, 0x02FC, 3, 0x0798, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT0__KPP_ROW_7 \ + IOMUX_PAD(0x06E4, 0x02FC, 4, 0x08D4, 2, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT0__GPIO_1_15 \ + IOMUX_PAD(0x06E4, 0x02FC, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT0__DCIC2_DCIC_OUT \ + IOMUX_PAD(0x06E4, 0x02FC, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT0__ANATOP_ANATOP_TESTO_2 \ + IOMUX_PAD(0x06E4, 0x02FC, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD2_DAT1__USDHC2_DAT1 \ + IOMUX_PAD(0x06E8, 0x0300, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT1__WEIM_WEIM_CS_2 \ + IOMUX_PAD(0x06E8, 0x0300, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS \ + IOMUX_PAD(0x06E8, 0x0300, 3, 0x07AC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT1__KPP_COL_7 \ + IOMUX_PAD(0x06E8, 0x0300, 4, 0x08C8, 2, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT1__GPIO_1_14 \ + IOMUX_PAD(0x06E8, 0x0300, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT1__CCM_WAIT \ + IOMUX_PAD(0x06E8, 0x0300, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT1__ANATOP_ANATOP_TESTO_0 \ + IOMUX_PAD(0x06E8, 0x0300, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD2_DAT2__USDHC2_DAT2 \ + IOMUX_PAD(0x06EC, 0x0304, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT2__WEIM_WEIM_CS_3 \ + IOMUX_PAD(0x06EC, 0x0304, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT2__AUDMUX_AUD4_TXD \ + IOMUX_PAD(0x06EC, 0x0304, 3, 0x079C, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT2__KPP_ROW_6 \ + IOMUX_PAD(0x06EC, 0x0304, 4, 0x08D0, 2, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT2__GPIO_1_13 \ + IOMUX_PAD(0x06EC, 0x0304, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT2__CCM_STOP \ + IOMUX_PAD(0x06EC, 0x0304, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT2__ANATOP_ANATOP_TESTO_1 \ + IOMUX_PAD(0x06EC, 0x0304, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD2_DAT3__USDHC2_DAT3 \ + IOMUX_PAD(0x06F0, 0x0308, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT3__KPP_COL_6 \ + IOMUX_PAD(0x06F0, 0x0308, 2, 0x08C4, 2, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT3__AUDMUX_AUD4_TXC \ + IOMUX_PAD(0x06F0, 0x0308, 3, 0x07A8, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT3__PCIE_CTRL_DIAG_STATUS_BUS_MUX_11 \ + IOMUX_PAD(0x06F0, 0x0308, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT3__GPIO_1_12 \ + IOMUX_PAD(0x06F0, 0x0308, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT3__SJC_DONE \ + IOMUX_PAD(0x06F0, 0x0308, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD2_DAT3__ANATOP_ANATOP_TESTO_3 \ + IOMUX_PAD(0x06F0, 0x0308, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_CLK__USDHC3_CLK_50MHZ \ + IOMUX_PAD(0x06F4, 0x030C, 0, 0x0934, 1, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__USDHC3_CLK_100MHZ \ + IOMUX_PAD(0x06F4, 0x030C, 0, 0x0934, 1, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_CLK__USDHC3_CLK_200MHZ \ + IOMUX_PAD(0x06F4, 0x030C, 0, 0x0934, 1, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_CLK__UART2_CTS \ + IOMUX_PAD(0x06F4, 0x030C, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__UART2_RTS \ + IOMUX_PAD(0x06F4, 0x030C, 1, 0x0900, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__CAN1_RXCAN \ + IOMUX_PAD(0x06F4, 0x030C, 2, 0x07C8, 2, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__USBOH3_UH3_DFD_OUT_5 \ + IOMUX_PAD(0x06F4, 0x030C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__USBOH3_UH2_DFD_OUT_5 \ + IOMUX_PAD(0x06F4, 0x030C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__GPIO_7_3 \ + IOMUX_PAD(0x06F4, 0x030C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__MIPI_CORE_DPHY_TEST_IN_17 \ + IOMUX_PAD(0x06F4, 0x030C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CLK__ANATOP_ANATOP_TESTO_14 \ + IOMUX_PAD(0x06F4, 0x030C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_CMD__USDHC3_CMD_50MHZ \ + IOMUX_PAD(0x06F8, 0x0310, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__USDHC3_CMD_100MHZ \ + IOMUX_PAD(0x06F8, 0x0310, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_CMD__USDHC3_CMD_200MHZ \ + IOMUX_PAD(0x06F8, 0x0310, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_CMD__UART2_CTS \ + IOMUX_PAD(0x06F8, 0x0310, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MXSDL_PAD_SD3_CMD__UART2_RTS \ + IOMUX_PAD(0x06F8, 0x0310, 1, 0x0900, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__CAN1_TXCAN \ + IOMUX_PAD(0x06F8, 0x0310, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__USBOH3_UH3_DFD_OUT_4 \ + IOMUX_PAD(0x06F8, 0x0310, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__USBOH3_UH2_DFD_OUT_4 \ + IOMUX_PAD(0x06F8, 0x0310, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__GPIO_7_2 \ + IOMUX_PAD(0x06F8, 0x0310, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__MIPI_CORE_DPHY_TEST_IN_16 \ + IOMUX_PAD(0x06F8, 0x0310, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_CMD__ANATOP_ANATOP_TESTO_13 \ + IOMUX_PAD(0x06F8, 0x0310, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ \ + IOMUX_PAD(0x06FC, 0x0314, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_100MHZ \ + IOMUX_PAD(0x06FC, 0x0314, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT0__USDHC3_DAT0_200MHZ \ + IOMUX_PAD(0x06FC, 0x0314, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT0__UART1_CTS \ + IOMUX_PAD(0x06FC, 0x0314, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__UART1_RTS \ + IOMUX_PAD(0x06FC, 0x0314, 1, 0x08F8, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__CAN2_TXCAN \ + IOMUX_PAD(0x06FC, 0x0314, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__USBOH3_UH3_DFD_OUT_6 \ + IOMUX_PAD(0x06FC, 0x0314, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__USBOH3_UH2_DFD_OUT_6 \ + IOMUX_PAD(0x06FC, 0x0314, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__GPIO_7_4 \ + IOMUX_PAD(0x06FC, 0x0314, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__MIPI_CORE_DPHY_TEST_IN_18 \ + IOMUX_PAD(0x06FC, 0x0314, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT0__ANATOP_ANATOP_TESTO_15 \ + IOMUX_PAD(0x06FC, 0x0314, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ \ + IOMUX_PAD(0x0700, 0x0318, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_100MHZ \ + IOMUX_PAD(0x0700, 0x0318, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT1__USDHC3_DAT1_200MHZ \ + IOMUX_PAD(0x0700, 0x0318, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT1__UART1_CTS \ + IOMUX_PAD(0x0700, 0x0318, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__UART1_RTS \ + IOMUX_PAD(0x0700, 0x0318, 1, 0x08F8, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__CAN2_RXCAN \ + IOMUX_PAD(0x0700, 0x0318, 2, 0x07CC, 1, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__USBOH3_UH3_DFD_OUT_7 \ + IOMUX_PAD(0x0700, 0x0318, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__USBOH3_UH2_DFD_OUT_7 \ + IOMUX_PAD(0x0700, 0x0318, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__GPIO_7_5 \ + IOMUX_PAD(0x0700, 0x0318, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__MIPI_CORE_DPHY_TEST_IN_19 \ + IOMUX_PAD(0x0700, 0x0318, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT1__ANATOP_ANATOP_TESTI_0 \ + IOMUX_PAD(0x0700, 0x0318, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ \ + IOMUX_PAD(0x0704, 0x031C, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_100MHZ \ + IOMUX_PAD(0x0704, 0x031C, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT2__USDHC3_DAT2_200MHZ \ + IOMUX_PAD(0x0704, 0x031C, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT2__PCIE_CTRL_DIAG_STATUS_BUS_MUX_28 \ + IOMUX_PAD(0x0704, 0x031C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT2__USBOH3_UH3_DFD_OUT_8 \ + IOMUX_PAD(0x0704, 0x031C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT2__USBOH3_UH2_DFD_OUT_8 \ + IOMUX_PAD(0x0704, 0x031C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT2__GPIO_7_6 \ + IOMUX_PAD(0x0704, 0x031C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT2__MIPI_CORE_DPHY_TEST_IN_20 \ + IOMUX_PAD(0x0704, 0x031C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT2__ANATOP_ANATOP_TESTI_1 \ + IOMUX_PAD(0x0704, 0x031C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ \ + IOMUX_PAD(0x0708, 0x0320, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_100MHZ \ + IOMUX_PAD(0x0708, 0x0320, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT3__USDHC3_DAT3_200MHZ \ + IOMUX_PAD(0x0708, 0x0320, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT3__UART3_CTS \ + IOMUX_PAD(0x0708, 0x0320, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__UART3_RTS \ + IOMUX_PAD(0x0708, 0x0320, 1, 0x0908, 4, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__PCIE_CTRL_DIAG_STATUS_BUS_MUX_29 \ + IOMUX_PAD(0x0708, 0x0320, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__USBOH3_UH3_DFD_OUT_9 \ + IOMUX_PAD(0x0708, 0x0320, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__USBOH3_UH2_DFD_OUT_9 \ + IOMUX_PAD(0x0708, 0x0320, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__GPIO_7_7 \ + IOMUX_PAD(0x0708, 0x0320, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__MIPI_CORE_DPHY_TEST_IN_21 \ + IOMUX_PAD(0x0708, 0x0320, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT3__ANATOP_ANATOP_TESTI_2 \ + IOMUX_PAD(0x0708, 0x0320, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ \ + IOMUX_PAD(0x070C, 0x0324, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_100MHZ \ + IOMUX_PAD(0x070C, 0x0324, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT4__USDHC3_DAT4_200MHZ \ + IOMUX_PAD(0x070C, 0x0324, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT4__UART2_TXD \ + IOMUX_PAD(0x070C, 0x0324, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__UART2_RXD \ + IOMUX_PAD(0x070C, 0x0324, 1, 0x0904, 4, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__PCIE_CTRL_DIAG_STATUS_BUS_MUX_27 \ + IOMUX_PAD(0x070C, 0x0324, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__USBOH3_UH3_DFD_OUT_3 \ + IOMUX_PAD(0x070C, 0x0324, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__USBOH3_UH2_DFD_OUT_3 \ + IOMUX_PAD(0x070C, 0x0324, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__GPIO_7_1 \ + IOMUX_PAD(0x070C, 0x0324, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__MIPI_CORE_DPHY_TEST_IN_15 \ + IOMUX_PAD(0x070C, 0x0324, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT4__ANATOP_ANATOP_TESTO_12 \ + IOMUX_PAD(0x070C, 0x0324, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ \ + IOMUX_PAD(0x0710, 0x0328, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_100MHZ \ + IOMUX_PAD(0x0710, 0x0328, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT5__USDHC3_DAT5_200MHZ \ + IOMUX_PAD(0x0710, 0x0328, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT5__UART2_TXD \ + IOMUX_PAD(0x0710, 0x0328, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__UART2_RXD \ + IOMUX_PAD(0x0710, 0x0328, 1, 0x0904, 5, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__PCIE_CTRL_DIAG_STATUS_BUS_MUX_26 \ + IOMUX_PAD(0x0710, 0x0328, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__USBOH3_UH3_DFD_OUT_2 \ + IOMUX_PAD(0x0710, 0x0328, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__USBOH3_UH2_DFD_OUT_2 \ + IOMUX_PAD(0x0710, 0x0328, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__GPIO_7_0 \ + IOMUX_PAD(0x0710, 0x0328, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__MIPI_CORE_DPHY_TEST_IN_14 \ + IOMUX_PAD(0x0710, 0x0328, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT5__ANATOP_ANATOP_TESTO_11 \ + IOMUX_PAD(0x0710, 0x0328, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ \ + IOMUX_PAD(0x0714, 0x032C, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_100MHZ \ + IOMUX_PAD(0x0714, 0x032C, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT6__USDHC3_DAT6_200MHZ \ + IOMUX_PAD(0x0714, 0x032C, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT6__UART1_TXD \ + IOMUX_PAD(0x0714, 0x032C, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__UART1_RXD \ + IOMUX_PAD(0x0714, 0x032C, 1, 0x08FC, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__PCIE_CTRL_DIAG_STATUS_BUS_MUX_25 \ + IOMUX_PAD(0x0714, 0x032C, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__USBOH3_UH3_DFD_OUT_1 \ + IOMUX_PAD(0x0714, 0x032C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__USBOH3_UH2_DFD_OUT_1 \ + IOMUX_PAD(0x0714, 0x032C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__GPIO_6_18 \ + IOMUX_PAD(0x0714, 0x032C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__MIPI_CORE_DPHY_TEST_IN_13 \ + IOMUX_PAD(0x0714, 0x032C, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT6__ANATOP_ANATOP_TESTO_10 \ + IOMUX_PAD(0x0714, 0x032C, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ \ + IOMUX_PAD(0x0718, 0x0330, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_100MHZ \ + IOMUX_PAD(0x0718, 0x0330, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD3_DAT7__USDHC3_DAT7_200MHZ \ + IOMUX_PAD(0x0718, 0x0330, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD3_DAT7__UART1_TXD \ + IOMUX_PAD(0x0718, 0x0330, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__UART1_RXD \ + IOMUX_PAD(0x0718, 0x0330, 1, 0x08FC, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__PCIE_CTRL_DIAG_STATUS_BUS_MUX_24 \ + IOMUX_PAD(0x0718, 0x0330, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__USBOH3_UH3_DFD_OUT_0 \ + IOMUX_PAD(0x0718, 0x0330, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__USBOH3_UH2_DFD_OUT_0 \ + IOMUX_PAD(0x0718, 0x0330, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__GPIO_6_17 \ + IOMUX_PAD(0x0718, 0x0330, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__MIPI_CORE_DPHY_TEST_IN_12 \ + IOMUX_PAD(0x0718, 0x0330, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_DAT7__ANATOP_USBPHY2_TSTO_PLL_CLK20DIV \ + IOMUX_PAD(0x0718, 0x0330, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD3_RST__USDHC3_RST \ + IOMUX_PAD(0x071C, 0x0334, 0, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__UART3_CTS \ + IOMUX_PAD(0x071C, 0x0334, 1, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__UART3_RTS \ + IOMUX_PAD(0x071C, 0x0334, 1, 0x0908, 5, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__PCIE_CTRL_DIAG_STATUS_BUS_MUX_30 \ + IOMUX_PAD(0x071C, 0x0334, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__USBOH3_UH3_DFD_OUT_10 \ + IOMUX_PAD(0x071C, 0x0334, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__USBOH3_UH2_DFD_OUT_10 \ + IOMUX_PAD(0x071C, 0x0334, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__GPIO_7_8 \ + IOMUX_PAD(0x071C, 0x0334, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__MIPI_CORE_DPHY_TEST_IN_22 \ + IOMUX_PAD(0x071C, 0x0334, 6, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD3_RST__ANATOP_ANATOP_TESTI_3 \ + IOMUX_PAD(0x071C, 0x0334, 7, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_CLK__USDHC4_CLK_50MHZ \ + IOMUX_PAD(0x0720, 0x0338, 0, 0x0938, 1, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_CLK__USDHC4_CLK_100MHZ \ + IOMUX_PAD(0x0720, 0x0338, 0, 0x0938, 1, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_CLK__USDHC4_CLK_200MHZ \ + IOMUX_PAD(0x0720, 0x0338, 0, 0x0938, 1, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_CLK__RAWNAND_WRN \ + IOMUX_PAD(0x0720, 0x0338, 1, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_SD4_CLK__UART3_TXD \ + IOMUX_PAD(0x0720, 0x0338, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_CLK__UART3_RXD \ + IOMUX_PAD(0x0720, 0x0338, 2, 0x090C, 2, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_CLK__PCIE_CTRL_DIAG_STATUS_BUS_MUX_6 \ + IOMUX_PAD(0x0720, 0x0338, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_CLK__GPIO_7_10 \ + IOMUX_PAD(0x0720, 0x0338, 5, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_CMD__USDHC4_CMD_50MHZ \ + IOMUX_PAD(0x0724, 0x033C, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_CMD__USDHC4_CMD_100MHZ \ + IOMUX_PAD(0x0724, 0x033C, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_CMD__USDHC4_CMD_200MHZ \ + IOMUX_PAD(0x0724, 0x033C, 0 | IOMUX_CONFIG_SION, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_CMD__RAWNAND_RDN \ + IOMUX_PAD(0x0724, 0x033C, 1, 0x0000, 0, MX6DL_GPMI_PAD_CTRL2) +#define MX6DL_PAD_SD4_CMD__UART3_TXD \ + IOMUX_PAD(0x0724, 0x033C, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_CMD__UART3_RXD \ + IOMUX_PAD(0x0724, 0x033C, 2, 0x090C, 3, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_CMD__PCIE_CTRL_DIAG_STATUS_BUS_MUX_5 \ + IOMUX_PAD(0x0724, 0x033C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_CMD__GPIO_7_9 \ + IOMUX_PAD(0x0724, 0x033C, 5, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT0__RAWNAND_D8 \ + IOMUX_PAD(0x0728, 0x0340, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ \ + IOMUX_PAD(0x0728, 0x0340, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT0__USDHC4_DAT0_100MHZ \ + IOMUX_PAD(0x0728, 0x0340, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT0__USDHC4_DAT0_200MHZ \ + IOMUX_PAD(0x0728, 0x0340, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT0__RAWNAND_DQS \ + IOMUX_PAD(0x0728, 0x0340, 2, 0x0000, 0, MX6DL_GPMI_PAD_CTRL1) +#define MX6DL_PAD_SD4_DAT0__USBOH3_UH2_DFD_OUT_24 \ + IOMUX_PAD(0x0728, 0x0340, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT0__USBOH3_UH3_DFD_OUT_24 \ + IOMUX_PAD(0x0728, 0x0340, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT0__GPIO_2_8 \ + IOMUX_PAD(0x0728, 0x0340, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT0__IPU1_IPU_DIAG_BUS_8 \ + IOMUX_PAD(0x0728, 0x0340, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT1__RAWNAND_D9 \ + IOMUX_PAD(0x072C, 0x0344, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ \ + IOMUX_PAD(0x072C, 0x0344, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT1__USDHC4_DAT1_100MHZ \ + IOMUX_PAD(0x072C, 0x0344, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT1__USDHC4_DAT1_200MHZ \ + IOMUX_PAD(0x072C, 0x0344, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT1__PWM3_PWMO \ + IOMUX_PAD(0x072C, 0x0344, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT1__USBOH3_UH2_DFD_OUT_25 \ + IOMUX_PAD(0x072C, 0x0344, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT1__USBOH3_UH3_DFD_OUT_25 \ + IOMUX_PAD(0x072C, 0x0344, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT1__GPIO_2_9 \ + IOMUX_PAD(0x072C, 0x0344, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT1__IPU1_IPU_DIAG_BUS_9 \ + IOMUX_PAD(0x072C, 0x0344, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT2__RAWNAND_D10 \ + IOMUX_PAD(0x0730, 0x0348, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ \ + IOMUX_PAD(0x0730, 0x0348, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT2__USDHC4_DAT2_100MHZ \ + IOMUX_PAD(0x0730, 0x0348, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT2__USDHC4_DAT2_200MHZ \ + IOMUX_PAD(0x0730, 0x0348, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT2__PWM4_PWMO \ + IOMUX_PAD(0x0730, 0x0348, 2, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT2__USBOH3_UH2_DFD_OUT_26 \ + IOMUX_PAD(0x0730, 0x0348, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT2__USBOH3_UH3_DFD_OUT_26 \ + IOMUX_PAD(0x0730, 0x0348, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT2__GPIO_2_10 \ + IOMUX_PAD(0x0730, 0x0348, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT2__IPU1_IPU_DIAG_BUS_10 \ + IOMUX_PAD(0x0730, 0x0348, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT3__RAWNAND_D11 \ + IOMUX_PAD(0x0734, 0x034C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ \ + IOMUX_PAD(0x0734, 0x034C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT3__USDHC4_DAT3_100MHZ \ + IOMUX_PAD(0x0734, 0x034C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT3__USDHC4_DAT3_200MHZ \ + IOMUX_PAD(0x0734, 0x034C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT3__USBOH3_UH2_DFD_OUT_27 \ + IOMUX_PAD(0x0734, 0x034C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT3__USBOH3_UH3_DFD_OUT_27 \ + IOMUX_PAD(0x0734, 0x034C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT3__GPIO_2_11 \ + IOMUX_PAD(0x0734, 0x034C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT3__IPU1_IPU_DIAG_BUS_11 \ + IOMUX_PAD(0x0734, 0x034C, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT4__RAWNAND_D12 \ + IOMUX_PAD(0x0738, 0x0350, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ \ + IOMUX_PAD(0x0738, 0x0350, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__USDHC4_DAT4_100MHZ \ + IOMUX_PAD(0x0738, 0x0350, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT4__USDHC4_DAT4_200MHZ \ + IOMUX_PAD(0x0738, 0x0350, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT4__UART2_TXD \ + IOMUX_PAD(0x0738, 0x0350, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__UART2_RXD \ + IOMUX_PAD(0x0738, 0x0350, 2, 0x0904, 6, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__USBOH3_UH2_DFD_OUT_28 \ + IOMUX_PAD(0x0738, 0x0350, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__USBOH3_UH3_DFD_OUT_28 \ + IOMUX_PAD(0x0738, 0x0350, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__GPIO_2_12 \ + IOMUX_PAD(0x0738, 0x0350, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT4__IPU1_IPU_DIAG_BUS_12 \ + IOMUX_PAD(0x0738, 0x0350, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT5__RAWNAND_D13 \ + IOMUX_PAD(0x073C, 0x0354, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ \ + IOMUX_PAD(0x073C, 0x0354, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__USDHC4_DAT5_100MHZ \ + IOMUX_PAD(0x073C, 0x0354, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT5__USDHC4_DAT5_200MHZ \ + IOMUX_PAD(0x073C, 0x0354, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT5__UART2_CTS \ + IOMUX_PAD(0x073C, 0x0354, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__UART2_RTS \ + IOMUX_PAD(0x073C, 0x0354, 2, 0x0900, 4, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__USBOH3_UH2_DFD_OUT_29 \ + IOMUX_PAD(0x073C, 0x0354, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__USBOH3_UH3_DFD_OUT_29 \ + IOMUX_PAD(0x073C, 0x0354, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__GPIO_2_13 \ + IOMUX_PAD(0x073C, 0x0354, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT5__IPU1_IPU_DIAG_BUS_13 \ + IOMUX_PAD(0x073C, 0x0354, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT6__RAWNAND_D14 \ + IOMUX_PAD(0x0740, 0x0358, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ \ + IOMUX_PAD(0x0740, 0x0358, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__USDHC4_DAT6_100MHZ \ + IOMUX_PAD(0x0740, 0x0358, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT6__USDHC4_DAT6_200MHZ \ + IOMUX_PAD(0x0740, 0x0358, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT6__UART2_CTS \ + IOMUX_PAD(0x0740, 0x0358, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__UART2_RTS \ + IOMUX_PAD(0x0740, 0x0358, 2, 0x0900, 5, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__USBOH3_UH2_DFD_OUT_30 \ + IOMUX_PAD(0x0740, 0x0358, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__USBOH3_UH3_DFD_OUT_30 \ + IOMUX_PAD(0x0740, 0x0358, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__GPIO_2_14 \ + IOMUX_PAD(0x0740, 0x0358, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT6__IPU1_IPU_DIAG_BUS_14 \ + IOMUX_PAD(0x0740, 0x0358, 6, 0x0000, 0, NO_PAD_CTRL) + +#define MX6DL_PAD_SD4_DAT7__RAWNAND_D15 \ + IOMUX_PAD(0x0744, 0x035C, 0, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ \ + IOMUX_PAD(0x0744, 0x035C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_100MHZ \ + IOMUX_PAD(0x0744, 0x035C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_100MHZ) +#define MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_200MHZ \ + IOMUX_PAD(0x0744, 0x035C, 1, 0x0000, 0, MX6DL_USDHC_PAD_CTRL_200MHZ) +#define MX6DL_PAD_SD4_DAT7__UART2_TXD \ + IOMUX_PAD(0x0744, 0x035C, 2, 0x0000, 0, MX6DL_UART_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__UART2_RXD \ + IOMUX_PAD(0x0744, 0x035C, 2, 0x0904, 7, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__USBOH3_UH2_DFD_OUT_31 \ + IOMUX_PAD(0x0744, 0x035C, 3, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__USBOH3_UH3_DFD_OUT_31 \ + IOMUX_PAD(0x0744, 0x035C, 4, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__GPIO_2_15 \ + IOMUX_PAD(0x0744, 0x035C, 5, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_SD4_DAT7__IPU1_IPU_DIAG_BUS_15 \ + IOMUX_PAD(0x0744, 0x035C, 6, 0x0000, 0, NO_PAD_CTRL) + +#endif /*__MACH_IOMUX_MX6DL_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h index ca94008e8e76..3345cca68ecb 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h @@ -2429,7 +2429,7 @@ typedef enum iomux_config { #define _MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN \ IOMUX_PAD(0x0618, 0x0248, 1, 0x0000, 0, 0) #define _MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT \ - IOMUX_PAD(0x0618, 0x0248, 2, 0x083C, 1, 0) + IOMUX_PAD(0x0618, 0x0248, 0x12, 0x083C, 1, 0) #define _MX6Q_PAD_GPIO_16__USDHC1_LCTL \ IOMUX_PAD(0x0618, 0x0248, 3, 0x0000, 0, 0) #define _MX6Q_PAD_GPIO_16__SPDIF_IN1 \ diff --git a/arch/arm/plat-mxc/include/mach/mx6.h b/arch/arm/plat-mxc/include/mach/mx6.h index e09be19b8d82..d4b31eaeb60c 100644 --- a/arch/arm/plat-mxc/include/mach/mx6.h +++ b/arch/arm/plat-mxc/include/mach/mx6.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,231 +41,236 @@ * This option is used to set or clear the RXDMUXSEL bit in control reg 3. * Certain platforms need this bit to be set in order to receive Irda data. */ -#define MXC_UART_IR_RXDMUX 0x0004 +#define MXC_UART_IR_RXDMUX 0x0004 /*! * This option is used to set or clear the RXDMUXSEL bit in control reg 3. * Certain platforms need this bit to be set in order to receive UART data. */ -#define MXC_UART_RXDMUX 0x0004 +#define MXC_UART_RXDMUX 0x0004 /*! * The maximum frequency that the pixel clock can be at so as to * activate DVFS-PER. */ -#define DVFS_MAX_PIX_CLK 54000000 +#define DVFS_MAX_PIX_CLK 54000000 /* IROM */ -#define IROM_BASE_ADDR 0x0 +#define IROM_BASE_ADDR 0x0 #define IROM_SIZE SZ_64K /* CPU Memory Map */ -#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 OCRAM_ARB_BASE_ADDR 0x00900000 -#define OCRAM_ARB_END_ADDR 0x009FFFFF -#define IRAM_BASE_ADDR OCRAM_ARB_BASE_ADDR -#define PCIE_ARB_BASE_ADDR 0x01000000 -#define PCIE_ARB_END_ADDR 0x01FFFFFF +#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 OCRAM_ARB_BASE_ADDR 0x00900000 +#define OCRAM_ARB_END_ADDR 0x009FFFFF +#define IRAM_BASE_ADDR OCRAM_ARB_BASE_ADDR +#define PCIE_ARB_BASE_ADDR 0x01000000 +#define PCIE_ARB_END_ADDR 0x01FFFFFF /* IRAM */ #define MX6Q_IRAM_BASE_ADDR IRAM_BASE_ADDR /* The last 4K is for cpu hotplug to workaround wdog issue*/ #define MX6Q_IRAM_SIZE (SZ_256K - SZ_4K) +#define MX6DL_IRAM_SIZE (SZ_128K - SZ_4K) /* Blocks connected via pl301periph */ -#define ROMCP_ARB_BASE_ADDR 0x00000000 -#define ROMCP_ARB_END_ADDR 0x000FFFFF -#define BOOT_ROM_BASE_ADDR ROMCP_ARB_BASE_ADDR -#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 MX6Q_HDMI_ARB_BASE_ADDR 0x00120000 -#define MX6Q_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 ROMCP_ARB_BASE_ADDR 0x00000000 +#define ROMCP_ARB_END_ADDR 0x000FFFFF +#define BOOT_ROM_BASE_ADDR ROMCP_ARB_BASE_ADDR +#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 MX6Q_HDMI_ARB_BASE_ADDR 0x00120000 +#define MX6Q_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 /* GPV - PL301 configuration ports */ -#define GPV0_BASE_ADDR 0x00B00000 -#define GPV1_BASE_ADDR 0x00C00000 -#define GPV2_BASE_ADDR 0x00200000 -#define GPV3_BASE_ADDR 0x00300000 -#define GPV4_BASE_ADDR 0x00800000 - -#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 MX6Q_SATA_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 MX6Q_IPU1_ARB_BASE_ADDR 0x02400000 -#define MX6Q_IPU1_ARB_END_ADDR 0x027FFFFF -#define MX6Q_IPU2_ARB_BASE_ADDR 0x02800000 -#define MX6Q_IPU2_ARB_END_ADDR 0x02BFFFFF -#define WEIM_ARB_BASE_ADDR 0x08000000 -#define WEIM_ARB_END_ADDR 0x0FFFFFFF +#define GPV0_BASE_ADDR 0x00B00000 +#define GPV1_BASE_ADDR 0x00C00000 +#define GPV2_BASE_ADDR 0x00200000 +#define GPV3_BASE_ADDR 0x00300000 +#define GPV4_BASE_ADDR 0x00800000 + +#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 MX6Q_SATA_BASE_ADDR 0x02200000 +#define MX6Q_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 MX6Q_IPU1_ARB_BASE_ADDR 0x02400000 +#define MX6Q_IPU1_ARB_END_ADDR 0x027FFFFF +#define MX6Q_IPU2_ARB_BASE_ADDR 0x02800000 +#define MX6Q_IPU2_ARB_END_ADDR 0x02BFFFFF +#define WEIM_ARB_BASE_ADDR 0x08000000 +#define WEIM_ARB_END_ADDR 0x0FFFFFFF /* Legacy Defines */ -#define CSD0_DDR_BASE_ADDR MMDC0_ARB_BASE_ADDR -#define CSD1_DDR_BASE_ADDR MMDC1_ARB_BASE_ADDR -#define CS0_BASE_ADDR WEIM_ARB_BASE_ADDR -#define NAND_FLASH_BASE_ADDR APBH_DMA_ARB_BASE_ADDR +#define CSD0_DDR_BASE_ADDR MMDC0_ARB_BASE_ADDR +#define CSD1_DDR_BASE_ADDR MMDC1_ARB_BASE_ADDR +#define CS0_BASE_ADDR WEIM_ARB_BASE_ADDR +#define NAND_FLASH_BASE_ADDR APBH_DMA_ARB_BASE_ADDR #define MX6Q_GPMI_BASE_ADDR (APBH_DMA_ARB_BASE_ADDR + 0x02000) #define MX6Q_BCH_BASE_ADDR (APBH_DMA_ARB_BASE_ADDR + 0x04000) /* Defines for Blocks connected via AIPS (SkyBlue) */ -#define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR -#define ATZ2_BASE_ADDR AIPS2_ARB_BASE_ADDR +#define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR +#define ATZ2_BASE_ADDR AIPS2_ARB_BASE_ADDR /* slots 0,7 of SDMA reserved, therefore left unused in IPMUX3 */ -#define MX6Q_SPDIF_BASE_ADDR (ATZ1_BASE_ADDR + 0x04000) /* slot 1 */ -#define MX6Q_ECSPI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x08000) /* slot 2 */ -#define MX6Q_ECSPI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x0C000) /* slot 3 */ -#define MX6Q_ECSPI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x10000) /* slot 4 */ -#define MX6Q_ECSPI4_BASE_ADDR (ATZ1_BASE_ADDR + 0x14000) /* slot 5 */ -#define MX6Q_ECSPI5_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000) /* slot 6 */ -#define UART1_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000) /* slot 8 */ -#define ESAI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000) /* slot 9 */ -#define MX6Q_SSI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000) /* slot 10 */ -#define MX6Q_SSI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000) /* slot 11 */ -#define MX6Q_SSI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000) /* slot 12 */ -#define MX6Q_ASRC_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000) /* slot 13 */ -#define SPBA_BASE_ADDR (ATZ1_BASE_ADDR + 0x3C000) /* slot 15 */ -#define MX6Q_VPU_BASE_ADDR (ATZ1_BASE_ADDR + 0x40000) /* slot 33, +#define MX6Q_SPDIF_BASE_ADDR (ATZ1_BASE_ADDR + 0x04000) /* slot 1 */ +#define MX6Q_ECSPI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x08000) /* slot 2 */ +#define MX6Q_ECSPI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x0C000) /* slot 3 */ +#define MX6Q_ECSPI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x10000) /* slot 4 */ +#define MX6Q_ECSPI4_BASE_ADDR (ATZ1_BASE_ADDR + 0x14000) /* slot 5 */ +#define MX6Q_ECSPI5_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000) /* slot 6 */ +#define UART1_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000) /* slot 8 */ +#define ESAI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000) /* slot 9 */ +#define MX6Q_SSI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000) /* slot 10 */ +#define MX6Q_SSI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000) /* slot 11 */ +#define MX6Q_SSI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000) /* slot 12 */ +#define MX6Q_ASRC_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000) /* slot 13 */ +#define SPBA_BASE_ADDR (ATZ1_BASE_ADDR + 0x3C000) /* slot 15 */ +#define MX6Q_VPU_BASE_ADDR (ATZ1_BASE_ADDR + 0x40000) /* slot 33, global en[1], til 0x7BFFF */ /* ATZ#1- On Platform */ -#define AIPS1_ON_BASE_ADDR (ATZ1_BASE_ADDR + 0x7C000) +#define AIPS1_ON_BASE_ADDR (ATZ1_BASE_ADDR + 0x7C000) /* ATZ#1- Off Platform */ -#define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000) - -#define MX6Q_PWM1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x0000) -#define MX6Q_PWM2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4000) -#define MX6Q_PWM3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x8000) -#define MX6Q_PWM4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0xC000) -#define MX6Q_CAN1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x10000) -#define MX6Q_CAN2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x14000) -#define GPT_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 MX6Q_WDOG1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x3C000) -#define MX6Q_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 MX6Q_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 MX6Q_IOMUXC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x60000) -#define DCIC1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000) -#define DCIC2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000) -#define MX6Q_SDMA_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000) -#define MX6Q_DVFSCORE_BASE_ADDR (GPC_BASE_ADDR + 0x180) +#define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000) + +#define MX6Q_PWM1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x0000) +#define MX6Q_PWM2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4000) +#define MX6Q_PWM3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x8000) +#define MX6Q_PWM4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0xC000) +#define MX6Q_CAN1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x10000) +#define MX6Q_CAN2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x14000) +#define GPT_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 MX6Q_WDOG1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x3C000) +#define MX6Q_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 MX6Q_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 MX6Q_IOMUXC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x60000) +#define DCIC1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000) +#define DCIC2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000) +#define MX6Q_SDMA_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000) +#define MX6DL_EPXP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x70000) +#define MX6DL_EPDC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x74000) +#define MX6DL_LCDIF_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x78000) +#define MX6Q_DVFSCORE_BASE_ADDR (GPC_BASE_ADDR + 0x180) /* ATZ#2- On Platform */ -#define AIPS2_ON_BASE_ADDR (ATZ2_BASE_ADDR + 0x7C000) +#define AIPS2_ON_BASE_ADDR (ATZ2_BASE_ADDR + 0x7C000) /* ATZ#2- Off Platform */ -#define AIPS2_OFF_BASE_ADDR (ATZ2_BASE_ADDR + 0x80000) +#define AIPS2_OFF_BASE_ADDR (ATZ2_BASE_ADDR + 0x80000) /* ATZ#2 - Global enable (0) */ -#define CAAM_BASE_ADDR ATZ2_BASE_ADDR -#define ARM_BASE_ADDR (ATZ2_BASE_ADDR + 0x40000) +#define CAAM_BASE_ADDR ATZ2_BASE_ADDR +#define ARM_BASE_ADDR (ATZ2_BASE_ADDR + 0x40000) /* ARM Cortex A9 MPCore Platform */ #define MX6Q_A9_PLATFRM_BASE (ARM_BASE_ADDR + 0x20000) -#define MX6Q_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000) -#define MX6Q_USB_OTG_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000) -#define MX6Q_USB_HS1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4200) -#define MX6Q_USB_HS2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4400) -#define MX6Q_USB_HS3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4600) -#define ENET_BASE_ADDR (AIPS2_OFF_BASE_ADDR+0x8000) -#define MLB_BASE_ADDR (AIPS2_OFF_BASE_ADDR+0xC000) - -#define MX6Q_USDHC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x10000) -#define MX6Q_USDHC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x14000) -#define MX6Q_USDHC3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x18000) -#define MX6Q_USDHC4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x1C000) -#define MX6Q_I2C1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x20000) -#define MX6Q_I2C2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x24000) -#define MX6Q_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 MMDC_P1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000) -#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) -#define IP2APB_PERFMON3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4C000) -#define IP2APB_TZASC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x50000) -#define IP2APB_TZASC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000) -#define MX6Q_AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000) -#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 UART2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x68000) -#define UART3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x6C000) -#define UART4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x70000) -#define UART5_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x74000) +#define MX6Q_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000) +#define MX6Q_USB_OTG_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000) +#define MX6Q_USB_HS1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4200) +#define MX6Q_USB_HS2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4400) +#define MX6Q_USB_HS3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4600) +#define ENET_BASE_ADDR (AIPS2_OFF_BASE_ADDR+0x8000) +#define MLB_BASE_ADDR (AIPS2_OFF_BASE_ADDR+0xC000) + +#define MX6Q_USDHC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x10000) +#define MX6Q_USDHC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x14000) +#define MX6Q_USDHC3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x18000) +#define MX6Q_USDHC4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x1C000) +#define MX6Q_I2C1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x20000) +#define MX6Q_I2C2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x24000) +#define MX6Q_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 MMDC_P1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000) +#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) +#define IP2APB_PERFMON3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4C000) +#define IP2APB_TZASC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x50000) +#define IP2APB_TZASC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000) +#define MX6Q_AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000) +#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 UART2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x68000) +#define UART3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x6C000) +#define UART4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x70000) +#define UART5_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x74000) +#define MX6DL_I2C4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x78000) /* Cortex-A9 MPCore private memory region */ -#define ARM_PERIPHBASE 0x00A00000 -#define SCU_BASE_ADDR ARM_PERIPHBASE +#define ARM_PERIPHBASE 0x00A00000 +#define SCU_BASE_ADDR ARM_PERIPHBASE #define LOCAL_TWD_ADDR (SCU_BASE_ADDR + 0x600) -#define IC_INTERFACES_BASE_ADDR (ARM_PERIPHBASE + 0x0100) -#define GLOBAL_TIMER_BASE_ADDR (ARM_PERIPHBASE + 0x0200) -#define PRIVATE_TIMERS_WD_BASE_ADDR (ARM_PERIPHBASE + 0x0600) -#define IC_DISTRIBUTOR_BASE_ADDR (ARM_PERIPHBASE + 0x1000) +#define IC_INTERFACES_BASE_ADDR (ARM_PERIPHBASE + 0x0100) +#define GLOBAL_TIMER_BASE_ADDR (ARM_PERIPHBASE + 0x0200) +#define PRIVATE_TIMERS_WD_BASE_ADDR (ARM_PERIPHBASE + 0x0600) +#define IC_DISTRIBUTOR_BASE_ADDR (ARM_PERIPHBASE + 0x1000) #define L2_BASE_ADDR (ARM_PERIPHBASE + 0x2000) -#define MX6Q_UART1_BASE_ADDR UART1_BASE_ADDR -#define MX6Q_UART2_BASE_ADDR UART2_BASE_ADDR -#define MX6Q_UART3_BASE_ADDR UART3_BASE_ADDR -#define MX6Q_UART4_BASE_ADDR UART4_BASE_ADDR -#define MX6Q_FEC_BASE_ADDR ENET_BASE_ADDR -#define MX6Q_MIPI_DSI_BASE_ADDR MIPI_DSI_BASE_ADDR +#define MX6Q_UART1_BASE_ADDR UART1_BASE_ADDR +#define MX6Q_UART2_BASE_ADDR UART2_BASE_ADDR +#define MX6Q_UART3_BASE_ADDR UART3_BASE_ADDR +#define MX6Q_UART4_BASE_ADDR UART4_BASE_ADDR +#define MX6Q_FEC_BASE_ADDR ENET_BASE_ADDR +#define MX6Q_MIPI_DSI_BASE_ADDR MIPI_DSI_BASE_ADDR #define MX6Q_MIPI_CSI2_BASE_ADDR MIPI_CSI2_BASE_ADDR /* define virtual address */ -#define PERIPBASE_VIRT 0xF2000000 -#define BOOT_ROM_BASE_ADDR_VIRT (PERIPBASE_VIRT + BOOT_ROM_BASE_ADDR) -#define AIPS1_BASE_ADDR_VIRT (PERIPBASE_VIRT + AIPS1_ARB_BASE_ADDR) -#define AIPS2_BASE_ADDR_VIRT (PERIPBASE_VIRT + AIPS2_ARB_BASE_ADDR) -#define ARM_PERIPHBASE_VIRT (PERIPBASE_VIRT + ARM_PERIPHBASE) -#define ROMCP_SIZE SZ_1M -#define AIPS1_SIZE SZ_1M -#define AIPS2_SIZE SZ_1M -#define ARM_PERIPHBASE_SIZE (SZ_8K + SZ_4K) +#define PERIPBASE_VIRT 0xF2000000 +#define BOOT_ROM_BASE_ADDR_VIRT (PERIPBASE_VIRT + BOOT_ROM_BASE_ADDR) +#define AIPS1_BASE_ADDR_VIRT (PERIPBASE_VIRT + AIPS1_ARB_BASE_ADDR) +#define AIPS2_BASE_ADDR_VIRT (PERIPBASE_VIRT + AIPS2_ARB_BASE_ADDR) +#define ARM_PERIPHBASE_VIRT (PERIPBASE_VIRT + ARM_PERIPHBASE) +#define ROMCP_SIZE SZ_1M +#define AIPS1_SIZE SZ_1M +#define AIPS2_SIZE SZ_1M +#define ARM_PERIPHBASE_SIZE (SZ_8K + SZ_4K) /* GPC offsets */ #define MXC_GPC_CNTR_OFFSET 0x0 -#define MX6_IO_ADDRESS(x) (void __force __iomem *)((x) + PERIPBASE_VIRT) +#define MX6_IO_ADDRESS(x) (void __force __iomem *)((x) + PERIPBASE_VIRT) /*! * This macro defines the physical to virtual address mapping for all the @@ -283,151 +288,153 @@ /* * Interrupt numbers */ -#define MXC_INT_START 32 -#define MXC_INT_GPR 32 -#define MXC_INT_CHEETAH_CSYSPWRUPREQ 33 -#define MX6Q_INT_SDMA 34 -#define MX6Q_INT_VPU_JPG 35 -#define MXC_INT_INTERRUPT_36_NUM 36 -#define MX6Q_INT_IPU1_ERR 37 -#define MX6Q_INT_IPU1_SYN 38 -#define MX6Q_INT_IPU2_ERR 39 -#define MX6Q_INT_IPU2_SYN 40 -#define MXC_INT_GPU3D_IRQ 41 -#define MXC_INT_GPU2D_IRQ 42 -#define MXC_INT_OPENVG_XAQ2 43 -#define MX6Q_INT_VPU_IPI 44 -#define MXC_INT_APBHDMA_DMA 45 -#define MXC_INT_WEIM 46 -#define MXC_INT_RAWNAND_BCH 47 -#define MXC_INT_RAWNAND_GPMI 48 -#define MXC_INT_DTCP 49 -#define MXC_INT_VDOA 50 -#define MX6Q_INT_SNVS 51 -#define MXC_INT_SNVS_SEC 52 -#define MXC_INT_CSU 53 -#define MX6Q_INT_USDHC1 54 -#define MX6Q_INT_USDHC2 55 -#define MX6Q_INT_USDHC3 56 -#define MX6Q_INT_USDHC4 57 -#define MXC_INT_UART1_ANDED 58 -#define MXC_INT_UART2_ANDED 59 -#define MXC_INT_UART3_ANDED 60 -#define MXC_INT_UART4_ANDED 61 -#define MXC_INT_UART5_ANDED 62 -#define MX6Q_INT_ECSPI1 63 -#define MX6Q_INT_ECSPI2 64 -#define MX6Q_INT_ECSPI3 65 -#define MX6Q_INT_ECSPI4 66 -#define MX6Q_INT_ECSPI5 67 -#define MX6Q_INT_I2C1 68 -#define MX6Q_INT_I2C2 69 -#define MX6Q_INT_I2C3 70 -#define MX6Q_INT_SATA 71 -#define MX6Q_INT_USB_HS1 72 -#define MX6Q_INT_USB_HS2 73 -#define MX6Q_INT_USB_HS3 74 -#define MX6Q_INT_USB_OTG 75 -#define MX6Q_INT_USB_PHY0 76 -#define MX6Q_INT_USB_PHY1 77 +#define MXC_INT_START 32 +#define MXC_INT_GPR 32 +#define MXC_INT_CHEETAH_CSYSPWRUPREQ 33 +#define MX6Q_INT_SDMA 34 +#define MX6Q_INT_VPU_JPG 35 +#define MXC_INT_INTERRUPT_36_NUM 36 +#define MX6Q_INT_IPU1_ERR 37 +#define MX6Q_INT_IPU1_SYN 38 +#define MX6Q_INT_IPU2_ERR 39 +#define MX6Q_INT_IPU2_SYN 40 +#define MXC_INT_GPU3D_IRQ 41 +#define MXC_INT_GPU2D_IRQ 42 +#define MXC_INT_OPENVG_XAQ2 43 +#define MX6Q_INT_VPU_IPI 44 +#define MXC_INT_APBHDMA_DMA 45 +#define MXC_INT_WEIM 46 +#define MXC_INT_RAWNAND_BCH 47 +#define MXC_INT_RAWNAND_GPMI 48 +#define MXC_INT_DTCP 49 +#define MXC_INT_VDOA 50 +#define MX6Q_INT_SNVS 51 +#define MXC_INT_SNVS_SEC 52 +#define MXC_INT_CSU 53 +#define MX6Q_INT_USDHC1 54 +#define MX6Q_INT_USDHC2 55 +#define MX6Q_INT_USDHC3 56 +#define MX6Q_INT_USDHC4 57 +#define MXC_INT_UART1_ANDED 58 +#define MXC_INT_UART2_ANDED 59 +#define MXC_INT_UART3_ANDED 60 +#define MXC_INT_UART4_ANDED 61 +#define MXC_INT_UART5_ANDED 62 +#define MX6Q_INT_ECSPI1 63 +#define MX6Q_INT_ECSPI2 64 +#define MX6Q_INT_ECSPI3 65 +#define MX6Q_INT_ECSPI4 66 +#define MX6Q_INT_ECSPI5 67 +#define MX6DL_INT_I2C4 67 +#define MX6Q_INT_I2C1 68 +#define MX6Q_INT_I2C2 69 +#define MX6Q_INT_I2C3 70 +#define MX6Q_INT_SATA 71 +#define MX6DL_INT_LCDIF 71 +#define MX6Q_INT_USB_HS1 72 +#define MX6Q_INT_USB_HS2 73 +#define MX6Q_INT_USB_HS3 74 +#define MX6Q_INT_USB_OTG 75 +#define MX6Q_INT_USB_PHY0 76 +#define MX6Q_INT_USB_PHY1 77 /* * MX6Q_INT_USB_PHY2, MX6Q_INT_USB_PHY3 are dummy interrupts * In order to compile pass for platform device's definition */ -#define MX6Q_INT_USB_PHY2 73 -#define MX6Q_INT_USB_PHY3 74 -#define MX6Q_INT_SSI1 78 -#define MX6Q_INT_SSI2 79 -#define MX6Q_INT_SSI3 80 -#define MXC_INT_ANATOP_TEMPSNSR 81 -#define MX6Q_INT_ASRC 82 -#define MXC_INT_ESAI 83 -#define MX6Q_INT_SPDIF 84 -#define MXC_INT_MLB 85 -#define MXC_INT_ANATOP_ANA1 86 -#define MXC_INT_GPT 87 -#define MXC_INT_EPIT1 88 -#define MXC_INT_EPIT2 89 -#define MXC_INT_GPIO1_INT7_NUM 90 -#define MXC_INT_GPIO1_INT6_NUM 91 -#define MXC_INT_GPIO1_INT5_NUM 92 -#define MXC_INT_GPIO1_INT4_NUM 93 -#define MXC_INT_GPIO1_INT3_NUM 94 -#define MXC_INT_GPIO1_INT2_NUM 95 -#define MXC_INT_GPIO1_INT1_NUM 96 -#define MXC_INT_GPIO1_INT0_NUM 97 -#define MXC_INT_GPIO1_INT15_0_NUM 98 -#define MXC_INT_GPIO1_INT31_16_NUM 99 -#define MXC_INT_GPIO2_INT15_0_NUM 100 -#define MXC_INT_GPIO2_INT31_16_NUM 101 -#define MXC_INT_GPIO3_INT15_0_NUM 102 -#define MXC_INT_GPIO3_INT31_16_NUM 103 -#define MXC_INT_GPIO4_INT15_0_NUM 104 -#define MXC_INT_GPIO4_INT31_16_NUM 105 -#define MXC_INT_GPIO5_INT15_0_NUM 106 -#define MXC_INT_GPIO5_INT31_16_NUM 107 -#define MXC_INT_GPIO6_INT15_0_NUM 108 -#define MXC_INT_GPIO6_INT31_16_NUM 109 -#define MXC_INT_GPIO7_INT15_0_NUM 110 -#define MXC_INT_GPIO7_INT31_16_NUM 111 -#define MXC_INT_WDOG1 112 -#define MXC_INT_WDOG2 113 -#define MXC_INT_KPP 114 -#define MX6Q_INT_PWM1 115 -#define MX6Q_INT_PWM2 116 -#define MX6Q_INT_PWM3 117 -#define MX6Q_INT_PWM4 118 -#define MXC_INT_CCM_INT1_NUM 119 -#define MXC_INT_CCM_INT2_NUM 120 -#define MX6Q_INT_GPC1 121 -#define MXC_INT_GPC_INT2_NUM 122 -#define MXC_INT_SRC 123 -#define MXC_INT_CHEETAH_L2 124 -#define MXC_INT_CHEETAH_PARITY 125 -#define MXC_INT_CHEETAH_PERFORM 126 -#define MXC_INT_CHEETAH_TRIGGER 127 -#define MXC_INT_SRC_CPU_WDOG 128 -#define MXC_INT_INTERRUPT_129_NUM 129 -#define MXC_INT_INTERRUPT_130_NUM 130 -#define MXC_INT_INTERRUPT_131_NUM 131 -#define MXC_INT_CSI_INTR1 132 -#define MXC_INT_CSI_INTR2 133 -#define MXC_INT_DSI 134 -#define MXC_INT_HSI 135 -#define MXC_INT_SJC 136 -#define MXC_INT_CAAM_INT0_NUM 137 -#define MXC_INT_CAAM_INT1_NUM 138 -#define MXC_INT_INTERRUPT_139_NUM 139 -#define MXC_INT_TZASC1 140 -#define MXC_INT_TZASC2 141 -#define MX6Q_INT_CAN1 142 -#define MX6Q_INT_CAN2 143 -#define MXC_INT_PERFMON1 144 -#define MXC_INT_PERFMON2 145 -#define MXC_INT_PERFMON3 146 -#define MX6Q_INT_HDMI_TX 147 -#define MX6Q_INT_HDMI_TX_WAKEUP 148 -#define MXC_INT_MLB_AHB0 149 -#define MXC_INT_ENET1 150 -#define MXC_INT_ENET2 151 -#define MXC_INT_PCIE_0 152 -#define MXC_INT_PCIE_1 153 -#define MXC_INT_PCIE_2 154 -#define MXC_INT_PCIE_3 155 -#define MXC_INT_DCIC1 156 -#define MXC_INT_DCIC2 157 -#define MXC_INT_MLB_AHB1 158 -#define MXC_INT_ANATOP_ANA2 159 -#define MXC_INT_END 159 - -#define MX6Q_INT_UART1 MXC_INT_UART1_ANDED -#define MX6Q_INT_UART2 MXC_INT_UART2_ANDED -#define MX6Q_INT_UART3 MXC_INT_UART3_ANDED -#define MX6Q_INT_UART4 MXC_INT_UART4_ANDED -#define MX6Q_INT_FEC MXC_INT_ENET1 -#define MX6Q_INT_DSI MXC_INT_DSI - -#define IRQ_LOCALTIMER 29 +#define MX6Q_INT_USB_PHY2 73 +#define MX6Q_INT_USB_PHY3 74 +#define MX6Q_INT_SSI1 78 +#define MX6Q_INT_SSI2 79 +#define MX6Q_INT_SSI3 80 +#define MXC_INT_ANATOP_TEMPSNSR 81 +#define MX6Q_INT_ASRC 82 +#define MXC_INT_ESAI 83 +#define MX6Q_INT_SPDIF 84 +#define MXC_INT_MLB 85 +#define MXC_INT_ANATOP_ANA1 86 +#define MXC_INT_GPT 87 +#define MXC_INT_EPIT1 88 +#define MXC_INT_EPIT2 89 +#define MXC_INT_GPIO1_INT7_NUM 90 +#define MXC_INT_GPIO1_INT6_NUM 91 +#define MXC_INT_GPIO1_INT5_NUM 92 +#define MXC_INT_GPIO1_INT4_NUM 93 +#define MXC_INT_GPIO1_INT3_NUM 94 +#define MXC_INT_GPIO1_INT2_NUM 95 +#define MXC_INT_GPIO1_INT1_NUM 96 +#define MXC_INT_GPIO1_INT0_NUM 97 +#define MXC_INT_GPIO1_INT15_0_NUM 98 +#define MXC_INT_GPIO1_INT31_16_NUM 99 +#define MXC_INT_GPIO2_INT15_0_NUM 100 +#define MXC_INT_GPIO2_INT31_16_NUM 101 +#define MXC_INT_GPIO3_INT15_0_NUM 102 +#define MXC_INT_GPIO3_INT31_16_NUM 103 +#define MXC_INT_GPIO4_INT15_0_NUM 104 +#define MXC_INT_GPIO4_INT31_16_NUM 105 +#define MXC_INT_GPIO5_INT15_0_NUM 106 +#define MXC_INT_GPIO5_INT31_16_NUM 107 +#define MXC_INT_GPIO6_INT15_0_NUM 108 +#define MXC_INT_GPIO6_INT31_16_NUM 109 +#define MXC_INT_GPIO7_INT15_0_NUM 110 +#define MXC_INT_GPIO7_INT31_16_NUM 111 +#define MXC_INT_WDOG1 112 +#define MXC_INT_WDOG2 113 +#define MXC_INT_KPP 114 +#define MX6Q_INT_PWM1 115 +#define MX6Q_INT_PWM2 116 +#define MX6Q_INT_PWM3 117 +#define MX6Q_INT_PWM4 118 +#define MXC_INT_CCM_INT1_NUM 119 +#define MXC_INT_CCM_INT2_NUM 120 +#define MX6Q_INT_GPC1 121 +#define MXC_INT_GPC_INT2_NUM 122 +#define MXC_INT_SRC 123 +#define MXC_INT_CHEETAH_L2 124 +#define MXC_INT_CHEETAH_PARITY 125 +#define MXC_INT_CHEETAH_PERFORM 126 +#define MXC_INT_CHEETAH_TRIGGER 127 +#define MXC_INT_SRC_CPU_WDOG 128 +#define MX6DL_INT_EPDC 129 +#define MX6DL_INT_EPXP 130 +#define MXC_INT_INTERRUPT_131_NUM 131 +#define MXC_INT_CSI_INTR1 132 +#define MXC_INT_CSI_INTR2 133 +#define MXC_INT_DSI 134 +#define MXC_INT_HSI 135 +#define MXC_INT_SJC 136 +#define MXC_INT_CAAM_INT0_NUM 137 +#define MXC_INT_CAAM_INT1_NUM 138 +#define MXC_INT_INTERRUPT_139_NUM 139 +#define MXC_INT_TZASC1 140 +#define MXC_INT_TZASC2 141 +#define MX6Q_INT_CAN1 142 +#define MX6Q_INT_CAN2 143 +#define MX6Q_INT_PERFMON1 144 +#define MX6Q_INT_PERFMON2 145 +#define MX6Q_INT_PERFMON3 146 +#define MX6Q_INT_HDMI_TX 147 +#define MX6Q_INT_HDMI_TX_WAKEUP 148 +#define MXC_INT_MLB_AHB0 149 +#define MXC_INT_ENET1 150 +#define MXC_INT_ENET2 151 +#define MXC_INT_PCIE_0 152 +#define MXC_INT_PCIE_1 153 +#define MXC_INT_PCIE_2 154 +#define MXC_INT_PCIE_3 155 +#define MXC_INT_DCIC1 156 +#define MXC_INT_DCIC2 157 +#define MXC_INT_MLB_AHB1 158 +#define MXC_INT_ANATOP_ANA2 159 +#define MXC_INT_END 159 + +#define MX6Q_INT_UART1 MXC_INT_UART1_ANDED +#define MX6Q_INT_UART2 MXC_INT_UART2_ANDED +#define MX6Q_INT_UART3 MXC_INT_UART3_ANDED +#define MX6Q_INT_UART4 MXC_INT_UART4_ANDED +#define MX6Q_INT_FEC MXC_INT_ENET1 +#define MX6Q_INT_DSI MXC_INT_DSI + +#define IRQ_LOCALTIMER 29 /* APBH-DMA */ #define MX6Q_DMA_CHANNEL_AHB_APBH_GPMI0 0 diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index 628ef1467a6b..c8f18052c6af 100755 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007, 2011 Freescale Semiconductor, Inc. + * Copyright 2004-2007, 2011-2012 Freescale Semiconductor, Inc. * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) * * This program is free software; you can redistribute it and/or @@ -36,6 +36,8 @@ #define MXC_CPU_MX50 50 #define MXC_CPU_MX51 51 #define MXC_CPU_MX53 53 +#define MXC_CPU_MX6Q 63 +#define MXC_CPU_MX6DL 61 #define IMX_CHIP_REVISION_1_0 0x10 #define IMX_CHIP_REVISION_1_1 0x11 @@ -218,12 +220,20 @@ extern unsigned int __mxc_cpu_type; # define cpu_is_mx53() (0) #endif -#ifndef __ASSEMBLY__ +#ifdef CONFIG_SOC_IMX6Q +# define mxc_cpu_type __mxc_cpu_type +# define cpu_is_mx6q() (mxc_cpu_type == MXC_CPU_MX6Q) +# define cpu_is_mx6dl() (mxc_cpu_type == MXC_CPU_MX6DL) +#else +# define cpu_is_mx6q() (0) +# define cpu_is_mx6dl() (0) +#endif +#ifndef __ASSEMBLY__ #ifdef CONFIG_SOC_IMX6Q -#define cpu_is_mx6q() (1) +extern int mx6q_revision(void); #else -#define cpu_is_mx6q() (0) +#define mx6q_revision(void) (0) #endif struct cpu_op { @@ -264,6 +274,7 @@ extern int tzic_enable_wake(int is_idle); #define cpu_is_mx5() (cpu_is_mx51() || cpu_is_mx53() || cpu_is_mx50()) #define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35()) #define cpu_is_mx2() (cpu_is_mx21() || cpu_is_mx27()) +#define cpu_is_mx6() (cpu_is_mx6q() || cpu_is_mx6dl()) #define MXC_PGCR_PCR 1 #define MXC_SRPGCR_PCR 1 diff --git a/arch/arm/plat-mxc/include/mach/mxc_edid.h b/arch/arm/plat-mxc/include/mach/mxc_edid.h index 4cbbb78ad703..10baa01bf9b1 100755 --- a/arch/arm/plat-mxc/include/mach/mxc_edid.h +++ b/arch/arm/plat-mxc/include/mach/mxc_edid.h @@ -1,5 +1,5 @@ /* - * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -26,10 +26,31 @@ #ifndef MXC_EDID_H #define MXC_EDID_H +#include <linux/fb.h> + #define FB_VMODE_ASPECT_4_3 0x10 #define FB_VMODE_ASPECT_16_9 0x20 #define FB_VMODE_ASPECT_MASK (FB_VMODE_ASPECT_4_3 | FB_VMODE_ASPECT_16_9) +enum cea_audio_coding_types { + AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0, + AUDIO_CODING_TYPE_LPCM = 1, + AUDIO_CODING_TYPE_AC3 = 2, + AUDIO_CODING_TYPE_MPEG1 = 3, + AUDIO_CODING_TYPE_MP3 = 4, + AUDIO_CODING_TYPE_MPEG2 = 5, + AUDIO_CODING_TYPE_AACLC = 6, + AUDIO_CODING_TYPE_DTS = 7, + AUDIO_CODING_TYPE_ATRAC = 8, + AUDIO_CODING_TYPE_SACD = 9, + AUDIO_CODING_TYPE_EAC3 = 10, + AUDIO_CODING_TYPE_DTS_HD = 11, + AUDIO_CODING_TYPE_MLP = 12, + AUDIO_CODING_TYPE_DST = 13, + AUDIO_CODING_TYPE_WMAPRO = 14, + AUDIO_CODING_TYPE_RESERVED = 15, +}; + struct mxc_edid_cfg { bool cea_underscan; bool cea_basicaudio; @@ -43,6 +64,10 @@ struct mxc_edid_cfg { bool vsd_dc_30bit; bool vsd_dc_y444; bool vsd_dvi_dual; + + u8 max_channels; + u8 sample_sizes; + u8 sample_rates; }; int mxc_edid_var_to_vic(struct fb_var_screeninfo *var); diff --git a/arch/arm/plat-mxc/include/mach/regs-usbphy-mx6.h b/arch/arm/plat-mxc/include/mach/regs-usbphy-mx6.h index 060b176b43af..473d16c4fb48 100644 --- a/arch/arm/plat-mxc/include/mach/regs-usbphy-mx6.h +++ b/arch/arm/plat-mxc/include/mach/regs-usbphy-mx6.h @@ -1,7 +1,7 @@ /* * Freescale USBPHY Register Definitions * - * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -468,6 +468,7 @@ /* Host2/3 HSIC Ctrl */ #define CLK_VLD (1 << 31) /* Indicating whether HSIC clock is valid */ +#define HSIC_DEV_CONN (1 << 21) /* set after device connected */ #define HSIC_EN (1 << 12) /* HSIC enable */ #define HSIC_CLK_ON (1 << 11) /* Force HSIC module 480M clock on, * even when in Host is in suspend mode diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h index 1a51cca1bfa4..7021c85d1b59 100755 --- a/arch/arm/plat-mxc/include/mach/system.h +++ b/arch/arm/plat-mxc/include/mach/system.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,5 +25,4 @@ extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode); void arch_idle(void); void arch_reset(char mode, const char *cmd); -int mxs_reset_block(void __iomem *hwreg, int just_enable); #endif /* __ASM_ARCH_MXC_SYSTEM_H__ */ diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c index b50963b9b403..bb9c45a0127e 100755 --- a/arch/arm/plat-mxc/usb_common.c +++ b/arch/arm/plat-mxc/usb_common.c @@ -88,7 +88,7 @@ static int fsl_check_usbclk(void) usb_ahb_clk = clk_get(NULL, "usb_ahb_clk"); if (clk_enable(usb_ahb_clk)) { - if (cpu_is_mx6q()) + if (cpu_is_mx6q() || cpu_is_mx6dl()) return 0; /* there is no ahb clock at mx6 */ printk(KERN_ERR "clk_enable(usb_ahb_clk) failed\n"); return -EINVAL; @@ -97,7 +97,7 @@ static int fsl_check_usbclk(void) usb_clk = clk_get(NULL, "usb_clk"); if (clk_enable(usb_clk)) { - if (cpu_is_mx6q()) + if (cpu_is_mx6q() || cpu_is_mx6dl()) return 0; /* there is usb_clk at mx6 */ printk(KERN_ERR "clk_enable(usb_clk) failed\n"); return -EINVAL; @@ -502,7 +502,7 @@ int fsl_usb_host_init(struct platform_device *pdev) if (usb_register_remote_wakeup(pdev)) pr_debug("%s port is not a wakeup source.\n", pdata->name); - if (!cpu_is_mx6q()) { + if (!(cpu_is_mx6q() || cpu_is_mx6dl())) { if (xops->xcvr_type == PORTSC_PTS_SERIAL) { if (cpu_is_mx35()) { usbh2_set_serial_xcvr(); @@ -814,7 +814,7 @@ int usbotg_init(struct platform_device *pdev) return -EINVAL; if (xops->init) xops->init(xops); - if (!(cpu_is_mx6q())) { + if (!((cpu_is_mx6q() || cpu_is_mx6dl()))) { UOG_PORTSC1 = UOG_PORTSC1 & ~PORTSC_PHCD; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 4c053288032f..89d1b01d9af9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -145,10 +145,14 @@ config MXC_PXP bool "MXC PxP support" select DMA_ENGINE +config MXC_PXP_V2 + bool "MXC PxP V2 support" + select DMA_ENGINE + config MXC_PXP_CLIENT_DEVICE bool "MXC PxP Client Device" default y - depends on MXC_PXP + depends on MXC_PXP || MXC_PXP_V2 config TXX9_DMAC tristate "Toshiba TXx9 SoC DMA support" @@ -240,7 +244,7 @@ config IMX_DMA config MXS_DMA bool "MXS DMA support" - depends on SOC_IMX23 || SOC_IMX28 + depends on SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q select DMA_ENGINE help Support the MXS DMA engine. This engine including APBH-DMA diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index e34807156e7a..0b7457b456a9 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_MV_XOR) += mv_xor.o obj-$(CONFIG_DW_DMAC) += dw_dmac.o obj-$(CONFIG_AT_HDMAC) += at_hdmac.o obj-$(CONFIG_MX3_IPU) += ipu/ -obj-$(CONFIG_MXC_PXP) += pxp/ +obj-y += pxp/ obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o obj-$(CONFIG_SH_DMAE) += shdma.o obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index b06cd4ca626f..4456b331e1d5 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * Refer to drivers/dma/imx-sdma.c * @@ -22,10 +22,10 @@ #include <linux/platform_device.h> #include <linux/dmaengine.h> #include <linux/delay.h> +#include <linux/mxs-dma.h> #include <asm/irq.h> #include <mach/mxs.h> -#include <mach/dma.h> #include <mach/common.h> /* @@ -349,10 +349,32 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan) clk_disable_unprepare(mxs_dma->clk); } +/* + * How to use the flags for ->device_prep_slave_sg() : + * [1] If there is only one DMA command in the DMA chain, the code should be: + * ...... + * ->device_prep_slave_sg(DMA_CTRL_ACK); + * ...... + * [2] If there are two DMA commands in the DMA chain, the code should be + * ...... + * ->device_prep_slave_sg(0); + * ...... + * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + * ...... + * [3] If there are more than two DMA commands in the DMA chain, the code + * should be: + * ...... + * ->device_prep_slave_sg(0); // First + * ...... + * ->device_prep_slave_sg(DMA_PREP_INTERRUPT [| DMA_CTRL_ACK]); + * ...... + * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); // Last + * ...... + */ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, - unsigned long append) + unsigned long flags) { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; @@ -360,6 +382,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct scatterlist *sg; int i, j; u32 *pio; + bool append = flags & DMA_PREP_INTERRUPT; int idx = append ? mxs_chan->desc_count : 0; if (mxs_chan->status == DMA_IN_PROGRESS && !append) @@ -386,7 +409,6 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits |= CCW_CHAIN; ccw->bits &= ~CCW_IRQ; ccw->bits &= ~CCW_DEC_SEM; - ccw->bits &= ~CCW_WAIT4END; } else { idx = 0; } @@ -401,7 +423,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits = 0; ccw->bits |= CCW_IRQ; ccw->bits |= CCW_DEC_SEM; - ccw->bits |= CCW_WAIT4END; + if (flags & DMA_CTRL_ACK) + ccw->bits |= CCW_WAIT4END; ccw->bits |= CCW_HALT_ON_TERM; ccw->bits |= CCW_TERM_FLUSH; ccw->bits |= BF_CCW(sg_len, PIO_NUM); @@ -432,7 +455,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits &= ~CCW_CHAIN; ccw->bits |= CCW_IRQ; ccw->bits |= CCW_DEC_SEM; - ccw->bits |= CCW_WAIT4END; + if (flags & DMA_CTRL_ACK) + ccw->bits |= CCW_WAIT4END; } } } diff --git a/drivers/dma/pxp/Makefile b/drivers/dma/pxp/Makefile index 88e51a7fb1e2..7372a8c032d3 100644 --- a/drivers/dma/pxp/Makefile +++ b/drivers/dma/pxp/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_MXC_PXP) += pxp_dma.o +obj-$(CONFIG_MXC_PXP_V2) += pxp_dma_v2.o obj-$(CONFIG_MXC_PXP_CLIENT_DEVICE) += pxp_device.o diff --git a/drivers/dma/pxp/pxp_device.c b/drivers/dma/pxp/pxp_device.c index 5f3016be80f5..6b3d7aa37dce 100644 --- a/drivers/dma/pxp/pxp_device.c +++ b/drivers/dma/pxp/pxp_device.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,10 +24,14 @@ #include <linux/uaccess.h> #include <linux/delay.h> #include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/sched.h> #include <linux/pxp_dma.h> #include <linux/atomic.h> +#include <mach/dma.h> + static atomic_t open_count = ATOMIC_INIT(0); static DEFINE_SPINLOCK(pxp_mem_lock); @@ -237,6 +241,14 @@ static int pxp_device_mmap(struct file *file, struct vm_area_struct *vma) request_size, vma->vm_page_prot) ? -EAGAIN : 0; } +static bool chan_filter(struct dma_chan *chan, void *arg) +{ + if (imx_dma_is_pxp(chan)) + return true; + else + return false; +} + static long pxp_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -258,7 +270,7 @@ static long pxp_device_ioctl(struct file *filp, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_PRIVATE, mask); - info->dma_chan = dma_request_channel(mask, NULL, NULL); + info->dma_chan = dma_request_channel(mask, chan_filter, NULL); if (!info->dma_chan) { pr_err("Unsccessfully received channel!\n"); kfree(info); diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c new file mode 100644 index 000000000000..3fadd9a5f762 --- /dev/null +++ b/drivers/dma/pxp/pxp_dma_v2.c @@ -0,0 +1,1633 @@ +/* + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * Based on STMP378X PxP driver + * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/dmaengine.h> +#include <linux/pxp_dma.h> +#include <linux/timer.h> +#include <linux/clk.h> +#include <linux/workqueue.h> +#include <linux/sched.h> + +#include "regs-pxp_v2.h" + +#define PXP_DOWNSCALE_THRESHOLD 0x4000 + +static LIST_HEAD(head); +static int timeout_in_ms = 600; + +struct pxp_dma { + struct dma_device dma; +}; + +struct pxps { + struct platform_device *pdev; + struct clk *clk; + void __iomem *base; + int irq; /* PXP IRQ to the CPU */ + + spinlock_t lock; + struct mutex clk_mutex; + int clk_stat; +#define CLK_STAT_OFF 0 +#define CLK_STAT_ON 1 + int pxp_ongoing; + int lut_state; + + struct device *dev; + struct pxp_dma pxp_dma; + struct pxp_channel channel[NR_PXP_VIRT_CHANNEL]; + wait_queue_head_t done; + struct work_struct work; + + /* describes most recent processing configuration */ + struct pxp_config_data pxp_conf_state; + + /* to turn clock off when pxp is inactive */ + struct timer_list clk_timer; +}; + +#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma) +#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd) +#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan) +#define to_pxp(id) container_of(id, struct pxps, pxp_dma) + +#define PXP_DEF_BUFS 2 +#define PXP_MIN_PIX 8 + +#define PXP_WAITCON ((__raw_readl(pxp->base + HW_PXP_STAT) & \ + BM_PXP_STAT_IRQ) != BM_PXP_STAT_IRQ) + +static uint32_t pxp_s0_formats[] = { + PXP_PIX_FMT_RGB24, + PXP_PIX_FMT_RGB565, + PXP_PIX_FMT_RGB555, + PXP_PIX_FMT_YUV420P, + PXP_PIX_FMT_YUV422P, +}; + +/* + * PXP common functions + */ +static void dump_pxp_reg(struct pxps *pxp) +{ + dev_dbg(pxp->dev, "PXP_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_CTRL)); + dev_dbg(pxp->dev, "PXP_STAT 0x%x", + __raw_readl(pxp->base + HW_PXP_STAT)); + dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_CTRL)); + dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_BUF)); + dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_BUF2)); + dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_PITCH)); + dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_LRC)); + dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC)); + dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC)); + dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC)); + dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x", + __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC)); + dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_CTRL)); + dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_BUF)); + dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_UBUF)); + dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_VBUF)); + dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_PITCH)); + dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND)); + dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_SCALE)); + dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_OFFSET)); + dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW)); + dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x", + __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH)); + dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_AS_CTRL)); + dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x", + __raw_readl(pxp->base + HW_PXP_AS_BUF)); + dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x", + __raw_readl(pxp->base + HW_PXP_AS_PITCH)); + dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x", + __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW)); + dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x", + __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH)); + dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC1_COEF0)); + dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC1_COEF1)); + dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC1_COEF2)); + dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_CTRL)); + dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_COEF0)); + dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_COEF1)); + dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_COEF2)); + dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_COEF3)); + dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_COEF4)); + dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x", + __raw_readl(pxp->base + HW_PXP_CSC2_COEF5)); + dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_LUT_CTRL)); + dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x", + __raw_readl(pxp->base + HW_PXP_LUT_ADDR)); + dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x", + __raw_readl(pxp->base + HW_PXP_LUT_DATA)); + dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x", + __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM)); + dev_dbg(pxp->dev, "PXP_CFA 0x%x", + __raw_readl(pxp->base + HW_PXP_CFA)); + dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST_CTRL)); + dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST2_PARAM)); + dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST4_PARAM)); + dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0)); + dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1)); + dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0)); + dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1)); + dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2)); + dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x", + __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3)); + dev_dbg(pxp->dev, "PXP_POWER 0x%x", + __raw_readl(pxp->base + HW_PXP_POWER)); + dev_dbg(pxp->dev, "PXP_NEXT 0x%x", + __raw_readl(pxp->base + HW_PXP_NEXT)); + dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x", + __raw_readl(pxp->base + HW_PXP_DEBUGCTRL)); + dev_dbg(pxp->dev, "PXP_DEBUG 0x%x", + __raw_readl(pxp->base + HW_PXP_DEBUG)); + dev_dbg(pxp->dev, "PXP_VERSION 0x%x", + __raw_readl(pxp->base + HW_PXP_VERSION)); +} + +static bool is_yuv(u32 pix_fmt) +{ + if ((pix_fmt == PXP_PIX_FMT_YUYV) | + (pix_fmt == PXP_PIX_FMT_UYVY) | + (pix_fmt == PXP_PIX_FMT_Y41P) | + (pix_fmt == PXP_PIX_FMT_YUV444) | + (pix_fmt == PXP_PIX_FMT_NV12) | + (pix_fmt == PXP_PIX_FMT_GREY) | + (pix_fmt == PXP_PIX_FMT_YVU410P) | + (pix_fmt == PXP_PIX_FMT_YUV410P) | + (pix_fmt == PXP_PIX_FMT_YVU420P) | + (pix_fmt == PXP_PIX_FMT_YUV420P) | + (pix_fmt == PXP_PIX_FMT_YUV420P2) | + (pix_fmt == PXP_PIX_FMT_YVU422P) | + (pix_fmt == PXP_PIX_FMT_YUV422P)) { + return true; + } else { + return false; + } +} + +static void pxp_set_ctrl(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_proc_data *proc_data = &pxp_conf->proc_data; + u32 ctrl; + u32 fmt_ctrl; + + /* Configure S0 input format */ + switch (pxp_conf->s0_param.pixel_fmt) { + case PXP_PIX_FMT_RGB24: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888; + break; + case PXP_PIX_FMT_RGB565: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565; + break; + case PXP_PIX_FMT_RGB555: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555; + break; + case PXP_PIX_FMT_YUV420P: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420; + break; + case PXP_PIX_FMT_GREY: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8; + break; + case PXP_PIX_FMT_YUV422P: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422; + break; + default: + fmt_ctrl = 0; + } + + ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl); + __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL); + + /* Configure output format based on out_channel format */ + switch (pxp_conf->out_param.pixel_fmt) { + case PXP_PIX_FMT_RGB24: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888; + break; + case PXP_PIX_FMT_RGB565: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565; + break; + case PXP_PIX_FMT_RGB555: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555; + break; + case PXP_PIX_FMT_YUV420P: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420; + break; + case PXP_PIX_FMT_YUV422P: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422; + break; + case PXP_PIX_FMT_GREY: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8; + break; + default: + fmt_ctrl = 0; + } + + ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl); + __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL); + + ctrl = 0; + if (proc_data->scaling) + ; + if (proc_data->vflip) + ctrl |= BM_PXP_CTRL_VFLIP; + if (proc_data->hflip) + ctrl |= BM_PXP_CTRL_HFLIP; + if (proc_data->rotate) + ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90); + + /* H/W support: controls where rotation will occur in the PXP datapath, + * will export an interfance if needed + */ + /* ctrl |= BM_PXP_CTRL_ROT_POS; post rotation */ + + __raw_writel(ctrl, pxp->base + HW_PXP_CTRL); +} + +static int pxp_start(struct pxps *pxp) +{ + __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET); + __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET); + dump_pxp_reg(pxp); + + return 0; +} + +static void pxp_set_outbuf(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *out_params = &pxp_conf->out_param; + + __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF); + + __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) | + BF_PXP_OUT_LRC_Y(out_params->height - 1), + pxp->base + HW_PXP_OUT_LRC); + + __raw_writel(out_params->stride, pxp->base + HW_PXP_OUT_PITCH); +} + +static void pxp_set_s0colorkey(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *s0_params = &pxp_conf->s0_param; + + /* Low and high are set equal. V4L does not allow a chromakey range */ + if (s0_params->color_key == -1) { + /* disable color key */ + __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW); + __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH); + } else { + __raw_writel(s0_params->color_key, + pxp->base + HW_PXP_PS_CLRKEYLOW); + __raw_writel(s0_params->color_key, + pxp->base + HW_PXP_PS_CLRKEYHIGH); + } +} + +static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no]; + + /* Low and high are set equal. V4L does not allow a chromakey range */ + if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) { + __raw_writel(ol_params->color_key, + pxp->base + HW_PXP_AS_CLRKEYLOW); + __raw_writel(ol_params->color_key, + pxp->base + HW_PXP_AS_CLRKEYHIGH); + } else { + /* disable color key */ + __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW); + __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH); + } +} + +static void pxp_set_oln(int layer_no, struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; + dma_addr_t phys_addr = olparams_data->paddr; + __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF); + + /* Fixme */ + __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC); + __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width) | + BF_PXP_OUT_AS_LRC_Y(olparams_data->height), + pxp->base + HW_PXP_OUT_AS_LRC); +} + +static void pxp_set_olparam(int layer_no, struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; + u32 olparam; + + olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha); + if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB24) + olparam |= + BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888); + else + olparam |= + BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565); + if (olparams_data->global_alpha_enable) + olparam |= + BF_PXP_AS_CTRL_ALPHA_CTRL + (BV_PXP_AS_CTRL_ALPHA_CTRL__Override); + if (olparams_data->color_key_enable) + olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY; + if (olparams_data->combine_enable) + ; + __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL); +} + +static void pxp_set_s0param(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *s0params_data = &pxp_conf->s0_param; + struct pxp_proc_data *proc_data = &pxp_conf->proc_data; + u32 s0param; + + s0param = BF_PXP_OUT_PS_ULC_X(proc_data->srect.left); + s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->srect.top); + __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC); + s0param = BF_PXP_OUT_PS_LRC_X(s0params_data->width); + s0param |= BF_PXP_OUT_PS_LRC_Y(s0params_data->height); + __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC); + +} + +/* TODO: crop behavior is re-designed in h/w. */ +static void pxp_set_s0crop(struct pxps *pxp) +{ +} + +static int pxp_set_scaling(struct pxps *pxp) +{ + int ret = 0; + u32 xscale, yscale, s0scale; + struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data; + + if ((proc_data->srect.width == proc_data->drect.width) && + (proc_data->srect.height == proc_data->drect.height)) { + proc_data->scaling = 0; + __raw_writel(0x10001000, pxp->base + HW_PXP_PS_SCALE); + goto out; + } + + proc_data->scaling = 1; + xscale = proc_data->srect.width * 0x1000 / proc_data->drect.width; + yscale = proc_data->srect.height * 0x1000 / proc_data->drect.height; + if (xscale > PXP_DOWNSCALE_THRESHOLD) + xscale = PXP_DOWNSCALE_THRESHOLD; + if (yscale > PXP_DOWNSCALE_THRESHOLD) + yscale = PXP_DOWNSCALE_THRESHOLD; + s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) | + BF_PXP_PS_SCALE_XSCALE(xscale); + __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE); + +out: + pxp_set_ctrl(pxp); + + return ret; +} + +static void pxp_set_bg(struct pxps *pxp) +{ + __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor, + pxp->base + HW_PXP_PS_BACKGROUND); +} + +static void pxp_set_lut(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + int lut_op = pxp_conf->proc_data.lut_transform; + u32 reg_val; + int i; + bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false; + u8 *cmap = pxp_conf->proc_data.lut_map; + u32 entry_src; + u32 pix_val; + u8 entry[4]; + + /* + * If LUT already configured as needed, return... + * Unless CMAP is needed and it has been updated. + */ + if ((pxp->lut_state == lut_op) && + !(use_cmap && pxp_conf->proc_data.lut_map_updated)) + return; + + if (lut_op == PXP_LUT_NONE) { + __raw_writel(BM_PXP_LUT_CTRL_BYPASS, + pxp->base + HW_PXP_LUT_CTRL); + } else if (((lut_op & PXP_LUT_INVERT) != 0) + && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) { + /* Fill out LUT table with inverted monochromized values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) { + entry_src = use_cmap ? cmap[pix_val + i] : pix_val + i; + entry[i] = (entry_src < 0x80) ? 0xFF : 0x00; + } + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } else if ((lut_op & PXP_LUT_INVERT) != 0) { + /* Fill out LUT table with 8-bit inverted values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) { + entry_src = use_cmap ? cmap[pix_val + i] : pix_val + i; + entry[i] = ~entry_src & 0xFF; + } + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) { + /* Fill out LUT table with 8-bit monochromized values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) { + entry_src = use_cmap ? cmap[pix_val + i] : pix_val + i; + entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF; + } + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } else if (use_cmap) { + /* Fill out LUT table using colormap values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) + entry[i] = cmap[pix_val + i]; + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } + + pxp->lut_state = lut_op; +} + +static void pxp_set_csc(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *s0_params = &pxp_conf->s0_param; + struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0]; + struct pxp_layer_param *out_params = &pxp_conf->out_param; + + bool input_is_YUV = is_yuv(s0_params->pixel_fmt); + bool output_is_YUV = is_yuv(out_params->pixel_fmt); + + if (input_is_YUV && output_is_YUV) { + /* + * Input = YUV, Output = YUV + * No CSC unless we need to do combining + */ + if (ol_params->combine_enable) { + /* Must convert to RGB for combining with RGB overlay */ + + /* CSC1 - YUV->RGB */ + __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0); + __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1); + __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2); + + /* CSC2 - RGB->YUV */ + __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL); + __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0); + __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1); + __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2); + __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3); + __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4); + __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5); + } else { + /* Input & Output both YUV, so bypass both CSCs */ + + /* CSC1 - Bypass */ + __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); + + /* CSC2 - Bypass */ + __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); + } + } else if (input_is_YUV && !output_is_YUV) { + /* + * Input = YUV, Output = RGB + * Use CSC1 to convert to RGB + */ + + /* CSC1 - YUV->RGB */ + __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0); + __raw_writel(0x01230204, pxp->base + HW_PXP_CSC1_COEF1); + __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2); + + /* CSC2 - Bypass */ + __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); + } else if (!input_is_YUV && output_is_YUV) { + /* + * Input = RGB, Output = YUV + * Use CSC2 to convert to YUV + */ + + /* CSC1 - Bypass */ + __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); + + /* CSC2 - RGB->YUV */ + __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL); + __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0); + __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1); + __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2); + __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3); + __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4); + __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5); + } else { + /* + * Input = RGB, Output = RGB + * Input & Output both RGB, so bypass both CSCs + */ + + /* CSC1 - Bypass */ + __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); + + /* CSC2 - Bypass */ + __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); + } + + /* YCrCb colorspace */ + /* Not sure when we use this...no YCrCb formats are defined for PxP */ + /* + __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR); + __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR); + __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR); + */ + +} + +static void pxp_set_s0buf(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_layer_param *s0_params = &pxp_conf->s0_param; + dma_addr_t Y, U, V; + + Y = s0_params->paddr; + __raw_writel(Y, pxp->base + HW_PXP_PS_BUF); + if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) || + (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) || + (s0_params->pixel_fmt == PXP_PIX_FMT_GREY)) { + /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */ + int s = 2; + U = Y + (s0_params->width * s0_params->height); + V = U + ((s0_params->width * s0_params->height) >> s); + __raw_writel(U, pxp->base + HW_PXP_PS_UBUF); + __raw_writel(V, pxp->base + HW_PXP_PS_VBUF); + } + + /* TODO: only support RGB565, Y8 */ + if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) + __raw_writel(s0_params->width, pxp->base + HW_PXP_PS_PITCH); + else + __raw_writel(s0_params->width * 2, pxp->base + HW_PXP_PS_PITCH); +} + +/** + * pxp_config() - configure PxP for a processing task + * @pxps: PXP context. + * @pxp_chan: PXP channel. + * @return: 0 on success or negative error code on failure. + */ +static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan) +{ + struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state; + int ol_nr; + int i; + + /* Configure PxP regs */ + pxp_set_ctrl(pxp); + pxp_set_s0param(pxp); + pxp_set_s0crop(pxp); + pxp_set_scaling(pxp); + ol_nr = pxp_conf_data->layer_nr - 2; + while (ol_nr > 0) { + i = pxp_conf_data->layer_nr - 2 - ol_nr; + pxp_set_oln(i, pxp); + pxp_set_olparam(i, pxp); + /* only the color key in higher overlay will take effect. */ + pxp_set_olcolorkey(i, pxp); + ol_nr--; + } + pxp_set_s0colorkey(pxp); + pxp_set_csc(pxp); + pxp_set_bg(pxp); + pxp_set_lut(pxp); + + pxp_set_s0buf(pxp); + pxp_set_outbuf(pxp); + + return 0; +} + +static void pxp_clk_enable(struct pxps *pxp) +{ + mutex_lock(&pxp->clk_mutex); + + if (pxp->clk_stat == CLK_STAT_ON) { + mutex_unlock(&pxp->clk_mutex); + return; + } + + clk_enable(pxp->clk); + pxp->clk_stat = CLK_STAT_ON; + + mutex_unlock(&pxp->clk_mutex); +} + +static void pxp_clk_disable(struct pxps *pxp) +{ + unsigned long flags; + + mutex_lock(&pxp->clk_mutex); + + if (pxp->clk_stat == CLK_STAT_OFF) { + mutex_unlock(&pxp->clk_mutex); + return; + } + + spin_lock_irqsave(&pxp->lock, flags); + if ((pxp->pxp_ongoing == 0) && list_empty(&head)) { + spin_unlock_irqrestore(&pxp->lock, flags); + clk_disable(pxp->clk); + pxp->clk_stat = CLK_STAT_OFF; + } else + spin_unlock_irqrestore(&pxp->lock, flags); + + mutex_unlock(&pxp->clk_mutex); +} + +static inline void clkoff_callback(struct work_struct *w) +{ + struct pxps *pxp = container_of(w, struct pxps, work); + + pxp_clk_disable(pxp); +} + +static void pxp_clkoff_timer(unsigned long arg) +{ + struct pxps *pxp = (struct pxps *)arg; + + if ((pxp->pxp_ongoing == 0) && list_empty(&head)) + schedule_work(&pxp->work); + else + mod_timer(&pxp->clk_timer, + jiffies + msecs_to_jiffies(timeout_in_ms)); +} + +static struct pxp_tx_desc *pxpdma_first_active(struct pxp_channel *pxp_chan) +{ + return list_entry(pxp_chan->active_list.next, struct pxp_tx_desc, list); +} + +static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan) +{ + return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list); +} + +/* called with pxp_chan->lock held */ +static void __pxpdma_dostart(struct pxp_channel *pxp_chan) +{ + struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device); + struct pxps *pxp = to_pxp(pxp_dma); + struct pxp_tx_desc *desc; + struct pxp_tx_desc *child; + int i = 0; + + /* so far we presume only one transaction on active_list */ + /* S0 */ + desc = pxpdma_first_active(pxp_chan); + memcpy(&pxp->pxp_conf_state.s0_param, + &desc->layer_param.s0_param, sizeof(struct pxp_layer_param)); + memcpy(&pxp->pxp_conf_state.proc_data, + &desc->proc_data, sizeof(struct pxp_proc_data)); + + /* Save PxP configuration */ + list_for_each_entry(child, &desc->tx_list, list) { + if (i == 0) { /* Output */ + memcpy(&pxp->pxp_conf_state.out_param, + &child->layer_param.out_param, + sizeof(struct pxp_layer_param)); + } else { /* Overlay */ + memcpy(&pxp->pxp_conf_state.ol_param[i - 1], + &child->layer_param.ol_param, + sizeof(struct pxp_layer_param)); + } + + i++; + } + pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__, + pxp->pxp_conf_state.s0_param.width, + pxp->pxp_conf_state.s0_param.height, + pxp->pxp_conf_state.s0_param.paddr); + pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__, + pxp->pxp_conf_state.out_param.width, + pxp->pxp_conf_state.out_param.height, + pxp->pxp_conf_state.out_param.paddr); +} + +static void pxpdma_dostart_work(struct pxps *pxp) +{ + struct pxp_channel *pxp_chan = NULL; + unsigned long flags, flags1; + + while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE) + ; + + spin_lock_irqsave(&pxp->lock, flags); + if (list_empty(&head)) { + pxp->pxp_ongoing = 0; + spin_unlock_irqrestore(&pxp->lock, flags); + return; + } + + pxp_chan = list_entry(head.next, struct pxp_channel, list); + + spin_lock_irqsave(&pxp_chan->lock, flags1); + if (!list_empty(&pxp_chan->active_list)) { + struct pxp_tx_desc *desc; + /* REVISIT */ + desc = pxpdma_first_active(pxp_chan); + __pxpdma_dostart(pxp_chan); + } + spin_unlock_irqrestore(&pxp_chan->lock, flags1); + + /* Configure PxP */ + pxp_config(pxp, pxp_chan); + + pxp_start(pxp); + + spin_unlock_irqrestore(&pxp->lock, flags); +} + +static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct list_head *list) +{ + struct pxp_tx_desc *desc = NULL; + do { + desc = pxpdma_first_queued(pxp_chan); + list_move_tail(&desc->list, list); + } while (!list_empty(&pxp_chan->queue)); +} + +static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct pxp_tx_desc *desc = to_tx_desc(tx); + struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan); + dma_cookie_t cookie; + unsigned long flags; + + dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n"); + + mutex_lock(&pxp_chan->chan_mutex); + + cookie = pxp_chan->dma_chan.cookie; + + if (++cookie < 0) + cookie = 1; + + /* from dmaengine.h: "last cookie value returned to client" */ + pxp_chan->dma_chan.cookie = cookie; + tx->cookie = cookie; + + /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */ + spin_lock_irqsave(&pxp_chan->lock, flags); + + /* Here we add the tx descriptor to our PxP task queue. */ + list_add_tail(&desc->list, &pxp_chan->queue); + + spin_unlock_irqrestore(&pxp_chan->lock, flags); + + dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n"); + + mutex_unlock(&pxp_chan->chan_mutex); + return cookie; +} + +/* Called with pxp_chan->chan_mutex held */ +static int pxp_desc_alloc(struct pxp_channel *pxp_chan, int n) +{ + struct pxp_tx_desc *desc = vmalloc(n * sizeof(struct pxp_tx_desc)); + + if (!desc) + return -ENOMEM; + + pxp_chan->n_tx_desc = n; + pxp_chan->desc = desc; + INIT_LIST_HEAD(&pxp_chan->active_list); + INIT_LIST_HEAD(&pxp_chan->queue); + INIT_LIST_HEAD(&pxp_chan->free_list); + + while (n--) { + struct dma_async_tx_descriptor *txd = &desc->txd; + + memset(txd, 0, sizeof(*txd)); + INIT_LIST_HEAD(&desc->tx_list); + dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan); + txd->tx_submit = pxp_tx_submit; + + list_add(&desc->list, &pxp_chan->free_list); + + desc++; + } + + return 0; +} + +/** + * pxp_init_channel() - initialize a PXP channel. + * @pxp_dma: PXP DMA context. + * @pchan: pointer to the channel object. + * @return 0 on success or negative error code on failure. + */ +static int pxp_init_channel(struct pxp_dma *pxp_dma, + struct pxp_channel *pxp_chan) +{ + unsigned long flags; + struct pxps *pxp = to_pxp(pxp_dma); + int ret = 0, n_desc = 0; + + /* + * We are using _virtual_ channel here. + * Each channel contains all parameters of corresponding layers + * for one transaction; each layer is represented as one descriptor + * (i.e., pxp_tx_desc) here. + */ + + spin_lock_irqsave(&pxp->lock, flags); + + /* max desc nr: S0+OL+OUT = 1+8+1 */ + n_desc = 16; + + spin_unlock_irqrestore(&pxp->lock, flags); + + if (n_desc && !pxp_chan->desc) + ret = pxp_desc_alloc(pxp_chan, n_desc); + + return ret; +} + +/** + * pxp_uninit_channel() - uninitialize a PXP channel. + * @pxp_dma: PXP DMA context. + * @pchan: pointer to the channel object. + * @return 0 on success or negative error code on failure. + */ +static int pxp_uninit_channel(struct pxp_dma *pxp_dma, + struct pxp_channel *pxp_chan) +{ + int ret = 0; + + if (pxp_chan->desc) + vfree(pxp_chan->desc); + + pxp_chan->desc = NULL; + + return ret; +} + +static irqreturn_t pxp_irq(int irq, void *dev_id) +{ + struct pxps *pxp = dev_id; + struct pxp_channel *pxp_chan; + struct pxp_tx_desc *desc; + dma_async_tx_callback callback; + void *callback_param; + unsigned long flags; + u32 hist_status; + + dump_pxp_reg(pxp); + + hist_status = + __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS; + + __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR); + + spin_lock_irqsave(&pxp->lock, flags); + + if (list_empty(&head)) { + pxp->pxp_ongoing = 0; + spin_unlock_irqrestore(&pxp->lock, flags); + return IRQ_NONE; + } + + pxp_chan = list_entry(head.next, struct pxp_channel, list); + list_del_init(&pxp_chan->list); + + if (list_empty(&pxp_chan->active_list)) { + pr_debug("PXP_IRQ pxp_chan->active_list empty. chan_id %d\n", + pxp_chan->dma_chan.chan_id); + pxp->pxp_ongoing = 0; + spin_unlock_irqrestore(&pxp->lock, flags); + return IRQ_NONE; + } + + /* Get descriptor and call callback */ + desc = pxpdma_first_active(pxp_chan); + + pxp_chan->completed = desc->txd.cookie; + + callback = desc->txd.callback; + callback_param = desc->txd.callback_param; + + /* Send histogram status back to caller */ + desc->hist_status = hist_status; + + if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback) + callback(callback_param); + + pxp_chan->status = PXP_CHANNEL_INITIALIZED; + + list_splice_init(&desc->tx_list, &pxp_chan->free_list); + list_move(&desc->list, &pxp_chan->free_list); + + wake_up(&pxp->done); + pxp->pxp_ongoing = 0; + mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms)); + + spin_unlock_irqrestore(&pxp->lock, flags); + + return IRQ_HANDLED; +} + +/* called with pxp_chan->lock held */ +static struct pxp_tx_desc *pxpdma_desc_get(struct pxp_channel *pxp_chan) +{ + struct pxp_tx_desc *desc, *_desc; + struct pxp_tx_desc *ret = NULL; + + list_for_each_entry_safe(desc, _desc, &pxp_chan->free_list, list) { + list_del_init(&desc->list); + ret = desc; + break; + } + + return ret; +} + +/* called with pxp_chan->lock held */ +static void pxpdma_desc_put(struct pxp_channel *pxp_chan, + struct pxp_tx_desc *desc) +{ + if (desc) { + struct device *dev = &pxp_chan->dma_chan.dev->device; + struct pxp_tx_desc *child; + + list_for_each_entry(child, &desc->tx_list, list) + dev_info(dev, "moving child desc %p to freelist\n", child); + list_splice_init(&desc->tx_list, &pxp_chan->free_list); + dev_info(dev, "moving desc %p to freelist\n", desc); + list_add(&desc->list, &pxp_chan->free_list); + } +} + +/* Allocate and initialise a transfer descriptor. */ +static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan, + struct scatterlist + *sgl, + unsigned int sg_len, + enum dma_transfer_direction + direction, + unsigned long tx_flags) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); + struct pxps *pxp = to_pxp(pxp_dma); + struct pxp_tx_desc *desc = NULL; + struct pxp_tx_desc *first = NULL, *prev = NULL; + struct scatterlist *sg; + unsigned long flags; + dma_addr_t phys_addr; + int i; + + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) { + dev_err(chan->device->dev, "Invalid DMA direction %d!\n", + direction); + return NULL; + } + + if (unlikely(sg_len < 2)) + return NULL; + + spin_lock_irqsave(&pxp_chan->lock, flags); + for_each_sg(sgl, sg, sg_len, i) { + desc = pxpdma_desc_get(pxp_chan); + if (!desc) { + pxpdma_desc_put(pxp_chan, first); + dev_err(chan->device->dev, "Can't get DMA desc.\n"); + spin_unlock_irqrestore(&pxp_chan->lock, flags); + return NULL; + } + + phys_addr = sg_dma_address(sg); + + if (!first) { + first = desc; + + desc->layer_param.s0_param.paddr = phys_addr; + } else { + list_add_tail(&desc->list, &first->tx_list); + prev->next = desc; + desc->next = NULL; + + if (i == 1) + desc->layer_param.out_param.paddr = phys_addr; + else + desc->layer_param.ol_param.paddr = phys_addr; + } + + prev = desc; + } + spin_unlock_irqrestore(&pxp_chan->lock, flags); + + pxp->pxp_conf_state.layer_nr = sg_len; + first->txd.flags = tx_flags; + first->len = sg_len; + pr_debug("%s:%d first %p, first->len %d, flags %08x\n", + __func__, __LINE__, first, first->len, first->txd.flags); + + return &first->txd; +} + +static void pxp_issue_pending(struct dma_chan *chan) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); + struct pxps *pxp = to_pxp(pxp_dma); + unsigned long flags0, flags; + + spin_lock_irqsave(&pxp->lock, flags0); + spin_lock_irqsave(&pxp_chan->lock, flags); + + if (!list_empty(&pxp_chan->queue)) { + pxpdma_dequeue(pxp_chan, &pxp_chan->active_list); + pxp_chan->status = PXP_CHANNEL_READY; + list_add_tail(&pxp_chan->list, &head); + } else { + spin_unlock_irqrestore(&pxp_chan->lock, flags); + spin_unlock_irqrestore(&pxp->lock, flags0); + return; + } + spin_unlock_irqrestore(&pxp_chan->lock, flags); + spin_unlock_irqrestore(&pxp->lock, flags0); + + pxp_clk_enable(pxp); + if (!wait_event_interruptible_timeout(pxp->done, PXP_WAITCON, 2 * HZ) || + signal_pending(current)) { + pxp_clk_disable(pxp); + return; + } + + spin_lock_irqsave(&pxp->lock, flags); + pxp->pxp_ongoing = 1; + spin_unlock_irqrestore(&pxp->lock, flags); + pxpdma_dostart_work(pxp); +} + +static void __pxp_terminate_all(struct dma_chan *chan) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + unsigned long flags; + + /* pchan->queue is modified in ISR, have to spinlock */ + spin_lock_irqsave(&pxp_chan->lock, flags); + list_splice_init(&pxp_chan->queue, &pxp_chan->free_list); + list_splice_init(&pxp_chan->active_list, &pxp_chan->free_list); + + spin_unlock_irqrestore(&pxp_chan->lock, flags); + + pxp_chan->status = PXP_CHANNEL_INITIALIZED; +} + +static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + + /* Only supports DMA_TERMINATE_ALL */ + if (cmd != DMA_TERMINATE_ALL) + return -ENXIO; + + mutex_lock(&pxp_chan->chan_mutex); + __pxp_terminate_all(chan); + mutex_unlock(&pxp_chan->chan_mutex); + + return 0; +} + +static int pxp_alloc_chan_resources(struct dma_chan *chan) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); + int ret; + + /* dmaengine.c now guarantees to only offer free channels */ + BUG_ON(chan->client_count > 1); + WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE); + + chan->cookie = 1; + pxp_chan->completed = -ENXIO; + + pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id); + ret = pxp_init_channel(pxp_dma, pxp_chan); + if (ret < 0) + goto err_chan; + + pxp_chan->status = PXP_CHANNEL_INITIALIZED; + + dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n", + chan->chan_id, pxp_chan->eof_irq); + + return ret; + +err_chan: + return ret; +} + +static void pxp_free_chan_resources(struct dma_chan *chan) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); + + mutex_lock(&pxp_chan->chan_mutex); + + __pxp_terminate_all(chan); + + pxp_chan->status = PXP_CHANNEL_FREE; + + pxp_uninit_channel(pxp_dma, pxp_chan); + + mutex_unlock(&pxp_chan->chan_mutex); +} + +static enum dma_status pxp_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct pxp_channel *pxp_chan = to_pxp_channel(chan); + + if (cookie != chan->cookie) + return DMA_ERROR; + + if (txstate) { + txstate->last = pxp_chan->completed; + txstate->used = chan->cookie; + txstate->residue = 0; + } + return DMA_SUCCESS; +} + +static int pxp_hw_init(struct pxps *pxp) +{ + struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; + struct pxp_proc_data *proc_data = &pxp_conf->proc_data; + u32 reg_val; + + /* Pull PxP out of reset */ + __raw_writel(0, pxp->base + HW_PXP_CTRL); + + /* Config defaults */ + + /* Initialize non-channel-specific PxP parameters */ + proc_data->drect.left = proc_data->srect.left = 0; + proc_data->drect.top = proc_data->srect.top = 0; + proc_data->drect.width = proc_data->srect.width = 0; + proc_data->drect.height = proc_data->srect.height = 0; + proc_data->scaling = 0; + proc_data->hflip = 0; + proc_data->vflip = 0; + proc_data->rotate = 0; + proc_data->bgcolor = 0; + + /* Initialize S0 channel parameters */ + pxp_conf->s0_param.pixel_fmt = pxp_s0_formats[0]; + pxp_conf->s0_param.width = 0; + pxp_conf->s0_param.height = 0; + pxp_conf->s0_param.color_key = -1; + pxp_conf->s0_param.color_key_enable = false; + + /* Initialize OL channel parameters */ + pxp_conf->ol_param[0].combine_enable = false; + pxp_conf->ol_param[0].width = 0; + pxp_conf->ol_param[0].height = 0; + pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565; + pxp_conf->ol_param[0].color_key_enable = false; + pxp_conf->ol_param[0].color_key = -1; + pxp_conf->ol_param[0].global_alpha_enable = false; + pxp_conf->ol_param[0].global_alpha = 0; + pxp_conf->ol_param[0].local_alpha_enable = false; + + /* Initialize Output channel parameters */ + pxp_conf->out_param.width = 0; + pxp_conf->out_param.height = 0; + pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565; + + proc_data->overlay_state = 0; + + /* Write default h/w config */ + pxp_set_ctrl(pxp); + pxp_set_s0param(pxp); + pxp_set_s0crop(pxp); + /* + * simply program the ULC to a higher value than the LRC + * to avoid any AS pixels to show up in the output buffer. + */ + __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_OUT_AS_ULC); + pxp_set_olparam(0, pxp); + pxp_set_olcolorkey(0, pxp); + + pxp_set_s0colorkey(pxp); + pxp_set_csc(pxp); + pxp_set_bg(pxp); + pxp_set_lut(pxp); + + /* One-time histogram configuration */ + reg_val = + BF_PXP_HIST_CTRL_PANEL_MODE(BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST_CTRL); + + reg_val = BF_PXP_HIST2_PARAM_VALUE0(0x00) | + BF_PXP_HIST2_PARAM_VALUE1(0x00F); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST2_PARAM); + + reg_val = BF_PXP_HIST4_PARAM_VALUE0(0x00) | + BF_PXP_HIST4_PARAM_VALUE1(0x05) | + BF_PXP_HIST4_PARAM_VALUE2(0x0A) | BF_PXP_HIST4_PARAM_VALUE3(0x0F); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST4_PARAM); + + reg_val = BF_PXP_HIST8_PARAM0_VALUE0(0x00) | + BF_PXP_HIST8_PARAM0_VALUE1(0x02) | + BF_PXP_HIST8_PARAM0_VALUE2(0x04) | BF_PXP_HIST8_PARAM0_VALUE3(0x06); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM0); + reg_val = BF_PXP_HIST8_PARAM1_VALUE4(0x09) | + BF_PXP_HIST8_PARAM1_VALUE5(0x0B) | + BF_PXP_HIST8_PARAM1_VALUE6(0x0D) | BF_PXP_HIST8_PARAM1_VALUE7(0x0F); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM1); + + reg_val = BF_PXP_HIST16_PARAM0_VALUE0(0x00) | + BF_PXP_HIST16_PARAM0_VALUE1(0x01) | + BF_PXP_HIST16_PARAM0_VALUE2(0x02) | + BF_PXP_HIST16_PARAM0_VALUE3(0x03); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM0); + reg_val = BF_PXP_HIST16_PARAM1_VALUE4(0x04) | + BF_PXP_HIST16_PARAM1_VALUE5(0x05) | + BF_PXP_HIST16_PARAM1_VALUE6(0x06) | + BF_PXP_HIST16_PARAM1_VALUE7(0x07); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM1); + reg_val = BF_PXP_HIST16_PARAM2_VALUE8(0x08) | + BF_PXP_HIST16_PARAM2_VALUE9(0x09) | + BF_PXP_HIST16_PARAM2_VALUE10(0x0A) | + BF_PXP_HIST16_PARAM2_VALUE11(0x0B); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM2); + reg_val = BF_PXP_HIST16_PARAM3_VALUE12(0x0C) | + BF_PXP_HIST16_PARAM3_VALUE13(0x0D) | + BF_PXP_HIST16_PARAM3_VALUE14(0x0E) | + BF_PXP_HIST16_PARAM3_VALUE15(0x0F); + __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM3); + + return 0; +} + +static int pxp_dma_init(struct pxps *pxp) +{ + struct pxp_dma *pxp_dma = &pxp->pxp_dma; + struct dma_device *dma = &pxp_dma->dma; + int i; + + dma_cap_set(DMA_SLAVE, dma->cap_mask); + dma_cap_set(DMA_PRIVATE, dma->cap_mask); + + /* Compulsory common fields */ + dma->dev = pxp->dev; + dma->device_alloc_chan_resources = pxp_alloc_chan_resources; + dma->device_free_chan_resources = pxp_free_chan_resources; + dma->device_tx_status = pxp_tx_status; + dma->device_issue_pending = pxp_issue_pending; + + /* Compulsory for DMA_SLAVE fields */ + dma->device_prep_slave_sg = pxp_prep_slave_sg; + dma->device_control = pxp_control; + + /* Initialize PxP Channels */ + INIT_LIST_HEAD(&dma->channels); + for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) { + struct pxp_channel *pxp_chan = pxp->channel + i; + struct dma_chan *dma_chan = &pxp_chan->dma_chan; + + spin_lock_init(&pxp_chan->lock); + mutex_init(&pxp_chan->chan_mutex); + + /* Only one EOF IRQ for PxP, shared by all channels */ + pxp_chan->eof_irq = pxp->irq; + pxp_chan->status = PXP_CHANNEL_FREE; + pxp_chan->completed = -ENXIO; + snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name), + "PXP EOF %d", i); + + dma_chan->device = &pxp_dma->dma; + dma_chan->cookie = 1; + dma_chan->chan_id = i; + list_add_tail(&dma_chan->device_node, &dma->channels); + } + + return dma_async_device_register(&pxp_dma->dma); +} + +static ssize_t clk_off_timeout_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", timeout_in_ms); +} + +static ssize_t clk_off_timeout_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int val; + if (sscanf(buf, "%d", &val) > 0) { + timeout_in_ms = val; + return count; + } + return -EINVAL; +} + +static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show, + clk_off_timeout_store); + +static int pxp_probe(struct platform_device *pdev) +{ + struct pxps *pxp; + struct resource *res; + int irq; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!res || irq < 0) { + err = -ENODEV; + goto exit; + } + + pxp = kzalloc(sizeof(*pxp), GFP_KERNEL); + if (!pxp) { + dev_err(&pdev->dev, "failed to allocate control object\n"); + err = -ENOMEM; + goto exit; + } + + pxp->dev = &pdev->dev; + + platform_set_drvdata(pdev, pxp); + pxp->irq = irq; + + pxp->pxp_ongoing = 0; + pxp->lut_state = 0; + + spin_lock_init(&pxp->lock); + mutex_init(&pxp->clk_mutex); + + if (!request_mem_region(res->start, resource_size(res), "pxp-mem")) { + err = -EBUSY; + goto freepxp; + } + + pxp->base = ioremap(res->start, SZ_4K); + pxp->pdev = pdev; + + pxp->clk = clk_get(NULL, "pxp_axi"); + clk_enable(pxp->clk); + + err = pxp_hw_init(pxp); + if (err) { + dev_err(&pdev->dev, "failed to initialize hardware\n"); + goto release; + } + clk_disable(pxp->clk); + + err = request_irq(pxp->irq, pxp_irq, 0, "pxp-irq", pxp); + if (err) + goto release; + /* Initialize DMA engine */ + err = pxp_dma_init(pxp); + if (err < 0) + goto err_dma_init; + + if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) { + dev_err(&pdev->dev, + "Unable to create file from clk_off_timeout\n"); + goto err_dma_init; + } + dump_pxp_reg(pxp); + + INIT_WORK(&pxp->work, clkoff_callback); + init_waitqueue_head(&pxp->done); + init_timer(&pxp->clk_timer); + pxp->clk_timer.function = pxp_clkoff_timer; + pxp->clk_timer.data = (unsigned long)pxp; +exit: + return err; +err_dma_init: + free_irq(pxp->irq, pxp); +release: + release_mem_region(res->start, resource_size(res)); +freepxp: + kfree(pxp); + dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe function\n"); + return err; +} + +static int __devexit pxp_remove(struct platform_device *pdev) +{ + struct pxps *pxp = platform_get_drvdata(pdev); + + cancel_work_sync(&pxp->work); + del_timer_sync(&pxp->clk_timer); + free_irq(pxp->irq, pxp); + clk_disable(pxp->clk); + clk_put(pxp->clk); + iounmap(pxp->base); + device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout); + + kfree(pxp); + + return 0; +} + +#ifdef CONFIG_PM +static int pxp_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct pxps *pxp = platform_get_drvdata(pdev); + + pxp_clk_enable(pxp); + while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE) + ; + + __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL); + pxp_clk_disable(pxp); + + return 0; +} + +static int pxp_resume(struct platform_device *pdev) +{ + struct pxps *pxp = platform_get_drvdata(pdev); + + pxp_clk_enable(pxp); + /* Pull PxP out of reset */ + __raw_writel(0, pxp->base + HW_PXP_CTRL); + pxp_clk_disable(pxp); + + return 0; +} +#else +#define pxp_suspend NULL +#define pxp_resume NULL +#endif + +static struct platform_driver pxp_driver = { + .driver = { + .name = "imx-pxp", + }, + .probe = pxp_probe, + .remove = __exit_p(pxp_remove), + .suspend = pxp_suspend, + .resume = pxp_resume, +}; + +static int __init pxp_init(void) +{ + return platform_driver_register(&pxp_driver); +} + +subsys_initcall(pxp_init); + +static void __exit pxp_exit(void) +{ + platform_driver_unregister(&pxp_driver); +} + +module_exit(pxp_exit); + +MODULE_DESCRIPTION("i.MX PxP driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/drivers/dma/pxp/regs-pxp_v2.h b/drivers/dma/pxp/regs-pxp_v2.h new file mode 100644 index 000000000000..5ac56ce00e45 --- /dev/null +++ b/drivers/dma/pxp/regs-pxp_v2.h @@ -0,0 +1,1152 @@ +/* + * Freescale PXP Register Definitions + * + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is created by xml file. Don't Edit it. + * + * Xml Revision: 1.29 + * Template revision: 1.3 + */ + +#ifndef __ARCH_ARM___PXP_H +#define __ARCH_ARM___PXP_H + +#define HW_PXP_CTRL (0x00000000) +#define HW_PXP_CTRL_SET (0x00000004) +#define HW_PXP_CTRL_CLR (0x00000008) +#define HW_PXP_CTRL_TOG (0x0000000c) + +#define BM_PXP_CTRL_SFTRST 0x80000000 +#define BM_PXP_CTRL_CLKGATE 0x40000000 +#define BM_PXP_CTRL_RSVD4 0x20000000 +#define BM_PXP_CTRL_EN_REPEAT 0x10000000 +#define BP_PXP_CTRL_RSVD3 26 +#define BM_PXP_CTRL_RSVD3 0x0C000000 +#define BF_PXP_CTRL_RSVD3(v) \ + (((v) << 26) & BM_PXP_CTRL_RSVD3) +#define BP_PXP_CTRL_INTERLACED_INPUT 24 +#define BM_PXP_CTRL_INTERLACED_INPUT 0x03000000 +#define BF_PXP_CTRL_INTERLACED_INPUT(v) \ + (((v) << 24) & BM_PXP_CTRL_INTERLACED_INPUT) +#define BV_PXP_CTRL_INTERLACED_INPUT__PROGRESSIVE 0x0 +#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD0 0x2 +#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD1 0x3 +#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000 +#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0 +#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1 +#define BM_PXP_CTRL_ROT_POS 0x00400000 +#define BM_PXP_CTRL_IN_PLACE 0x00200000 +#define BP_PXP_CTRL_RSVD1 12 +#define BM_PXP_CTRL_RSVD1 0x001FF000 +#define BF_PXP_CTRL_RSVD1(v) \ + (((v) << 12) & BM_PXP_CTRL_RSVD1) +#define BM_PXP_CTRL_VFLIP 0x00000800 +#define BM_PXP_CTRL_HFLIP 0x00000400 +#define BP_PXP_CTRL_ROTATE 8 +#define BM_PXP_CTRL_ROTATE 0x00000300 +#define BF_PXP_CTRL_ROTATE(v) \ + (((v) << 8) & BM_PXP_CTRL_ROTATE) +#define BV_PXP_CTRL_ROTATE__ROT_0 0x0 +#define BV_PXP_CTRL_ROTATE__ROT_90 0x1 +#define BV_PXP_CTRL_ROTATE__ROT_180 0x2 +#define BV_PXP_CTRL_ROTATE__ROT_270 0x3 +#define BP_PXP_CTRL_RSVD0 5 +#define BM_PXP_CTRL_RSVD0 0x000000E0 +#define BF_PXP_CTRL_RSVD0(v) \ + (((v) << 5) & BM_PXP_CTRL_RSVD0) +#define BM_PXP_CTRL_ENABLE_LCD_HANDSHAKE 0x00000010 +#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008 +#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004 +#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002 +#define BM_PXP_CTRL_ENABLE 0x00000001 + +#define HW_PXP_STAT (0x00000010) +#define HW_PXP_STAT_SET (0x00000014) +#define HW_PXP_STAT_CLR (0x00000018) +#define HW_PXP_STAT_TOG (0x0000001c) + +#define BP_PXP_STAT_BLOCKX 24 +#define BM_PXP_STAT_BLOCKX 0xFF000000 +#define BF_PXP_STAT_BLOCKX(v) \ + (((v) << 24) & BM_PXP_STAT_BLOCKX) +#define BP_PXP_STAT_BLOCKY 16 +#define BM_PXP_STAT_BLOCKY 0x00FF0000 +#define BF_PXP_STAT_BLOCKY(v) \ + (((v) << 16) & BM_PXP_STAT_BLOCKY) +#define BP_PXP_STAT_RSVD2 9 +#define BM_PXP_STAT_RSVD2 0x0000FE00 +#define BF_PXP_STAT_RSVD2(v) \ + (((v) << 9) & BM_PXP_STAT_RSVD2) +#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100 +#define BP_PXP_STAT_AXI_ERROR_ID 4 +#define BM_PXP_STAT_AXI_ERROR_ID 0x000000F0 +#define BF_PXP_STAT_AXI_ERROR_ID(v) \ + (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID) +#define BM_PXP_STAT_NEXT_IRQ 0x00000008 +#define BM_PXP_STAT_AXI_READ_ERROR 0x00000004 +#define BM_PXP_STAT_AXI_WRITE_ERROR 0x00000002 +#define BM_PXP_STAT_IRQ 0x00000001 + +#define HW_PXP_OUT_CTRL (0x00000020) +#define HW_PXP_OUT_CTRL_SET (0x00000024) +#define HW_PXP_OUT_CTRL_CLR (0x00000028) +#define HW_PXP_OUT_CTRL_TOG (0x0000002c) + +#define BP_PXP_OUT_CTRL_ALPHA 24 +#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000 +#define BF_PXP_OUT_CTRL_ALPHA(v) \ + (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA) +#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000 +#define BP_PXP_OUT_CTRL_RSVD1 10 +#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00 +#define BF_PXP_OUT_CTRL_RSVD1(v) \ + (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1) +#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8 +#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300 +#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \ + (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT) +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0 +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1 +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2 +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3 +#define BP_PXP_OUT_CTRL_RSVD0 5 +#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0 +#define BF_PXP_OUT_CTRL_RSVD0(v) \ + (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0) +#define BP_PXP_OUT_CTRL_FORMAT 0 +#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F +#define BF_PXP_OUT_CTRL_FORMAT(v) \ + (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT) +#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0 +#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5 +#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8 +#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9 +#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE +#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10 +#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12 +#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13 +#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14 +#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15 +#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18 +#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19 +#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A +#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B + +#define HW_PXP_OUT_BUF (0x00000030) + +#define BP_PXP_OUT_BUF_ADDR 0 +#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF +#define BF_PXP_OUT_BUF_ADDR(v) (v) + +#define HW_PXP_OUT_BUF2 (0x00000040) + +#define BP_PXP_OUT_BUF2_ADDR 0 +#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF +#define BF_PXP_OUT_BUF2_ADDR(v) (v) + +#define HW_PXP_OUT_PITCH (0x00000050) + +#define BP_PXP_OUT_PITCH_RSVD 16 +#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000 +#define BF_PXP_OUT_PITCH_RSVD(v) \ + (((v) << 16) & BM_PXP_OUT_PITCH_RSVD) +#define BP_PXP_OUT_PITCH_PITCH 0 +#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF +#define BF_PXP_OUT_PITCH_PITCH(v) \ + (((v) << 0) & BM_PXP_OUT_PITCH_PITCH) + +#define HW_PXP_OUT_LRC (0x00000060) + +#define BP_PXP_OUT_LRC_RSVD1 30 +#define BM_PXP_OUT_LRC_RSVD1 0xC0000000 +#define BF_PXP_OUT_LRC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_LRC_RSVD1) +#define BP_PXP_OUT_LRC_X 16 +#define BM_PXP_OUT_LRC_X 0x3FFF0000 +#define BF_PXP_OUT_LRC_X(v) \ + (((v) << 16) & BM_PXP_OUT_LRC_X) +#define BP_PXP_OUT_LRC_RSVD0 14 +#define BM_PXP_OUT_LRC_RSVD0 0x0000C000 +#define BF_PXP_OUT_LRC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_LRC_RSVD0) +#define BP_PXP_OUT_LRC_Y 0 +#define BM_PXP_OUT_LRC_Y 0x00003FFF +#define BF_PXP_OUT_LRC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_LRC_Y) + +#define HW_PXP_OUT_PS_ULC (0x00000070) + +#define BP_PXP_OUT_PS_ULC_RSVD1 30 +#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000 +#define BF_PXP_OUT_PS_ULC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1) +#define BP_PXP_OUT_PS_ULC_X 16 +#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000 +#define BF_PXP_OUT_PS_ULC_X(v) \ + (((v) << 16) & BM_PXP_OUT_PS_ULC_X) +#define BP_PXP_OUT_PS_ULC_RSVD0 14 +#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000 +#define BF_PXP_OUT_PS_ULC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0) +#define BP_PXP_OUT_PS_ULC_Y 0 +#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF +#define BF_PXP_OUT_PS_ULC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_PS_ULC_Y) + +#define HW_PXP_OUT_PS_LRC (0x00000080) + +#define BP_PXP_OUT_PS_LRC_RSVD1 30 +#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000 +#define BF_PXP_OUT_PS_LRC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1) +#define BP_PXP_OUT_PS_LRC_X 16 +#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000 +#define BF_PXP_OUT_PS_LRC_X(v) \ + (((v) << 16) & BM_PXP_OUT_PS_LRC_X) +#define BP_PXP_OUT_PS_LRC_RSVD0 14 +#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000 +#define BF_PXP_OUT_PS_LRC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0) +#define BP_PXP_OUT_PS_LRC_Y 0 +#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF +#define BF_PXP_OUT_PS_LRC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_PS_LRC_Y) + +#define HW_PXP_OUT_AS_ULC (0x00000090) + +#define BP_PXP_OUT_AS_ULC_RSVD1 30 +#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000 +#define BF_PXP_OUT_AS_ULC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1) +#define BP_PXP_OUT_AS_ULC_X 16 +#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000 +#define BF_PXP_OUT_AS_ULC_X(v) \ + (((v) << 16) & BM_PXP_OUT_AS_ULC_X) +#define BP_PXP_OUT_AS_ULC_RSVD0 14 +#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000 +#define BF_PXP_OUT_AS_ULC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0) +#define BP_PXP_OUT_AS_ULC_Y 0 +#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF +#define BF_PXP_OUT_AS_ULC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_AS_ULC_Y) + +#define HW_PXP_OUT_AS_LRC (0x000000a0) + +#define BP_PXP_OUT_AS_LRC_RSVD1 30 +#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000 +#define BF_PXP_OUT_AS_LRC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1) +#define BP_PXP_OUT_AS_LRC_X 16 +#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000 +#define BF_PXP_OUT_AS_LRC_X(v) \ + (((v) << 16) & BM_PXP_OUT_AS_LRC_X) +#define BP_PXP_OUT_AS_LRC_RSVD0 14 +#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000 +#define BF_PXP_OUT_AS_LRC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0) +#define BP_PXP_OUT_AS_LRC_Y 0 +#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF +#define BF_PXP_OUT_AS_LRC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_AS_LRC_Y) + +#define HW_PXP_PS_CTRL (0x000000b0) +#define HW_PXP_PS_CTRL_SET (0x000000b4) +#define HW_PXP_PS_CTRL_CLR (0x000000b8) +#define HW_PXP_PS_CTRL_TOG (0x000000bc) + +#define BP_PXP_PS_CTRL_RSVD1 12 +#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000 +#define BF_PXP_PS_CTRL_RSVD1(v) \ + (((v) << 12) & BM_PXP_PS_CTRL_RSVD1) +#define BP_PXP_PS_CTRL_DECX 10 +#define BM_PXP_PS_CTRL_DECX 0x00000C00 +#define BF_PXP_PS_CTRL_DECX(v) \ + (((v) << 10) & BM_PXP_PS_CTRL_DECX) +#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0 +#define BV_PXP_PS_CTRL_DECX__DECX2 0x1 +#define BV_PXP_PS_CTRL_DECX__DECX4 0x2 +#define BV_PXP_PS_CTRL_DECX__DECX8 0x3 +#define BP_PXP_PS_CTRL_DECY 8 +#define BM_PXP_PS_CTRL_DECY 0x00000300 +#define BF_PXP_PS_CTRL_DECY(v) \ + (((v) << 8) & BM_PXP_PS_CTRL_DECY) +#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0 +#define BV_PXP_PS_CTRL_DECY__DECY2 0x1 +#define BV_PXP_PS_CTRL_DECY__DECY4 0x2 +#define BV_PXP_PS_CTRL_DECY__DECY8 0x3 +#define BP_PXP_PS_CTRL_RSVD0 5 +#define BM_PXP_PS_CTRL_RSVD0 0x000000E0 +#define BF_PXP_PS_CTRL_RSVD0(v) \ + (((v) << 5) & BM_PXP_PS_CTRL_RSVD0) +#define BP_PXP_PS_CTRL_FORMAT 0 +#define BM_PXP_PS_CTRL_FORMAT 0x0000001F +#define BF_PXP_PS_CTRL_FORMAT(v) \ + (((v) << 0) & BM_PXP_PS_CTRL_FORMAT) +#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE +#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10 +#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12 +#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13 +#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14 +#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15 +#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18 +#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19 +#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A +#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B +#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E +#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F + +#define HW_PXP_PS_BUF (0x000000c0) + +#define BP_PXP_PS_BUF_ADDR 0 +#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF +#define BF_PXP_PS_BUF_ADDR(v) (v) + +#define HW_PXP_PS_UBUF (0x000000d0) + +#define BP_PXP_PS_UBUF_ADDR 0 +#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF +#define BF_PXP_PS_UBUF_ADDR(v) (v) + +#define HW_PXP_PS_VBUF (0x000000e0) + +#define BP_PXP_PS_VBUF_ADDR 0 +#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF +#define BF_PXP_PS_VBUF_ADDR(v) (v) + +#define HW_PXP_PS_PITCH (0x000000f0) + +#define BP_PXP_PS_PITCH_RSVD 16 +#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000 +#define BF_PXP_PS_PITCH_RSVD(v) \ + (((v) << 16) & BM_PXP_PS_PITCH_RSVD) +#define BP_PXP_PS_PITCH_PITCH 0 +#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF +#define BF_PXP_PS_PITCH_PITCH(v) \ + (((v) << 0) & BM_PXP_PS_PITCH_PITCH) + +#define HW_PXP_PS_BACKGROUND (0x00000100) + +#define BP_PXP_PS_BACKGROUND_RSVD 24 +#define BM_PXP_PS_BACKGROUND_RSVD 0xFF000000 +#define BF_PXP_PS_BACKGROUND_RSVD(v) \ + (((v) << 24) & BM_PXP_PS_BACKGROUND_RSVD) +#define BP_PXP_PS_BACKGROUND_COLOR 0 +#define BM_PXP_PS_BACKGROUND_COLOR 0x00FFFFFF +#define BF_PXP_PS_BACKGROUND_COLOR(v) \ + (((v) << 0) & BM_PXP_PS_BACKGROUND_COLOR) + +#define HW_PXP_PS_SCALE (0x00000110) + +#define BM_PXP_PS_SCALE_RSVD2 0x80000000 +#define BP_PXP_PS_SCALE_YSCALE 16 +#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000 +#define BF_PXP_PS_SCALE_YSCALE(v) \ + (((v) << 16) & BM_PXP_PS_SCALE_YSCALE) +#define BM_PXP_PS_SCALE_RSVD1 0x00008000 +#define BP_PXP_PS_SCALE_XSCALE 0 +#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF +#define BF_PXP_PS_SCALE_XSCALE(v) \ + (((v) << 0) & BM_PXP_PS_SCALE_XSCALE) + +#define HW_PXP_PS_OFFSET (0x00000120) + +#define BP_PXP_PS_OFFSET_RSVD2 28 +#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000 +#define BF_PXP_PS_OFFSET_RSVD2(v) \ + (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2) +#define BP_PXP_PS_OFFSET_YOFFSET 16 +#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000 +#define BF_PXP_PS_OFFSET_YOFFSET(v) \ + (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET) +#define BP_PXP_PS_OFFSET_RSVD1 12 +#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000 +#define BF_PXP_PS_OFFSET_RSVD1(v) \ + (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1) +#define BP_PXP_PS_OFFSET_XOFFSET 0 +#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF +#define BF_PXP_PS_OFFSET_XOFFSET(v) \ + (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET) + +#define HW_PXP_PS_CLRKEYLOW (0x00000130) + +#define BP_PXP_PS_CLRKEYLOW_RSVD1 24 +#define BM_PXP_PS_CLRKEYLOW_RSVD1 0xFF000000 +#define BF_PXP_PS_CLRKEYLOW_RSVD1(v) \ + (((v) << 24) & BM_PXP_PS_CLRKEYLOW_RSVD1) +#define BP_PXP_PS_CLRKEYLOW_PIXEL 0 +#define BM_PXP_PS_CLRKEYLOW_PIXEL 0x00FFFFFF +#define BF_PXP_PS_CLRKEYLOW_PIXEL(v) \ + (((v) << 0) & BM_PXP_PS_CLRKEYLOW_PIXEL) + +#define HW_PXP_PS_CLRKEYHIGH (0x00000140) + +#define BP_PXP_PS_CLRKEYHIGH_RSVD1 24 +#define BM_PXP_PS_CLRKEYHIGH_RSVD1 0xFF000000 +#define BF_PXP_PS_CLRKEYHIGH_RSVD1(v) \ + (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_RSVD1) +#define BP_PXP_PS_CLRKEYHIGH_PIXEL 0 +#define BM_PXP_PS_CLRKEYHIGH_PIXEL 0x00FFFFFF +#define BF_PXP_PS_CLRKEYHIGH_PIXEL(v) \ + (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_PIXEL) + +#define HW_PXP_AS_CTRL (0x00000150) + +#define BP_PXP_AS_CTRL_RSVD1 21 +#define BM_PXP_AS_CTRL_RSVD1 0xFFE00000 +#define BF_PXP_AS_CTRL_RSVD1(v) \ + (((v) << 21) & BM_PXP_AS_CTRL_RSVD1) +#define BM_PXP_AS_CTRL_ALPHA_INVERT 0x00100000 +#define BP_PXP_AS_CTRL_ROP 16 +#define BM_PXP_AS_CTRL_ROP 0x000F0000 +#define BF_PXP_AS_CTRL_ROP(v) \ + (((v) << 16) & BM_PXP_AS_CTRL_ROP) +#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0 +#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1 +#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2 +#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3 +#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4 +#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5 +#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6 +#define BV_PXP_AS_CTRL_ROP__NOT 0x7 +#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8 +#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9 +#define BV_PXP_AS_CTRL_ROP__XORAS 0xA +#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB +#define BP_PXP_AS_CTRL_ALPHA 8 +#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00 +#define BF_PXP_AS_CTRL_ALPHA(v) \ + (((v) << 8) & BM_PXP_AS_CTRL_ALPHA) +#define BP_PXP_AS_CTRL_FORMAT 4 +#define BM_PXP_AS_CTRL_FORMAT 0x000000F0 +#define BF_PXP_AS_CTRL_FORMAT(v) \ + (((v) << 4) & BM_PXP_AS_CTRL_FORMAT) +#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0 +#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8 +#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9 +#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE +#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008 +#define BP_PXP_AS_CTRL_ALPHA_CTRL 1 +#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006 +#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \ + (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL) +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0 +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1 +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2 +#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3 +#define BM_PXP_AS_CTRL_RSVD0 0x00000001 + +#define HW_PXP_AS_BUF (0x00000160) + +#define BP_PXP_AS_BUF_ADDR 0 +#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF +#define BF_PXP_AS_BUF_ADDR(v) (v) + +#define HW_PXP_AS_PITCH (0x00000170) + +#define BP_PXP_AS_PITCH_RSVD 16 +#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000 +#define BF_PXP_AS_PITCH_RSVD(v) \ + (((v) << 16) & BM_PXP_AS_PITCH_RSVD) +#define BP_PXP_AS_PITCH_PITCH 0 +#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF +#define BF_PXP_AS_PITCH_PITCH(v) \ + (((v) << 0) & BM_PXP_AS_PITCH_PITCH) + +#define HW_PXP_AS_CLRKEYLOW (0x00000180) + +#define BP_PXP_AS_CLRKEYLOW_RSVD1 24 +#define BM_PXP_AS_CLRKEYLOW_RSVD1 0xFF000000 +#define BF_PXP_AS_CLRKEYLOW_RSVD1(v) \ + (((v) << 24) & BM_PXP_AS_CLRKEYLOW_RSVD1) +#define BP_PXP_AS_CLRKEYLOW_PIXEL 0 +#define BM_PXP_AS_CLRKEYLOW_PIXEL 0x00FFFFFF +#define BF_PXP_AS_CLRKEYLOW_PIXEL(v) \ + (((v) << 0) & BM_PXP_AS_CLRKEYLOW_PIXEL) + +#define HW_PXP_AS_CLRKEYHIGH (0x00000190) + +#define BP_PXP_AS_CLRKEYHIGH_RSVD1 24 +#define BM_PXP_AS_CLRKEYHIGH_RSVD1 0xFF000000 +#define BF_PXP_AS_CLRKEYHIGH_RSVD1(v) \ + (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_RSVD1) +#define BP_PXP_AS_CLRKEYHIGH_PIXEL 0 +#define BM_PXP_AS_CLRKEYHIGH_PIXEL 0x00FFFFFF +#define BF_PXP_AS_CLRKEYHIGH_PIXEL(v) \ + (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_PIXEL) + +#define HW_PXP_CSC1_COEF0 (0x000001a0) + +#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000 +#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000 +#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000 +#define BP_PXP_CSC1_COEF0_C0 18 +#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000 +#define BF_PXP_CSC1_COEF0_C0(v) \ + (((v) << 18) & BM_PXP_CSC1_COEF0_C0) +#define BP_PXP_CSC1_COEF0_UV_OFFSET 9 +#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00 +#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \ + (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET) +#define BP_PXP_CSC1_COEF0_Y_OFFSET 0 +#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF +#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \ + (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET) + +#define HW_PXP_CSC1_COEF1 (0x000001b0) + +#define BP_PXP_CSC1_COEF1_RSVD1 27 +#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000 +#define BF_PXP_CSC1_COEF1_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1) +#define BP_PXP_CSC1_COEF1_C1 16 +#define BM_PXP_CSC1_COEF1_C1 0x07FF0000 +#define BF_PXP_CSC1_COEF1_C1(v) \ + (((v) << 16) & BM_PXP_CSC1_COEF1_C1) +#define BP_PXP_CSC1_COEF1_RSVD0 11 +#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800 +#define BF_PXP_CSC1_COEF1_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0) +#define BP_PXP_CSC1_COEF1_C4 0 +#define BM_PXP_CSC1_COEF1_C4 0x000007FF +#define BF_PXP_CSC1_COEF1_C4(v) \ + (((v) << 0) & BM_PXP_CSC1_COEF1_C4) + +#define HW_PXP_CSC1_COEF2 (0x000001c0) + +#define BP_PXP_CSC1_COEF2_RSVD1 27 +#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000 +#define BF_PXP_CSC1_COEF2_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1) +#define BP_PXP_CSC1_COEF2_C2 16 +#define BM_PXP_CSC1_COEF2_C2 0x07FF0000 +#define BF_PXP_CSC1_COEF2_C2(v) \ + (((v) << 16) & BM_PXP_CSC1_COEF2_C2) +#define BP_PXP_CSC1_COEF2_RSVD0 11 +#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800 +#define BF_PXP_CSC1_COEF2_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0) +#define BP_PXP_CSC1_COEF2_C3 0 +#define BM_PXP_CSC1_COEF2_C3 0x000007FF +#define BF_PXP_CSC1_COEF2_C3(v) \ + (((v) << 0) & BM_PXP_CSC1_COEF2_C3) + +#define HW_PXP_CSC2_CTRL (0x000001d0) + +#define BP_PXP_CSC2_CTRL_RSVD 3 +#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8 +#define BF_PXP_CSC2_CTRL_RSVD(v) \ + (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD) +#define BP_PXP_CSC2_CTRL_CSC_MODE 1 +#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006 +#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \ + (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE) +#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0 +#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1 +#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2 +#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3 +#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001 + +#define HW_PXP_CSC2_COEF0 (0x000001e0) + +#define BP_PXP_CSC2_COEF0_RSVD1 27 +#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF0_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1) +#define BP_PXP_CSC2_COEF0_A2 16 +#define BM_PXP_CSC2_COEF0_A2 0x07FF0000 +#define BF_PXP_CSC2_COEF0_A2(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF0_A2) +#define BP_PXP_CSC2_COEF0_RSVD0 11 +#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF0_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0) +#define BP_PXP_CSC2_COEF0_A1 0 +#define BM_PXP_CSC2_COEF0_A1 0x000007FF +#define BF_PXP_CSC2_COEF0_A1(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF0_A1) + +#define HW_PXP_CSC2_COEF1 (0x000001f0) + +#define BP_PXP_CSC2_COEF1_RSVD1 27 +#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF1_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1) +#define BP_PXP_CSC2_COEF1_B1 16 +#define BM_PXP_CSC2_COEF1_B1 0x07FF0000 +#define BF_PXP_CSC2_COEF1_B1(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF1_B1) +#define BP_PXP_CSC2_COEF1_RSVD0 11 +#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF1_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0) +#define BP_PXP_CSC2_COEF1_A3 0 +#define BM_PXP_CSC2_COEF1_A3 0x000007FF +#define BF_PXP_CSC2_COEF1_A3(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF1_A3) + +#define HW_PXP_CSC2_COEF2 (0x00000200) + +#define BP_PXP_CSC2_COEF2_RSVD1 27 +#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF2_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1) +#define BP_PXP_CSC2_COEF2_B3 16 +#define BM_PXP_CSC2_COEF2_B3 0x07FF0000 +#define BF_PXP_CSC2_COEF2_B3(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF2_B3) +#define BP_PXP_CSC2_COEF2_RSVD0 11 +#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF2_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0) +#define BP_PXP_CSC2_COEF2_B2 0 +#define BM_PXP_CSC2_COEF2_B2 0x000007FF +#define BF_PXP_CSC2_COEF2_B2(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF2_B2) + +#define HW_PXP_CSC2_COEF3 (0x00000210) + +#define BP_PXP_CSC2_COEF3_RSVD1 27 +#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF3_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1) +#define BP_PXP_CSC2_COEF3_C2 16 +#define BM_PXP_CSC2_COEF3_C2 0x07FF0000 +#define BF_PXP_CSC2_COEF3_C2(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF3_C2) +#define BP_PXP_CSC2_COEF3_RSVD0 11 +#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF3_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0) +#define BP_PXP_CSC2_COEF3_C1 0 +#define BM_PXP_CSC2_COEF3_C1 0x000007FF +#define BF_PXP_CSC2_COEF3_C1(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF3_C1) + +#define HW_PXP_CSC2_COEF4 (0x00000220) + +#define BP_PXP_CSC2_COEF4_RSVD1 25 +#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000 +#define BF_PXP_CSC2_COEF4_RSVD1(v) \ + (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1) +#define BP_PXP_CSC2_COEF4_D1 16 +#define BM_PXP_CSC2_COEF4_D1 0x01FF0000 +#define BF_PXP_CSC2_COEF4_D1(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF4_D1) +#define BP_PXP_CSC2_COEF4_RSVD0 11 +#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF4_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0) +#define BP_PXP_CSC2_COEF4_C3 0 +#define BM_PXP_CSC2_COEF4_C3 0x000007FF +#define BF_PXP_CSC2_COEF4_C3(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF4_C3) + +#define HW_PXP_CSC2_COEF5 (0x00000230) + +#define BP_PXP_CSC2_COEF5_RSVD1 25 +#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000 +#define BF_PXP_CSC2_COEF5_RSVD1(v) \ + (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1) +#define BP_PXP_CSC2_COEF5_D3 16 +#define BM_PXP_CSC2_COEF5_D3 0x01FF0000 +#define BF_PXP_CSC2_COEF5_D3(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF5_D3) +#define BP_PXP_CSC2_COEF5_RSVD0 9 +#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00 +#define BF_PXP_CSC2_COEF5_RSVD0(v) \ + (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0) +#define BP_PXP_CSC2_COEF5_D2 0 +#define BM_PXP_CSC2_COEF5_D2 0x000001FF +#define BF_PXP_CSC2_COEF5_D2(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF5_D2) + +#define HW_PXP_LUT_CTRL (0x00000240) + +#define BM_PXP_LUT_CTRL_BYPASS 0x80000000 +#define BP_PXP_LUT_CTRL_RSVD3 26 +#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000 +#define BF_PXP_LUT_CTRL_RSVD3(v) \ + (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3) +#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24 +#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000 +#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \ + (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE) +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0 +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1 +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2 +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3 +#define BP_PXP_LUT_CTRL_RSVD2 18 +#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000 +#define BF_PXP_LUT_CTRL_RSVD2(v) \ + (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2) +#define BP_PXP_LUT_CTRL_OUT_MODE 16 +#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000 +#define BF_PXP_LUT_CTRL_OUT_MODE(v) \ + (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE) +#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0 +#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1 +#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2 +#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3 +#define BP_PXP_LUT_CTRL_RSVD1 11 +#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800 +#define BF_PXP_LUT_CTRL_RSVD1(v) \ + (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1) +#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400 +#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200 +#define BM_PXP_LUT_CTRL_INVALID 0x00000100 +#define BP_PXP_LUT_CTRL_RSVD0 1 +#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE +#define BF_PXP_LUT_CTRL_RSVD0(v) \ + (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0) +#define BM_PXP_LUT_CTRL_DMA_START 0x00000001 + +#define HW_PXP_LUT_ADDR (0x00000250) + +#define BM_PXP_LUT_ADDR_RSVD2 0x80000000 +#define BP_PXP_LUT_ADDR_NUM_BYTES 16 +#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000 +#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \ + (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES) +#define BP_PXP_LUT_ADDR_RSVD1 14 +#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000 +#define BF_PXP_LUT_ADDR_RSVD1(v) \ + (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1) +#define BP_PXP_LUT_ADDR_ADDR 0 +#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF +#define BF_PXP_LUT_ADDR_ADDR(v) \ + (((v) << 0) & BM_PXP_LUT_ADDR_ADDR) + +#define HW_PXP_LUT_DATA (0x00000260) + +#define BP_PXP_LUT_DATA_DATA 0 +#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF +#define BF_PXP_LUT_DATA_DATA(v) (v) + +#define HW_PXP_LUT_EXTMEM (0x00000270) + +#define BP_PXP_LUT_EXTMEM_ADDR 0 +#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF +#define BF_PXP_LUT_EXTMEM_ADDR(v) (v) + +#define HW_PXP_CFA (0x00000280) + +#define BP_PXP_CFA_DATA 0 +#define BM_PXP_CFA_DATA 0xFFFFFFFF +#define BF_PXP_CFA_DATA(v) (v) + +#define HW_PXP_HIST_CTRL (0x00000290) + +#define BP_PXP_HIST_CTRL_RSVD 6 +#define BM_PXP_HIST_CTRL_RSVD 0xFFFFFFC0 +#define BF_PXP_HIST_CTRL_RSVD(v) \ + (((v) << 6) & BM_PXP_HIST_CTRL_RSVD) +#define BP_PXP_HIST_CTRL_PANEL_MODE 4 +#define BM_PXP_HIST_CTRL_PANEL_MODE 0x00000030 +#define BF_PXP_HIST_CTRL_PANEL_MODE(v) \ + (((v) << 4) & BM_PXP_HIST_CTRL_PANEL_MODE) +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY4 0x0 +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY8 0x1 +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16 0x2 +#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY32 0x3 +#define BP_PXP_HIST_CTRL_STATUS 0 +#define BM_PXP_HIST_CTRL_STATUS 0x0000000F +#define BF_PXP_HIST_CTRL_STATUS(v) \ + (((v) << 0) & BM_PXP_HIST_CTRL_STATUS) + +#define HW_PXP_HIST2_PARAM (0x000002a0) + +#define BP_PXP_HIST2_PARAM_RSVD 16 +#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000 +#define BF_PXP_HIST2_PARAM_RSVD(v) \ + (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD) +#define BP_PXP_HIST2_PARAM_RSVD1 13 +#define BM_PXP_HIST2_PARAM_RSVD1 0x0000E000 +#define BF_PXP_HIST2_PARAM_RSVD1(v) \ + (((v) << 13) & BM_PXP_HIST2_PARAM_RSVD1) +#define BP_PXP_HIST2_PARAM_VALUE1 8 +#define BM_PXP_HIST2_PARAM_VALUE1 0x00001F00 +#define BF_PXP_HIST2_PARAM_VALUE1(v) \ + (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1) +#define BP_PXP_HIST2_PARAM_RSVD0 5 +#define BM_PXP_HIST2_PARAM_RSVD0 0x000000E0 +#define BF_PXP_HIST2_PARAM_RSVD0(v) \ + (((v) << 5) & BM_PXP_HIST2_PARAM_RSVD0) +#define BP_PXP_HIST2_PARAM_VALUE0 0 +#define BM_PXP_HIST2_PARAM_VALUE0 0x0000001F +#define BF_PXP_HIST2_PARAM_VALUE0(v) \ + (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0) + +#define HW_PXP_HIST4_PARAM (0x000002b0) + +#define BP_PXP_HIST4_PARAM_RSVD3 29 +#define BM_PXP_HIST4_PARAM_RSVD3 0xE0000000 +#define BF_PXP_HIST4_PARAM_RSVD3(v) \ + (((v) << 29) & BM_PXP_HIST4_PARAM_RSVD3) +#define BP_PXP_HIST4_PARAM_VALUE3 24 +#define BM_PXP_HIST4_PARAM_VALUE3 0x1F000000 +#define BF_PXP_HIST4_PARAM_VALUE3(v) \ + (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3) +#define BP_PXP_HIST4_PARAM_RSVD2 21 +#define BM_PXP_HIST4_PARAM_RSVD2 0x00E00000 +#define BF_PXP_HIST4_PARAM_RSVD2(v) \ + (((v) << 21) & BM_PXP_HIST4_PARAM_RSVD2) +#define BP_PXP_HIST4_PARAM_VALUE2 16 +#define BM_PXP_HIST4_PARAM_VALUE2 0x001F0000 +#define BF_PXP_HIST4_PARAM_VALUE2(v) \ + (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2) +#define BP_PXP_HIST4_PARAM_RSVD1 13 +#define BM_PXP_HIST4_PARAM_RSVD1 0x0000E000 +#define BF_PXP_HIST4_PARAM_RSVD1(v) \ + (((v) << 13) & BM_PXP_HIST4_PARAM_RSVD1) +#define BP_PXP_HIST4_PARAM_VALUE1 8 +#define BM_PXP_HIST4_PARAM_VALUE1 0x00001F00 +#define BF_PXP_HIST4_PARAM_VALUE1(v) \ + (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1) +#define BP_PXP_HIST4_PARAM_RSVD0 5 +#define BM_PXP_HIST4_PARAM_RSVD0 0x000000E0 +#define BF_PXP_HIST4_PARAM_RSVD0(v) \ + (((v) << 5) & BM_PXP_HIST4_PARAM_RSVD0) +#define BP_PXP_HIST4_PARAM_VALUE0 0 +#define BM_PXP_HIST4_PARAM_VALUE0 0x0000001F +#define BF_PXP_HIST4_PARAM_VALUE0(v) \ + (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0) + +#define HW_PXP_HIST8_PARAM0 (0x000002c0) + +#define BP_PXP_HIST8_PARAM0_RSVD3 29 +#define BM_PXP_HIST8_PARAM0_RSVD3 0xE0000000 +#define BF_PXP_HIST8_PARAM0_RSVD3(v) \ + (((v) << 29) & BM_PXP_HIST8_PARAM0_RSVD3) +#define BP_PXP_HIST8_PARAM0_VALUE3 24 +#define BM_PXP_HIST8_PARAM0_VALUE3 0x1F000000 +#define BF_PXP_HIST8_PARAM0_VALUE3(v) \ + (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3) +#define BP_PXP_HIST8_PARAM0_RSVD2 21 +#define BM_PXP_HIST8_PARAM0_RSVD2 0x00E00000 +#define BF_PXP_HIST8_PARAM0_RSVD2(v) \ + (((v) << 21) & BM_PXP_HIST8_PARAM0_RSVD2) +#define BP_PXP_HIST8_PARAM0_VALUE2 16 +#define BM_PXP_HIST8_PARAM0_VALUE2 0x001F0000 +#define BF_PXP_HIST8_PARAM0_VALUE2(v) \ + (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2) +#define BP_PXP_HIST8_PARAM0_RSVD1 13 +#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000E000 +#define BF_PXP_HIST8_PARAM0_RSVD1(v) \ + (((v) << 13) & BM_PXP_HIST8_PARAM0_RSVD1) +#define BP_PXP_HIST8_PARAM0_VALUE1 8 +#define BM_PXP_HIST8_PARAM0_VALUE1 0x00001F00 +#define BF_PXP_HIST8_PARAM0_VALUE1(v) \ + (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1) +#define BP_PXP_HIST8_PARAM0_RSVD0 5 +#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000E0 +#define BF_PXP_HIST8_PARAM0_RSVD0(v) \ + (((v) << 5) & BM_PXP_HIST8_PARAM0_RSVD0) +#define BP_PXP_HIST8_PARAM0_VALUE0 0 +#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000001F +#define BF_PXP_HIST8_PARAM0_VALUE0(v) \ + (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0) + +#define HW_PXP_HIST8_PARAM1 (0x000002d0) + +#define BP_PXP_HIST8_PARAM1_RSVD7 29 +#define BM_PXP_HIST8_PARAM1_RSVD7 0xE0000000 +#define BF_PXP_HIST8_PARAM1_RSVD7(v) \ + (((v) << 29) & BM_PXP_HIST8_PARAM1_RSVD7) +#define BP_PXP_HIST8_PARAM1_VALUE7 24 +#define BM_PXP_HIST8_PARAM1_VALUE7 0x1F000000 +#define BF_PXP_HIST8_PARAM1_VALUE7(v) \ + (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7) +#define BP_PXP_HIST8_PARAM1_RSVD6 21 +#define BM_PXP_HIST8_PARAM1_RSVD6 0x00E00000 +#define BF_PXP_HIST8_PARAM1_RSVD6(v) \ + (((v) << 21) & BM_PXP_HIST8_PARAM1_RSVD6) +#define BP_PXP_HIST8_PARAM1_VALUE6 16 +#define BM_PXP_HIST8_PARAM1_VALUE6 0x001F0000 +#define BF_PXP_HIST8_PARAM1_VALUE6(v) \ + (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6) +#define BP_PXP_HIST8_PARAM1_RSVD5 13 +#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000E000 +#define BF_PXP_HIST8_PARAM1_RSVD5(v) \ + (((v) << 13) & BM_PXP_HIST8_PARAM1_RSVD5) +#define BP_PXP_HIST8_PARAM1_VALUE5 8 +#define BM_PXP_HIST8_PARAM1_VALUE5 0x00001F00 +#define BF_PXP_HIST8_PARAM1_VALUE5(v) \ + (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5) +#define BP_PXP_HIST8_PARAM1_RSVD4 5 +#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000E0 +#define BF_PXP_HIST8_PARAM1_RSVD4(v) \ + (((v) << 5) & BM_PXP_HIST8_PARAM1_RSVD4) +#define BP_PXP_HIST8_PARAM1_VALUE4 0 +#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000001F +#define BF_PXP_HIST8_PARAM1_VALUE4(v) \ + (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4) + +#define HW_PXP_HIST16_PARAM0 (0x000002e0) + +#define BP_PXP_HIST16_PARAM0_RSVD3 29 +#define BM_PXP_HIST16_PARAM0_RSVD3 0xE0000000 +#define BF_PXP_HIST16_PARAM0_RSVD3(v) \ + (((v) << 29) & BM_PXP_HIST16_PARAM0_RSVD3) +#define BP_PXP_HIST16_PARAM0_VALUE3 24 +#define BM_PXP_HIST16_PARAM0_VALUE3 0x1F000000 +#define BF_PXP_HIST16_PARAM0_VALUE3(v) \ + (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3) +#define BP_PXP_HIST16_PARAM0_RSVD2 21 +#define BM_PXP_HIST16_PARAM0_RSVD2 0x00E00000 +#define BF_PXP_HIST16_PARAM0_RSVD2(v) \ + (((v) << 21) & BM_PXP_HIST16_PARAM0_RSVD2) +#define BP_PXP_HIST16_PARAM0_VALUE2 16 +#define BM_PXP_HIST16_PARAM0_VALUE2 0x001F0000 +#define BF_PXP_HIST16_PARAM0_VALUE2(v) \ + (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2) +#define BP_PXP_HIST16_PARAM0_RSVD1 13 +#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000E000 +#define BF_PXP_HIST16_PARAM0_RSVD1(v) \ + (((v) << 13) & BM_PXP_HIST16_PARAM0_RSVD1) +#define BP_PXP_HIST16_PARAM0_VALUE1 8 +#define BM_PXP_HIST16_PARAM0_VALUE1 0x00001F00 +#define BF_PXP_HIST16_PARAM0_VALUE1(v) \ + (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1) +#define BP_PXP_HIST16_PARAM0_RSVD0 5 +#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000E0 +#define BF_PXP_HIST16_PARAM0_RSVD0(v) \ + (((v) << 5) & BM_PXP_HIST16_PARAM0_RSVD0) +#define BP_PXP_HIST16_PARAM0_VALUE0 0 +#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000001F +#define BF_PXP_HIST16_PARAM0_VALUE0(v) \ + (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0) + +#define HW_PXP_HIST16_PARAM1 (0x000002f0) + +#define BP_PXP_HIST16_PARAM1_RSVD7 29 +#define BM_PXP_HIST16_PARAM1_RSVD7 0xE0000000 +#define BF_PXP_HIST16_PARAM1_RSVD7(v) \ + (((v) << 29) & BM_PXP_HIST16_PARAM1_RSVD7) +#define BP_PXP_HIST16_PARAM1_VALUE7 24 +#define BM_PXP_HIST16_PARAM1_VALUE7 0x1F000000 +#define BF_PXP_HIST16_PARAM1_VALUE7(v) \ + (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7) +#define BP_PXP_HIST16_PARAM1_RSVD6 21 +#define BM_PXP_HIST16_PARAM1_RSVD6 0x00E00000 +#define BF_PXP_HIST16_PARAM1_RSVD6(v) \ + (((v) << 21) & BM_PXP_HIST16_PARAM1_RSVD6) +#define BP_PXP_HIST16_PARAM1_VALUE6 16 +#define BM_PXP_HIST16_PARAM1_VALUE6 0x001F0000 +#define BF_PXP_HIST16_PARAM1_VALUE6(v) \ + (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6) +#define BP_PXP_HIST16_PARAM1_RSVD5 13 +#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000E000 +#define BF_PXP_HIST16_PARAM1_RSVD5(v) \ + (((v) << 13) & BM_PXP_HIST16_PARAM1_RSVD5) +#define BP_PXP_HIST16_PARAM1_VALUE5 8 +#define BM_PXP_HIST16_PARAM1_VALUE5 0x00001F00 +#define BF_PXP_HIST16_PARAM1_VALUE5(v) \ + (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5) +#define BP_PXP_HIST16_PARAM1_RSVD4 5 +#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000E0 +#define BF_PXP_HIST16_PARAM1_RSVD4(v) \ + (((v) << 5) & BM_PXP_HIST16_PARAM1_RSVD4) +#define BP_PXP_HIST16_PARAM1_VALUE4 0 +#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000001F +#define BF_PXP_HIST16_PARAM1_VALUE4(v) \ + (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4) + +#define HW_PXP_HIST16_PARAM2 (0x00000300) + +#define BP_PXP_HIST16_PARAM2_RSVD11 29 +#define BM_PXP_HIST16_PARAM2_RSVD11 0xE0000000 +#define BF_PXP_HIST16_PARAM2_RSVD11(v) \ + (((v) << 29) & BM_PXP_HIST16_PARAM2_RSVD11) +#define BP_PXP_HIST16_PARAM2_VALUE11 24 +#define BM_PXP_HIST16_PARAM2_VALUE11 0x1F000000 +#define BF_PXP_HIST16_PARAM2_VALUE11(v) \ + (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11) +#define BP_PXP_HIST16_PARAM2_RSVD10 21 +#define BM_PXP_HIST16_PARAM2_RSVD10 0x00E00000 +#define BF_PXP_HIST16_PARAM2_RSVD10(v) \ + (((v) << 21) & BM_PXP_HIST16_PARAM2_RSVD10) +#define BP_PXP_HIST16_PARAM2_VALUE10 16 +#define BM_PXP_HIST16_PARAM2_VALUE10 0x001F0000 +#define BF_PXP_HIST16_PARAM2_VALUE10(v) \ + (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10) +#define BP_PXP_HIST16_PARAM2_RSVD9 13 +#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000E000 +#define BF_PXP_HIST16_PARAM2_RSVD9(v) \ + (((v) << 13) & BM_PXP_HIST16_PARAM2_RSVD9) +#define BP_PXP_HIST16_PARAM2_VALUE9 8 +#define BM_PXP_HIST16_PARAM2_VALUE9 0x00001F00 +#define BF_PXP_HIST16_PARAM2_VALUE9(v) \ + (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9) +#define BP_PXP_HIST16_PARAM2_RSVD8 5 +#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000E0 +#define BF_PXP_HIST16_PARAM2_RSVD8(v) \ + (((v) << 5) & BM_PXP_HIST16_PARAM2_RSVD8) +#define BP_PXP_HIST16_PARAM2_VALUE8 0 +#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000001F +#define BF_PXP_HIST16_PARAM2_VALUE8(v) \ + (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8) + +#define HW_PXP_HIST16_PARAM3 (0x00000310) + +#define BP_PXP_HIST16_PARAM3_RSVD15 29 +#define BM_PXP_HIST16_PARAM3_RSVD15 0xE0000000 +#define BF_PXP_HIST16_PARAM3_RSVD15(v) \ + (((v) << 29) & BM_PXP_HIST16_PARAM3_RSVD15) +#define BP_PXP_HIST16_PARAM3_VALUE15 24 +#define BM_PXP_HIST16_PARAM3_VALUE15 0x1F000000 +#define BF_PXP_HIST16_PARAM3_VALUE15(v) \ + (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15) +#define BP_PXP_HIST16_PARAM3_RSVD14 21 +#define BM_PXP_HIST16_PARAM3_RSVD14 0x00E00000 +#define BF_PXP_HIST16_PARAM3_RSVD14(v) \ + (((v) << 21) & BM_PXP_HIST16_PARAM3_RSVD14) +#define BP_PXP_HIST16_PARAM3_VALUE14 16 +#define BM_PXP_HIST16_PARAM3_VALUE14 0x001F0000 +#define BF_PXP_HIST16_PARAM3_VALUE14(v) \ + (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14) +#define BP_PXP_HIST16_PARAM3_RSVD13 13 +#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000E000 +#define BF_PXP_HIST16_PARAM3_RSVD13(v) \ + (((v) << 13) & BM_PXP_HIST16_PARAM3_RSVD13) +#define BP_PXP_HIST16_PARAM3_VALUE13 8 +#define BM_PXP_HIST16_PARAM3_VALUE13 0x00001F00 +#define BF_PXP_HIST16_PARAM3_VALUE13(v) \ + (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13) +#define BP_PXP_HIST16_PARAM3_RSVD12 5 +#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000E0 +#define BF_PXP_HIST16_PARAM3_RSVD12(v) \ + (((v) << 5) & BM_PXP_HIST16_PARAM3_RSVD12) +#define BP_PXP_HIST16_PARAM3_VALUE12 0 +#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000001F +#define BF_PXP_HIST16_PARAM3_VALUE12(v) \ + (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12) + +#define HW_PXP_POWER (0x00000320) + +#define BP_PXP_POWER_CTRL 12 +#define BM_PXP_POWER_CTRL 0xFFFFF000 +#define BF_PXP_POWER_CTRL(v) \ + (((v) << 12) & BM_PXP_POWER_CTRL) +#define BP_PXP_POWER_ROT_MEM_LP_STATE 9 +#define BM_PXP_POWER_ROT_MEM_LP_STATE 0x00000E00 +#define BF_PXP_POWER_ROT_MEM_LP_STATE(v) \ + (((v) << 9) & BM_PXP_POWER_ROT_MEM_LP_STATE) +#define BV_PXP_POWER_ROT_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_ROT_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_ROT_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_ROT_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 6 +#define BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 0x000001C0 +#define BF_PXP_POWER_LUT_LP_STATE_WAY1_BANKN(v) \ + (((v) << 6) & BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN) +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__NONE 0x0 +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__LS 0x1 +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__DS 0x2 +#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__SD 0x4 +#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 3 +#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 0x00000038 +#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANKN(v) \ + (((v) << 3) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN) +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__NONE 0x0 +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__LS 0x1 +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__DS 0x2 +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__SD 0x4 +#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0 +#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0x00000007 +#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANK0(v) \ + (((v) << 0) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0) +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__NONE 0x0 +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__LS 0x1 +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__DS 0x2 +#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__SD 0x4 + +#define HW_PXP_NEXT (0x00000400) + +#define BP_PXP_NEXT_POINTER 2 +#define BM_PXP_NEXT_POINTER 0xFFFFFFFC +#define BF_PXP_NEXT_POINTER(v) \ + (((v) << 2) & BM_PXP_NEXT_POINTER) +#define BM_PXP_NEXT_RSVD 0x00000002 +#define BM_PXP_NEXT_ENABLED 0x00000001 + +#define HW_PXP_DEBUGCTRL (0x00000410) + +#define BP_PXP_DEBUGCTRL_RSVD 12 +#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000 +#define BF_PXP_DEBUGCTRL_RSVD(v) \ + (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD) +#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8 +#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00 +#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \ + (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT) +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8 +#define BP_PXP_DEBUGCTRL_SELECT 0 +#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF +#define BF_PXP_DEBUGCTRL_SELECT(v) \ + (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT) +#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0 +#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1 +#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2 +#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3 +#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4 +#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5 +#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6 +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7 +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8 +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14 + +#define HW_PXP_DEBUG (0x00000420) + +#define BP_PXP_DEBUG_DATA 0 +#define BM_PXP_DEBUG_DATA 0xFFFFFFFF +#define BF_PXP_DEBUG_DATA(v) (v) + +#define HW_PXP_VERSION (0x00000430) + +#define BP_PXP_VERSION_MAJOR 24 +#define BM_PXP_VERSION_MAJOR 0xFF000000 +#define BF_PXP_VERSION_MAJOR(v) \ + (((v) << 24) & BM_PXP_VERSION_MAJOR) +#define BP_PXP_VERSION_MINOR 16 +#define BM_PXP_VERSION_MINOR 0x00FF0000 +#define BF_PXP_VERSION_MINOR(v) \ + (((v) << 16) & BM_PXP_VERSION_MINOR) +#define BP_PXP_VERSION_STEP 0 +#define BM_PXP_VERSION_STEP 0x0000FFFF +#define BF_PXP_VERSION_STEP(v) \ + (((v) << 0) & BM_PXP_VERSION_STEP) +#endif /* __ARCH_ARM___PXP_H */ diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c index 121b328ad18b..0e0792b65a01 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c +++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -506,8 +506,6 @@ int prp_vf_sdc_select(void *private) int prp_vf_sdc_deselect(void *private) { cam_data *cam; - int err = 0; - err = prpvf_stop(private); if (private) { cam = (cam_data *) private; @@ -516,7 +514,7 @@ int prp_vf_sdc_deselect(void *private) cam->vf_enable_csi = NULL; cam->vf_disable_csi = NULL; } - return err; + return 0; } /*! diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c index 99fa4eaecfac..e6bf7910faef 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c +++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -472,8 +472,6 @@ int prp_vf_sdc_select_bg(void *private) int prp_vf_sdc_deselect_bg(void *private) { cam_data *cam = (cam_data *) private; - int err = 0; - err = prpvf_stop(private); if (cam) { cam->vf_start_sdc = NULL; @@ -481,7 +479,7 @@ int prp_vf_sdc_deselect_bg(void *private) cam->vf_enable_csi = NULL; cam->vf_disable_csi = NULL; } - return err; + return 0; } /*! diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c index 12c4a9f53927..75d35b116fe2 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c @@ -40,6 +40,8 @@ #include "ipu_prp_sw.h" #define init_MUTEX(sem) sema_init(sem, 1) +#define MXC_SENSOR_NUM 2 +static int sensor_index; static int video_nr = -1, local_buf_num; static cam_data *g_cam; @@ -453,12 +455,30 @@ static int mxc_streamoff(cam_data *cam) if (cam->capture_on == false) return 0; - if (cam->enc_disable) - err = cam->enc_disable(cam); - if (cam->enc_disable_csi) { - err = cam->enc_disable_csi(cam); - if (err != 0) - return err; + if (strcmp(mxc_capture_inputs[cam->current_input].name, + "CSI MEM") == 0) { + if (cam->enc_disable_csi) { + err = cam->enc_disable_csi(cam); + if (err != 0) + return err; + } + if (cam->enc_disable) { + err = cam->enc_disable(cam); + if (err != 0) + return err; + } + } else if (strcmp(mxc_capture_inputs[cam->current_input].name, + "CSI IC MEM") == 0) { + if (cam->enc_disable) { + err = cam->enc_disable(cam); + if (err != 0) + return err; + } + if (cam->enc_disable_csi) { + err = cam->enc_disable_csi(cam); + if (err != 0) + return err; + } } mxc_free_frames(cam); @@ -618,9 +638,11 @@ static int start_preview(cam_data *cam) if (err != 0) return err; - err = cam->vf_start_sdc(cam); - if (err != 0) - return err; + if (cam->vf_start_sdc) { + err = cam->vf_start_sdc(cam); + if (err != 0) + return err; + } if (cam->vf_enable_csi) err = cam->vf_enable_csi(cam); @@ -652,12 +674,11 @@ static int stop_preview(cam_data *cam) { int err = 0; - pr_debug("MVC: stop preview\n"); - - if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) - err = prp_vf_sdc_deselect(cam); - else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY) - err = prp_vf_sdc_deselect_bg(cam); + if (cam->vf_stop_sdc) { + err = cam->vf_stop_sdc(cam); + if (err != 0) + return err; + } if (cam->vf_disable_csi) { err = cam->vf_disable_csi(cam); @@ -665,6 +686,11 @@ static int stop_preview(cam_data *cam) return err; } + if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) + err = prp_vf_sdc_deselect(cam); + else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY) + err = prp_vf_sdc_deselect_bg(cam); + return err; } @@ -1009,8 +1035,9 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c) */ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c) { - int ret = 0; + int i, ret = 0; int tmp_rotation = IPU_ROTATE_NONE; + struct sensor_data *sensor_data; pr_debug("In MVC:mxc_v4l2_s_ctrl\n"); @@ -1179,6 +1206,25 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c) ipu_csi_flash_strobe(true); #endif break; + case V4L2_CID_MXC_SWITCH_CAM: + if (cam->sensor != cam->all_sensors[c->value]) { + /* power down other cameraes before enable new one */ + for (i = 0; i < sensor_index; i++) { + if (i != c->value) { + vidioc_int_dev_exit(cam->all_sensors[i]); + vidioc_int_s_power(cam->all_sensors[i], 0); + } + } + sensor_data = cam->all_sensors[c->value]->priv; + if (sensor_data->io_init) + sensor_data->io_init(); + cam->sensor = cam->all_sensors[c->value]; + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, true, true); + vidioc_int_s_power(cam->sensor, 1); + vidioc_int_dev_init(cam->sensor); + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, false, false); + } + break; default: pr_debug(" default case\n"); ret = -EINVAL; @@ -1655,7 +1701,7 @@ static int mxc_v4l_close(struct file *file) } /* for the case somebody hit the ctrl C */ - if (cam->overlay_pid == current->pid) { + if (cam->overlay_pid == current->pid && cam->overlay_on) { err = stop_preview(cam); cam->overlay_on = false; } @@ -2794,17 +2840,32 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) { cam_data *cam = slave->u.slave->master->priv; struct v4l2_format cam_fmt; + int i; pr_debug("In MVC: mxc_v4l2_master_attach\n"); pr_debug(" slave.name = %s\n", slave->name); pr_debug(" master.name = %s\n", slave->u.slave->master->name); - cam->sensor = slave; if (slave == NULL) { pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); return -1; } + cam->sensor = slave; + + if (sensor_index < MXC_SENSOR_NUM) { + cam->all_sensors[sensor_index] = slave; + sensor_index++; + } else { + pr_err("ERROR: v4l2 capture: slave number exceeds the maximum.\n"); + return -1; + } + + for (i = 0; i < sensor_index - 1; i++) { + vidioc_int_dev_exit(cam->all_sensors[i]); + vidioc_int_s_power(cam->all_sensors[i], 0); + } + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, true, true); vidioc_int_s_power(cam->sensor, 1); vidioc_int_dev_init(slave); diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h index 350d4bd7f59c..5b7b0bfe7706 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -194,10 +194,35 @@ typedef struct _cam_data { /* camera sensor interface */ struct camera_sensor *cam_sensor; /* old version */ + struct v4l2_int_device *all_sensors[2]; struct v4l2_int_device *sensor; void *ipu; } cam_data; +struct sensor_data { + const struct ov5642_platform_data *platform_data; + struct v4l2_int_device *v4l2_int_device; + struct i2c_client *i2c_client; + struct v4l2_pix_format pix; + struct v4l2_captureparm streamcap; + bool on; + + /* control settings */ + int brightness; + int hue; + int contrast; + int saturation; + int red; + int green; + int blue; + int ae_mode; + + u32 mclk; + int csi; + + void (*io_init)(void); +}; + #if defined(CONFIG_MXC_IPU_V1) || defined(CONFIG_VIDEO_MXC_EMMA_CAMERA) \ || defined(CONFIG_VIDEO_MXC_CSI_CAMERA_MODULE) \ || defined(CONFIG_VIDEO_MXC_CSI_CAMERA) diff --git a/drivers/media/video/mxc/capture/ov3640.c b/drivers/media/video/mxc/capture/ov3640.c index 570f50bae161..b1d1abb884d9 100644 --- a/drivers/media/video/mxc/capture/ov3640.c +++ b/drivers/media/video/mxc/capture/ov3640.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -72,27 +72,7 @@ struct ov3640_mode_info { /*! * Maintains the information on the current state of the sesor. */ -struct sensor { - const struct ov3640_platform_data *platform_data; - struct v4l2_int_device *v4l2_int_device; - struct i2c_client *i2c_client; - struct v4l2_pix_format pix; - struct v4l2_captureparm streamcap; - bool on; - - /* control settings */ - int brightness; - int hue; - int contrast; - int saturation; - int red; - int green; - int blue; - int ae_mode; - - u32 mclk; - int csi; -} ov3640_data; +struct sensor_data ov3640_data; static struct reg_value ov3640_setting_15fps_QXGA_2048_1536[] = { #if 0 @@ -1005,7 +985,7 @@ static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) */ static int ioctl_s_power(struct v4l2_int_device *s, int on) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; if (on && !sensor->on) { if (io_regulator) @@ -1033,6 +1013,9 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) regulator_disable(io_regulator); if (gpo_regulator) regulator_disable(gpo_regulator); + + if (camera_plat->pwdn) + camera_plat->pwdn(1); } sensor->on = on; @@ -1049,7 +1032,7 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) */ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_captureparm *cparm = &a->parm.capture; int ret = 0; @@ -1094,7 +1077,7 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; u32 tgt_fps; /* target frames per secound */ enum ov3640_frame_rate frame_rate; @@ -1178,7 +1161,7 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; f->fmt.pix = sensor->pix; @@ -1357,7 +1340,7 @@ static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, */ static int ioctl_dev_init(struct v4l2_int_device *s) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; u32 tgt_xclk; /* target xclk */ u32 tgt_fps; /* target frames per secound */ enum ov3640_frame_rate frame_rate; @@ -1460,6 +1443,7 @@ static int ov3640_probe(struct i2c_client *client, ov3640_data.mclk = 24000000; /* 6 - 54 MHz, typical 24MHz */ ov3640_data.mclk = plat_data->mclk; ov3640_data.csi = plat_data->csi; + ov3640_data.io_init = plat_data->io_init; ov3640_data.i2c_client = client; ov3640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY; @@ -1547,9 +1531,6 @@ static int ov3640_probe(struct i2c_client *client, if (plat_data->io_init) plat_data->io_init(); - if (plat_data->pwdn) - plat_data->pwdn(0); - camera_plat = plat_data; ov3640_int_device.priv = &ov3640_data; diff --git a/drivers/media/video/mxc/capture/ov5640.c b/drivers/media/video/mxc/capture/ov5640.c index 64ee178f2e58..f9087499b5f1 100644 --- a/drivers/media/video/mxc/capture/ov5640.c +++ b/drivers/media/video/mxc/capture/ov5640.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -78,27 +78,7 @@ struct ov5640_mode_info { /*! * Maintains the information on the current state of the sesor. */ -struct sensor { - const struct ov5640_platform_data *platform_data; - struct v4l2_int_device *v4l2_int_device; - struct i2c_client *i2c_client; - struct v4l2_pix_format pix; - struct v4l2_captureparm streamcap; - bool on; - - /* control settings */ - int brightness; - int hue; - int contrast; - int saturation; - int red; - int green; - int blue; - int ae_mode; - - u32 mclk; - int csi; -} ov5640_data; +struct sensor_data ov5640_data; static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = { {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3008, 0x42, 0, 0}, @@ -960,7 +940,7 @@ static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) */ static int ioctl_s_power(struct v4l2_int_device *s, int on) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; if (on && !sensor->on) { if (io_regulator) @@ -988,7 +968,10 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) regulator_disable(io_regulator); if (gpo_regulator) regulator_disable(gpo_regulator); - } + + if (camera_plat->pwdn) + camera_plat->pwdn(1); +} sensor->on = on; @@ -1004,7 +987,7 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) */ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_captureparm *cparm = &a->parm.capture; int ret = 0; @@ -1049,7 +1032,7 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; u32 tgt_fps; /* target frames per secound */ enum ov5640_frame_rate frame_rate; @@ -1133,7 +1116,7 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; f->fmt.pix = sensor->pix; @@ -1312,7 +1295,7 @@ static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, */ static int ioctl_dev_init(struct v4l2_int_device *s) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; u32 tgt_xclk; /* target xclk */ u32 tgt_fps; /* target frames per secound */ enum ov5640_frame_rate frame_rate; @@ -1415,6 +1398,7 @@ static int ov5640_probe(struct i2c_client *client, ov5640_data.mclk = 24000000; /* 6 - 54 MHz, typical 24MHz */ ov5640_data.mclk = plat_data->mclk; ov5640_data.csi = plat_data->csi; + ov5640_data.io_init = plat_data->io_init; ov5640_data.i2c_client = client; ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; @@ -1484,9 +1468,6 @@ static int ov5640_probe(struct i2c_client *client, if (plat_data->io_init) plat_data->io_init(); - if (plat_data->pwdn) - plat_data->pwdn(0); - camera_plat = plat_data; ov5640_int_device.priv = &ov5640_data; diff --git a/drivers/media/video/mxc/capture/ov5640_mipi.c b/drivers/media/video/mxc/capture/ov5640_mipi.c index 7b678f7fa0e4..bd47d9d45413 100644 --- a/drivers/media/video/mxc/capture/ov5640_mipi.c +++ b/drivers/media/video/mxc/capture/ov5640_mipi.c @@ -80,27 +80,7 @@ struct ov5640_mode_info { /*! * Maintains the information on the current state of the sesor. */ -struct sensor { - const struct ov5640_platform_data *platform_data; - struct v4l2_int_device *v4l2_int_device; - struct i2c_client *i2c_client; - struct v4l2_pix_format pix; - struct v4l2_captureparm streamcap; - bool on; - - /* control settings */ - int brightness; - int hue; - int contrast; - int saturation; - int red; - int green; - int blue; - int ae_mode; - - u32 mclk; - int csi; -} ov5640_data; +struct sensor_data ov5640_data; static struct reg_value ov5640_init_setting_30fps_VGA[] = { {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, @@ -773,7 +753,7 @@ static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) */ static int ioctl_s_power(struct v4l2_int_device *s, int on) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; if (on && !sensor->on) { if (io_regulator) @@ -801,6 +781,9 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) regulator_disable(io_regulator); if (gpo_regulator) regulator_disable(gpo_regulator); + + if (camera_plat->pwdn) + camera_plat->pwdn(1); } sensor->on = on; @@ -817,7 +800,7 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) */ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_captureparm *cparm = &a->parm.capture; int ret = 0; @@ -862,7 +845,7 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; u32 tgt_fps; /* target frames per secound */ enum ov5640_frame_rate frame_rate; @@ -946,7 +929,7 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; f->fmt.pix = sensor->pix; @@ -1125,7 +1108,7 @@ static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, */ static int ioctl_dev_init(struct v4l2_int_device *s) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; u32 tgt_xclk; /* target xclk */ u32 tgt_fps; /* target frames per secound */ int ret; @@ -1250,6 +1233,7 @@ static int ov5640_probe(struct i2c_client *client, ov5640_data.mclk = 24000000; /* 6 - 54 MHz, typical 24MHz */ ov5640_data.mclk = plat_data->mclk; ov5640_data.csi = plat_data->csi; + ov5640_data.io_init = plat_data->io_init; ov5640_data.i2c_client = client; ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY; @@ -1319,9 +1303,6 @@ static int ov5640_probe(struct i2c_client *client, if (plat_data->io_init) plat_data->io_init(); - if (plat_data->pwdn) - plat_data->pwdn(0); - camera_plat = plat_data; ov5640_int_device.priv = &ov5640_data; diff --git a/drivers/media/video/mxc/capture/ov5642.c b/drivers/media/video/mxc/capture/ov5642.c index 206c96b5ebc7..38f22e7a942a 100644 --- a/drivers/media/video/mxc/capture/ov5642.c +++ b/drivers/media/video/mxc/capture/ov5642.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -79,27 +79,7 @@ struct ov5642_mode_info { /*! * Maintains the information on the current state of the sesor. */ -struct sensor { - const struct ov5642_platform_data *platform_data; - struct v4l2_int_device *v4l2_int_device; - struct i2c_client *i2c_client; - struct v4l2_pix_format pix; - struct v4l2_captureparm streamcap; - bool on; - - /* control settings */ - int brightness; - int hue; - int contrast; - int saturation; - int red; - int green; - int blue; - int ae_mode; - - u32 mclk; - int csi; -} ov5642_data; +struct sensor_data ov5642_data; static struct reg_value ov5642_rotate_none_VGA[] = { {0x3818, 0xc1, 0x00, 0x00}, {0x3621, 0x87, 0x00, 0x00}, @@ -2155,7 +2135,7 @@ static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) */ static int ioctl_s_power(struct v4l2_int_device *s, int on) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; if (on && !sensor->on) { if (io_regulator) @@ -2183,6 +2163,9 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) regulator_disable(io_regulator); if (gpo_regulator) regulator_disable(gpo_regulator); + + if (camera_plat->pwdn) + camera_plat->pwdn(1); } sensor->on = on; @@ -2199,7 +2182,7 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) */ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_captureparm *cparm = &a->parm.capture; int ret = 0; @@ -2244,7 +2227,7 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; u32 tgt_fps; /* target frames per secound */ enum ov5642_frame_rate frame_rate; @@ -2326,7 +2309,7 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) */ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) { - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; f->fmt.pix = sensor->pix; @@ -2387,7 +2370,7 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) { int retval = 0; - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; __u32 captureMode = sensor->streamcap.capturemode; pr_debug("In ov5642:ioctl_s_ctrl %d\n", @@ -2561,7 +2544,7 @@ static int ioctl_dev_init(struct v4l2_int_device *s) u8 RegVal = 0; int retval = 0; - struct sensor *sensor = s->priv; + struct sensor_data *sensor = s->priv; u32 tgt_xclk; /* target xclk */ u32 tgt_fps; /* target frames per secound */ enum ov5642_frame_rate frame_rate; @@ -2689,6 +2672,7 @@ static int ov5642_probe(struct i2c_client *client, ov5642_data.mclk = 24000000; /* 6 - 54 MHz, typical 24MHz */ ov5642_data.mclk = plat_data->mclk; ov5642_data.csi = plat_data->csi; + ov5642_data.io_init = plat_data->io_init; ov5642_data.i2c_client = client; ov5642_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; @@ -2758,9 +2742,6 @@ static int ov5642_probe(struct i2c_client *client, if (plat_data->io_init) plat_data->io_init(); - if (plat_data->pwdn) - plat_data->pwdn(0); - camera_plat = plat_data; ov5642_int_device.priv = &ov5642_data; diff --git a/drivers/media/video/mxc/capture/sensor_clock.c b/drivers/media/video/mxc/capture/sensor_clock.c index 2159836699f3..2e758d177ffc 100644 --- a/drivers/media/video/mxc/capture/sensor_clock.c +++ b/drivers/media/video/mxc/capture/sensor_clock.c @@ -71,7 +71,7 @@ void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi) pr_err("invalid csi num %d\n", csi); return; } - } else if (cpu_is_mx6q()) { + } else if (cpu_is_mx6q() || cpu_is_mx6dl()) { if (csi == 0) { if (machine_is_mx6q_sabrelite()) mclk = "clko2_clk"; diff --git a/drivers/mfd/mxc-hdmi-core.c b/drivers/mfd/mxc-hdmi-core.c index 5f86788750a1..1aa92a01c40c 100644 --- a/drivers/mfd/mxc-hdmi-core.c +++ b/drivers/mfd/mxc-hdmi-core.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ #include <mach/clock.h> #include <mach/mxc_hdmi.h> #include <mach/ipu-v3.h> +#include <mach/mxc_edid.h> #include "../mxc/ipu3/ipu_prv.h" #include <linux/mfd/mxc-hdmi-core.h> #include <linux/fsl_devices.h> @@ -48,18 +49,20 @@ struct mxc_hdmi_data { }; static unsigned long hdmi_base; -struct clk *isfr_clk; -struct clk *iahb_clk; +static struct clk *isfr_clk; +static struct clk *iahb_clk; static unsigned int irq_enable_cnt; -spinlock_t irq_spinlock; -bool irq_initialized; -bool irq_enabled; -unsigned int sample_rate; -unsigned long pixel_clk_rate; -struct clk *pixel_clk; -int hdmi_ratio; +static spinlock_t irq_spinlock; +static spinlock_t edid_spinlock; +static bool irq_initialized; +static bool irq_enabled; +static unsigned int sample_rate; +static unsigned long pixel_clk_rate; +static struct clk *pixel_clk; +static int hdmi_ratio; int mxc_hdmi_ipu_id; int mxc_hdmi_disp_id; +static struct mxc_edid_cfg hdmi_core_edid_cfg; u8 hdmi_readb(unsigned int reg) { @@ -466,6 +469,24 @@ void hdmi_set_sample_rate(unsigned int rate) hdmi_set_clk_regenerator(); } +void hdmi_set_edid_cfg(struct mxc_edid_cfg *cfg) +{ + unsigned long flags; + + spin_lock_irqsave(&edid_spinlock, flags); + memcpy(&hdmi_core_edid_cfg, cfg, sizeof(struct mxc_edid_cfg)); + spin_unlock_irqrestore(&edid_spinlock, flags); +} + +void hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg) +{ + unsigned long flags; + + spin_lock_irqsave(&edid_spinlock, flags); + memcpy(cfg, &hdmi_core_edid_cfg, sizeof(struct mxc_edid_cfg)); + spin_unlock_irqrestore(&edid_spinlock, flags); +} + static int mxc_hdmi_core_probe(struct platform_device *pdev) { struct fsl_mxc_hdmi_core_platform_data *pdata = pdev->dev.platform_data; @@ -497,6 +518,7 @@ static int mxc_hdmi_core_probe(struct platform_device *pdev) irq_initialized = false; irq_enabled = true; spin_lock_init(&irq_spinlock); + spin_lock_init(&edid_spinlock); isfr_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_isfr_clk"); if (IS_ERR(isfr_clk)) { diff --git a/drivers/misc/mxs-perfmon.c b/drivers/misc/mxs-perfmon.c index 5986e1ca9508..c2ac287a3cb7 100644 --- a/drivers/misc/mxs-perfmon.c +++ b/drivers/misc/mxs-perfmon.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -171,7 +171,7 @@ perfmon_show(struct device *dev, struct device_attribute *attr, char *buf) if (pdata->plt_init) pdata->plt_init(); - mxs_reset_block((void *)pd->base, true); + mxs_reset_block((void *)pd->base); pd->initial = true; } @@ -234,7 +234,7 @@ perfmon_store(struct device *dev, struct device_attribute *attr, if (pdata->plt_init) pdata->plt_init(); - mxs_reset_block((void *)pd->base, true); + mxs_reset_block((void *)pd->base); pd->initial = true; } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 625bd9e46d70..efb3e7c36b88 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1464,8 +1464,8 @@ static void mmc_blk_remove(struct mmc_card *card) #endif } -#ifdef CONFIG_PM -static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int mmc_blk_suspend(struct mmc_card *card) { struct mmc_blk_data *part_md; struct mmc_blk_data *md = mmc_get_drvdata(card); diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index e07d6c90caec..d4a50128fe03 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -120,7 +120,8 @@ static int mmc_bus_remove(struct device *dev) return 0; } -static int mmc_bus_pm_suspend(struct device *dev) +#ifdef CONFIG_PM_SLEEP +static int mmc_bus_suspend(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); @@ -128,11 +129,11 @@ static int mmc_bus_pm_suspend(struct device *dev) pm_message_t state = { PM_EVENT_SUSPEND }; if (dev->driver && drv->suspend) - ret = drv->suspend(card, state); + ret = drv->suspend(card); return ret; } -static int mmc_bus_pm_resume(struct device *dev) +static int mmc_bus_resume(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); @@ -142,6 +143,7 @@ static int mmc_bus_pm_resume(struct device *dev) ret = drv->resume(card); return ret; } +#endif #ifdef CONFIG_PM_RUNTIME static int mmc_runtime_suspend(struct device *dev) @@ -165,8 +167,9 @@ static int mmc_runtime_idle(struct device *dev) #endif /* CONFIG_PM_RUNTIME */ static const struct dev_pm_ops mmc_bus_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_pm_suspend, mmc_bus_pm_resume) - SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, mmc_runtime_idle) + SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) + SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, +mmc_runtime_idle) }; static struct bus_type mmc_bus_type = { diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 845ce7c533b9..b11876c2c2df 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -397,6 +397,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); if (err) return err; + mdelay(1); /* Must check status to be sure of no errors */ do { diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5a7d8f5d41e0..28eb9d664fd8 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -477,17 +477,17 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) bus_speed = UHS_SDR104_BUS_SPEED; timing = MMC_TIMING_UHS_SDR104; card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; - } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && - (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { - bus_speed = UHS_DDR50_BUS_SPEED; - timing = MMC_TIMING_UHS_DDR50; - card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50)) { bus_speed = UHS_SDR50_BUS_SPEED; timing = MMC_TIMING_UHS_SDR50; card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; + } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && + (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { + bus_speed = UHS_DDR50_BUS_SPEED; + timing = MMC_TIMING_UHS_DDR50; + card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { @@ -733,8 +733,9 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr) * If the host supports one of UHS-I modes, request the card * to switch to 1.8V signaling level. */ - if (host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + if ((host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)) + && (host->ocr_avail_sd & MMC_VDD_165_195)) ocr |= SD_OCR_S18R; /* If the host can supply more than 150mA, XPC should be set to 1. */ diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 5aec0bfe6fd6..fc9b25b5e48d 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -31,17 +31,21 @@ /* VENDOR SPEC register */ #define SDHCI_VENDOR_SPEC 0xC0 #define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 -#define SDHCI_MIX_CTRL 0x48 -#define SDHCI_TUNE_CTRL_STATUS 0x68 -#define SDHCI_TUNE_CTRL_STEP 0x1 -#define SDHCI_TUNE_CTRL_MIN 0x0 -#define SDHCI_TUNE_CTRL_MAX ((1 << 7) - 1) #define SDHCI_MIX_CTRL_EXE_TUNE (1 << 22) #define SDHCI_MIX_CTRL_SMPCLK_SEL (1 << 23) -#define SDHCI_MIX_CTRL_AUTOTUNE_EN (1 << 24) +#define SDHCI_MIX_CTRL_AUTO_TUNE (1 << 24) #define SDHCI_MIX_CTRL_FBCLK_SEL (1 << 25) +#define SDHCI_DLL_CTRL 0x60 +#define SDHCI_DLL_OVERRIDE_OFFSET 0x9 +#define SDHCI_DLL_OVERRIDE_EN_OFFSET 0x8 + +#define SDHCI_TUNE_CTRL_STATUS 0x68 +#define SDHCI_TUNE_CTRL_STEP 0x1 +#define SDHCI_TUNE_CTRL_MIN 0x0 +#define SDHCI_TUNE_CTRL_MAX ((1 << 7) - 1) + #define SDHCI_VENDOR_SPEC_VSELECT (1 << 1) #define SDHCI_VENDOR_SPEC_FRC_SDCLK_ON (1 << 8) @@ -52,6 +56,14 @@ #define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0) #define SDHCI_CTRL_D3CD 0x08 + +#define SDHCI_PROT_CTRL_DMASEL_MASK (3 << 8) +#define SDHCI_PROT_CTRL_DTW (3 << 1) +#define SDHCI_PROT_CTRL_8BIT (2 << 1) +#define SDHCI_PROT_CTRL_4BIT (1 << 1) +#define SDHCI_PROT_CTRL_1BIT (0 << 1) +#define SDHCI_PROT_CTRL_LCTL (1 << 0) + /* * The CMDTYPE of the CMD register (offset 0xE) should be set to * "11" when the STOP CMD12 is issued on imx53 to abort one @@ -88,6 +100,21 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) /* fake CARD_PRESENT flag on mx25/35 */ u32 val = readl(host->ioaddr + reg); + /* + * mx6q: SDHCI_PRESENT_STATE bit 16, CINST is not functional on SD3. + * So move the section up, and check GPIO for card presence again in + * the following block. + */ + if (reg == SDHCI_PRESENT_STATE && cpu_is_mx6()) { + u32 fsl_prss = readl(host->ioaddr + SDHCI_PRESENT_STATE); + /* save the least 20 bits */ + val |= fsl_prss & 0x000FFFFF; + /* move dat[0-3] line signal bits */ + val |= (fsl_prss & 0x0F000000) >> 4; + /* move cmd line signal bits */ + val |= (fsl_prss & 0x00800000) << 1; + } + if (unlikely((reg == SDHCI_PRESENT_STATE) && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) { struct esdhc_platform_data *boarddata = @@ -102,9 +129,10 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) val |= SDHCI_CARD_PRESENT; } - if (reg == SDHCI_INT_STATUS && cpu_is_mx6q()) { + if (reg == SDHCI_INT_STATUS && cpu_is_mx6() + && mx6q_revision() == IMX_CHIP_REVISION_1_0) { /* - * on mx6q, there is low possibility that + * on mx6q TO1.0, there is low possibility that * DATA END interrupt comes ealier than DMA * END interrupt which is conflict with standard * host controller spec. In this case, read the @@ -113,13 +141,13 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) if ((val & SDHCI_INT_DATA_END) && \ !(val & SDHCI_INT_DMA_END)) val = readl(host->ioaddr + reg); - } else if (reg == SDHCI_CAPABILITIES_1 && cpu_is_mx6q()) { + } else if (reg == SDHCI_CAPABILITIES_1 && cpu_is_mx6()) { /* * on mx6q, no cap_1 available, fake one. */ val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 | \ SDHCI_SUPPORT_SDR50; - } else if (reg == SDHCI_MAX_CURRENT && cpu_is_mx6q()) { + } else if (reg == SDHCI_MAX_CURRENT && cpu_is_mx6()) { /* * on mx6q, no max current available, fake one. */ @@ -129,16 +157,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) val |= 0xFF << SDHCI_MAX_CURRENT_180_SHIFT; } - if (reg == SDHCI_PRESENT_STATE && cpu_is_mx6q()) { - u32 fsl_prss = readl(host->ioaddr + SDHCI_PRESENT_STATE); - /* save the least 20 bits */ - val = fsl_prss & 0x000FFFFF; - /* move dat[0-3] line signal bits */ - val |= (fsl_prss & 0x0F000000) >> 4; - /* move cmd line signal bits */ - val |= (fsl_prss & 0x00800000) << 1; - } - return val; } @@ -157,10 +175,11 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) val &= ~(SDHCI_INT_CARD_REMOVE | \ SDHCI_INT_CARD_INSERT); - if (!(val & SDHCI_INT_CARD_INT) && cpu_is_mx6q()) + if (!(val & SDHCI_INT_CARD_INT) && cpu_is_mx6() + && mx6q_revision() == IMX_CHIP_REVISION_1_0) /* * write 1 to clear card interrupt status bit - * (only applied to mx6q) + * (only applied to mx6q TO1.0) * uSDHC used for mx6q has such problem which is * not consistant with standard host controller * definition. @@ -170,7 +189,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) writel(SDHCI_INT_CARD_INT, \ host->ioaddr + SDHCI_INT_STATUS); - if (val & SDHCI_INT_CARD_INT && (!cpu_is_mx6q())) { + if (val & SDHCI_INT_CARD_INT && !cpu_is_mx6()) { /* * clear D3CD bit and set D3CD bit to avoid * losing card interrupt @@ -238,19 +257,21 @@ void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) { u32 reg; - reg = sdhci_readl(host, SDHCI_MIX_CTRL); + reg = readl(host->ioaddr + SDHCI_MIX_CTRL); reg |= SDHCI_MIX_CTRL_EXE_TUNE | \ SDHCI_MIX_CTRL_SMPCLK_SEL | \ - SDHCI_MIX_CTRL_AUTOTUNE_EN | \ + SDHCI_MIX_CTRL_AUTO_TUNE | \ SDHCI_MIX_CTRL_FBCLK_SEL; - sdhci_writel(host, reg, SDHCI_MIX_CTRL); - sdhci_writel(host, (val << 8), SDHCI_TUNE_CTRL_STATUS); + writel(reg, host->ioaddr + SDHCI_MIX_CTRL); + writel((val << 8), host->ioaddr + SDHCI_TUNE_CTRL_STATUS); } static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct esdhc_platform_data *boarddata = + host->mmc->parent->platform_data; struct pltfm_imx_data *imx_data = pltfm_host->priv; u32 orig_reg; @@ -291,10 +312,26 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) orig_reg |= (val & SDHCI_CTRL_TUNED_CLK) ? 0 : SDHCI_MIX_CTRL_SMPCLK_SEL; + orig_reg |= (val & SDHCI_CTRL_UHS_DDR50) + ? SDHCI_MIX_CTRL_DDREN : 0; writel(orig_reg, host->ioaddr + SDHCI_MIX_CTRL); + /* set clock frequency again */ + esdhc_set_clock(host, host->clock); imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK; + /* delay line setting */ + if (!boarddata->delay_line) + return; + + if (val & SDHCI_CTRL_UHS_DDR50) + writel((boarddata->delay_line \ + << SDHCI_DLL_OVERRIDE_OFFSET) \ + | (1 << SDHCI_DLL_OVERRIDE_EN_OFFSET), + host->ioaddr + SDHCI_DLL_CTRL); + else + writel(0, host->ioaddr + SDHCI_DLL_CTRL); + return; case SDHCI_TRANSFER_MODE: /* @@ -318,9 +355,14 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) val |= SDHCI_CMD_ABORTCMD; writel(0x08800880, host->ioaddr + SDHCI_CAPABILITIES_1); - if (cpu_is_mx6q()) { + if (cpu_is_mx6()) { imx_data->scratchpad |= \ - (readl(host->ioaddr + SDHCI_MIX_CTRL) & (0xf << 22)); + (readl(host->ioaddr + SDHCI_MIX_CTRL) & \ + (SDHCI_MIX_CTRL_EXE_TUNE | \ + SDHCI_MIX_CTRL_SMPCLK_SEL | \ + SDHCI_MIX_CTRL_AUTO_TUNE | \ + SDHCI_MIX_CTRL_FBCLK_SEL | \ + SDHCI_MIX_CTRL_DDREN)); writel(imx_data->scratchpad, host->ioaddr + SDHCI_MIX_CTRL); @@ -338,6 +380,59 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) esdhc_clrset_le(host, 0xffff, val, reg); } +static u8 esdhc_readb_le(struct sdhci_host *host, int reg) +{ + u8 ret; + u32 reg_val; + + ret = 0; + switch (reg) { + case SDHCI_POWER_CONTROL: + reg_val = readl(host->ioaddr + SDHCI_VENDOR_SPEC); + ret |= reg_val & SDHCI_VENDOR_SPEC_VSELECT + ? SDHCI_POWER_180 : SDHCI_POWER_330; + /* could not power off */ + ret |= SDHCI_POWER_ON; + return ret; + case SDHCI_HOST_CONTROL: + reg_val = readl(host->ioaddr + SDHCI_HOST_CONTROL); + ret |= reg_val & SDHCI_PROT_CTRL_LCTL + ? SDHCI_CTRL_LED : ~SDHCI_CTRL_LED; + ret |= (reg_val & SDHCI_PROT_CTRL_DMASEL_MASK) >> 5; + if (SDHCI_PROT_CTRL_8BIT == (reg_val & SDHCI_PROT_CTRL_DTW)) { + ret &= ~SDHCI_CTRL_4BITBUS; + ret |= SDHCI_CTRL_8BITBUS; + } else if (SDHCI_PROT_CTRL_4BIT + == (reg_val & SDHCI_PROT_CTRL_DTW)) { + ret &= ~SDHCI_CTRL_8BITBUS; + ret |= SDHCI_CTRL_4BITBUS; + } else if (SDHCI_PROT_CTRL_1BIT + == (reg_val & SDHCI_PROT_CTRL_DTW)) + ret &= ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_4BITBUS); + return ret; + case SDHCI_SOFTWARE_RESET: + reg_val = readl(host->ioaddr + SDHCI_CLOCK_CONTROL); + ret = reg_val >> 24; + return ret; + case SDHCI_RESPONSE + 3: + reg_val = readl(host->ioaddr + SDHCI_RESPONSE); + ret = reg_val >> 24; + return ret; + case SDHCI_RESPONSE + 7: + reg_val = readl(host->ioaddr + SDHCI_RESPONSE + 4); + ret = reg_val >> 24; + return ret; + case SDHCI_RESPONSE + 11: + reg_val = readl(host->ioaddr + SDHCI_RESPONSE + 8); + ret = reg_val >> 24; + return ret; + default: + ret = 0; + break; + } + return ret; +} + static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) { u32 new_val; @@ -375,9 +470,14 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) return; case SDHCI_HOST_CONTROL: /* FSL messed up here, so we can just keep those three */ - new_val = val & (SDHCI_CTRL_LED | \ - SDHCI_CTRL_4BITBUS | \ - SDHCI_CTRL_D3CD); + new_val = val & (SDHCI_CTRL_LED); + if (val & SDHCI_CTRL_8BITBUS) { + new_val |= SDHCI_PROT_CTRL_8BIT; + new_val &= ~SDHCI_PROT_CTRL_4BIT; + } else if (val & SDHCI_CTRL_4BITBUS) { + new_val &= ~SDHCI_PROT_CTRL_8BIT; + new_val |= SDHCI_PROT_CTRL_4BIT; + } /* ensure the endianess */ new_val |= ESDHC_HOST_CONTROL_LE; /* DMA mode bits are shifted */ @@ -413,9 +513,40 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) return -ENOSYS; } +static int plt_8bit_width(struct sdhci_host *host, int width) +{ + u32 reg = readl(host->ioaddr + SDHCI_HOST_CONTROL); + + reg &= ~SDHCI_PROT_CTRL_DTW; + + if (width == MMC_BUS_WIDTH_8) + reg |= SDHCI_PROT_CTRL_8BIT; + else if (width == MMC_BUS_WIDTH_4) + reg |= SDHCI_PROT_CTRL_4BIT; + else if (width == MMC_BUS_WIDTH_1) + host->mmc->ios.ddr = 0; + + writel(reg, host->ioaddr + SDHCI_HOST_CONTROL); + return 0; +} + +static void plt_clk_ctrl(struct sdhci_host *host, bool enable) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + if (enable) { + clk_enable(pltfm_host->clk); + host->clk_status = true; + } else { + clk_disable(pltfm_host->clk); + host->clk_status = false; + } +} + static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl_le, .read_w = esdhc_readw_le, + .read_b = esdhc_readb_le, .write_l = esdhc_writel_le, .write_w = esdhc_writew_le, .write_b = esdhc_writeb_le, @@ -423,14 +554,21 @@ static struct sdhci_ops sdhci_esdhc_ops = { .get_max_clock = esdhc_pltfm_get_max_clock, .get_min_clock = esdhc_pltfm_get_min_clock, .pre_tuning = esdhc_prepare_tuning, + .platform_8bit_width = plt_8bit_width, + .platform_clk_ctrl = plt_clk_ctrl, }; static irqreturn_t cd_irq(int irq, void *data) { struct sdhci_host *sdhost = (struct sdhci_host *)data; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhost); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + + writel(0, sdhost->ioaddr + SDHCI_MIX_CTRL); + writel(0, sdhost->ioaddr + SDHCI_TUNE_CTRL_STATUS); - sdhci_writel(sdhost, 0, SDHCI_MIX_CTRL); - sdhci_writel(sdhost, 0, SDHCI_TUNE_CTRL_STATUS); + if (cpu_is_mx6()) + imx_data->scratchpad &= ~SDHCI_MIX_CTRL_DDREN; tasklet_schedule(&sdhost->card_tasklet); return IRQ_HANDLED; }; @@ -442,6 +580,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd struct clk *clk; int err; struct pltfm_imx_data *imx_data; + u32 reg; clk = clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { @@ -469,9 +608,43 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd /* write_protect can't be routed to controller, use gpio */ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro; - if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51() || cpu_is_mx6q())) + if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51() || cpu_is_mx6())) imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; + host->ocr_avail_sd = MMC_VDD_29_30 | MMC_VDD_30_31 | \ + MMC_VDD_32_33 | MMC_VDD_33_34; + host->ocr_avail_mmc = MMC_VDD_29_30 | MMC_VDD_30_31 | \ + MMC_VDD_32_33 | MMC_VDD_33_34; + + if (boarddata->support_18v) + host->ocr_avail_sd |= MMC_VDD_165_195; + if (boarddata->support_8bit) + host->mmc->caps |= MMC_CAP_8_BIT_DATA; + if (boarddata->keep_power_at_suspend) + host->mmc->pm_caps |= MMC_PM_KEEP_POWER; + if (cpu_is_mx6()) { + host->mmc->caps |= MMC_CAP_1_8V_DDR; + host->tuning_min = SDHCI_TUNE_CTRL_MIN; + host->tuning_max = SDHCI_TUNE_CTRL_MAX; + host->tuning_step = SDHCI_TUNE_CTRL_STEP; + host->clk_mgr_en = true; + } + + reg = readl(host->ioaddr + SDHCI_MIX_CTRL); + /* disable card interrupt enable bit, and clear status bit + * the default value of this enable bit is 1, but it should + * be 0 regarding to standard host controller spec 2.1.3. + * if this bit is 1, it may cause some problems. + * there's dat1 glitch when some cards inserting into the slot, + * thus wrongly generate a card interrupt that will cause + * system panic because it lacks of sdio handler + * following code will solve the problem. + */ + reg = sdhci_readl(host, SDHCI_INT_ENABLE); + reg &= ~SDHCI_INT_CARD_INT; + sdhci_writel(host, reg, SDHCI_INT_ENABLE); + sdhci_writel(host, SDHCI_INT_CARD_INT, SDHCI_INT_STATUS); + if (boarddata) { /* Device is always present, e.x, populated emmc device */ if (boarddata->always_present) { @@ -508,16 +681,9 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd /* Now we have a working card_detect again */ host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; } - host->ocr_avail_sd = MMC_VDD_29_30 | MMC_VDD_30_31 | \ - MMC_VDD_32_33 | MMC_VDD_33_34; - - if (boarddata->support_18v) - host->ocr_avail_sd |= MMC_VDD_165_195; - - host->tuning_min = SDHCI_TUNE_CTRL_MIN; - host->tuning_max = SDHCI_TUNE_CTRL_MAX; - host->tuning_step = SDHCI_TUNE_CTRL_STEP; + if (host->clk_mgr_en) + clk_disable(pltfm_host->clk); return 0; no_card_detect_irq: diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 8ee1d622c56d..c64cdcdca4ba 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -1,7 +1,7 @@ /* * Freescale eSDHC controller driver generics for OF and pltfm. * - * Copyright (C) 2007, 2011 Freescale Semiconductor, Inc. + * Copyright (C) 2007, 2011, 2012 Freescale Semiconductor, Inc. * Copyright (c) 2009 MontaVista Software, Inc. * Copyright (c) 2010 Pengutronix e.K. * Author: Wolfram Sang <w.sang@pengutronix.de> @@ -54,7 +54,7 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) int ddr_mode = 0; boarddata = host->mmc->parent->platform_data; - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { pre_div = 1; if (readl(host->ioaddr + SDHCI_MIX_CTRL) & SDHCI_MIX_CTRL_DDREN) { diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index bd5a79f3cb82..d6f72f8c69a3 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -449,7 +449,7 @@ config MTD_NAND_NANDSIM config MTD_NAND_GPMI_NAND bool "GPMI NAND Flash Controller driver" - depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28) + depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) select MTD_PARTITIONS select MTD_CMDLINE_PARTS help diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h index 4effb8c579db..04acf6413b16 100644 --- a/drivers/mtd/nand/gpmi-nand/bch-regs.h +++ b/drivers/mtd/nand/gpmi-nand/bch-regs.h @@ -1,7 +1,7 @@ /* * Freescale GPMI NAND Flash Driver * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * Copyright 2008 Embedded Alley Solutions, Inc. * * This program is free software; you can redistribute it and/or modify @@ -51,15 +51,26 @@ #define BP_BCH_FLASH0LAYOUT0_ECC0 12 #define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0) -#define BF_BCH_FLASH0LAYOUT0_ECC0(v) \ - (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0) +#define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11 +#define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) +#define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \ + (GPMI_IS_MX6Q(x) \ + ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \ + & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \ + : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \ + & BM_BCH_FLASH0LAYOUT0_ECC0) \ + ) #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0 #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) -#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v) \ - (((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\ - & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) +#define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ + (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) +#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \ + (GPMI_IS_MX6Q(x) \ + ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ + : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ + ) #define HW_BCH_FLASH0LAYOUT1 0x00000090 @@ -72,13 +83,24 @@ #define BP_BCH_FLASH0LAYOUT1_ECCN 12 #define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN) -#define BF_BCH_FLASH0LAYOUT1_ECCN(v) \ - (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN) +#define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11 +#define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) +#define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \ + (GPMI_IS_MX6Q(x) \ + ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \ + & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \ + : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \ + & BM_BCH_FLASH0LAYOUT1_ECCN) \ + ) #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0 #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) -#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v) \ - (((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ - & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) +#define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ + (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) +#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \ + (GPMI_IS_MX6Q(x) \ + ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ + : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ + ) #endif diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index b2c987bd6dc5..698535773ff4 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -1,7 +1,7 @@ /* * Freescale GPMI NAND Flash Driver * - * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. * Copyright (C) 2008 Embedded Alley Solutions, Inc. * * This program is free software; you can redistribute it and/or modify @@ -223,13 +223,13 @@ int bch_set_geometry(struct gpmi_nand_data *this) /* Configure layout 0. */ writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) - | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength) - | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size), + | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this) + | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this), r->bch_regs + HW_BCH_FLASH0LAYOUT0); writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) - | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength) - | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size), + | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this) + | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this), r->bch_regs + HW_BCH_FLASH0LAYOUT1); /* Set *all* chip selects to use layout 0. */ @@ -803,7 +803,8 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) if (GPMI_IS_MX23(this)) { mask = MX23_BM_GPMI_DEBUG_READY0 << chip; reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); - } else if (GPMI_IS_MX28(this)) { + } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) { + /* MX28 shares the same R/B register as MX6Q. */ mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); reg = readl(r->gpmi_regs + HW_GPMI_STAT); } else @@ -849,7 +850,9 @@ int gpmi_send_command(struct gpmi_nand_data *this) sg_init_one(sgl, this->cmd_buffer, this->command_length); dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE); desc = channel->device->device_prep_slave_sg(channel, - sgl, 1, DMA_MEM_TO_DEV, 1); + sgl, 1, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { pr_err("step 2 error\n"); return -1; @@ -891,7 +894,8 @@ int gpmi_send_data(struct gpmi_nand_data *this) /* [2] send DMA request */ prepare_data_dma(this, DMA_TO_DEVICE); desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, - 1, DMA_MEM_TO_DEV, 1); + 1, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -927,7 +931,8 @@ int gpmi_read_data(struct gpmi_nand_data *this) /* [2] : send DMA request */ prepare_data_dma(this, DMA_FROM_DEVICE); desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, - 1, DMA_DEV_TO_MEM, 1); + 1, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -974,7 +979,8 @@ int gpmi_send_page(struct gpmi_nand_data *this, desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, + DMA_CTRL_ACK); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -994,6 +1000,7 @@ int gpmi_read_page(struct gpmi_nand_data *this, struct dma_async_tx_descriptor *desc; struct dma_chan *channel = get_dma_chan(this); int chip = this->current_chip; + unsigned long flags; u32 pio[6]; /* [1] Wait for the chip to report ready. */ @@ -1036,9 +1043,14 @@ int gpmi_read_page(struct gpmi_nand_data *this, pio[3] = geo->page_size; pio[4] = payload; pio[5] = auxiliary; + + /* Set DMA_CTRL_ACK for MX6Q which uses the new GPMI. */ + flags = DMA_PREP_INTERRUPT; + if (GPMI_IS_MX6Q(this)) + flags |= DMA_CTRL_ACK; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_TRANS_NONE, 1); + ARRAY_SIZE(pio), DMA_TRANS_NONE, flags); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -1055,9 +1067,11 @@ int gpmi_read_page(struct gpmi_nand_data *this, | BF_GPMI_CTRL0_ADDRESS(address) | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); pio[1] = 0; + pio[2] = 0; /* set GPMI_HW_GPMI_ECCCTRL, disable the BCH */ desc = channel->device->device_prep_slave_sg(channel, - (struct scatterlist *)pio, 2, - DMA_TRANS_NONE, 1); + (struct scatterlist *)pio, 3, + DMA_TRANS_NONE, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { pr_err("step 3 error\n"); return -1; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index ff61e35581e7..ea3ce22ff9d5 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1,7 +1,7 @@ /* * Freescale GPMI NAND Flash Driver * - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. * Copyright (C) 2008 Embedded Alley Solutions, Inc. * * This program is free software; you can redistribute it and/or modify @@ -1493,6 +1493,8 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) chip->ecc.mode = NAND_ECC_HW; chip->ecc.size = 1; chip->ecc.layout = &gpmi_hw_ecclayout; + if (pdata->enable_bbt) + chip->options |= NAND_BBT_USE_FLASH | NAND_USE_FLASH_BBT_NO_OOB; /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ this->bch_geometry.payload_size = 1024; @@ -1582,6 +1584,9 @@ static const struct platform_device_id gpmi_ids[] = { }, { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, + }, { + .name = "imx6q-gpmi-nand", + .driver_data = IS_MX6Q, }, {}, }; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index e023bccb7781..06a072bf85a1 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -1,7 +1,7 @@ /* * Freescale GPMI NAND Flash Driver * - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. * Copyright (C) 2008 Embedded Alley Solutions, Inc. * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@ #include <linux/mtd/nand.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <mach/dma.h> +#include <linux/mxs-dma.h> struct resources { void *gpmi_regs; @@ -268,6 +268,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *, /* Use the platform_id to distinguish different Archs. */ #define IS_MX23 0x1 #define IS_MX28 0x2 +#define IS_MX6Q 0x8 #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) +#define GPMI_IS_MX6Q(x) ((x)->pdev->id_entry->driver_data == IS_MX6Q) #endif diff --git a/drivers/mxc/asrc/mxc_asrc.c b/drivers/mxc/asrc/mxc_asrc.c index bf36aec4bd34..dbf3fffcb100 100644 --- a/drivers/mxc/asrc/mxc_asrc.c +++ b/drivers/mxc/asrc/mxc_asrc.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -890,14 +890,19 @@ static void asrc_output_dma_callback(void *data) static void mxc_free_dma_buf(struct asrc_pair_params *params) { int i; - for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { - if (params->input_dma[i].dma_vaddr != NULL) { - kfree(params->input_dma[i].dma_vaddr); + + if (params->input_dma[0].dma_vaddr != NULL) { + kfree(params->input_dma[0].dma_vaddr); + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { params->input_dma[i].dma_vaddr = NULL; + params->input_dma[i].dma_paddr = 0; } - if (params->output_dma[i].dma_vaddr != NULL) { - kfree(params->output_dma[i].dma_vaddr); + } + if (params->output_dma[0].dma_vaddr != NULL) { + kfree(params->output_dma[0].dma_vaddr); + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { params->output_dma[i].dma_vaddr = NULL; + params->output_dma[i].dma_paddr = 0; } } @@ -907,9 +912,23 @@ static void mxc_free_dma_buf(struct asrc_pair_params *params) static int mxc_allocate_dma_buf(struct asrc_pair_params *params) { int i; + + params->input_dma[0].dma_vaddr = NULL; + params->input_dma[0].dma_vaddr = + kzalloc(params->input_buffer_size * ASRC_DMA_BUFFER_NUM, + GFP_KERNEL); + + if (!params->input_dma[0].dma_vaddr) { + mxc_free_dma_buf(params); + pr_info("can't allocate buff\n"); + return -ENOBUFS; + } + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { params->input_dma[i].dma_vaddr = - kzalloc(params->input_buffer_size, GFP_KERNEL); + (unsigned char *) + ((unsigned long)params->input_dma[0].dma_vaddr + + i * params->input_buffer_size); params->input_dma[i].dma_paddr = virt_to_dma(NULL, params->input_dma[i].dma_vaddr); if (params->input_dma[i].dma_vaddr == NULL) { @@ -918,17 +937,30 @@ static int mxc_allocate_dma_buf(struct asrc_pair_params *params) return -ENOBUFS; } } + + params->output_dma[0].dma_vaddr = NULL; + params->output_dma[0].dma_vaddr = + kzalloc(params->output_buffer_size * ASRC_DMA_BUFFER_NUM, + GFP_KERNEL); + if (!params->output_dma[0].dma_vaddr) { + mxc_free_dma_buf(params); + pr_info("can't allocate buff\n"); + return -ENOBUFS; + } + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { params->output_dma[i].dma_vaddr = - kzalloc(params->output_buffer_size, GFP_KERNEL); + (unsigned char *) + ((unsigned long)params->output_dma[0].dma_vaddr + + i * params->output_buffer_size); params->output_dma[i].dma_paddr = virt_to_dma(NULL, params->output_dma[i].dma_vaddr); if (params->output_dma[i].dma_vaddr == NULL) { mxc_free_dma_buf(params); + pr_info("can't allocate buff\n"); return -ENOBUFS; } } - return 0; } diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index 40297a8718af..8a0efa444440 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -1259,7 +1259,7 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, if (idma_is_set(ipu, IDMAC_CHA_PRI, dma_chan)) { unsigned reg = IDMAC_CH_LOCK_EN_1; uint32_t value = 0; - if (cpu_is_mx53() || cpu_is_mx6q()) { + if (cpu_is_mx53() || cpu_is_mx6q() || cpu_is_mx6dl()) { _ipu_ch_param_set_axi_id(ipu, dma_chan, 0); switch (dma_chan) { case 5: @@ -1327,7 +1327,7 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, } else _ipu_ch_param_set_axi_id(ipu, dma_chan, 1); } else { - if (cpu_is_mx6q()) + if (cpu_is_mx6q() || cpu_is_mx6dl()) _ipu_ch_param_set_axi_id(ipu, dma_chan, 1); } diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c index 0e0e03835e87..20d523aac9e1 100644 --- a/drivers/mxc/vpu/mxc_vpu.c +++ b/drivers/mxc/vpu/mxc_vpu.c @@ -45,6 +45,10 @@ #include <mach/mxc_vpu.h> +/* Define one new pgprot which combined uncached and XN(never executable) */ +#define pgprot_noncachedxn(prot) \ + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN) + struct vpu_priv { struct fasync_struct *async_queue; struct work_struct work; @@ -511,7 +515,13 @@ static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm) unsigned long pfn; vm->vm_flags |= VM_IO | VM_RESERVED; - vm->vm_page_prot = pgprot_noncached(vm->vm_page_prot); + /* + * Since vpu registers have been mapped with ioremap() at probe + * which L_PTE_XN is 1, and the same physical address must be + * mapped multiple times with same type, so set L_PTE_XN to 1 here. + * Otherwise, there may be unexpected result in video codec. + */ + vm->vm_page_prot = pgprot_noncachedxn(vm->vm_page_prot); pfn = phy_vpu_base_addr >> PAGE_SHIFT; pr_debug("size=0x%x, page no.=0x%x\n", (int)(vm->vm_end - vm->vm_start), (int)pfn); diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 18d356e0a8eb..872b7c4c5cc6 100755 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -19,7 +19,7 @@ * Copyright (c) 2004-2006 Macq Electronique SA. * * Support for FEC IEEE 1588. - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. */ #include <linux/module.h> @@ -145,6 +145,8 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ #define FEC_ENET_TS_AVAIL ((uint)0x00010000) #define FEC_ENET_TS_TIMER ((uint)0x00008000) +#define FEC_ENET_MII_CLK ((uint)2500000) +#define FEC_ENET_HOLD_TIME ((uint)0x100) /* 2 internal clock cycle*/ #if defined(CONFIG_FEC_1588) && (defined(CONFIG_ARCH_MX28) || \ defined(CONFIG_ARCH_MX6)) @@ -608,6 +610,7 @@ fec_enet_interrupt(int irq, void *dev_id) { struct net_device *ndev = dev_id; struct fec_enet_private *fep = netdev_priv(ndev); + struct fec_ptp_private *fpp = fep->ptp_priv; uint int_events; irqreturn_t ret = IRQ_NONE; @@ -629,6 +632,12 @@ fec_enet_interrupt(int irq, void *dev_id) fec_enet_tx(ndev); } + if (int_events & FEC_ENET_TS_TIMER) { + ret = IRQ_HANDLED; + if (fep->ptimer_present && fpp) + fpp->prtc++; + } + if (int_events & FEC_ENET_MII) { ret = IRQ_HANDLED; complete(&fep->mdio_done); @@ -838,7 +847,7 @@ static int fec_enet_mii_probe(struct net_device *ndev) } /* mask with MAC supported features */ - if (cpu_is_mx6q()) + if (cpu_is_mx6()) phy_dev->supported &= PHY_GBIT_FEATURES; else phy_dev->supported &= PHY_BASIC_FEATURES; @@ -893,15 +902,12 @@ static int fec_enet_mii_init(struct platform_device *pdev) /* * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) */ - fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1; + fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), + (FEC_ENET_MII_CLK << 2)) << 1; - if (cpu_is_mx6q()) { - /* FIXME: non-1588 MII clk: 66MHz, 1588 mode : 40MHz */ - if (fep->ptimer_present) - fep->phy_speed = 0xe; - else - fep->phy_speed = 0x11a; - } + /* set hold time to 2 internal clock cycle */ + if (cpu_is_mx6()) + fep->phy_speed |= FEC_ENET_HOLD_TIME; writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); @@ -1458,7 +1464,7 @@ fec_restart(struct net_device *dev, int duplex) fep->phy_dev->speed == SPEED_1000) val |= (0x1 << 5); - if (cpu_is_mx6q()) { + if (cpu_is_mx6()) { /* enable endian swap */ val |= (0x1 << 8); /* enable ENET store and forward mode */ @@ -1489,7 +1495,7 @@ fec_stop(struct net_device *dev) writel(1, fep->hwp + FEC_ECNTRL); udelay(10); - if (cpu_is_mx6q()) + if (cpu_is_mx6()) /* FIXME: we have to enable enet to keep mii interrupt works. */ writel(2, fep->hwp + FEC_ECNTRL); diff --git a/drivers/net/fec_1588.c b/drivers/net/fec_1588.c index c7d3a63b96e1..43b60941cc99 100644 --- a/drivers/net/fec_1588.c +++ b/drivers/net/fec_1588.c @@ -1,7 +1,7 @@ /* * drivers/net/fec_1588.c * - * Copyright (C) 2011 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. * Copyright (C) 2009 IXXAT Automation, GmbH * * FEC Ethernet Driver -- IEEE 1588 interface functionality @@ -164,7 +164,7 @@ int fec_ptp_start(struct fec_ptp_private *priv) * enable FEC1 timer's slave mode. */ if ((fpp == ptp_private[0]) || !(ptp_private[0]->ptp_active)) { writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL); - writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, + writel(FEC_T_INC_CLK << FEC_T_INC_OFFSET, fpp->hwp + FEC_ATIME_INC); writel(FEC_T_PERIOD_ONE_SEC, fpp->hwp + FEC_ATIME_EVT_PERIOD); /* start counter */ @@ -180,7 +180,7 @@ int fec_ptp_start(struct fec_ptp_private *priv) fpp->prtc = ptp_private[1]->prtc; writel(FEC_T_CTRL_RESTART, ptp_private[1]->hwp + FEC_ATIME_CTRL); - writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, + writel(FEC_T_INC_CLK << FEC_T_INC_OFFSET, ptp_private[1]->hwp + FEC_ATIME_INC); /* Set the timer as slave mode */ writel(FEC_T_CTRL_SLAVE, @@ -190,7 +190,7 @@ int fec_ptp_start(struct fec_ptp_private *priv) } #endif } else { - writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, + writel(FEC_T_INC_CLK << FEC_T_INC_OFFSET, fpp->hwp + FEC_ATIME_INC); /* Set the timer as slave mode */ writel(FEC_T_CTRL_SLAVE, fpp->hwp + FEC_ATIME_CTRL); @@ -584,18 +584,18 @@ static void fec_handle_ptpdrift(struct ptp_set_comp *comp, ptc->corr_inc = 0; ptc->corr_period = 0; return; - } else if (ndrift >= FEC_ATIME_40MHZ) { - ptc->corr_inc = (u32)(ndrift / FEC_ATIME_40MHZ); + } else if (ndrift >= FEC_ATIME_CLK) { + ptc->corr_inc = (u32)(ndrift / FEC_ATIME_CLK); ptc->corr_period = 1; return; } else { tmp_winner = 0xFFFFFFFF; adj_inc = 1; - if (ndrift > (FEC_ATIME_40MHZ / FEC_T_INC_40MHZ)) { - adj_inc = FEC_T_INC_40MHZ / 2; - } else if (ndrift > (FEC_ATIME_40MHZ / (FEC_T_INC_40MHZ * 4))) { - adj_inc = FEC_T_INC_40MHZ / 4; + if (ndrift > (FEC_ATIME_CLK / FEC_T_INC_CLK)) { + adj_inc = FEC_T_INC_CLK / 2; + } else if (ndrift > (FEC_ATIME_CLK / (FEC_T_INC_CLK * 4))) { + adj_inc = FEC_T_INC_CLK / 4; adj_period = 2; } else { adj_inc = 4; @@ -603,15 +603,15 @@ static void fec_handle_ptpdrift(struct ptp_set_comp *comp, } for (i = 1; i < adj_inc; i++) { - tmp_current = (FEC_ATIME_40MHZ * i) % ndrift; + tmp_current = (FEC_ATIME_CLK * i) % ndrift; if (tmp_current == 0) { ptc->corr_inc = i; - ptc->corr_period = (u32)((FEC_ATIME_40MHZ * + ptc->corr_period = (u32)((FEC_ATIME_CLK * adj_period * i) / ndrift); break; } else if (tmp_current < tmp_winner) { ptc->corr_inc = i; - ptc->corr_period = (u32)((FEC_ATIME_40MHZ * + ptc->corr_period = (u32)((FEC_ATIME_CLK * adj_period * i) / ndrift); tmp_winner = tmp_current; } @@ -632,9 +632,9 @@ static void fec_set_drift(struct fec_ptp_private *priv, return; if (comp->o_ops == TRUE) - corr_ns = FEC_T_INC_40MHZ + tc.corr_inc; + corr_ns = FEC_T_INC_CLK + tc.corr_inc; else - corr_ns = FEC_T_INC_40MHZ - tc.corr_inc; + corr_ns = FEC_T_INC_CLK - tc.corr_inc; if (!priv->ptp_slave) fpp = priv; diff --git a/drivers/net/fec_1588.h b/drivers/net/fec_1588.h index e947abdf4a82..8e21519ec45d 100644 --- a/drivers/net/fec_1588.h +++ b/drivers/net/fec_1588.h @@ -1,7 +1,7 @@ /* * drivers/net/fec_1588.h * - * Copyright (C) 2011 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,12 +42,10 @@ #define FEC_T_INC_CORR_OFFSET 8 -#define FEC_T_INC_40MHZ 25 -#define FEC_ATIME_40MHZ 40000000 -/* -#define FEC_T_INC_40MHZ 15 -#define FEC_ATIME_40MHZ 66000000 -*/ +#define FEC_T_INC_50MHZ 20 +#define FEC_ATIME_50MHZ 50000000 +#define FEC_T_INC_CLK FEC_T_INC_50MHZ +#define FEC_ATIME_CLK FEC_ATIME_50MHZ #define FEC_T_PERIOD_ONE_SEC 0x3B9ACA00 diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index d1b23067619f..073548836413 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -25,5 +25,6 @@ config ATH_DEBUG source "drivers/net/wireless/ath/ath5k/Kconfig" source "drivers/net/wireless/ath/ath9k/Kconfig" source "drivers/net/wireless/ath/carl9170/Kconfig" +source "drivers/net/wireless/ath/ath6kl/Kconfig" endif diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 0e8f528c81c0..d1214696a35b 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH9K_HW) += ath9k/ obj-$(CONFIG_CARL9170) += carl9170/ +obj-$(CONFIG_ATH6KL) += ath6kl/ obj-$(CONFIG_ATH_COMMON) += ath.o diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig new file mode 100644 index 000000000000..fc9f69c1f945 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -0,0 +1,17 @@ +config ATH6KL + tristate "Atheros ath6kl support" + depends on MMC + depends on CFG80211 + select WIRELESS_EXT + select WEXT_PRIV + ---help--- + This module adds support for wireless adapters based on + Atheros AR6003 chipset running over SDIO. If you choose to + build it as a module, it will be called ath6kl. Pls note + that AR6002 and AR6001 are not supported by this driver. + +config ATH6KL_DEBUG + bool "Atheros ath6kl debugging" + depends on ATH6KL + ---help--- + Enables debug support diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile new file mode 100644 index 000000000000..e1bb07ea8e80 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2004-2010 Atheros Communications Inc. +# All rights reserved. +# +# +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# +# +# Author(s): ="Atheros" +#------------------------------------------------------------------------------ + +obj-$(CONFIG_ATH6KL) := ath6kl.o +ath6kl-y += debug.o +ath6kl-y += htc_hif.o +ath6kl-y += htc.o +ath6kl-y += bmi.o +ath6kl-y += cfg80211.o +ath6kl-y += init.o +ath6kl-y += main.o +ath6kl-y += txrx.o +ath6kl-y += wmi.o +ath6kl-y += node.o +ath6kl-y += sdio.o diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c new file mode 100644 index 000000000000..84676697d7eb --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/bmi.c @@ -0,0 +1,692 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "hif-ops.h" +#include "target.h" +#include "debug.h" + +static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar) +{ + u32 addr; + unsigned long timeout; + int ret; + + ar->bmi.cmd_credits = 0; + + /* Read the counter register to get the command credits */ + addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; + + timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); + while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) { + + /* + * Hit the credit counter with a 4-byte access, the first byte + * read will hit the counter and cause a decrement, while the + * remaining 3 bytes has no effect. The rationale behind this + * is to make all HIF accesses 4-byte aligned. + */ + ret = hif_read_write_sync(ar, addr, + (u8 *)&ar->bmi.cmd_credits, 4, + HIF_RD_SYNC_BYTE_INC); + if (ret) { + ath6kl_err("Unable to decrement the command credit count register: %d\n", + ret); + return ret; + } + + /* The counter is only 8 bits. + * Ignore anything in the upper 3 bytes + */ + ar->bmi.cmd_credits &= 0xFF; + } + + if (!ar->bmi.cmd_credits) { + ath6kl_err("bmi communication timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar, bool need_timeout) +{ + unsigned long timeout; + u32 rx_word = 0; + int ret = 0; + + timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); + while ((!need_timeout || time_before(jiffies, timeout)) && !rx_word) { + ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS, + (u8 *)&rx_word, sizeof(rx_word), + HIF_RD_SYNC_BYTE_INC); + if (ret) { + ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n"); + return ret; + } + + /* all we really want is one bit */ + rx_word &= (1 << ENDPOINT1); + } + + if (!rx_word) { + ath6kl_err("bmi_recv_buf FIFO empty\n"); + return -EINVAL; + } + + return ret; +} + +static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len) +{ + int ret; + u32 addr; + + ret = ath6kl_get_bmi_cmd_credits(ar); + if (ret) + return ret; + + addr = ar->mbox_info.htc_addr; + + ret = hif_read_write_sync(ar, addr, buf, len, + HIF_WR_SYNC_BYTE_INC); + if (ret) + ath6kl_err("unable to send the bmi data to the device\n"); + + return ret; +} + +static int ath6kl_bmi_recv_buf(struct ath6kl *ar, + u8 *buf, u32 len, bool want_timeout) +{ + int ret; + u32 addr; + + /* + * During normal bootup, small reads may be required. + * Rather than issue an HIF Read and then wait as the Target + * adds successive bytes to the FIFO, we wait here until + * we know that response data is available. + * + * This allows us to cleanly timeout on an unexpected + * Target failure rather than risk problems at the HIF level. + * In particular, this avoids SDIO timeouts and possibly garbage + * data on some host controllers. And on an interconnect + * such as Compact Flash (as well as some SDIO masters) which + * does not provide any indication on data timeout, it avoids + * a potential hang or garbage response. + * + * Synchronization is more difficult for reads larger than the + * size of the MBOX FIFO (128B), because the Target is unable + * to push the 129th byte of data until AFTER the Host posts an + * HIF Read and removes some FIFO data. So for large reads the + * Host proceeds to post an HIF Read BEFORE all the data is + * actually available to read. Fortunately, large BMI reads do + * not occur in practice -- they're supported for debug/development. + * + * So Host/Target BMI synchronization is divided into these cases: + * CASE 1: length < 4 + * Should not happen + * + * CASE 2: 4 <= length <= 128 + * Wait for first 4 bytes to be in FIFO + * If CONSERVATIVE_BMI_READ is enabled, also wait for + * a BMI command credit, which indicates that the ENTIRE + * response is available in the the FIFO + * + * CASE 3: length > 128 + * Wait for the first 4 bytes to be in FIFO + * + * For most uses, a small timeout should be sufficient and we will + * usually see a response quickly; but there may be some unusual + * (debug) cases of BMI_EXECUTE where we want an larger timeout. + * For now, we use an unbounded busy loop while waiting for + * BMI_EXECUTE. + * + * If BMI_EXECUTE ever needs to support longer-latency execution, + * especially in production, this code needs to be enhanced to sleep + * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently + * a function of Host processor speed. + */ + if (len >= 4) { /* NB: Currently, always true */ + ret = ath6kl_bmi_get_rx_lkahd(ar, want_timeout); + if (ret) + return ret; + } + + addr = ar->mbox_info.htc_addr; + ret = hif_read_write_sync(ar, addr, buf, len, + HIF_RD_SYNC_BYTE_INC); + if (ret) { + ath6kl_err("Unable to read the bmi data from the device: %d\n", + ret); + return ret; + } + + return 0; +} + +int ath6kl_bmi_done(struct ath6kl *ar) +{ + int ret; + u32 cid = BMI_DONE; + + if (ar->bmi.done_sent) { + ath6kl_dbg(ATH6KL_DBG_BMI, "bmi done skipped\n"); + return 0; + } + + ar->bmi.done_sent = true; + + ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid)); + if (ret) { + ath6kl_err("Unable to send bmi done: %d\n", ret); + return ret; + } + + ath6kl_bmi_cleanup(ar); + + return 0; +} + +int ath6kl_bmi_get_target_info(struct ath6kl *ar, + struct ath6kl_bmi_target_info *targ_info) +{ + int ret; + u32 cid = BMI_GET_TARGET_INFO; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid)); + if (ret) { + ath6kl_err("Unable to send get target info: %d\n", ret); + return ret; + } + + ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version, + sizeof(targ_info->version), true); + if (ret) { + ath6kl_err("Unable to recv target info: %d\n", ret); + return ret; + } + + if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) { + /* Determine how many bytes are in the Target's targ_info */ + ret = ath6kl_bmi_recv_buf(ar, + (u8 *)&targ_info->byte_count, + sizeof(targ_info->byte_count), + true); + if (ret) { + ath6kl_err("unable to read target info byte count: %d\n", + ret); + return ret; + } + + /* + * The target's targ_info doesn't match the host's targ_info. + * We need to do some backwards compatibility to make this work. + */ + if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) { + WARN_ON(1); + return -EINVAL; + } + + /* Read the remainder of the targ_info */ + ret = ath6kl_bmi_recv_buf(ar, + ((u8 *)targ_info) + + sizeof(targ_info->byte_count), + sizeof(*targ_info) - + sizeof(targ_info->byte_count), + true); + + if (ret) { + ath6kl_err("Unable to read target info (%d bytes): %d\n", + targ_info->byte_count, ret); + return ret; + } + } + + ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n", + targ_info->version, targ_info->type); + + return 0; +} + +int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) +{ + u32 cid = BMI_READ_MEMORY; + int ret; + u32 offset; + u32 len_remain, rx_len; + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = BMI_DATASZ_MAX + sizeof(cid) + sizeof(addr) + sizeof(len); + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, + "bmi read memory: device: addr: 0x%x, len: %d\n", + addr, len); + + len_remain = len; + + while (len_remain) { + rx_len = (len_remain < BMI_DATASZ_MAX) ? + len_remain : BMI_DATASZ_MAX; + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len)); + offset += sizeof(len); + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", + ret); + return ret; + } + ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len, true); + if (ret) { + ath6kl_err("Unable to read from the device: %d\n", + ret); + return ret; + } + memcpy(&buf[len - len_remain], ar->bmi.cmd_buf, rx_len); + len_remain -= rx_len; addr += rx_len; + } + + return 0; +} + +int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) +{ + u32 cid = BMI_WRITE_MEMORY; + int ret; + u32 offset; + u32 len_remain, tx_len; + const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len); + u8 aligned_buf[BMI_DATASZ_MAX]; + u8 *src; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + if ((BMI_DATASZ_MAX + header) > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + + memset(ar->bmi.cmd_buf, 0, BMI_DATASZ_MAX + header); + + ath6kl_dbg(ATH6KL_DBG_BMI, + "bmi write memory: addr: 0x%x, len: %d\n", addr, len); + + len_remain = len; + while (len_remain) { + src = &buf[len - len_remain]; + + if (len_remain < (BMI_DATASZ_MAX - header)) { + if (len_remain & 3) { + /* align it with 4 bytes */ + len_remain = len_remain + + (4 - (len_remain & 3)); + memcpy(aligned_buf, src, len_remain); + src = aligned_buf; + } + tx_len = len_remain; + } else { + tx_len = (BMI_DATASZ_MAX - header); + } + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len)); + offset += sizeof(tx_len); + memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len); + offset += tx_len; + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", + ret); + return ret; + } + len_remain -= tx_len; addr += tx_len; + } + + return 0; +} + +int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param) +{ + u32 cid = BMI_EXECUTE; + int ret; + u32 offset; + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = sizeof(cid) + sizeof(addr) + sizeof(param); + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, "bmi execute: addr: 0x%x, param: %d)\n", + addr, *param); + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param)); + offset += sizeof(*param); + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", ret); + return ret; + } + + ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), false); + if (ret) { + ath6kl_err("Unable to read from the device: %d\n", ret); + return ret; + } + + memcpy(param, ar->bmi.cmd_buf, sizeof(*param)); + + return 0; +} + +int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr) +{ + u32 cid = BMI_SET_APP_START; + int ret; + u32 offset; + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = sizeof(cid) + sizeof(addr); + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, "bmi set app start: addr: 0x%x\n", addr); + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", ret); + return ret; + } + + return 0; +} + +int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param) +{ + u32 cid = BMI_READ_SOC_REGISTER; + int ret; + u32 offset; + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = sizeof(cid) + sizeof(addr); + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, "bmi read SOC reg: addr: 0x%x\n", addr); + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", ret); + return ret; + } + + ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), true); + if (ret) { + ath6kl_err("Unable to read from the device: %d\n", ret); + return ret; + } + memcpy(param, ar->bmi.cmd_buf, sizeof(*param)); + + return 0; +} + +int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param) +{ + u32 cid = BMI_WRITE_SOC_REGISTER; + int ret; + u32 offset; + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = sizeof(cid) + sizeof(addr) + sizeof(param); + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, + "bmi write SOC reg: addr: 0x%x, param: %d\n", + addr, param); + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + memcpy(&(ar->bmi.cmd_buf[offset]), ¶m, sizeof(param)); + offset += sizeof(param); + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", ret); + return ret; + } + + return 0; +} + +int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len) +{ + u32 cid = BMI_LZ_DATA; + int ret; + u32 offset; + u32 len_remain, tx_len; + const u32 header = sizeof(cid) + sizeof(len); + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = BMI_DATASZ_MAX + header; + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, "bmi send LZ data: len: %d)\n", + len); + + len_remain = len; + while (len_remain) { + tx_len = (len_remain < (BMI_DATASZ_MAX - header)) ? + len_remain : (BMI_DATASZ_MAX - header); + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len)); + offset += sizeof(tx_len); + memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain], + tx_len); + offset += tx_len; + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to write to the device: %d\n", + ret); + return ret; + } + + len_remain -= tx_len; + } + + return 0; +} + +int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr) +{ + u32 cid = BMI_LZ_STREAM_START; + int ret; + u32 offset; + u16 size; + + if (ar->bmi.done_sent) { + ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid); + return -EACCES; + } + + size = sizeof(cid) + sizeof(addr); + if (size > MAX_BMI_CMDBUF_SZ) { + WARN_ON(1); + return -EINVAL; + } + memset(ar->bmi.cmd_buf, 0, size); + + ath6kl_dbg(ATH6KL_DBG_BMI, + "bmi LZ stream start: addr: 0x%x)\n", + addr); + + offset = 0; + memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); + offset += sizeof(addr); + + ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); + if (ret) { + ath6kl_err("Unable to start LZ stream to the device: %d\n", + ret); + return ret; + } + + return 0; +} + +int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) +{ + int ret; + u32 last_word = 0; + u32 last_word_offset = len & ~0x3; + u32 unaligned_bytes = len & 0x3; + + ret = ath6kl_bmi_lz_stream_start(ar, addr); + if (ret) + return ret; + + if (unaligned_bytes) { + /* copy the last word into a zero padded buffer */ + memcpy(&last_word, &buf[last_word_offset], unaligned_bytes); + } + + ret = ath6kl_bmi_lz_data(ar, buf, last_word_offset); + if (ret) + return ret; + + if (unaligned_bytes) + ret = ath6kl_bmi_lz_data(ar, (u8 *)&last_word, 4); + + if (!ret) { + /* Close compressed stream and open a new (fake) one. + * This serves mainly to flush Target caches. */ + ret = ath6kl_bmi_lz_stream_start(ar, 0x00); + } + return ret; +} + +int ath6kl_bmi_init(struct ath6kl *ar) +{ + ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC); + + if (!ar->bmi.cmd_buf) + return -ENOMEM; + + return 0; +} + +void ath6kl_bmi_cleanup(struct ath6kl *ar) +{ + kfree(ar->bmi.cmd_buf); + ar->bmi.cmd_buf = NULL; +} diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h new file mode 100644 index 000000000000..83546d76d979 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/bmi.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef BMI_H +#define BMI_H + +/* + * Bootloader Messaging Interface (BMI) + * + * BMI is a very simple messaging interface used during initialization + * to read memory, write memory, execute code, and to define an + * application entry PC. + * + * It is used to download an application to ATH6KL, to provide + * patches to code that is already resident on ATH6KL, and generally + * to examine and modify state. The Host has an opportunity to use + * BMI only once during bootup. Once the Host issues a BMI_DONE + * command, this opportunity ends. + * + * The Host writes BMI requests to mailbox0, and reads BMI responses + * from mailbox0. BMI requests all begin with a command + * (see below for specific commands), and are followed by + * command-specific data. + * + * Flow control: + * The Host can only issue a command once the Target gives it a + * "BMI Command Credit", using ATH6KL Counter #4. As soon as the + * Target has completed a command, it issues another BMI Command + * Credit (so the Host can issue the next command). + * + * BMI handles all required Target-side cache flushing. + */ + +#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \ + (sizeof(u32) * 3 /* cmd + addr + len */)) + +/* Maximum data size used for BMI transfers */ +#define BMI_DATASZ_MAX 256 + +/* BMI Commands */ + +#define BMI_NO_COMMAND 0 + +#define BMI_DONE 1 +/* + * Semantics: Host is done using BMI + * Request format: + * u32 command (BMI_DONE) + * Response format: none + */ + +#define BMI_READ_MEMORY 2 +/* + * Semantics: Host reads ATH6KL memory + * Request format: + * u32 command (BMI_READ_MEMORY) + * u32 address + * u32 length, at most BMI_DATASZ_MAX + * Response format: + * u8 data[length] + */ + +#define BMI_WRITE_MEMORY 3 +/* + * Semantics: Host writes ATH6KL memory + * Request format: + * u32 command (BMI_WRITE_MEMORY) + * u32 address + * u32 length, at most BMI_DATASZ_MAX + * u8 data[length] + * Response format: none + */ + +#define BMI_EXECUTE 4 +/* + * Semantics: Causes ATH6KL to execute code + * Request format: + * u32 command (BMI_EXECUTE) + * u32 address + * u32 parameter + * Response format: + * u32 return value + */ + +#define BMI_SET_APP_START 5 +/* + * Semantics: Set Target application starting address + * Request format: + * u32 command (BMI_SET_APP_START) + * u32 address + * Response format: none + */ + +#define BMI_READ_SOC_REGISTER 6 +/* + * Semantics: Read a 32-bit Target SOC register. + * Request format: + * u32 command (BMI_READ_REGISTER) + * u32 address + * Response format: + * u32 value + */ + +#define BMI_WRITE_SOC_REGISTER 7 +/* + * Semantics: Write a 32-bit Target SOC register. + * Request format: + * u32 command (BMI_WRITE_REGISTER) + * u32 address + * u32 value + * + * Response format: none + */ + +#define BMI_GET_TARGET_ID 8 +#define BMI_GET_TARGET_INFO 8 +/* + * Semantics: Fetch the 4-byte Target information + * Request format: + * u32 command (BMI_GET_TARGET_ID/INFO) + * Response format1 (old firmware): + * u32 TargetVersionID + * Response format2 (newer firmware): + * u32 TARGET_VERSION_SENTINAL + * struct bmi_target_info; + */ + +#define TARGET_VERSION_SENTINAL 0xffffffff +#define TARGET_TYPE_AR6003 3 + +#define BMI_ROMPATCH_INSTALL 9 +/* + * Semantics: Install a ROM Patch. + * Request format: + * u32 command (BMI_ROMPATCH_INSTALL) + * u32 Target ROM Address + * u32 Target RAM Address or Value (depending on Target Type) + * u32 Size, in bytes + * u32 Activate? 1-->activate; + * 0-->install but do not activate + * Response format: + * u32 PatchID + */ + +#define BMI_ROMPATCH_UNINSTALL 10 +/* + * Semantics: Uninstall a previously-installed ROM Patch, + * automatically deactivating, if necessary. + * Request format: + * u32 command (BMI_ROMPATCH_UNINSTALL) + * u32 PatchID + * + * Response format: none + */ + +#define BMI_ROMPATCH_ACTIVATE 11 +/* + * Semantics: Activate a list of previously-installed ROM Patches. + * Request format: + * u32 command (BMI_ROMPATCH_ACTIVATE) + * u32 rompatch_count + * u32 PatchID[rompatch_count] + * + * Response format: none + */ + +#define BMI_ROMPATCH_DEACTIVATE 12 +/* + * Semantics: Deactivate a list of active ROM Patches. + * Request format: + * u32 command (BMI_ROMPATCH_DEACTIVATE) + * u32 rompatch_count + * u32 PatchID[rompatch_count] + * + * Response format: none + */ + + +#define BMI_LZ_STREAM_START 13 +/* + * Semantics: Begin an LZ-compressed stream of input + * which is to be uncompressed by the Target to an + * output buffer at address. The output buffer must + * be sufficiently large to hold the uncompressed + * output from the compressed input stream. This BMI + * command should be followed by a series of 1 or more + * BMI_LZ_DATA commands. + * u32 command (BMI_LZ_STREAM_START) + * u32 address + * Note: Not supported on all versions of ROM firmware. + */ + +#define BMI_LZ_DATA 14 +/* + * Semantics: Host writes ATH6KL memory with LZ-compressed + * data which is uncompressed by the Target. This command + * must be preceded by a BMI_LZ_STREAM_START command. A series + * of BMI_LZ_DATA commands are considered part of a single + * input stream until another BMI_LZ_STREAM_START is issued. + * Request format: + * u32 command (BMI_LZ_DATA) + * u32 length (of compressed data), + * at most BMI_DATASZ_MAX + * u8 CompressedData[length] + * Response format: none + * Note: Not supported on all versions of ROM firmware. + */ + +#define BMI_COMMUNICATION_TIMEOUT 1000 /* in msec */ + +struct ath6kl; +struct ath6kl_bmi_target_info { + __le32 byte_count; /* size of this structure */ + __le32 version; /* target version id */ + __le32 type; /* target type */ +} __packed; + +int ath6kl_bmi_init(struct ath6kl *ar); +void ath6kl_bmi_cleanup(struct ath6kl *ar); +int ath6kl_bmi_done(struct ath6kl *ar); +int ath6kl_bmi_get_target_info(struct ath6kl *ar, + struct ath6kl_bmi_target_info *targ_info); +int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len); +int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len); +int ath6kl_bmi_execute(struct ath6kl *ar, + u32 addr, u32 *param); +int ath6kl_bmi_set_app_start(struct ath6kl *ar, + u32 addr); +int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param); +int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param); +int ath6kl_bmi_lz_data(struct ath6kl *ar, + u8 *buf, u32 len); +int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, + u32 addr); +int ath6kl_bmi_fast_download(struct ath6kl *ar, + u32 addr, u8 *buf, u32 len); +#endif diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c new file mode 100644 index 000000000000..4284a41ff775 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -0,0 +1,1538 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "cfg80211.h" +#include "debug.h" + +#define RATETAB_ENT(_rate, _rateid, _flags) { \ + .bitrate = (_rate), \ + .flags = (_flags), \ + .hw_value = (_rateid), \ +} + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .hw_value = (_channel), \ + .center_freq = 5000 + (5 * (_channel)), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_rate ath6kl_rates[] = { + RATETAB_ENT(10, 0x1, 0), + RATETAB_ENT(20, 0x2, 0), + RATETAB_ENT(55, 0x4, 0), + RATETAB_ENT(110, 0x8, 0), + RATETAB_ENT(60, 0x10, 0), + RATETAB_ENT(90, 0x20, 0), + RATETAB_ENT(120, 0x40, 0), + RATETAB_ENT(180, 0x80, 0), + RATETAB_ENT(240, 0x100, 0), + RATETAB_ENT(360, 0x200, 0), + RATETAB_ENT(480, 0x400, 0), + RATETAB_ENT(540, 0x800, 0), +}; + +#define ath6kl_a_rates (ath6kl_rates + 4) +#define ath6kl_a_rates_size 8 +#define ath6kl_g_rates (ath6kl_rates + 0) +#define ath6kl_g_rates_size 12 + +static struct ieee80211_channel ath6kl_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct ieee80211_channel ath6kl_5ghz_a_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +static struct ieee80211_supported_band ath6kl_band_2ghz = { + .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels), + .channels = ath6kl_2ghz_channels, + .n_bitrates = ath6kl_g_rates_size, + .bitrates = ath6kl_g_rates, +}; + +static struct ieee80211_supported_band ath6kl_band_5ghz = { + .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels), + .channels = ath6kl_5ghz_a_channels, + .n_bitrates = ath6kl_a_rates_size, + .bitrates = ath6kl_a_rates, +}; + +static int ath6kl_set_wpa_version(struct ath6kl *ar, + enum nl80211_wpa_versions wpa_version) +{ + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version); + + if (!wpa_version) { + ar->auth_mode = NONE_AUTH; + } else if (wpa_version & NL80211_WPA_VERSION_2) { + ar->auth_mode = WPA2_AUTH; + } else if (wpa_version & NL80211_WPA_VERSION_1) { + ar->auth_mode = WPA_AUTH; + } else { + ath6kl_err("%s: %u not supported\n", __func__, wpa_version); + return -ENOTSUPP; + } + + return 0; +} + +static int ath6kl_set_auth_type(struct ath6kl *ar, + enum nl80211_auth_type auth_type) +{ + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type); + + switch (auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + ar->dot11_auth_mode = OPEN_AUTH; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + ar->dot11_auth_mode = SHARED_AUTH; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + ar->dot11_auth_mode = LEAP_AUTH; + break; + + case NL80211_AUTHTYPE_AUTOMATIC: + ar->dot11_auth_mode = OPEN_AUTH; + ar->auto_auth_stage = AUTH_OPEN_IN_PROGRESS; + break; + + default: + ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type); + return -ENOTSUPP; + } + + return 0; +} + +static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast) +{ + u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto; + u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len : &ar->grp_crpto_len; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n", + __func__, cipher, ucast); + + switch (cipher) { + case 0: + /* our own hack to use value 0 as no crypto used */ + *ar_cipher = NONE_CRYPT; + *ar_cipher_len = 0; + break; + case WLAN_CIPHER_SUITE_WEP40: + *ar_cipher = WEP_CRYPT; + *ar_cipher_len = 5; + break; + case WLAN_CIPHER_SUITE_WEP104: + *ar_cipher = WEP_CRYPT; + *ar_cipher_len = 13; + break; + case WLAN_CIPHER_SUITE_TKIP: + *ar_cipher = TKIP_CRYPT; + *ar_cipher_len = 0; + break; + case WLAN_CIPHER_SUITE_CCMP: + *ar_cipher = AES_CRYPT; + *ar_cipher_len = 0; + break; + default: + ath6kl_err("cipher 0x%x not supported\n", cipher); + return -ENOTSUPP; + } + + return 0; +} + +static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt) +{ + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt); + + if (key_mgmt == WLAN_AKM_SUITE_PSK) { + if (ar->auth_mode == WPA_AUTH) + ar->auth_mode = WPA_PSK_AUTH; + else if (ar->auth_mode == WPA2_AUTH) + ar->auth_mode = WPA2_PSK_AUTH; + } else if (key_mgmt != WLAN_AKM_SUITE_8021X) { + ar->auth_mode = NONE_AUTH; + } +} + +static bool ath6kl_cfg80211_ready(struct ath6kl *ar) +{ + if (!test_bit(WMI_READY, &ar->flag)) { + ath6kl_err("wmi is not ready\n"); + return false; + } + + if (ar->wlan_state == WLAN_DISABLED) { + ath6kl_err("wlan disabled\n"); + return false; + } + + return true; +} + +static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct ath6kl *ar = ath6kl_priv(dev); + int status; + + ar->sme_state = SME_CONNECTING; + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { + ath6kl_err("destroy in progress\n"); + return -EBUSY; + } + + if (test_bit(SKIP_SCAN, &ar->flag) && + ((sme->channel && sme->channel->center_freq == 0) || + (sme->bssid && is_zero_ether_addr(sme->bssid)))) { + ath6kl_err("SkipScan: channel or bssid invalid\n"); + return -EINVAL; + } + + if (down_interruptible(&ar->sem)) { + ath6kl_err("busy, couldn't get access\n"); + return -ERESTARTSYS; + } + + if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { + ath6kl_err("busy, destroy in progress\n"); + up(&ar->sem); + return -EBUSY; + } + + if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) { + /* + * sleep until the command queue drains + */ + wait_event_interruptible_timeout(ar->event_wq, + ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0, + WMI_TIMEOUT); + if (signal_pending(current)) { + ath6kl_err("cmd queue drain timeout\n"); + up(&ar->sem); + return -EINTR; + } + } + + if (test_bit(CONNECTED, &ar->flag) && + ar->ssid_len == sme->ssid_len && + !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) { + ar->reconnect_flag = true; + status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid, + ar->ch_hint); + + up(&ar->sem); + if (status) { + ath6kl_err("wmi_reconnect_cmd failed\n"); + return -EIO; + } + return 0; + } else if (ar->ssid_len == sme->ssid_len && + !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) { + ath6kl_disconnect(ar); + } + + memset(ar->ssid, 0, sizeof(ar->ssid)); + ar->ssid_len = sme->ssid_len; + memcpy(ar->ssid, sme->ssid, sme->ssid_len); + + if (sme->channel) + ar->ch_hint = sme->channel->center_freq; + + memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); + if (sme->bssid && !is_broadcast_ether_addr(sme->bssid)) + memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid)); + + ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions); + + status = ath6kl_set_auth_type(ar, sme->auth_type); + if (status) { + up(&ar->sem); + return status; + } + + if (sme->crypto.n_ciphers_pairwise) + ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true); + else + ath6kl_set_cipher(ar, 0, true); + + ath6kl_set_cipher(ar, sme->crypto.cipher_group, false); + + if (sme->crypto.n_akm_suites) + ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]); + + if ((sme->key_len) && + (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) { + struct ath6kl_key *key = NULL; + + if (sme->key_idx < WMI_MIN_KEY_INDEX || + sme->key_idx > WMI_MAX_KEY_INDEX) { + ath6kl_err("key index %d out of bounds\n", + sme->key_idx); + up(&ar->sem); + return -ENOENT; + } + + key = &ar->keys[sme->key_idx]; + key->key_len = sme->key_len; + memcpy(key->key, sme->key, key->key_len); + key->cipher = ar->prwise_crypto; + ar->def_txkey_index = sme->key_idx; + + ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx, + ar->prwise_crypto, + GROUP_USAGE | TX_USAGE, + key->key_len, + NULL, + key->key, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + } + + if (!ar->usr_bss_filter) { + if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) { + ath6kl_err("couldn't set bss filtering\n"); + up(&ar->sem); + return -EIO; + } + } + + ar->nw_type = ar->next_mode; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: connect called with authmode %d dot11 auth %d" + " PW crypto %d PW crypto len %d GRP crypto %d" + " GRP crypto len %d channel hint %u\n", + __func__, + ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, + ar->prwise_crypto_len, ar->grp_crypto, + ar->grp_crpto_len, ar->ch_hint); + + ar->reconnect_flag = 0; + status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, + ar->dot11_auth_mode, ar->auth_mode, + ar->prwise_crypto, + ar->prwise_crypto_len, + ar->grp_crypto, ar->grp_crpto_len, + ar->ssid_len, ar->ssid, + ar->req_bssid, ar->ch_hint, + ar->connect_ctrl_flags); + + up(&ar->sem); + + if (status == -EINVAL) { + memset(ar->ssid, 0, sizeof(ar->ssid)); + ar->ssid_len = 0; + ath6kl_err("invalid request\n"); + return -ENOENT; + } else if (status) { + ath6kl_err("ath6kl_wmi_connect_cmd failed\n"); + return -EIO; + } + + if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) && + ((ar->auth_mode == WPA_PSK_AUTH) + || (ar->auth_mode == WPA2_PSK_AUTH))) { + mod_timer(&ar->disconnect_timer, + jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL)); + } + + ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD; + set_bit(CONNECT_PEND, &ar->flag); + + return 0; +} + +void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, + u8 *bssid, u16 listen_intvl, + u16 beacon_intvl, + enum network_type nw_type, + u8 beacon_ie_len, u8 assoc_req_len, + u8 assoc_resp_len, u8 *assoc_info) +{ + u16 size = 0; + u16 capability = 0; + struct cfg80211_bss *bss = NULL; + struct ieee80211_mgmt *mgmt = NULL; + struct ieee80211_channel *ibss_ch = NULL; + s32 signal = 50 * 100; + u8 ie_buf_len = 0; + unsigned char ie_buf[256]; + unsigned char *ptr_ie_buf = ie_buf; + unsigned char *ieeemgmtbuf = NULL; + u8 source_mac[ETH_ALEN]; + u16 capa_mask; + u16 capa_val; + + /* capinfo + listen interval */ + u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); + + /* capinfo + status code + associd */ + u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16); + + u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset; + u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len + + assoc_resp_ie_offset; + + assoc_req_len -= assoc_req_ie_offset; + assoc_resp_len -= assoc_resp_ie_offset; + + ar->auto_auth_stage = AUTH_IDLE; + + if (nw_type & ADHOC_NETWORK) { + if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: ath6k not in ibss mode\n", __func__); + return; + } + } + + if (nw_type & INFRA_NETWORK) { + if (ar->wdev->iftype != NL80211_IFTYPE_STATION) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: ath6k not in station mode\n", __func__); + return; + } + } + + if (nw_type & ADHOC_NETWORK) { + capa_mask = WLAN_CAPABILITY_IBSS; + capa_val = WLAN_CAPABILITY_IBSS; + } else { + capa_mask = WLAN_CAPABILITY_ESS; + capa_val = WLAN_CAPABILITY_ESS; + } + + /* Before informing the join/connect event, make sure that + * bss entry is present in scan list, if it not present + * construct and insert into scan list, otherwise that + * event will be dropped on the way by cfg80211, due to + * this keys will not be plumbed in case of WEP and + * application will not be aware of join/connect status. */ + bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid, + ar->wdev->ssid, ar->wdev->ssid_len, + capa_mask, capa_val); + + /* + * Earlier we were updating the cfg about bss by making a beacon frame + * only if the entry for bss is not there. This can have some issue if + * ROAM event is generated and a heavy traffic is ongoing. The ROAM + * event is handled through a work queue and by the time it really gets + * handled, BSS would have been aged out. So it is better to update the + * cfg about BSS irrespective of its entry being present right now or + * not. + */ + + if (nw_type & ADHOC_NETWORK) { + /* construct 802.11 mgmt beacon */ + if (ptr_ie_buf) { + *ptr_ie_buf++ = WLAN_EID_SSID; + *ptr_ie_buf++ = ar->ssid_len; + memcpy(ptr_ie_buf, ar->ssid, ar->ssid_len); + ptr_ie_buf += ar->ssid_len; + + *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS; + *ptr_ie_buf++ = 2; /* length */ + *ptr_ie_buf++ = 0; /* ATIM window */ + *ptr_ie_buf++ = 0; /* ATIM window */ + + /* TODO: update ibss params and include supported rates, + * DS param set, extened support rates, wmm. */ + + ie_buf_len = ptr_ie_buf - ie_buf; + } + + capability |= WLAN_CAPABILITY_IBSS; + + if (ar->prwise_crypto == WEP_CRYPT) + capability |= WLAN_CAPABILITY_PRIVACY; + + memcpy(source_mac, ar->net_dev->dev_addr, ETH_ALEN); + ptr_ie_buf = ie_buf; + } else { + capability = *(u16 *) (&assoc_info[beacon_ie_len]); + memcpy(source_mac, bssid, ETH_ALEN); + ptr_ie_buf = assoc_req_ie; + ie_buf_len = assoc_req_len; + } + + size = offsetof(struct ieee80211_mgmt, u) + + sizeof(mgmt->u.beacon) + + ie_buf_len; + + ieeemgmtbuf = kzalloc(size, GFP_ATOMIC); + if (!ieeemgmtbuf) { + ath6kl_err("ieee mgmt buf alloc error\n"); + cfg80211_put_bss(bss); + return; + } + + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_BEACON); + memset(mgmt->da, 0xff, ETH_ALEN); /* broadcast addr */ + memcpy(mgmt->sa, source_mac, ETH_ALEN); + memcpy(mgmt->bssid, bssid, ETH_ALEN); + mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_intvl); + mgmt->u.beacon.capab_info = cpu_to_le16(capability); + memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len); + + ibss_ch = ieee80211_get_channel(ar->wdev->wiphy, (int)channel); + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: inform bss with bssid %pM channel %d beacon_intvl %d capability 0x%x\n", + __func__, mgmt->bssid, ibss_ch->hw_value, + beacon_intvl, capability); + + bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, + ibss_ch, mgmt, + size, signal, GFP_KERNEL); + kfree(ieeemgmtbuf); + cfg80211_put_bss(bss); + + if (nw_type & ADHOC_NETWORK) { + cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL); + return; + } + + if (!test_bit(CONNECTED, &ar->flag)) { + /* inform connect result to cfg80211 */ + ar->sme_state = SME_DISCONNECTED; + cfg80211_connect_result(ar->net_dev, bssid, + assoc_req_ie, assoc_req_len, + assoc_resp_ie, assoc_resp_len, + WLAN_STATUS_SUCCESS, GFP_KERNEL); + } else { + /* inform roam event to cfg80211 */ + cfg80211_roamed(ar->net_dev, ibss_ch, bssid, + assoc_req_ie, assoc_req_len, + assoc_resp_ie, assoc_resp_len, GFP_KERNEL); + } +} + +static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, + struct net_device *dev, u16 reason_code) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev); + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__, + reason_code); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { + ath6kl_err("busy, destroy in progress\n"); + return -EBUSY; + } + + if (down_interruptible(&ar->sem)) { + ath6kl_err("busy, couldn't get access\n"); + return -ERESTARTSYS; + } + + ar->reconnect_flag = 0; + ath6kl_disconnect(ar); + memset(ar->ssid, 0, sizeof(ar->ssid)); + ar->ssid_len = 0; + + if (!test_bit(SKIP_SCAN, &ar->flag)) + memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); + + up(&ar->sem); + + return 0; +} + +void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, + u8 *bssid, u8 assoc_resp_len, + u8 *assoc_info, u16 proto_reason) +{ + struct ath6kl_key *key = NULL; + u16 status; + + if (ar->scan_req) { + cfg80211_scan_done(ar->scan_req, true); + ar->scan_req = NULL; + } + + if (ar->nw_type & ADHOC_NETWORK) { + if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: ath6k not in ibss mode\n", __func__); + return; + } + memset(bssid, 0, ETH_ALEN); + cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL); + return; + } + + if (ar->nw_type & INFRA_NETWORK) { + if (ar->wdev->iftype != NL80211_IFTYPE_STATION) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: ath6k not in station mode\n", __func__); + return; + } + } + + if (!test_bit(CONNECT_PEND, &ar->flag)) { + if (reason != DISCONNECT_CMD) + ath6kl_wmi_disconnect_cmd(ar->wmi); + + return; + } + + if (reason == NO_NETWORK_AVAIL) { + /* connect cmd failed */ + ath6kl_wmi_disconnect_cmd(ar->wmi); + return; + } + + if (reason != DISCONNECT_CMD) + return; + + if (!ar->auto_auth_stage) { + clear_bit(CONNECT_PEND, &ar->flag); + + if (ar->sme_state == SME_CONNECTING) { + cfg80211_connect_result(ar->net_dev, + bssid, NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else { + cfg80211_disconnected(ar->net_dev, reason, + NULL, 0, GFP_KERNEL); + } + + ar->sme_state = SME_DISCONNECTED; + return; + } + + if (ar->dot11_auth_mode != OPEN_AUTH) + return; + + /* + * If the current auth algorithm is open, try shared and + * make autoAuthStage idle. We do not make it leap for now + * being. + */ + key = &ar->keys[ar->def_txkey_index]; + if (down_interruptible(&ar->sem)) { + ath6kl_err("busy, couldn't get access\n"); + return; + } + + ar->dot11_auth_mode = SHARED_AUTH; + ar->auto_auth_stage = AUTH_IDLE; + + ath6kl_wmi_addkey_cmd(ar->wmi, + ar->def_txkey_index, + ar->prwise_crypto, + GROUP_USAGE | TX_USAGE, + key->key_len, NULL, + key->key, + KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + + status = ath6kl_wmi_connect_cmd(ar->wmi, + ar->nw_type, + ar->dot11_auth_mode, + ar->auth_mode, + ar->prwise_crypto, + ar->prwise_crypto_len, + ar->grp_crypto, + ar->grp_crpto_len, + ar->ssid_len, + ar->ssid, + ar->req_bssid, + ar->ch_hint, + ar->connect_ctrl_flags); + up(&ar->sem); +} + +static inline bool is_ch_11a(u16 ch) +{ + return (!((ch >= 2412) && (ch <= 2484))); +} + +static void ath6kl_cfg80211_scan_node(void *arg, struct bss *ni) +{ + struct wiphy *wiphy = (struct wiphy *)arg; + u16 size; + unsigned char *ieeemgmtbuf = NULL; + struct ieee80211_mgmt *mgmt; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + struct ath6kl_common_ie *cie; + s32 signal; + int freq; + + cie = &ni->ni_cie; + + if (is_ch_11a(cie->ie_chan)) + band = wiphy->bands[IEEE80211_BAND_5GHZ]; /* 11a */ + else if ((cie->ie_erp) || (cie->ie_xrates)) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11g */ + else + band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11b */ + + size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u); + ieeemgmtbuf = kmalloc(size, GFP_ATOMIC); + if (!ieeemgmtbuf) { + ath6kl_err("ieee mgmt buf alloc error\n"); + return; + } + + /* + * TODO: Update target to include 802.11 mac header while sending + * bss info. Target removes 802.11 mac header while sending the bss + * info to host, cfg80211 needs it, for time being just filling the + * da, sa and bssid fields alone. + */ + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + memset(mgmt->da, 0xff, ETH_ALEN); /*broadcast addr */ + memcpy(mgmt->sa, ni->ni_macaddr, ETH_ALEN); + memcpy(mgmt->bssid, ni->ni_macaddr, ETH_ALEN); + memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u), + ni->ni_buf, ni->ni_framelen); + + freq = cie->ie_chan; + channel = ieee80211_get_channel(wiphy, freq); + signal = ni->ni_snr * 100; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: bssid %pM ch %d freq %d size %d\n", __func__, + mgmt->bssid, channel->hw_value, freq, size); + cfg80211_inform_bss_frame(wiphy, channel, mgmt, + size, signal, GFP_KERNEL); + + kfree(ieeemgmtbuf); +} + +static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); + int ret = 0; + u32 force_fg_scan = 0; + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (!ar->usr_bss_filter) { + if (ath6kl_wmi_bssfilter_cmd(ar->wmi, + (test_bit(CONNECTED, &ar->flag) ? + ALL_BUT_BSS_FILTER : + ALL_BSS_FILTER), 0) != 0) { + ath6kl_err("couldn't set bss filtering\n"); + return -EIO; + } + } + + if (request->n_ssids && request->ssids[0].ssid_len) { + u8 i; + + if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) + request->n_ssids = MAX_PROBED_SSID_INDEX - 1; + + for (i = 0; i < request->n_ssids; i++) + ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1, + SPECIFIC_SSID_FLAG, + request->ssids[i].ssid_len, + request->ssids[i].ssid); + } + + if (test_bit(CONNECTED, &ar->flag)) + force_fg_scan = 1; + + if (ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, force_fg_scan, + false, 0, 0, 0, NULL) != 0) { + ath6kl_err("wmi_startscan_cmd failed\n"); + ret = -EIO; + } + + ar->scan_req = request; + + return ret; +} + +void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status) +{ + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status); + + if (ar->scan_req) { + /* Translate data to cfg80211 mgmt format */ + ath6kl_wmi_iterate_nodes(ar->wmi, ath6kl_cfg80211_scan_node, + ar->wdev->wiphy); + + cfg80211_scan_done(ar->scan_req, ((status & -ECANCELED) + || (status & -EBUSY)) ? true : + false); + + if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) { + u8 i; + + for (i = 0; i < ar->scan_req->n_ssids; i++) { + ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1, + DISABLE_SSID_FLAG, + 0, NULL); + } + } + ar->scan_req = NULL; + } +} + +static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); + struct ath6kl_key *key = NULL; + u8 key_usage; + u8 key_type; + int status = 0; + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: key index %d out of bounds\n", __func__, + key_index); + return -ENOENT; + } + + key = &ar->keys[key_index]; + memset(key, 0, sizeof(struct ath6kl_key)); + + if (pairwise) + key_usage = PAIRWISE_USAGE; + else + key_usage = GROUP_USAGE; + + if (params) { + if (params->key_len > WLAN_MAX_KEY_LEN || + params->seq_len > sizeof(key->seq)) + return -EINVAL; + + key->key_len = params->key_len; + memcpy(key->key, params->key, key->key_len); + key->seq_len = params->seq_len; + memcpy(key->seq, params->seq, key->seq_len); + key->cipher = params->cipher; + } + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + key_type = WEP_CRYPT; + break; + + case WLAN_CIPHER_SUITE_TKIP: + key_type = TKIP_CRYPT; + break; + + case WLAN_CIPHER_SUITE_CCMP: + key_type = AES_CRYPT; + break; + + default: + return -ENOTSUPP; + } + + if (((ar->auth_mode == WPA_PSK_AUTH) + || (ar->auth_mode == WPA2_PSK_AUTH)) + && (key_usage & GROUP_USAGE)) + del_timer(&ar->disconnect_timer); + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n", + __func__, key_index, key->key_len, key_type, + key_usage, key->seq_len); + + ar->def_txkey_index = key_index; + status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, + key_type, key_usage, key->key_len, + key->seq, key->key, KEY_OP_INIT_VAL, + (u8 *) mac_addr, SYNC_BOTH_WMIFLAG); + + if (status) + return -EIO; + + return 0; +} + +static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: key index %d out of bounds\n", __func__, + key_index); + return -ENOENT; + } + + if (!ar->keys[key_index].key_len) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: index %d is empty\n", __func__, key_index); + return 0; + } + + ar->keys[key_index].key_len = 0; + + return ath6kl_wmi_deletekey_cmd(ar->wmi, key_index); +} + +static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback) (void *cookie, + struct key_params *)) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); + struct ath6kl_key *key = NULL; + struct key_params params; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: key index %d out of bounds\n", __func__, + key_index); + return -ENOENT; + } + + key = &ar->keys[key_index]; + memset(¶ms, 0, sizeof(params)); + params.cipher = key->cipher; + params.key_len = key->key_len; + params.seq_len = key->seq_len; + params.seq = key->seq; + params.key = key->key; + + callback(cookie, ¶ms); + + return key->key_len ? 0 : -ENOENT; +} + +static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, + bool multicast) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); + struct ath6kl_key *key = NULL; + int status = 0; + u8 key_usage; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: key index %d out of bounds\n", + __func__, key_index); + return -ENOENT; + } + + if (!ar->keys[key_index].key_len) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n", + __func__, key_index); + return -EINVAL; + } + + ar->def_txkey_index = key_index; + key = &ar->keys[ar->def_txkey_index]; + key_usage = GROUP_USAGE; + if (ar->prwise_crypto == WEP_CRYPT) + key_usage |= TX_USAGE; + + status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, + ar->prwise_crypto, key_usage, + key->key_len, key->seq, key->key, + KEY_OP_INIT_VAL, NULL, + SYNC_BOTH_WMIFLAG); + if (status) + return -EIO; + + return 0; +} + +void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid, + bool ismcast) +{ + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast); + + cfg80211_michael_mic_failure(ar->net_dev, ar->bssid, + (ismcast ? NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE), keyid, NULL, + GFP_KERNEL); +} + +static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); + int ret; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__, + changed); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold); + if (ret != 0) { + ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n"); + return -EIO; + } + } + + return 0; +} + +/* + * The type nl80211_tx_power_setting replaces the following + * data type from 2.6.36 onwards +*/ +static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy, + enum nl80211_tx_power_setting type, + int dbm) +{ + struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); + u8 ath6kl_dbm; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__, + type, dbm); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + switch (type) { + case NL80211_TX_POWER_AUTOMATIC: + return 0; + case NL80211_TX_POWER_LIMITED: + ar->tx_pwr = ath6kl_dbm = dbm; + break; + default: + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n", + __func__, type); + return -EOPNOTSUPP; + } + + ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, ath6kl_dbm); + + return 0; +} + +static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) +{ + struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (test_bit(CONNECTED, &ar->flag)) { + ar->tx_pwr = 0; + + if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi) != 0) { + ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n"); + return -EIO; + } + + wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0, + 5 * HZ); + + if (signal_pending(current)) { + ath6kl_err("target did not respond\n"); + return -EINTR; + } + } + + *dbm = ar->tx_pwr; + return 0; +} + +static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool pmgmt, int timeout) +{ + struct ath6kl *ar = ath6kl_priv(dev); + struct wmi_power_mode_cmd mode; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n", + __func__, pmgmt, timeout); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + if (pmgmt) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__); + mode.pwr_mode = REC_POWER; + } else { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__); + mode.pwr_mode = MAX_PERF_POWER; + } + + if (ath6kl_wmi_powermode_cmd(ar->wmi, mode.pwr_mode) != 0) { + ath6kl_err("wmi_powermode_cmd failed\n"); + return -EIO; + } + + return 0; +} + +static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct ath6kl *ar = ath6kl_priv(ndev); + struct wireless_dev *wdev = ar->wdev; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + switch (type) { + case NL80211_IFTYPE_STATION: + ar->next_mode = INFRA_NETWORK; + break; + case NL80211_IFTYPE_ADHOC: + ar->next_mode = ADHOC_NETWORK; + break; + default: + ath6kl_err("invalid interface type %u\n", type); + return -EOPNOTSUPP; + } + + wdev->iftype = type; + + return 0; +} + +static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *ibss_param) +{ + struct ath6kl *ar = ath6kl_priv(dev); + int status; + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + ar->ssid_len = ibss_param->ssid_len; + memcpy(ar->ssid, ibss_param->ssid, ar->ssid_len); + + if (ibss_param->channel) + ar->ch_hint = ibss_param->channel->center_freq; + + if (ibss_param->channel_fixed) { + /* + * TODO: channel_fixed: The channel should be fixed, do not + * search for IBSSs to join on other channels. Target + * firmware does not support this feature, needs to be + * updated. + */ + return -EOPNOTSUPP; + } + + memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); + if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid)) + memcpy(ar->req_bssid, ibss_param->bssid, sizeof(ar->req_bssid)); + + ath6kl_set_wpa_version(ar, 0); + + status = ath6kl_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM); + if (status) + return status; + + if (ibss_param->privacy) { + ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true); + ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false); + } else { + ath6kl_set_cipher(ar, 0, true); + ath6kl_set_cipher(ar, 0, false); + } + + ar->nw_type = ar->next_mode; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: connect called with authmode %d dot11 auth %d" + " PW crypto %d PW crypto len %d GRP crypto %d" + " GRP crypto len %d channel hint %u\n", + __func__, + ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, + ar->prwise_crypto_len, ar->grp_crypto, + ar->grp_crpto_len, ar->ch_hint); + + status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, + ar->dot11_auth_mode, ar->auth_mode, + ar->prwise_crypto, + ar->prwise_crypto_len, + ar->grp_crypto, ar->grp_crpto_len, + ar->ssid_len, ar->ssid, + ar->req_bssid, ar->ch_hint, + ar->connect_ctrl_flags); + set_bit(CONNECT_PEND, &ar->flag); + + return 0; +} + +static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev); + + if (!ath6kl_cfg80211_ready(ar)) + return -EIO; + + ath6kl_disconnect(ar); + memset(ar->ssid, 0, sizeof(ar->ssid)); + ar->ssid_len = 0; + + return 0; +} + +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +static bool is_rate_legacy(s32 rate) +{ + static const s32 legacy[] = { 1000, 2000, 5500, 11000, + 6000, 9000, 12000, 18000, 24000, + 36000, 48000, 54000 + }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(legacy); i++) + if (rate == legacy[i]) + return true; + + return false; +} + +static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi) +{ + static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000, + 52000, 58500, 65000, 72200 + }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(ht20); i++) { + if (rate == ht20[i]) { + if (i == ARRAY_SIZE(ht20) - 1) + /* last rate uses sgi */ + *sgi = true; + else + *sgi = false; + + *mcs = i; + return true; + } + } + return false; +} + +static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi) +{ + static const s32 ht40[] = { 13500, 27000, 40500, 54000, + 81000, 108000, 121500, 135000, + 150000 + }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(ht40); i++) { + if (rate == ht40[i]) { + if (i == ARRAY_SIZE(ht40) - 1) + /* last rate uses sgi */ + *sgi = true; + else + *sgi = false; + + *mcs = i; + return true; + } + } + + return false; +} + +static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + struct ath6kl *ar = ath6kl_priv(dev); + long left; + bool sgi; + s32 rate; + int ret; + u8 mcs; + + if (memcmp(mac, ar->bssid, ETH_ALEN) != 0) + return -ENOENT; + + if (down_interruptible(&ar->sem)) + return -EBUSY; + + set_bit(STATS_UPDATE_PEND, &ar->flag); + + ret = ath6kl_wmi_get_stats_cmd(ar->wmi); + + if (ret != 0) { + up(&ar->sem); + return -EIO; + } + + left = wait_event_interruptible_timeout(ar->event_wq, + !test_bit(STATS_UPDATE_PEND, + &ar->flag), + WMI_TIMEOUT); + + up(&ar->sem); + + if (left == 0) + return -ETIMEDOUT; + else if (left < 0) + return left; + + if (ar->target_stats.rx_byte) { + sinfo->rx_bytes = ar->target_stats.rx_byte; + sinfo->filled |= STATION_INFO_RX_BYTES; + sinfo->rx_packets = ar->target_stats.rx_pkt; + sinfo->filled |= STATION_INFO_RX_PACKETS; + } + + if (ar->target_stats.tx_byte) { + sinfo->tx_bytes = ar->target_stats.tx_byte; + sinfo->filled |= STATION_INFO_TX_BYTES; + sinfo->tx_packets = ar->target_stats.tx_pkt; + sinfo->filled |= STATION_INFO_TX_PACKETS; + } + + sinfo->signal = ar->target_stats.cs_rssi; + sinfo->filled |= STATION_INFO_SIGNAL; + + rate = ar->target_stats.tx_ucast_rate; + + if (is_rate_legacy(rate)) { + sinfo->txrate.legacy = rate / 100; + } else if (is_rate_ht20(rate, &mcs, &sgi)) { + if (sgi) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.mcs = mcs - 1; + } else { + sinfo->txrate.mcs = mcs; + } + + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + } else if (is_rate_ht40(rate, &mcs, &sgi)) { + if (sgi) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.mcs = mcs - 1; + } else { + sinfo->txrate.mcs = mcs; + } + + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + } else { + ath6kl_warn("invalid rate: %d\n", rate); + return 0; + } + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + return 0; +} + +static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ath6kl *ar = ath6kl_priv(netdev); + return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid, + pmksa->pmkid, true); +} + +static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ath6kl *ar = ath6kl_priv(netdev); + return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid, + pmksa->pmkid, false); +} + +static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct ath6kl *ar = ath6kl_priv(netdev); + if (test_bit(CONNECTED, &ar->flag)) + return ath6kl_wmi_setpmkid_cmd(ar->wmi, ar->bssid, NULL, false); + return 0; +} + +static struct cfg80211_ops ath6kl_cfg80211_ops = { + .change_virtual_intf = ath6kl_cfg80211_change_iface, + .scan = ath6kl_cfg80211_scan, + .connect = ath6kl_cfg80211_connect, + .disconnect = ath6kl_cfg80211_disconnect, + .add_key = ath6kl_cfg80211_add_key, + .get_key = ath6kl_cfg80211_get_key, + .del_key = ath6kl_cfg80211_del_key, + .set_default_key = ath6kl_cfg80211_set_default_key, + .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params, + .set_tx_power = ath6kl_cfg80211_set_txpower, + .get_tx_power = ath6kl_cfg80211_get_txpower, + .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt, + .join_ibss = ath6kl_cfg80211_join_ibss, + .leave_ibss = ath6kl_cfg80211_leave_ibss, + .get_station = ath6kl_get_station, + .set_pmksa = ath6kl_set_pmksa, + .del_pmksa = ath6kl_del_pmksa, + .flush_pmksa = ath6kl_flush_pmksa, +}; + +struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) +{ + int ret = 0; + struct wireless_dev *wdev; + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) { + ath6kl_err("couldn't allocate wireless device\n"); + return NULL; + } + + /* create a new wiphy for use with cfg80211 */ + wdev->wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); + if (!wdev->wiphy) { + ath6kl_err("couldn't allocate wiphy device\n"); + kfree(wdev); + return NULL; + } + + /* set device pointer for wiphy */ + set_wiphy_dev(wdev->wiphy, dev); + + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* max num of ssids that can be probed during scanning */ + wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + ret = wiphy_register(wdev->wiphy); + if (ret < 0) { + ath6kl_err("couldn't register wiphy device\n"); + wiphy_free(wdev->wiphy); + kfree(wdev); + return NULL; + } + + return wdev; +} + +void ath6kl_cfg80211_deinit(struct ath6kl *ar) +{ + struct wireless_dev *wdev = ar->wdev; + + if (ar->scan_req) { + cfg80211_scan_done(ar->scan_req, true); + ar->scan_req = NULL; + } + + if (!wdev) + return; + + wiphy_unregister(wdev->wiphy); + wiphy_free(wdev->wiphy); + kfree(wdev); +} diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h new file mode 100644 index 000000000000..a84adc249c61 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ATH6KL_CFG80211_H +#define ATH6KL_CFG80211_H + +struct wireless_dev *ath6kl_cfg80211_init(struct device *dev); +void ath6kl_cfg80211_deinit(struct ath6kl *ar); + +void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status); + +void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, + u8 *bssid, u16 listen_intvl, + u16 beacon_intvl, + enum network_type nw_type, + u8 beacon_ie_len, u8 assoc_req_len, + u8 assoc_resp_len, u8 *assoc_info); + +void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, + u8 *bssid, u8 assoc_resp_len, + u8 *assoc_info, u16 proto_reason); + +void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid, + bool ismcast); + +#endif /* ATH6KL_CFG80211_H */ diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h new file mode 100644 index 000000000000..0a3a1d80d0a4 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/common.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef COMMON_H +#define COMMON_H + +#include <linux/netdevice.h> + +#define ATH6KL_MAX_IE 256 + +extern int ath6kl_printk(const char *level, const char *fmt, ...); + +#define A_CACHE_LINE_PAD 128 + +/* + * Reflects the version of binary interface exposed by ATH6KL target + * firmware. Needs to be incremented by 1 for any change in the firmware + * that requires upgrade of the driver on the host side for the change to + * work correctly + */ +#define ATH6KL_ABI_VERSION 1 + +#define SIGNAL_QUALITY_METRICS_NUM_MAX 2 + +enum { + SIGNAL_QUALITY_METRICS_SNR = 0, + SIGNAL_QUALITY_METRICS_RSSI, + SIGNAL_QUALITY_METRICS_ALL, +}; + +/* + * Data Path + */ + +#define WMI_MAX_TX_DATA_FRAME_LENGTH \ + (1500 + sizeof(struct wmi_data_hdr) + \ + sizeof(struct ethhdr) + \ + sizeof(struct ath6kl_llc_snap_hdr)) + +/* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */ +#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH \ + (3840 + sizeof(struct wmi_data_hdr) + \ + sizeof(struct ethhdr) + \ + sizeof(struct ath6kl_llc_snap_hdr)) + +#define EPPING_ALIGNMENT_PAD \ + (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) \ + - sizeof(struct htc_frame_hdr)) + +struct ath6kl_llc_snap_hdr { + u8 dsap; + u8 ssap; + u8 cntl; + u8 org_code[3]; + __be16 eth_type; +} __packed; + +enum crypto_type { + NONE_CRYPT = 0x01, + WEP_CRYPT = 0x02, + TKIP_CRYPT = 0x04, + AES_CRYPT = 0x08, +}; + +#define ATH6KL_NODE_HASHSIZE 32 +/* simple hash is enough for variation of macaddr */ +#define ATH6KL_NODE_HASH(addr) \ + (((const u8 *)(addr))[ETH_ALEN - 1] % \ + ATH6KL_NODE_HASHSIZE) + +/* + * Table of ath6kl_node instances. Each ieee80211com + * has at least one for holding the scan candidates. + * When operating as an access point or in ibss mode there + * is a second table for associated stations or neighbors. + */ +struct ath6kl_node_table { + void *nt_wmi; /* back reference */ + spinlock_t nt_nodelock; /* on node table */ + struct bss *nt_node_first; /* information of all nodes */ + struct bss *nt_node_last; /* information of all nodes */ + struct bss *nt_hash[ATH6KL_NODE_HASHSIZE]; + const char *nt_name; /* for debugging */ + u32 nt_node_age; /* node aging time */ +}; + +#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000 +#define WLAN_NODE_INACT_CNT 4 + +struct ath6kl_common_ie { + u16 ie_chan; + u8 *ie_tstamp; + u8 *ie_ssid; + u8 *ie_rates; + u8 *ie_xrates; + u8 *ie_country; + u8 *ie_wpa; + u8 *ie_rsn; + u8 *ie_wmm; + u8 *ie_ath; + u16 ie_capInfo; + u16 ie_beaconInt; + u8 *ie_tim; + u8 *ie_chswitch; + u8 ie_erp; + u8 *ie_wsc; + u8 *ie_htcap; + u8 *ie_htop; +}; + +struct bss { + u8 ni_macaddr[ETH_ALEN]; + u8 ni_snr; + s16 ni_rssi; + struct bss *ni_list_next; + struct bss *ni_list_prev; + struct bss *ni_hash_next; + struct bss *ni_hash_prev; + struct ath6kl_common_ie ni_cie; + u8 *ni_buf; + u16 ni_framelen; + struct ath6kl_node_table *ni_table; + u32 ni_refcnt; + + u32 ni_tstamp; + u32 ni_actcnt; +}; + +struct htc_endpoint_credit_dist; +struct ath6kl; +enum htc_credit_dist_reason; +struct htc_credit_state_info; + +struct bss *wlan_node_alloc(int wh_size); +void wlan_node_free(struct bss *ni); +void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, + const u8 *mac_addr); +struct bss *wlan_find_node(struct ath6kl_node_table *nt, + const u8 *mac_addr); +void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni); +void wlan_free_allnodes(struct ath6kl_node_table *nt); +void wlan_iterate_nodes(struct ath6kl_node_table *nt, + void (*f) (void *arg, struct bss *), + void *arg); + +void wlan_node_table_init(void *wmip, struct ath6kl_node_table *nt); +void wlan_node_table_cleanup(struct ath6kl_node_table *nt); + +void wlan_refresh_inactive_nodes(struct ath6kl_node_table *nt); + +struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 *ssid, + u32 ssid_len, bool is_wpa2, bool match_ssid); + +void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni); + +int ath6k_setup_credit_dist(void *htc_handle, + struct htc_credit_state_info *cred_info); +void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf, + struct list_head *epdist_list, + enum htc_credit_dist_reason reason); +void ath6k_credit_init(struct htc_credit_state_info *cred_inf, + struct list_head *ep_list, + int tot_credits); +void ath6k_seek_credits(struct htc_credit_state_info *cred_inf, + struct htc_endpoint_credit_dist *ep_dist); +struct ath6kl *ath6kl_core_alloc(struct device *sdev); +int ath6kl_core_init(struct ath6kl *ar); +int ath6kl_unavail_ev(struct ath6kl *ar); +struct sk_buff *ath6kl_buf_alloc(int size); +#endif /* COMMON_H */ diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h new file mode 100644 index 000000000000..86177f0b98a5 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef CORE_H +#define CORE_H + +#include <linux/etherdevice.h> +#include <linux/rtnetlink.h> +#include <linux/firmware.h> +#include <linux/sched.h> +#include <net/cfg80211.h> +#include "htc.h" +#include "wmi.h" +#include "bmi.h" + +#define MAX_ATH6KL 1 +#define ATH6KL_MAX_RX_BUFFERS 16 +#define ATH6KL_BUFFER_SIZE 1664 +#define ATH6KL_MAX_AMSDU_RX_BUFFERS 4 +#define ATH6KL_AMSDU_REFILL_THRESHOLD 3 +#define ATH6KL_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128) +#define MAX_MSDU_SUBFRAME_PAYLOAD_LEN 1508 +#define MIN_MSDU_SUBFRAME_PAYLOAD_LEN 46 + +#define USER_SAVEDKEYS_STAT_INIT 0 +#define USER_SAVEDKEYS_STAT_RUN 1 + +#define ATH6KL_TX_TIMEOUT 10 +#define ATH6KL_MAX_ENDPOINTS 4 +#define MAX_NODE_NUM 15 + +/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ +#define MAX_DEF_COOKIE_NUM 180 +#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ +#define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM) + +#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) + +#define DISCON_TIMER_INTVAL 10000 /* in msec */ +#define A_DEFAULT_LISTEN_INTERVAL 100 +#define A_MAX_WOW_LISTEN_INTERVAL 1000 + +/* AR6003 1.0 definitions */ +#define AR6003_REV1_VERSION 0x300002ba + +/* AR6003 2.0 definitions */ +#define AR6003_REV2_VERSION 0x30000384 +#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 +#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" +#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" +#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" +#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" + +/* AR6003 3.0 definitions */ +#define AR6003_REV3_VERSION 0x30000582 +#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" +#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" +#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" +#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \ + "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" + +/* Per STA data, used in AP mode */ +#define STA_PS_AWAKE BIT(0) +#define STA_PS_SLEEP BIT(1) +#define STA_PS_POLLED BIT(2) + +/* HTC TX packet tagging definitions */ +#define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED +#define ATH6KL_DATA_PKT_TAG (ATH6KL_CONTROL_PKT_TAG + 1) + +#define AR6003_CUST_DATA_SIZE 16 + +#define AGGR_WIN_IDX(x, y) ((x) % (y)) +#define AGGR_INCR_IDX(x, y) AGGR_WIN_IDX(((x) + 1), (y)) +#define AGGR_DCRM_IDX(x, y) AGGR_WIN_IDX(((x) - 1), (y)) +#define ATH6KL_MAX_SEQ_NO 0xFFF +#define ATH6KL_NEXT_SEQ_NO(x) (((x) + 1) & ATH6KL_MAX_SEQ_NO) + +#define NUM_OF_TIDS 8 +#define AGGR_SZ_DEFAULT 8 + +#define AGGR_WIN_SZ_MIN 2 +#define AGGR_WIN_SZ_MAX 8 + +#define TID_WINDOW_SZ(_x) ((_x) << 1) + +#define AGGR_NUM_OF_FREE_NETBUFS 16 + +#define AGGR_RX_TIMEOUT 400 /* in ms */ + +#define WMI_TIMEOUT (2 * HZ) + +#define MBOX_YIELD_LIMIT 99 + +/* configuration lags */ +/* + * ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in + * ERP IE of beacon to determine the short premable support when + * sending (Re)Assoc req. + * ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN: Don't send the power + * module state transition failure events which happen during + * scan, to the host. + */ +#define ATH6KL_CONF_IGNORE_ERP_BARKER BIT(0) +#define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1) +#define ATH6KL_CONF_ENABLE_11N BIT(2) +#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) + +enum wlan_low_pwr_state { + WLAN_POWER_STATE_ON, + WLAN_POWER_STATE_CUT_PWR, + WLAN_POWER_STATE_DEEP_SLEEP, + WLAN_POWER_STATE_WOW +}; + +enum sme_state { + SME_DISCONNECTED, + SME_CONNECTING, + SME_CONNECTED +}; + +enum ath6kl_wlan_state { + WLAN_DISABLED, + WLAN_ENABLED +}; + +struct skb_hold_q { + struct sk_buff *skb; + bool is_amsdu; + u16 seq_no; +}; + +struct rxtid { + bool aggr; + bool progress; + bool timer_mon; + u16 win_sz; + u16 seq_next; + u32 hold_q_sz; + struct skb_hold_q *hold_q; + struct sk_buff_head q; + spinlock_t lock; +}; + +struct rxtid_stats { + u32 num_into_aggr; + u32 num_dups; + u32 num_oow; + u32 num_mpdu; + u32 num_amsdu; + u32 num_delivered; + u32 num_timeouts; + u32 num_hole; + u32 num_bar; +}; + +struct aggr_info { + u8 aggr_sz; + u8 timer_scheduled; + struct timer_list timer; + struct net_device *dev; + struct rxtid rx_tid[NUM_OF_TIDS]; + struct sk_buff_head free_q; + struct rxtid_stats stat[NUM_OF_TIDS]; +}; + +struct ath6kl_wep_key { + u8 key_index; + u8 key_len; + u8 key[64]; +}; + +#define ATH6KL_KEY_SEQ_LEN 8 + +struct ath6kl_key { + u8 key[WLAN_MAX_KEY_LEN]; + u8 key_len; + u8 seq[ATH6KL_KEY_SEQ_LEN]; + u8 seq_len; + u32 cipher; +}; + +struct ath6kl_node_mapping { + u8 mac_addr[ETH_ALEN]; + u8 ep_id; + u8 tx_pend; +}; + +struct ath6kl_cookie { + struct sk_buff *skb; + u32 map_no; + struct htc_packet htc_pkt; + struct ath6kl_cookie *arc_list_next; +}; + +struct ath6kl_sta { + u16 sta_flags; + u8 mac[ETH_ALEN]; + u8 aid; + u8 keymgmt; + u8 ucipher; + u8 auth; + u8 wpa_ie[ATH6KL_MAX_IE]; + struct sk_buff_head psq; + spinlock_t psq_lock; +}; + +struct ath6kl_version { + u32 target_ver; + u32 wlan_ver; + u32 abi_ver; +}; + +struct ath6kl_bmi { + u32 cmd_credits; + bool done_sent; + u8 *cmd_buf; +}; + +struct target_stats { + u64 tx_pkt; + u64 tx_byte; + u64 tx_ucast_pkt; + u64 tx_ucast_byte; + u64 tx_mcast_pkt; + u64 tx_mcast_byte; + u64 tx_bcast_pkt; + u64 tx_bcast_byte; + u64 tx_rts_success_cnt; + u64 tx_pkt_per_ac[4]; + + u64 tx_err; + u64 tx_fail_cnt; + u64 tx_retry_cnt; + u64 tx_mult_retry_cnt; + u64 tx_rts_fail_cnt; + + u64 rx_pkt; + u64 rx_byte; + u64 rx_ucast_pkt; + u64 rx_ucast_byte; + u64 rx_mcast_pkt; + u64 rx_mcast_byte; + u64 rx_bcast_pkt; + u64 rx_bcast_byte; + u64 rx_frgment_pkt; + + u64 rx_err; + u64 rx_crc_err; + u64 rx_key_cache_miss; + u64 rx_decrypt_err; + u64 rx_dupl_frame; + + u64 tkip_local_mic_fail; + u64 tkip_cnter_measures_invoked; + u64 tkip_replays; + u64 tkip_fmt_err; + u64 ccmp_fmt_err; + u64 ccmp_replays; + + u64 pwr_save_fail_cnt; + + u64 cs_bmiss_cnt; + u64 cs_low_rssi_cnt; + u64 cs_connect_cnt; + u64 cs_discon_cnt; + + s32 tx_ucast_rate; + s32 rx_ucast_rate; + + u32 lq_val; + + u32 wow_pkt_dropped; + u16 wow_evt_discarded; + + s16 noise_floor_calib; + s16 cs_rssi; + s16 cs_ave_beacon_rssi; + u8 cs_ave_beacon_snr; + u8 cs_last_roam_msec; + u8 cs_snr; + + u8 wow_host_pkt_wakeups; + u8 wow_host_evt_wakeups; + + u32 arp_received; + u32 arp_matched; + u32 arp_replied; +}; + +struct ath6kl_mbox_info { + u32 htc_addr; + u32 htc_ext_addr; + u32 htc_ext_sz; + + u32 block_size; + + u32 gmbox_addr; + + u32 gmbox_sz; +}; + +/* + * 802.11i defines an extended IV for use with non-WEP ciphers. + * When the EXTIV bit is set in the key id byte an additional + * 4 bytes immediately follow the IV for TKIP. For CCMP the + * EXTIV bit is likewise set but the 8 bytes represent the + * CCMP header rather than IV+extended-IV. + */ + +#define ATH6KL_KEYBUF_SIZE 16 +#define ATH6KL_MICBUF_SIZE (8+8) /* space for both tx and rx */ + +#define ATH6KL_KEY_XMIT 0x01 +#define ATH6KL_KEY_RECV 0x02 +#define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */ + +/* + * WPA/RSN get/set key request. Specify the key/cipher + * type and whether the key is to be used for sending and/or + * receiving. The key index should be set only when working + * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). + * Otherwise a unicast/pairwise key is specified by the bssid + * (on a station) or mac address (on an ap). They key length + * must include any MIC key data; otherwise it should be no + * more than ATH6KL_KEYBUF_SIZE. + */ +struct ath6kl_req_key { + u8 ik_type; /* key/cipher type */ + u8 ik_pad; + u16 ik_keyix; /* key index */ + u8 ik_keylen; /* key length in bytes */ + u8 ik_flags; + u8 ik_macaddr[ETH_ALEN]; + u64 ik_keyrsc; /* key receive sequence counter */ + u64 ik_keytsc; /* key transmit sequence counter */ + u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE]; +}; + +/* Flag info */ +#define WMI_ENABLED 0 +#define WMI_READY 1 +#define CONNECTED 2 +#define STATS_UPDATE_PEND 3 +#define CONNECT_PEND 4 +#define WMM_ENABLED 5 +#define NETQ_STOPPED 6 +#define WMI_CTRL_EP_FULL 7 +#define DTIM_EXPIRED 8 +#define DESTROY_IN_PROGRESS 9 +#define NETDEV_REGISTERED 10 +#define SKIP_SCAN 11 + +struct ath6kl { + struct device *dev; + struct net_device *net_dev; + struct ath6kl_bmi bmi; + const struct ath6kl_hif_ops *hif_ops; + struct wmi *wmi; + int tx_pending[ENDPOINT_MAX]; + int total_tx_data_pend; + struct htc_target *htc_target; + void *hif_priv; + spinlock_t lock; + struct semaphore sem; + int ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 next_mode; + u8 nw_type; + u8 dot11_auth_mode; + u8 auth_mode; + u8 prwise_crypto; + u8 prwise_crypto_len; + u8 grp_crypto; + u8 grp_crpto_len; + u8 def_txkey_index; + struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; + u8 bssid[ETH_ALEN]; + u8 req_bssid[ETH_ALEN]; + u16 ch_hint; + u16 bss_ch; + u16 listen_intvl_b; + u16 listen_intvl_t; + struct ath6kl_version version; + u32 target_type; + u8 tx_pwr; + struct net_device_stats net_stats; + struct target_stats target_stats; + enum ath6kl_wlan_state wlan_state; + struct ath6kl_node_mapping node_map[MAX_NODE_NUM]; + u8 ibss_ps_enable; + u8 node_num; + u8 next_ep_id; + struct ath6kl_cookie *cookie_list; + u32 cookie_count; + enum htc_endpoint_id ac2ep_map[WMM_NUM_AC]; + bool ac_stream_active[WMM_NUM_AC]; + u8 ac_stream_pri_map[WMM_NUM_AC]; + u8 hiac_stream_active_pri; + u8 ep2ac_map[ENDPOINT_MAX]; + enum htc_endpoint_id ctrl_ep; + struct htc_credit_state_info credit_state_info; + u32 connect_ctrl_flags; + u32 user_key_ctrl; + u8 usr_bss_filter; + struct ath6kl_sta sta_list[AP_MAX_NUM_STA]; + u8 sta_list_index; + struct ath6kl_req_key ap_mode_bkey; + struct sk_buff_head mcastpsq; + spinlock_t mcastpsq_lock; + u8 intra_bss; + struct aggr_info *aggr_cntxt; + struct wmi_ap_mode_stat ap_stats; + u8 ap_country_code[3]; + struct list_head amsdu_rx_buffer_queue; + struct timer_list disconnect_timer; + u8 rx_meta_ver; + struct wireless_dev *wdev; + struct cfg80211_scan_request *scan_req; + struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; + enum sme_state sme_state; + enum wlan_low_pwr_state wlan_pwr_state; + struct wmi_scan_params_cmd sc_params; +#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 + u8 auto_auth_stage; + + u16 conf_flags; + wait_queue_head_t event_wq; + struct ath6kl_mbox_info mbox_info; + + struct ath6kl_cookie cookie_mem[MAX_COOKIE_NUM]; + int reconnect_flag; + unsigned long flag; + + u8 *fw_board; + size_t fw_board_len; + + u8 *fw_otp; + size_t fw_otp_len; + + u8 *fw; + size_t fw_len; + + u8 *fw_patch; + size_t fw_patch_len; + + struct workqueue_struct *ath6kl_wq; +}; + +static inline void *ath6kl_priv(struct net_device *dev) +{ + return wdev_priv(dev->ieee80211_ptr); +} + +static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info + *cred_info, + struct htc_endpoint_credit_dist + *ep_dist, int credits) +{ + ep_dist->credits += credits; + ep_dist->cred_assngd += credits; + cred_info->cur_free_credits -= credits; +} + +void ath6kl_destroy(struct net_device *dev, unsigned int unregister); +int ath6kl_configure_target(struct ath6kl *ar); +void ath6kl_detect_error(unsigned long ptr); +void disconnect_timer_handler(unsigned long ptr); +void init_netdev(struct net_device *dev); +void ath6kl_cookie_init(struct ath6kl *ar); +void ath6kl_cookie_cleanup(struct ath6kl *ar); +void ath6kl_rx(struct htc_target *target, struct htc_packet *packet); +void ath6kl_tx_complete(void *context, struct list_head *packet_queue); +enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, + struct htc_packet *packet); +void ath6kl_stop_txrx(struct ath6kl *ar); +void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar); +int ath6kl_access_datadiag(struct ath6kl *ar, u32 address, + u8 *data, u32 length, bool read); +int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data); +void ath6kl_init_profile_info(struct ath6kl *ar); +void ath6kl_tx_data_cleanup(struct ath6kl *ar); +void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile, + bool get_dbglogs); + +struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar); +void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); +int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); + +struct aggr_info *aggr_init(struct net_device *dev); +void ath6kl_rx_refill(struct htc_target *target, + enum htc_endpoint_id endpoint); +void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); +struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target, + enum htc_endpoint_id endpoint, + int len); +void aggr_module_destroy(struct aggr_info *aggr_info); +void aggr_reset_state(struct aggr_info *aggr_info); + +struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 * node_addr); +struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); + +void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver); +int ath6kl_control_tx(void *devt, struct sk_buff *skb, + enum htc_endpoint_id eid); +void ath6kl_connect_event(struct ath6kl *ar, u16 channel, + u8 *bssid, u16 listen_int, + u16 beacon_int, enum network_type net_type, + u8 beacon_ie_len, u8 assoc_req_len, + u8 assoc_resp_len, u8 *assoc_info); +void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, + u8 *bssid, u8 assoc_resp_len, + u8 *assoc_info, u16 prot_reason_status); +void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast); +void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr); +void ath6kl_scan_complete_evt(struct ath6kl *ar, int status); +void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len); +void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active); +enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac); + +void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid); + +void ath6kl_dtimexpiry_event(struct ath6kl *ar); +void ath6kl_disconnect(struct ath6kl *ar); +void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); +void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, + u8 win_sz); +void ath6kl_wakeup_event(void *dev); +void ath6kl_target_failure(struct ath6kl *ar); + +#endif /* CORE_H */ diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c new file mode 100644 index 000000000000..316136c8b903 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "debug.h" + +int ath6kl_printk(const char *level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int rtn; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + rtn = printk("%sath6kl: %pV", level, &vaf); + + va_end(args); + + return rtn; +} + +#ifdef CONFIG_ATH6KL_DEBUG +void ath6kl_dump_registers(struct ath6kl_device *dev, + struct ath6kl_irq_proc_registers *irq_proc_reg, + struct ath6kl_irq_enable_reg *irq_enable_reg) +{ + + ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n")); + + if (irq_proc_reg != NULL) { + ath6kl_dbg(ATH6KL_DBG_ANY, + "Host Int status: 0x%x\n", + irq_proc_reg->host_int_status); + ath6kl_dbg(ATH6KL_DBG_ANY, + "CPU Int status: 0x%x\n", + irq_proc_reg->cpu_int_status); + ath6kl_dbg(ATH6KL_DBG_ANY, + "Error Int status: 0x%x\n", + irq_proc_reg->error_int_status); + ath6kl_dbg(ATH6KL_DBG_ANY, + "Counter Int status: 0x%x\n", + irq_proc_reg->counter_int_status); + ath6kl_dbg(ATH6KL_DBG_ANY, + "Mbox Frame: 0x%x\n", + irq_proc_reg->mbox_frame); + ath6kl_dbg(ATH6KL_DBG_ANY, + "Rx Lookahead Valid: 0x%x\n", + irq_proc_reg->rx_lkahd_valid); + ath6kl_dbg(ATH6KL_DBG_ANY, + "Rx Lookahead 0: 0x%x\n", + irq_proc_reg->rx_lkahd[0]); + ath6kl_dbg(ATH6KL_DBG_ANY, + "Rx Lookahead 1: 0x%x\n", + irq_proc_reg->rx_lkahd[1]); + + if (dev->ar->mbox_info.gmbox_addr != 0) { + /* + * If the target supports GMBOX hardware, dump some + * additional state. + */ + ath6kl_dbg(ATH6KL_DBG_ANY, + "GMBOX Host Int status 2: 0x%x\n", + irq_proc_reg->host_int_status2); + ath6kl_dbg(ATH6KL_DBG_ANY, + "GMBOX RX Avail: 0x%x\n", + irq_proc_reg->gmbox_rx_avail); + ath6kl_dbg(ATH6KL_DBG_ANY, + "GMBOX lookahead alias 0: 0x%x\n", + irq_proc_reg->rx_gmbox_lkahd_alias[0]); + ath6kl_dbg(ATH6KL_DBG_ANY, + "GMBOX lookahead alias 1: 0x%x\n", + irq_proc_reg->rx_gmbox_lkahd_alias[1]); + } + + } + + if (irq_enable_reg != NULL) { + ath6kl_dbg(ATH6KL_DBG_ANY, + "Int status Enable: 0x%x\n", + irq_enable_reg->int_status_en); + ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n", + irq_enable_reg->cntr_int_status_en); + } + ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n"); +} + +static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) +{ + ath6kl_dbg(ATH6KL_DBG_ANY, + "--- endpoint: %d svc_id: 0x%X ---\n", + ep_dist->endpoint, ep_dist->svc_id); + ath6kl_dbg(ATH6KL_DBG_ANY, " dist_flags : 0x%X\n", + ep_dist->dist_flags); + ath6kl_dbg(ATH6KL_DBG_ANY, " cred_norm : %d\n", + ep_dist->cred_norm); + ath6kl_dbg(ATH6KL_DBG_ANY, " cred_min : %d\n", + ep_dist->cred_min); + ath6kl_dbg(ATH6KL_DBG_ANY, " credits : %d\n", + ep_dist->credits); + ath6kl_dbg(ATH6KL_DBG_ANY, " cred_assngd : %d\n", + ep_dist->cred_assngd); + ath6kl_dbg(ATH6KL_DBG_ANY, " seek_cred : %d\n", + ep_dist->seek_cred); + ath6kl_dbg(ATH6KL_DBG_ANY, " cred_sz : %d\n", + ep_dist->cred_sz); + ath6kl_dbg(ATH6KL_DBG_ANY, " cred_per_msg : %d\n", + ep_dist->cred_per_msg); + ath6kl_dbg(ATH6KL_DBG_ANY, " cred_to_dist : %d\n", + ep_dist->cred_to_dist); + ath6kl_dbg(ATH6KL_DBG_ANY, " txq_depth : %d\n", + get_queue_depth(&((struct htc_endpoint *) + ep_dist->htc_rsvd)->txq)); + ath6kl_dbg(ATH6KL_DBG_ANY, + "----------------------------------\n"); +} + +void dump_cred_dist_stats(struct htc_target *target) +{ + struct htc_endpoint_credit_dist *ep_list; + + if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC)) + return; + + list_for_each_entry(ep_list, &target->cred_dist_list, list) + dump_cred_dist(ep_list); + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:%p dist:%p\n", + target->cred_dist_cntxt, NULL); + ath6kl_dbg(ATH6KL_DBG_TRC, "credit distribution, total : %d, free : %d\n", + target->cred_dist_cntxt->total_avail_credits, + target->cred_dist_cntxt->cur_free_credits); +} + +#endif diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h new file mode 100644 index 000000000000..2e6058856a6a --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include "htc_hif.h" + +enum ATH6K_DEBUG_MASK { + ATH6KL_DBG_WLAN_CONNECT = BIT(0), /* wlan connect */ + ATH6KL_DBG_WLAN_SCAN = BIT(1), /* wlan scan */ + ATH6KL_DBG_WLAN_TX = BIT(2), /* wlan tx */ + ATH6KL_DBG_WLAN_RX = BIT(3), /* wlan rx */ + ATH6KL_DBG_BMI = BIT(4), /* bmi tracing */ + ATH6KL_DBG_HTC_SEND = BIT(5), /* htc send */ + ATH6KL_DBG_HTC_RECV = BIT(6), /* htc recv */ + ATH6KL_DBG_IRQ = BIT(7), /* interrupt processing */ + ATH6KL_DBG_PM = BIT(8), /* power management */ + ATH6KL_DBG_WLAN_NODE = BIT(9), /* general wlan node tracing */ + ATH6KL_DBG_WMI = BIT(10), /* wmi tracing */ + ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */ + ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */ + ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */ + ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx and wmi frames */ + ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ +}; + +extern unsigned int debug_mask; +extern int ath6kl_printk(const char *level, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#define ath6kl_info(fmt, ...) \ + ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) +#define ath6kl_err(fmt, ...) \ + ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__) +#define ath6kl_warn(fmt, ...) \ + ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) + +#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) + +#ifdef CONFIG_ATH6KL_DEBUG +#define ath6kl_dbg(mask, fmt, ...) \ + ({ \ + int rtn; \ + if (debug_mask & mask) \ + rtn = ath6kl_printk(KERN_DEBUG, fmt, ##__VA_ARGS__); \ + else \ + rtn = 0; \ + \ + rtn; \ + }) + +static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, + const char *msg, const void *buf, + size_t len) +{ + if (debug_mask & mask) { + ath6kl_dbg(mask, "%s\n", msg); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); + } +} + +void ath6kl_dump_registers(struct ath6kl_device *dev, + struct ath6kl_irq_proc_registers *irq_proc_reg, + struct ath6kl_irq_enable_reg *irq_en_reg); +void dump_cred_dist_stats(struct htc_target *target); +#else +static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, + const char *fmt, ...) +{ + return 0; +} + +static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, + const char *msg, const void *buf, + size_t len) +{ +} + +static inline void ath6kl_dump_registers(struct ath6kl_device *dev, + struct ath6kl_irq_proc_registers *irq_proc_reg, + struct ath6kl_irq_enable_reg *irq_en_reg) +{ + +} +static inline void dump_cred_dist_stats(struct htc_target *target) +{ +} +#endif + +#endif diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h new file mode 100644 index 000000000000..ad4966917e84 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HIF_OPS_H +#define HIF_OPS_H + +#include "hif.h" + +static inline int hif_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, + u32 len, u32 request) +{ + return ar->hif_ops->read_write_sync(ar, addr, buf, len, request); +} + +static inline int hif_write_async(struct ath6kl *ar, u32 address, u8 *buffer, + u32 length, u32 request, + struct htc_packet *packet) +{ + return ar->hif_ops->write_async(ar, address, buffer, length, + request, packet); +} +static inline void ath6kl_hif_irq_enable(struct ath6kl *ar) +{ + return ar->hif_ops->irq_enable(ar); +} + +static inline void ath6kl_hif_irq_disable(struct ath6kl *ar) +{ + return ar->hif_ops->irq_disable(ar); +} + +static inline struct hif_scatter_req *hif_scatter_req_get(struct ath6kl *ar) +{ + return ar->hif_ops->scatter_req_get(ar); +} + +static inline void hif_scatter_req_add(struct ath6kl *ar, + struct hif_scatter_req *s_req) +{ + return ar->hif_ops->scatter_req_add(ar, s_req); +} + +static inline int ath6kl_hif_enable_scatter(struct ath6kl *ar, + struct hif_dev_scat_sup_info *info) +{ + return ar->hif_ops->enable_scatter(ar, info); +} + +static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar) +{ + return ar->hif_ops->cleanup_scatter(ar); +} + +#endif diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h new file mode 100644 index 000000000000..7d39c1769fe4 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/hif.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HIF_H +#define HIF_H + +#include "common.h" +#include "core.h" + +#include <linux/scatterlist.h> + +#define BUS_REQUEST_MAX_NUM 64 +#define HIF_MBOX_BLOCK_SIZE 128 +#define HIF_MBOX0_BLOCK_SIZE 1 + +#define HIF_DMA_BUFFER_SIZE (32 * 1024) +#define CMD53_FIXED_ADDRESS 1 +#define CMD53_INCR_ADDRESS 2 + +#define MAX_SCATTER_REQUESTS 4 +#define MAX_SCATTER_ENTRIES_PER_REQ 16 +#define MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024) + +#define MANUFACTURER_ID_AR6003_BASE 0x300 + /* SDIO manufacturer ID and Codes */ +#define MANUFACTURER_ID_ATH6KL_BASE_MASK 0xFF00 +#define MANUFACTURER_CODE 0x271 /* Atheros */ + +/* Mailbox address in SDIO address space */ +#define HIF_MBOX_BASE_ADDR 0x800 +#define HIF_MBOX_WIDTH 0x800 + +#define HIF_MBOX_END_ADDR (HTC_MAILBOX_NUM_MAX * HIF_MBOX_WIDTH - 1) + +/* version 1 of the chip has only a 12K extended mbox range */ +#define HIF_MBOX0_EXT_BASE_ADDR 0x4000 +#define HIF_MBOX0_EXT_WIDTH (12*1024) + +/* GMBOX addresses */ +#define HIF_GMBOX_BASE_ADDR 0x7000 +#define HIF_GMBOX_WIDTH 0x4000 + +/* interrupt mode register */ +#define CCCR_SDIO_IRQ_MODE_REG 0xF0 + +/* mode to enable special 4-bit interrupt assertion without clock */ +#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) + +struct bus_request { + struct list_head list; + + /* request data */ + u32 address; + + u8 *buffer; + u32 length; + u32 request; + struct htc_packet *packet; + int status; + + /* this is a scatter request */ + struct hif_scatter_req *scat_req; +}; + +/* direction of transfer (read/write) */ +#define HIF_READ 0x00000001 +#define HIF_WRITE 0x00000002 +#define HIF_DIR_MASK (HIF_READ | HIF_WRITE) + +/* + * emode - This indicates the whether the command is to be executed in a + * blocking or non-blocking fashion (HIF_SYNCHRONOUS/ + * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been + * implemented using the asynchronous mode allowing the the bus + * driver to indicate the completion of operation through the + * registered callback routine. The requirement primarily comes + * from the contexts these operations get called from (a driver's + * transmit context or the ISR context in case of receive). + * Support for both of these modes is essential. + */ +#define HIF_SYNCHRONOUS 0x00000010 +#define HIF_ASYNCHRONOUS 0x00000020 +#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS) + +/* + * dmode - An interface may support different kinds of commands based on + * the tradeoff between the amount of data it can carry and the + * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/ + * HIF_BLOCK_BASIS). In case of latter, the data is rounded off + * to the nearest block size by padding. The size of the block is + * configurable at compile time using the HIF_BLOCK_SIZE and is + * negotiated with the target during initialization after the + * ATH6KL interrupts are enabled. + */ +#define HIF_BYTE_BASIS 0x00000040 +#define HIF_BLOCK_BASIS 0x00000080 +#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS) + +/* + * amode - This indicates if the address has to be incremented on ATH6KL + * after every read/write operation (HIF?FIXED_ADDRESS/ + * HIF_INCREMENTAL_ADDRESS). + */ +#define HIF_FIXED_ADDRESS 0x00000100 +#define HIF_INCREMENTAL_ADDRESS 0x00000200 +#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_WR_ASYNC_BYTE_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | \ + HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_WR_ASYNC_BLOCK_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | \ + HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_WR_SYNC_BYTE_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | \ + HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) + +#define HIF_WR_SYNC_BYTE_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | \ + HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_WR_SYNC_BLOCK_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | \ + HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_RD_SYNC_BYTE_INC \ + (HIF_READ | HIF_SYNCHRONOUS | \ + HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_RD_SYNC_BYTE_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | \ + HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) + +#define HIF_RD_ASYNC_BLOCK_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | \ + HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) + +#define HIF_RD_SYNC_BLOCK_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | \ + HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) + +struct hif_scatter_item { + u8 *buf; + int len; + struct htc_packet *packet; +}; + +struct hif_scatter_req { + struct list_head list; + /* address for the read/write operation */ + u32 addr; + + /* request flags */ + u32 req; + + /* total length of entire transfer */ + u32 len; + + u32 flags; + void (*complete) (struct hif_scatter_req *); + int status; + struct htc_endpoint *ep; + int scat_entries; + + struct hif_scatter_req_priv *req_priv; + + /* bounce buffer for upper layers to copy to/from */ + u8 *virt_dma_buf; + + struct hif_scatter_item scat_list[1]; +}; + +struct hif_dev_scat_sup_info { + int (*rw_scat_func) (struct ath6kl *ar, struct hif_scatter_req *); + int max_scat_entries; + int max_xfer_szper_scatreq; +}; + +struct hif_scatter_req_priv { + struct bus_request *busrequest; + struct scatterlist sgentries[MAX_SCATTER_ENTRIES_PER_REQ]; +}; + +struct ath6kl_hif_ops { + int (*read_write_sync)(struct ath6kl *ar, u32 addr, u8 *buf, + u32 len, u32 request); + int (*write_async)(struct ath6kl *ar, u32 address, u8 *buffer, + u32 length, u32 request, struct htc_packet *packet); + + void (*irq_enable)(struct ath6kl *ar); + void (*irq_disable)(struct ath6kl *ar); + + struct hif_scatter_req *(*scatter_req_get)(struct ath6kl *ar); + void (*scatter_req_add)(struct ath6kl *ar, + struct hif_scatter_req *s_req); + int (*enable_scatter)(struct ath6kl *ar, + struct hif_dev_scat_sup_info *info); + void (*cleanup_scatter)(struct ath6kl *ar); +}; + +#endif diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c new file mode 100644 index 000000000000..95c47bbd1d78 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc.c @@ -0,0 +1,2466 @@ +/* + * Copyright (c) 2007-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "htc_hif.h" +#include "debug.h" +#include "hif-ops.h" +#include <asm/unaligned.h> + +#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) + +static void htc_prep_send_pkt(struct htc_packet *packet, u8 flags, int ctrl0, + int ctrl1) +{ + struct htc_frame_hdr *hdr; + + packet->buf -= HTC_HDR_LENGTH; + hdr = (struct htc_frame_hdr *)packet->buf; + + /* Endianess? */ + put_unaligned((u16)packet->act_len, &hdr->payld_len); + hdr->flags = flags; + hdr->eid = packet->endpoint; + hdr->ctrl[0] = ctrl0; + hdr->ctrl[1] = ctrl1; +} + +static void htc_reclaim_txctrl_buf(struct htc_target *target, + struct htc_packet *pkt) +{ + spin_lock_bh(&target->htc_lock); + list_add_tail(&pkt->list, &target->free_ctrl_txbuf); + spin_unlock_bh(&target->htc_lock); +} + +static struct htc_packet *htc_get_control_buf(struct htc_target *target, + bool tx) +{ + struct htc_packet *packet = NULL; + struct list_head *buf_list; + + buf_list = tx ? &target->free_ctrl_txbuf : &target->free_ctrl_rxbuf; + + spin_lock_bh(&target->htc_lock); + + if (list_empty(buf_list)) { + spin_unlock_bh(&target->htc_lock); + return NULL; + } + + packet = list_first_entry(buf_list, struct htc_packet, list); + list_del(&packet->list); + spin_unlock_bh(&target->htc_lock); + + if (tx) + packet->buf = packet->buf_start + HTC_HDR_LENGTH; + + return packet; +} + +static void htc_tx_comp_update(struct htc_target *target, + struct htc_endpoint *endpoint, + struct htc_packet *packet) +{ + packet->completion = NULL; + packet->buf += HTC_HDR_LENGTH; + + if (!packet->status) + return; + + ath6kl_err("req failed (status:%d, ep:%d, len:%d creds:%d)\n", + packet->status, packet->endpoint, packet->act_len, + packet->info.tx.cred_used); + + /* on failure to submit, reclaim credits for this packet */ + spin_lock_bh(&target->tx_lock); + endpoint->cred_dist.cred_to_dist += + packet->info.tx.cred_used; + endpoint->cred_dist.txq_depth = get_queue_depth(&endpoint->txq); + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n", + target->cred_dist_cntxt, &target->cred_dist_list); + + ath6k_credit_distribute(target->cred_dist_cntxt, + &target->cred_dist_list, + HTC_CREDIT_DIST_SEND_COMPLETE); + + spin_unlock_bh(&target->tx_lock); +} + +static void htc_tx_complete(struct htc_endpoint *endpoint, + struct list_head *txq) +{ + if (list_empty(txq)) + return; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "send complete ep %d, (%d pkts)\n", + endpoint->eid, get_queue_depth(txq)); + + ath6kl_tx_complete(endpoint->target->dev->ar, txq); +} + +static void htc_tx_comp_handler(struct htc_target *target, + struct htc_packet *packet) +{ + struct htc_endpoint *endpoint = &target->endpoint[packet->endpoint]; + struct list_head container; + + htc_tx_comp_update(target, endpoint, packet); + INIT_LIST_HEAD(&container); + list_add_tail(&packet->list, &container); + /* do completion */ + htc_tx_complete(endpoint, &container); +} + +static void htc_async_tx_scat_complete(struct hif_scatter_req *scat_req) +{ + struct htc_endpoint *endpoint = scat_req->ep; + struct htc_target *target = endpoint->target; + struct htc_packet *packet; + struct list_head tx_compq; + int i; + + INIT_LIST_HEAD(&tx_compq); + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "htc_async_tx_scat_complete total len: %d entries: %d\n", + scat_req->len, scat_req->scat_entries); + + if (scat_req->status) + ath6kl_err("send scatter req failed: %d\n", scat_req->status); + + /* walk through the scatter list and process */ + for (i = 0; i < scat_req->scat_entries; i++) { + packet = scat_req->scat_list[i].packet; + if (!packet) { + WARN_ON(1); + return; + } + + packet->status = scat_req->status; + htc_tx_comp_update(target, endpoint, packet); + list_add_tail(&packet->list, &tx_compq); + } + + /* free scatter request */ + hif_scatter_req_add(target->dev->ar, scat_req); + + /* complete all packets */ + htc_tx_complete(endpoint, &tx_compq); +} + +static int htc_issue_send(struct htc_target *target, struct htc_packet *packet) +{ + int status; + bool sync = false; + u32 padded_len, send_len; + + if (!packet->completion) + sync = true; + + send_len = packet->act_len + HTC_HDR_LENGTH; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s: transmit len : %d (%s)\n", + __func__, send_len, sync ? "sync" : "async"); + + padded_len = CALC_TXRX_PADDED_LEN(target->dev, send_len); + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "DevSendPacket, padded len: %d mbox:0x%X (mode:%s)\n", + padded_len, + target->dev->ar->mbox_info.htc_addr, + sync ? "sync" : "async"); + + if (sync) { + status = hif_read_write_sync(target->dev->ar, + target->dev->ar->mbox_info.htc_addr, + packet->buf, padded_len, + HIF_WR_SYNC_BLOCK_INC); + + packet->status = status; + packet->buf += HTC_HDR_LENGTH; + } else + status = hif_write_async(target->dev->ar, + target->dev->ar->mbox_info.htc_addr, + packet->buf, padded_len, + HIF_WR_ASYNC_BLOCK_INC, packet); + + return status; +} + +static int htc_check_credits(struct htc_target *target, + struct htc_endpoint *ep, u8 *flags, + enum htc_endpoint_id eid, unsigned int len, + int *req_cred) +{ + + *req_cred = (len > target->tgt_cred_sz) ? + DIV_ROUND_UP(len, target->tgt_cred_sz) : 1; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "creds required:%d got:%d\n", + *req_cred, ep->cred_dist.credits); + + if (ep->cred_dist.credits < *req_cred) { + if (eid == ENDPOINT_0) + return -EINVAL; + + /* Seek more credits */ + ep->cred_dist.seek_cred = *req_cred - ep->cred_dist.credits; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n", + target->cred_dist_cntxt, &ep->cred_dist); + + ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist); + + ep->cred_dist.seek_cred = 0; + + if (ep->cred_dist.credits < *req_cred) { + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "not enough credits for ep %d - leaving packet in queue\n", + eid); + return -EINVAL; + } + } + + ep->cred_dist.credits -= *req_cred; + ep->ep_st.cred_cosumd += *req_cred; + + /* When we are getting low on credits, ask for more */ + if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) { + ep->cred_dist.seek_cred = + ep->cred_dist.cred_per_msg - ep->cred_dist.credits; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n", + target->cred_dist_cntxt, &ep->cred_dist); + + ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist); + + /* see if we were successful in getting more */ + if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) { + /* tell the target we need credits ASAP! */ + *flags |= HTC_FLAGS_NEED_CREDIT_UPDATE; + ep->ep_st.cred_low_indicate += 1; + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "host needs credits\n"); + } + } + + return 0; +} + +static void htc_tx_pkts_get(struct htc_target *target, + struct htc_endpoint *endpoint, + struct list_head *queue) +{ + int req_cred; + u8 flags; + struct htc_packet *packet; + unsigned int len; + + while (true) { + + flags = 0; + + if (list_empty(&endpoint->txq)) + break; + packet = list_first_entry(&endpoint->txq, struct htc_packet, + list); + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "got head pkt:0x%p , queue depth: %d\n", + packet, get_queue_depth(&endpoint->txq)); + + len = CALC_TXRX_PADDED_LEN(target->dev, + packet->act_len + HTC_HDR_LENGTH); + + if (htc_check_credits(target, endpoint, &flags, + packet->endpoint, len, &req_cred)) + break; + + /* now we can fully move onto caller's queue */ + packet = list_first_entry(&endpoint->txq, struct htc_packet, + list); + list_move_tail(&packet->list, queue); + + /* save the number of credits this packet consumed */ + packet->info.tx.cred_used = req_cred; + + /* all TX packets are handled asynchronously */ + packet->completion = htc_tx_comp_handler; + packet->context = target; + endpoint->ep_st.tx_issued += 1; + + /* save send flags */ + packet->info.tx.flags = flags; + packet->info.tx.seqno = endpoint->seqno; + endpoint->seqno++; + } +} + +/* See if the padded tx length falls on a credit boundary */ +static int htc_get_credit_padding(unsigned int cred_sz, int *len, + struct htc_endpoint *ep) +{ + int rem_cred, cred_pad; + + rem_cred = *len % cred_sz; + + /* No padding needed */ + if (!rem_cred) + return 0; + + if (!(ep->conn_flags & HTC_FLGS_TX_BNDL_PAD_EN)) + return -1; + + /* + * The transfer consumes a "partial" credit, this + * packet cannot be bundled unless we add + * additional "dummy" padding (max 255 bytes) to + * consume the entire credit. + */ + cred_pad = *len < cred_sz ? (cred_sz - *len) : rem_cred; + + if ((cred_pad > 0) && (cred_pad <= 255)) + *len += cred_pad; + else + /* The amount of padding is too large, send as non-bundled */ + return -1; + + return cred_pad; +} + +static int htc_setup_send_scat_list(struct htc_target *target, + struct htc_endpoint *endpoint, + struct hif_scatter_req *scat_req, + int n_scat, + struct list_head *queue) +{ + struct htc_packet *packet; + int i, len, rem_scat, cred_pad; + int status = 0; + + rem_scat = target->dev->max_tx_bndl_sz; + + for (i = 0; i < n_scat; i++) { + scat_req->scat_list[i].packet = NULL; + + if (list_empty(queue)) + break; + + packet = list_first_entry(queue, struct htc_packet, list); + len = CALC_TXRX_PADDED_LEN(target->dev, + packet->act_len + HTC_HDR_LENGTH); + + cred_pad = htc_get_credit_padding(target->tgt_cred_sz, + &len, endpoint); + if (cred_pad < 0) { + status = -EINVAL; + break; + } + + if (rem_scat < len) { + /* exceeds what we can transfer */ + status = -ENOSPC; + break; + } + + rem_scat -= len; + /* now remove it from the queue */ + packet = list_first_entry(queue, struct htc_packet, list); + list_del(&packet->list); + + scat_req->scat_list[i].packet = packet; + /* prepare packet and flag message as part of a send bundle */ + htc_prep_send_pkt(packet, + packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE, + cred_pad, packet->info.tx.seqno); + scat_req->scat_list[i].buf = packet->buf; + scat_req->scat_list[i].len = len; + + scat_req->len += len; + scat_req->scat_entries++; + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "%d, adding pkt : 0x%p len:%d (remaining space:%d)\n", + i, packet, len, rem_scat); + } + + /* Roll back scatter setup in case of any failure */ + if (status || (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE)) { + for (i = scat_req->scat_entries - 1; i >= 0; i--) { + packet = scat_req->scat_list[i].packet; + if (packet) { + packet->buf += HTC_HDR_LENGTH; + list_add(&packet->list, queue); + } + } + return -EINVAL; + } + + return 0; +} + +/* + * htc_issue_send_bundle: drain a queue and send as bundles + * this function may return without fully draining the queue + * when + * + * 1. scatter resources are exhausted + * 2. a message that will consume a partial credit will stop the + * bundling process early + * 3. we drop below the minimum number of messages for a bundle + */ +static void htc_issue_send_bundle(struct htc_endpoint *endpoint, + struct list_head *queue, + int *sent_bundle, int *n_bundle_pkts) +{ + struct htc_target *target = endpoint->target; + struct hif_scatter_req *scat_req = NULL; + struct hif_dev_scat_sup_info hif_info; + int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; + + hif_info = target->dev->hif_scat_info; + + while (true) { + n_scat = get_queue_depth(queue); + n_scat = min(n_scat, target->msg_per_bndl_max); + + if (n_scat < HTC_MIN_HTC_MSGS_TO_BUNDLE) + /* not enough to bundle */ + break; + + scat_req = hif_scatter_req_get(target->dev->ar); + + if (!scat_req) { + /* no scatter resources */ + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "no more scatter resources\n"); + break; + } + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "pkts to scatter: %d\n", + n_scat); + + scat_req->len = 0; + scat_req->scat_entries = 0; + + if (htc_setup_send_scat_list(target, endpoint, scat_req, + n_scat, queue)) { + hif_scatter_req_add(target->dev->ar, scat_req); + break; + } + + /* send path is always asynchronous */ + scat_req->complete = htc_async_tx_scat_complete; + scat_req->ep = endpoint; + n_sent_bundle++; + tot_pkts_bundle += scat_req->scat_entries; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "send scatter total bytes: %d , entries: %d\n", + scat_req->len, scat_req->scat_entries); + ath6kldev_submit_scat_req(target->dev, scat_req, false); + } + + *sent_bundle = n_sent_bundle; + *n_bundle_pkts = tot_pkts_bundle; + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_issue_send_bundle (sent:%d)\n", + n_sent_bundle); + + return; +} + +static void htc_tx_from_ep_txq(struct htc_target *target, + struct htc_endpoint *endpoint) +{ + struct list_head txq; + struct htc_packet *packet; + int bundle_sent; + int n_pkts_bundle; + + spin_lock_bh(&target->tx_lock); + + endpoint->tx_proc_cnt++; + if (endpoint->tx_proc_cnt > 1) { + endpoint->tx_proc_cnt--; + spin_unlock_bh(&target->tx_lock); + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_try_send (busy)\n"); + return; + } + + /* + * drain the endpoint TX queue for transmission as long + * as we have enough credits. + */ + INIT_LIST_HEAD(&txq); + + while (true) { + + if (list_empty(&endpoint->txq)) + break; + + htc_tx_pkts_get(target, endpoint, &txq); + + if (list_empty(&txq)) + break; + + spin_unlock_bh(&target->tx_lock); + + bundle_sent = 0; + n_pkts_bundle = 0; + + while (true) { + /* try to send a bundle on each pass */ + if ((target->tx_bndl_enable) && + (get_queue_depth(&txq) >= + HTC_MIN_HTC_MSGS_TO_BUNDLE)) { + int temp1 = 0, temp2 = 0; + + htc_issue_send_bundle(endpoint, &txq, + &temp1, &temp2); + bundle_sent += temp1; + n_pkts_bundle += temp2; + } + + if (list_empty(&txq)) + break; + + packet = list_first_entry(&txq, struct htc_packet, + list); + list_del(&packet->list); + + htc_prep_send_pkt(packet, packet->info.tx.flags, + 0, packet->info.tx.seqno); + htc_issue_send(target, packet); + } + + spin_lock_bh(&target->tx_lock); + + endpoint->ep_st.tx_bundles += bundle_sent; + endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle; + } + + endpoint->tx_proc_cnt = 0; + spin_unlock_bh(&target->tx_lock); +} + +static bool htc_try_send(struct htc_target *target, + struct htc_endpoint *endpoint, + struct htc_packet *tx_pkt) +{ + struct htc_ep_callbacks ep_cb; + int txq_depth; + bool overflow = false; + + ep_cb = endpoint->ep_cb; + + spin_lock_bh(&target->tx_lock); + txq_depth = get_queue_depth(&endpoint->txq); + spin_unlock_bh(&target->tx_lock); + + if (txq_depth >= endpoint->max_txq_depth) + overflow = true; + + if (overflow) + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "ep %d, tx queue will overflow :%d , tx depth:%d, max:%d\n", + endpoint->eid, overflow, txq_depth, + endpoint->max_txq_depth); + + if (overflow && ep_cb.tx_full) { + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "indicating overflowed tx packet: 0x%p\n", tx_pkt); + + if (ep_cb.tx_full(endpoint->target, tx_pkt) == + HTC_SEND_FULL_DROP) { + endpoint->ep_st.tx_dropped += 1; + return false; + } + } + + spin_lock_bh(&target->tx_lock); + list_add_tail(&tx_pkt->list, &endpoint->txq); + spin_unlock_bh(&target->tx_lock); + + htc_tx_from_ep_txq(target, endpoint); + + return true; +} + +static void htc_chk_ep_txq(struct htc_target *target) +{ + struct htc_endpoint *endpoint; + struct htc_endpoint_credit_dist *cred_dist; + + /* + * Run through the credit distribution list to see if there are + * packets queued. NOTE: no locks need to be taken since the + * distribution list is not dynamic (cannot be re-ordered) and we + * are not modifying any state. + */ + list_for_each_entry(cred_dist, &target->cred_dist_list, list) { + endpoint = (struct htc_endpoint *)cred_dist->htc_rsvd; + + spin_lock_bh(&target->tx_lock); + if (!list_empty(&endpoint->txq)) { + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "ep %d has %d credits and %d packets in tx queue\n", + cred_dist->endpoint, + endpoint->cred_dist.credits, + get_queue_depth(&endpoint->txq)); + spin_unlock_bh(&target->tx_lock); + /* + * Try to start the stalled queue, this list is + * ordered by priority. If there are credits + * available the highest priority queue will get a + * chance to reclaim credits from lower priority + * ones. + */ + htc_tx_from_ep_txq(target, endpoint); + spin_lock_bh(&target->tx_lock); + } + spin_unlock_bh(&target->tx_lock); + } +} + +static int htc_setup_tx_complete(struct htc_target *target) +{ + struct htc_packet *send_pkt = NULL; + int status; + + send_pkt = htc_get_control_buf(target, true); + + if (!send_pkt) + return -ENOMEM; + + if (target->htc_tgt_ver >= HTC_VERSION_2P1) { + struct htc_setup_comp_ext_msg *setup_comp_ext; + u32 flags = 0; + + setup_comp_ext = + (struct htc_setup_comp_ext_msg *)send_pkt->buf; + memset(setup_comp_ext, 0, sizeof(*setup_comp_ext)); + setup_comp_ext->msg_id = + cpu_to_le16(HTC_MSG_SETUP_COMPLETE_EX_ID); + + if (target->msg_per_bndl_max > 0) { + /* Indicate HTC bundling to the target */ + flags |= HTC_SETUP_COMP_FLG_RX_BNDL_EN; + setup_comp_ext->msg_per_rxbndl = + target->msg_per_bndl_max; + } + + memcpy(&setup_comp_ext->flags, &flags, + sizeof(setup_comp_ext->flags)); + set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext, + sizeof(struct htc_setup_comp_ext_msg), + ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); + + } else { + struct htc_setup_comp_msg *setup_comp; + setup_comp = (struct htc_setup_comp_msg *)send_pkt->buf; + memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg)); + setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID); + set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp, + sizeof(struct htc_setup_comp_msg), + ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); + } + + /* we want synchronous operation */ + send_pkt->completion = NULL; + htc_prep_send_pkt(send_pkt, 0, 0, 0); + status = htc_issue_send(target, send_pkt); + + if (send_pkt != NULL) + htc_reclaim_txctrl_buf(target, send_pkt); + + return status; +} + +void htc_set_credit_dist(struct htc_target *target, + struct htc_credit_state_info *cred_dist_cntxt, + u16 srvc_pri_order[], int list_len) +{ + struct htc_endpoint *endpoint; + int i, ep; + + target->cred_dist_cntxt = cred_dist_cntxt; + + list_add_tail(&target->endpoint[ENDPOINT_0].cred_dist.list, + &target->cred_dist_list); + + for (i = 0; i < list_len; i++) { + for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) { + endpoint = &target->endpoint[ep]; + if (endpoint->svc_id == srvc_pri_order[i]) { + list_add_tail(&endpoint->cred_dist.list, + &target->cred_dist_list); + break; + } + } + if (ep >= ENDPOINT_MAX) { + WARN_ON(1); + return; + } + } +} + +int htc_tx(struct htc_target *target, struct htc_packet *packet) +{ + struct htc_endpoint *endpoint; + struct list_head queue; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "htc_tx: ep id: %d, buf: 0x%p, len: %d\n", + packet->endpoint, packet->buf, packet->act_len); + + if (packet->endpoint >= ENDPOINT_MAX) { + WARN_ON(1); + return -EINVAL; + } + + endpoint = &target->endpoint[packet->endpoint]; + + if (!htc_try_send(target, endpoint, packet)) { + packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ? + -ECANCELED : -ENOSPC; + INIT_LIST_HEAD(&queue); + list_add(&packet->list, &queue); + htc_tx_complete(endpoint, &queue); + } + + return 0; +} + +/* flush endpoint TX queue */ +void htc_flush_txep(struct htc_target *target, + enum htc_endpoint_id eid, u16 tag) +{ + struct htc_packet *packet, *tmp_pkt; + struct list_head discard_q, container; + struct htc_endpoint *endpoint = &target->endpoint[eid]; + + if (!endpoint->svc_id) { + WARN_ON(1); + return; + } + + /* initialize the discard queue */ + INIT_LIST_HEAD(&discard_q); + + spin_lock_bh(&target->tx_lock); + + list_for_each_entry_safe(packet, tmp_pkt, &endpoint->txq, list) { + if ((tag == HTC_TX_PACKET_TAG_ALL) || + (tag == packet->info.tx.tag)) + list_move_tail(&packet->list, &discard_q); + } + + spin_unlock_bh(&target->tx_lock); + + list_for_each_entry_safe(packet, tmp_pkt, &discard_q, list) { + packet->status = -ECANCELED; + list_del(&packet->list); + ath6kl_dbg(ATH6KL_DBG_TRC, + "flushing tx pkt:0x%p, len:%d, ep:%d tag:0x%X\n", + packet, packet->act_len, + packet->endpoint, packet->info.tx.tag); + + INIT_LIST_HEAD(&container); + list_add_tail(&packet->list, &container); + htc_tx_complete(endpoint, &container); + } + +} + +static void htc_flush_txep_all(struct htc_target *target) +{ + struct htc_endpoint *endpoint; + int i; + + dump_cred_dist_stats(target); + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + endpoint = &target->endpoint[i]; + if (endpoint->svc_id == 0) + /* not in use.. */ + continue; + htc_flush_txep(target, i, HTC_TX_PACKET_TAG_ALL); + } +} + +void htc_indicate_activity_change(struct htc_target *target, + enum htc_endpoint_id eid, bool active) +{ + struct htc_endpoint *endpoint = &target->endpoint[eid]; + bool dist = false; + + if (endpoint->svc_id == 0) { + WARN_ON(1); + return; + } + + spin_lock_bh(&target->tx_lock); + + if (active) { + if (!(endpoint->cred_dist.dist_flags & HTC_EP_ACTIVE)) { + endpoint->cred_dist.dist_flags |= HTC_EP_ACTIVE; + dist = true; + } + } else { + if (endpoint->cred_dist.dist_flags & HTC_EP_ACTIVE) { + endpoint->cred_dist.dist_flags &= ~HTC_EP_ACTIVE; + dist = true; + } + } + + if (dist) { + endpoint->cred_dist.txq_depth = + get_queue_depth(&endpoint->txq); + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n", + target->cred_dist_cntxt, &target->cred_dist_list); + + ath6k_credit_distribute(target->cred_dist_cntxt, + &target->cred_dist_list, + HTC_CREDIT_DIST_ACTIVITY_CHANGE); + } + + spin_unlock_bh(&target->tx_lock); + + if (dist && !active) + htc_chk_ep_txq(target); +} + +/* HTC Rx */ + +static inline void htc_update_rx_stats(struct htc_endpoint *endpoint, + int n_look_ahds) +{ + endpoint->ep_st.rx_pkts++; + if (n_look_ahds == 1) + endpoint->ep_st.rx_lkahds++; + else if (n_look_ahds > 1) + endpoint->ep_st.rx_bundle_lkahd++; +} + +static inline bool htc_valid_rx_frame_len(struct htc_target *target, + enum htc_endpoint_id eid, int len) +{ + return (eid == target->dev->ar->ctrl_ep) ? + len <= ATH6KL_BUFFER_SIZE : len <= ATH6KL_AMSDU_BUFFER_SIZE; +} + +static int htc_add_rxbuf(struct htc_target *target, struct htc_packet *packet) +{ + struct list_head queue; + + INIT_LIST_HEAD(&queue); + list_add_tail(&packet->list, &queue); + return htc_add_rxbuf_multiple(target, &queue); +} + +static void htc_reclaim_rxbuf(struct htc_target *target, + struct htc_packet *packet, + struct htc_endpoint *ep) +{ + if (packet->info.rx.rx_flags & HTC_RX_PKT_NO_RECYCLE) { + htc_rxpkt_reset(packet); + packet->status = -ECANCELED; + ep->ep_cb.rx(ep->target, packet); + } else { + htc_rxpkt_reset(packet); + htc_add_rxbuf((void *)(target), packet); + } +} + +static void reclaim_rx_ctrl_buf(struct htc_target *target, + struct htc_packet *packet) +{ + spin_lock_bh(&target->htc_lock); + list_add_tail(&packet->list, &target->free_ctrl_rxbuf); + spin_unlock_bh(&target->htc_lock); +} + +static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet, + u32 rx_len) +{ + struct ath6kl_device *dev = target->dev; + u32 padded_len; + int status; + + padded_len = CALC_TXRX_PADDED_LEN(dev, rx_len); + + if (padded_len > packet->buf_len) { + ath6kl_err("not enough receive space for packet - padlen:%d recvlen:%d bufferlen:%d\n", + padded_len, rx_len, packet->buf_len); + return -ENOMEM; + } + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "dev_rx_pkt (0x%p : hdr:0x%X) padded len: %d mbox:0x%X (mode:%s)\n", + packet, packet->info.rx.exp_hdr, + padded_len, dev->ar->mbox_info.htc_addr, "sync"); + + status = hif_read_write_sync(dev->ar, + dev->ar->mbox_info.htc_addr, + packet->buf, padded_len, + HIF_RD_SYNC_BLOCK_FIX); + + packet->status = status; + + return status; +} + +/* + * optimization for recv packets, we can indicate a + * "hint" that there are more single-packets to fetch + * on this endpoint. + */ +static void set_rxpkt_indication_flag(u32 lk_ahd, + struct htc_endpoint *endpoint, + struct htc_packet *packet) +{ + struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd; + + if (htc_hdr->eid == packet->endpoint) { + if (!list_empty(&endpoint->rx_bufq)) + packet->info.rx.indicat_flags |= + HTC_RX_FLAGS_INDICATE_MORE_PKTS; + } +} + +static void chk_rx_water_mark(struct htc_endpoint *endpoint) +{ + struct htc_ep_callbacks ep_cb = endpoint->ep_cb; + + if (ep_cb.rx_refill_thresh > 0) { + spin_lock_bh(&endpoint->target->rx_lock); + if (get_queue_depth(&endpoint->rx_bufq) + < ep_cb.rx_refill_thresh) { + spin_unlock_bh(&endpoint->target->rx_lock); + ep_cb.rx_refill(endpoint->target, endpoint->eid); + return; + } + spin_unlock_bh(&endpoint->target->rx_lock); + } +} + +/* This function is called with rx_lock held */ +static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep, + u32 *lk_ahds, struct list_head *queue, int n_msg) +{ + struct htc_packet *packet; + /* FIXME: type of lk_ahds can't be right */ + struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)lk_ahds; + struct htc_ep_callbacks ep_cb; + int status = 0, j, full_len; + bool no_recycle; + + full_len = CALC_TXRX_PADDED_LEN(target->dev, + le16_to_cpu(htc_hdr->payld_len) + + sizeof(*htc_hdr)); + + if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) { + ath6kl_warn("Rx buffer requested with invalid length\n"); + return -EINVAL; + } + + ep_cb = ep->ep_cb; + for (j = 0; j < n_msg; j++) { + + /* + * Reset flag, any packets allocated using the + * rx_alloc() API cannot be recycled on + * cleanup,they must be explicitly returned. + */ + no_recycle = false; + + if (ep_cb.rx_allocthresh && + (full_len > ep_cb.rx_alloc_thresh)) { + ep->ep_st.rx_alloc_thresh_hit += 1; + ep->ep_st.rxalloc_thresh_byte += + le16_to_cpu(htc_hdr->payld_len); + + spin_unlock_bh(&target->rx_lock); + no_recycle = true; + + packet = ep_cb.rx_allocthresh(ep->target, ep->eid, + full_len); + spin_lock_bh(&target->rx_lock); + } else { + /* refill handler is being used */ + if (list_empty(&ep->rx_bufq)) { + if (ep_cb.rx_refill) { + spin_unlock_bh(&target->rx_lock); + ep_cb.rx_refill(ep->target, ep->eid); + spin_lock_bh(&target->rx_lock); + } + } + + if (list_empty(&ep->rx_bufq)) + packet = NULL; + else { + packet = list_first_entry(&ep->rx_bufq, + struct htc_packet, list); + list_del(&packet->list); + } + } + + if (!packet) { + target->rx_st_flags |= HTC_RECV_WAIT_BUFFERS; + target->ep_waiting = ep->eid; + return -ENOSPC; + } + + /* clear flags */ + packet->info.rx.rx_flags = 0; + packet->info.rx.indicat_flags = 0; + packet->status = 0; + + if (no_recycle) + /* + * flag that these packets cannot be + * recycled, they have to be returned to + * the user + */ + packet->info.rx.rx_flags |= HTC_RX_PKT_NO_RECYCLE; + + /* Caller needs to free this upon any failure */ + list_add_tail(&packet->list, queue); + + if (target->htc_flags & HTC_OP_STATE_STOPPING) { + status = -ECANCELED; + break; + } + + if (j) { + packet->info.rx.rx_flags |= HTC_RX_PKT_REFRESH_HDR; + packet->info.rx.exp_hdr = 0xFFFFFFFF; + } else + /* set expected look ahead */ + packet->info.rx.exp_hdr = *lk_ahds; + + packet->act_len = le16_to_cpu(htc_hdr->payld_len) + + HTC_HDR_LENGTH; + } + + return status; +} + +static int alloc_and_prep_rxpkts(struct htc_target *target, + u32 lk_ahds[], int msg, + struct htc_endpoint *endpoint, + struct list_head *queue) +{ + int status = 0; + struct htc_packet *packet, *tmp_pkt; + struct htc_frame_hdr *htc_hdr; + int i, n_msg; + + spin_lock_bh(&target->rx_lock); + + for (i = 0; i < msg; i++) { + + htc_hdr = (struct htc_frame_hdr *)&lk_ahds[i]; + + if (htc_hdr->eid >= ENDPOINT_MAX) { + ath6kl_err("invalid ep in look-ahead: %d\n", + htc_hdr->eid); + status = -ENOMEM; + break; + } + + if (htc_hdr->eid != endpoint->eid) { + ath6kl_err("invalid ep in look-ahead: %d should be : %d (index:%d)\n", + htc_hdr->eid, endpoint->eid, i); + status = -ENOMEM; + break; + } + + if (le16_to_cpu(htc_hdr->payld_len) > HTC_MAX_PAYLOAD_LENGTH) { + ath6kl_err("payload len %d exceeds max htc : %d !\n", + htc_hdr->payld_len, + (u32) HTC_MAX_PAYLOAD_LENGTH); + status = -ENOMEM; + break; + } + + if (endpoint->svc_id == 0) { + ath6kl_err("ep %d is not connected !\n", htc_hdr->eid); + status = -ENOMEM; + break; + } + + if (htc_hdr->flags & HTC_FLG_RX_BNDL_CNT) { + /* + * HTC header indicates that every packet to follow + * has the same padded length so that it can be + * optimally fetched as a full bundle. + */ + n_msg = (htc_hdr->flags & HTC_FLG_RX_BNDL_CNT) >> + HTC_FLG_RX_BNDL_CNT_S; + + /* the count doesn't include the starter frame */ + n_msg++; + if (n_msg > target->msg_per_bndl_max) { + status = -ENOMEM; + break; + } + + endpoint->ep_st.rx_bundle_from_hdr += 1; + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "htc hdr indicates :%d msg can be fetched as a bundle\n", + n_msg); + } else + /* HTC header only indicates 1 message to fetch */ + n_msg = 1; + + /* Setup packet buffers for each message */ + status = htc_setup_rxpkts(target, endpoint, &lk_ahds[i], queue, + n_msg); + + /* + * This is due to unavailabilty of buffers to rx entire data. + * Return no error so that free buffers from queue can be used + * to receive partial data. + */ + if (status == -ENOSPC) { + spin_unlock_bh(&target->rx_lock); + return 0; + } + + if (status) + break; + } + + spin_unlock_bh(&target->rx_lock); + + if (status) { + list_for_each_entry_safe(packet, tmp_pkt, queue, list) { + list_del(&packet->list); + htc_reclaim_rxbuf(target, packet, + &target->endpoint[packet->endpoint]); + } + } + + return status; +} + +static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets) +{ + if (packets->endpoint != ENDPOINT_0) { + WARN_ON(1); + return; + } + + if (packets->status == -ECANCELED) { + reclaim_rx_ctrl_buf(context, packets); + return; + } + + if (packets->act_len > 0) { + ath6kl_err("htc_ctrl_rx, got message with len:%zu\n", + packets->act_len + HTC_HDR_LENGTH); + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, + "Unexpected ENDPOINT 0 Message", + packets->buf - HTC_HDR_LENGTH, + packets->act_len + HTC_HDR_LENGTH); + } + + htc_reclaim_rxbuf(context, packets, &context->endpoint[0]); +} + +static void htc_proc_cred_rpt(struct htc_target *target, + struct htc_credit_report *rpt, + int n_entries, + enum htc_endpoint_id from_ep) +{ + struct htc_endpoint *endpoint; + int tot_credits = 0, i; + bool dist = false; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "htc_proc_cred_rpt, credit report entries:%d\n", n_entries); + + spin_lock_bh(&target->tx_lock); + + for (i = 0; i < n_entries; i++, rpt++) { + if (rpt->eid >= ENDPOINT_MAX) { + WARN_ON(1); + spin_unlock_bh(&target->tx_lock); + return; + } + + endpoint = &target->endpoint[rpt->eid]; + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, " ep %d got %d credits\n", + rpt->eid, rpt->credits); + + endpoint->ep_st.tx_cred_rpt += 1; + endpoint->ep_st.cred_retnd += rpt->credits; + + if (from_ep == rpt->eid) { + /* + * This credit report arrived on the same endpoint + * indicating it arrived in an RX packet. + */ + endpoint->ep_st.cred_from_rx += rpt->credits; + endpoint->ep_st.cred_rpt_from_rx += 1; + } else if (from_ep == ENDPOINT_0) { + /* credit arrived on endpoint 0 as a NULL message */ + endpoint->ep_st.cred_from_ep0 += rpt->credits; + endpoint->ep_st.cred_rpt_ep0 += 1; + } else { + endpoint->ep_st.cred_from_other += rpt->credits; + endpoint->ep_st.cred_rpt_from_other += 1; + } + + if (ENDPOINT_0 == rpt->eid) + /* always give endpoint 0 credits back */ + endpoint->cred_dist.credits += rpt->credits; + else { + endpoint->cred_dist.cred_to_dist += rpt->credits; + dist = true; + } + + /* + * Refresh tx depth for distribution function that will + * recover these credits NOTE: this is only valid when + * there are credits to recover! + */ + endpoint->cred_dist.txq_depth = + get_queue_depth(&endpoint->txq); + + tot_credits += rpt->credits; + } + + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, + "report indicated %d credits to distribute\n", + tot_credits); + + if (dist) { + /* + * This was a credit return based on a completed send + * operations note, this is done with the lock held + */ + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n", + target->cred_dist_cntxt, &target->cred_dist_list); + + ath6k_credit_distribute(target->cred_dist_cntxt, + &target->cred_dist_list, + HTC_CREDIT_DIST_SEND_COMPLETE); + } + + spin_unlock_bh(&target->tx_lock); + + if (tot_credits) + htc_chk_ep_txq(target); +} + +static int htc_parse_trailer(struct htc_target *target, + struct htc_record_hdr *record, + u8 *record_buf, u32 *next_lk_ahds, + enum htc_endpoint_id endpoint, + int *n_lk_ahds) +{ + struct htc_bundle_lkahd_rpt *bundle_lkahd_rpt; + struct htc_lookahead_report *lk_ahd; + int len; + + switch (record->rec_id) { + case HTC_RECORD_CREDITS: + len = record->len / sizeof(struct htc_credit_report); + if (!len) { + WARN_ON(1); + return -EINVAL; + } + + htc_proc_cred_rpt(target, + (struct htc_credit_report *) record_buf, + len, endpoint); + break; + case HTC_RECORD_LOOKAHEAD: + len = record->len / sizeof(*lk_ahd); + if (!len) { + WARN_ON(1); + return -EINVAL; + } + + lk_ahd = (struct htc_lookahead_report *) record_buf; + if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF)) + && next_lk_ahds) { + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "lk_ahd report found (pre valid:0x%X, post valid:0x%X)\n", + lk_ahd->pre_valid, lk_ahd->post_valid); + + /* look ahead bytes are valid, copy them over */ + memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4); + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead", + next_lk_ahds, 4); + + *n_lk_ahds = 1; + } + break; + case HTC_RECORD_LOOKAHEAD_BUNDLE: + len = record->len / sizeof(*bundle_lkahd_rpt); + if (!len || (len > HTC_HOST_MAX_MSG_PER_BUNDLE)) { + WARN_ON(1); + return -EINVAL; + } + + if (next_lk_ahds) { + int i; + + bundle_lkahd_rpt = + (struct htc_bundle_lkahd_rpt *) record_buf; + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd", + record_buf, record->len); + + for (i = 0; i < len; i++) { + memcpy((u8 *)&next_lk_ahds[i], + bundle_lkahd_rpt->lk_ahd, 4); + bundle_lkahd_rpt++; + } + + *n_lk_ahds = i; + } + break; + default: + ath6kl_err("unhandled record: id:%d len:%d\n", + record->rec_id, record->len); + break; + } + + return 0; + +} + +static int htc_proc_trailer(struct htc_target *target, + u8 *buf, int len, u32 *next_lk_ahds, + int *n_lk_ahds, enum htc_endpoint_id endpoint) +{ + struct htc_record_hdr *record; + int orig_len; + int status; + u8 *record_buf; + u8 *orig_buf; + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len); + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", buf, len); + + orig_buf = buf; + orig_len = len; + status = 0; + + while (len > 0) { + + if (len < sizeof(struct htc_record_hdr)) { + status = -ENOMEM; + break; + } + /* these are byte aligned structs */ + record = (struct htc_record_hdr *) buf; + len -= sizeof(struct htc_record_hdr); + buf += sizeof(struct htc_record_hdr); + + if (record->len > len) { + ath6kl_err("invalid record len: %d (id:%d) buf has: %d bytes left\n", + record->len, record->rec_id, len); + status = -ENOMEM; + break; + } + record_buf = buf; + + status = htc_parse_trailer(target, record, record_buf, + next_lk_ahds, endpoint, n_lk_ahds); + + if (status) + break; + + /* advance buffer past this record for next time around */ + buf += record->len; + len -= record->len; + } + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer", + orig_buf, orig_len); + + return status; +} + +static int htc_proc_rxhdr(struct htc_target *target, + struct htc_packet *packet, + u32 *next_lkahds, int *n_lkahds) +{ + int status = 0; + u16 payload_len; + u32 lk_ahd; + struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)packet->buf; + + if (n_lkahds != NULL) + *n_lkahds = 0; + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", packet->buf, + packet->act_len); + + /* + * NOTE: we cannot assume the alignment of buf, so we use the safe + * macros to retrieve 16 bit fields. + */ + payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); + + memcpy((u8 *)&lk_ahd, packet->buf, sizeof(lk_ahd)); + + if (packet->info.rx.rx_flags & HTC_RX_PKT_REFRESH_HDR) { + /* + * Refresh the expected header and the actual length as it + * was unknown when this packet was grabbed as part of the + * bundle. + */ + packet->info.rx.exp_hdr = lk_ahd; + packet->act_len = payload_len + HTC_HDR_LENGTH; + + /* validate the actual header that was refreshed */ + if (packet->act_len > packet->buf_len) { + ath6kl_err("refreshed hdr payload len (%d) in bundled recv is invalid (hdr: 0x%X)\n", + payload_len, lk_ahd); + /* + * Limit this to max buffer just to print out some + * of the buffer. + */ + packet->act_len = min(packet->act_len, packet->buf_len); + status = -ENOMEM; + goto fail_rx; + } + + if (packet->endpoint != htc_hdr->eid) { + ath6kl_err("refreshed hdr ep (%d) does not match expected ep (%d)\n", + htc_hdr->eid, packet->endpoint); + status = -ENOMEM; + goto fail_rx; + } + } + + if (lk_ahd != packet->info.rx.exp_hdr) { + ath6kl_err("htc_proc_rxhdr, lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n", + packet, packet->info.rx.rx_flags); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd", + &packet->info.rx.exp_hdr, 4); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header", + (u8 *)&lk_ahd, sizeof(lk_ahd)); + status = -ENOMEM; + goto fail_rx; + } + + if (htc_hdr->flags & HTC_FLG_RX_TRAILER) { + if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) || + htc_hdr->ctrl[0] > payload_len) { + ath6kl_err("htc_proc_rxhdr, invalid hdr (payload len should be :%d, CB[0] is:%d)\n", + payload_len, htc_hdr->ctrl[0]); + status = -ENOMEM; + goto fail_rx; + } + + if (packet->info.rx.rx_flags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { + next_lkahds = NULL; + n_lkahds = NULL; + } + + status = htc_proc_trailer(target, packet->buf + HTC_HDR_LENGTH + + payload_len - htc_hdr->ctrl[0], + htc_hdr->ctrl[0], next_lkahds, + n_lkahds, packet->endpoint); + + if (status) + goto fail_rx; + + packet->act_len -= htc_hdr->ctrl[0]; + } + + packet->buf += HTC_HDR_LENGTH; + packet->act_len -= HTC_HDR_LENGTH; + +fail_rx: + if (status) + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT", + packet->buf, + packet->act_len < 256 ? packet->act_len : 256); + else { + if (packet->act_len > 0) + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, + "HTC - Application Msg", + packet->buf, packet->act_len); + } + + return status; +} + +static void do_rx_completion(struct htc_endpoint *endpoint, + struct htc_packet *packet) +{ + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "htc calling ep %d recv callback on packet 0x%p\n", + endpoint->eid, packet); + endpoint->ep_cb.rx(endpoint->target, packet); +} + +static int htc_issue_rxpkt_bundle(struct htc_target *target, + struct list_head *rxq, + struct list_head *sync_compq, + int *n_pkt_fetched, bool part_bundle) +{ + struct hif_scatter_req *scat_req; + struct htc_packet *packet; + int rem_space = target->dev->max_rx_bndl_sz; + int n_scat_pkt, status = 0, i, len; + + n_scat_pkt = get_queue_depth(rxq); + n_scat_pkt = min(n_scat_pkt, target->msg_per_bndl_max); + + if ((get_queue_depth(rxq) - n_scat_pkt) > 0) { + /* + * We were forced to split this bundle receive operation + * all packets in this partial bundle must have their + * lookaheads ignored. + */ + part_bundle = true; + + /* + * This would only happen if the target ignored our max + * bundle limit. + */ + ath6kl_warn("htc_issue_rxpkt_bundle : partial bundle detected num:%d , %d\n", + get_queue_depth(rxq), n_scat_pkt); + } + + len = 0; + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "htc_issue_rxpkt_bundle (numpackets: %d , actual : %d)\n", + get_queue_depth(rxq), n_scat_pkt); + + scat_req = hif_scatter_req_get(target->dev->ar); + + if (scat_req == NULL) + goto fail_rx_pkt; + + scat_req->flags = 0; + + if (part_bundle) + scat_req->flags |= + HTC_SCAT_REQ_FLG_PART_BNDL; + + for (i = 0; i < n_scat_pkt; i++) { + int pad_len; + + packet = list_first_entry(rxq, struct htc_packet, list); + list_del(&packet->list); + + pad_len = CALC_TXRX_PADDED_LEN(target->dev, + packet->act_len); + + if ((rem_space - pad_len) < 0) { + list_add(&packet->list, rxq); + break; + } + + rem_space -= pad_len; + + if (part_bundle || (i < (n_scat_pkt - 1))) + /* + * Packet 0..n-1 cannot be checked for look-aheads + * since we are fetching a bundle the last packet + * however can have it's lookahead used + */ + packet->info.rx.rx_flags |= + HTC_RX_PKT_IGNORE_LOOKAHEAD; + + /* NOTE: 1 HTC packet per scatter entry */ + scat_req->scat_list[i].buf = packet->buf; + scat_req->scat_list[i].len = pad_len; + + packet->info.rx.rx_flags |= HTC_RX_PKT_PART_OF_BUNDLE; + + list_add_tail(&packet->list, sync_compq); + + WARN_ON(!scat_req->scat_list[i].len); + len += scat_req->scat_list[i].len; + } + + scat_req->len = len; + scat_req->scat_entries = i; + + status = ath6kldev_submit_scat_req(target->dev, scat_req, true); + + if (!status) + *n_pkt_fetched = i; + + /* free scatter request */ + hif_scatter_req_add(target->dev->ar, scat_req); + +fail_rx_pkt: + + return status; +} + +static int htc_proc_fetched_rxpkts(struct htc_target *target, + struct list_head *comp_pktq, u32 lk_ahds[], + int *n_lk_ahd) +{ + struct htc_packet *packet, *tmp_pkt; + struct htc_endpoint *ep; + int status = 0; + + list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) { + list_del(&packet->list); + ep = &target->endpoint[packet->endpoint]; + + /* process header for each of the recv packet */ + status = htc_proc_rxhdr(target, packet, lk_ahds, n_lk_ahd); + if (status) + return status; + + if (list_empty(comp_pktq)) { + /* + * Last packet's more packet flag is set + * based on the lookahead. + */ + if (*n_lk_ahd > 0) + set_rxpkt_indication_flag(lk_ahds[0], + ep, packet); + } else + /* + * Packets in a bundle automatically have + * this flag set. + */ + packet->info.rx.indicat_flags |= + HTC_RX_FLAGS_INDICATE_MORE_PKTS; + + htc_update_rx_stats(ep, *n_lk_ahd); + + if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE) + ep->ep_st.rx_bundl += 1; + + do_rx_completion(ep, packet); + } + + return status; +} + +static int htc_fetch_rxpkts(struct htc_target *target, + struct list_head *rx_pktq, + struct list_head *comp_pktq) +{ + int fetched_pkts; + bool part_bundle = false; + int status = 0; + + /* now go fetch the list of HTC packets */ + while (!list_empty(rx_pktq)) { + fetched_pkts = 0; + + if (target->rx_bndl_enable && (get_queue_depth(rx_pktq) > 1)) { + /* + * There are enough packets to attempt a + * bundle transfer and recv bundling is + * allowed. + */ + status = htc_issue_rxpkt_bundle(target, rx_pktq, + comp_pktq, + &fetched_pkts, + part_bundle); + if (status) + return status; + + if (!list_empty(rx_pktq)) + part_bundle = true; + } + + if (!fetched_pkts) { + struct htc_packet *packet; + + packet = list_first_entry(rx_pktq, struct htc_packet, + list); + + list_del(&packet->list); + + /* fully synchronous */ + packet->completion = NULL; + + if (!list_empty(rx_pktq)) + /* + * look_aheads in all packet + * except the last one in the + * bundle must be ignored + */ + packet->info.rx.rx_flags |= + HTC_RX_PKT_IGNORE_LOOKAHEAD; + + /* go fetch the packet */ + status = dev_rx_pkt(target, packet, packet->act_len); + if (status) + return status; + + list_add_tail(&packet->list, comp_pktq); + } + } + + return status; +} + +static int htc_rxmsg_pending_handler(struct htc_target *target, + u32 msg_look_ahead[], + int *num_pkts) +{ + struct htc_packet *packets, *tmp_pkt; + struct htc_endpoint *endpoint; + struct list_head rx_pktq, comp_pktq; + int status = 0; + u32 look_aheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int num_look_ahead = 1; + enum htc_endpoint_id id; + int n_fetched = 0; + + *num_pkts = 0; + + /* + * On first entry copy the look_aheads into our temp array for + * processing + */ + memcpy(look_aheads, msg_look_ahead, sizeof(look_aheads)); + + while (true) { + + /* + * First lookahead sets the expected endpoint IDs for all + * packets in a bundle. + */ + id = ((struct htc_frame_hdr *)&look_aheads[0])->eid; + endpoint = &target->endpoint[id]; + + if (id >= ENDPOINT_MAX) { + ath6kl_err("MsgPend, invalid endpoint in look-ahead: %d\n", + id); + status = -ENOMEM; + break; + } + + INIT_LIST_HEAD(&rx_pktq); + INIT_LIST_HEAD(&comp_pktq); + + /* + * Try to allocate as many HTC RX packets indicated by the + * look_aheads. + */ + status = alloc_and_prep_rxpkts(target, look_aheads, + num_look_ahead, endpoint, + &rx_pktq); + if (status) + break; + + if (get_queue_depth(&rx_pktq) >= 2) + /* + * A recv bundle was detected, force IRQ status + * re-check again + */ + target->dev->chk_irq_status_cnt = 1; + + n_fetched += get_queue_depth(&rx_pktq); + + num_look_ahead = 0; + + status = htc_fetch_rxpkts(target, &rx_pktq, &comp_pktq); + + if (!status) + chk_rx_water_mark(endpoint); + + /* Process fetched packets */ + status = htc_proc_fetched_rxpkts(target, &comp_pktq, + look_aheads, &num_look_ahead); + + if (!num_look_ahead || status) + break; + + /* + * For SYNCH processing, if we get here, we are running + * through the loop again due to a detected lookahead. Set + * flag that we should re-check IRQ status registers again + * before leaving IRQ processing, this can net better + * performance in high throughput situations. + */ + target->dev->chk_irq_status_cnt = 1; + } + + if (status) { + ath6kl_err("failed to get pending recv messages: %d\n", + status); + /* + * Cleanup any packets we allocated but didn't use to + * actually fetch any packets. + */ + list_for_each_entry_safe(packets, tmp_pkt, &rx_pktq, list) { + list_del(&packets->list); + htc_reclaim_rxbuf(target, packets, + &target->endpoint[packets->endpoint]); + } + + /* cleanup any packets in sync completion queue */ + list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) { + list_del(&packets->list); + htc_reclaim_rxbuf(target, packets, + &target->endpoint[packets->endpoint]); + } + + if (target->htc_flags & HTC_OP_STATE_STOPPING) { + ath6kl_warn("host is going to stop blocking receiver for htc_stop\n"); + ath6kldev_rx_control(target->dev, false); + } + } + + /* + * Before leaving, check to see if host ran out of buffers and + * needs to stop the receiver. + */ + if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) { + ath6kl_warn("host has no rx buffers blocking receiver to prevent overrun\n"); + ath6kldev_rx_control(target->dev, false); + } + *num_pkts = n_fetched; + + return status; +} + +/* + * Synchronously wait for a control message from the target, + * This function is used at initialization time ONLY. At init messages + * on ENDPOINT 0 are expected. + */ +static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) +{ + struct htc_packet *packet = NULL; + struct htc_frame_hdr *htc_hdr; + u32 look_ahead; + + if (ath6kldev_poll_mboxmsg_rx(target->dev, &look_ahead, + HTC_TARGET_RESPONSE_TIMEOUT)) + return NULL; + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "htc_wait_for_ctrl_msg: look_ahead : 0x%X\n", look_ahead); + + htc_hdr = (struct htc_frame_hdr *)&look_ahead; + + if (htc_hdr->eid != ENDPOINT_0) + return NULL; + + packet = htc_get_control_buf(target, false); + + if (!packet) + return NULL; + + packet->info.rx.rx_flags = 0; + packet->info.rx.exp_hdr = look_ahead; + packet->act_len = le16_to_cpu(htc_hdr->payld_len) + HTC_HDR_LENGTH; + + if (packet->act_len > packet->buf_len) + goto fail_ctrl_rx; + + /* we want synchronous operation */ + packet->completion = NULL; + + /* get the message from the device, this will block */ + if (dev_rx_pkt(target, packet, packet->act_len)) + goto fail_ctrl_rx; + + /* process receive header */ + packet->status = htc_proc_rxhdr(target, packet, NULL, NULL); + + if (packet->status) { + ath6kl_err("htc_wait_for_ctrl_msg, htc_proc_rxhdr failed (status = %d)\n", + packet->status); + goto fail_ctrl_rx; + } + + return packet; + +fail_ctrl_rx: + if (packet != NULL) { + htc_rxpkt_reset(packet); + reclaim_rx_ctrl_buf(target, packet); + } + + return NULL; +} + +int htc_add_rxbuf_multiple(struct htc_target *target, + struct list_head *pkt_queue) +{ + struct htc_endpoint *endpoint; + struct htc_packet *first_pkt; + bool rx_unblock = false; + int status = 0, depth; + + if (list_empty(pkt_queue)) + return -ENOMEM; + + first_pkt = list_first_entry(pkt_queue, struct htc_packet, list); + + if (first_pkt->endpoint >= ENDPOINT_MAX) + return status; + + depth = get_queue_depth(pkt_queue); + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "htc_add_rxbuf_multiple: ep id: %d, cnt:%d, len: %d\n", + first_pkt->endpoint, depth, first_pkt->buf_len); + + endpoint = &target->endpoint[first_pkt->endpoint]; + + if (target->htc_flags & HTC_OP_STATE_STOPPING) { + struct htc_packet *packet, *tmp_pkt; + + /* walk through queue and mark each one canceled */ + list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) { + packet->status = -ECANCELED; + list_del(&packet->list); + do_rx_completion(endpoint, packet); + } + + return status; + } + + spin_lock_bh(&target->rx_lock); + + list_splice_tail_init(pkt_queue, &endpoint->rx_bufq); + + /* check if we are blocked waiting for a new buffer */ + if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) { + if (target->ep_waiting == first_pkt->endpoint) { + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "receiver was blocked on ep:%d, unblocking.\n", + target->ep_waiting); + target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS; + target->ep_waiting = ENDPOINT_MAX; + rx_unblock = true; + } + } + + spin_unlock_bh(&target->rx_lock); + + if (rx_unblock && !(target->htc_flags & HTC_OP_STATE_STOPPING)) + /* TODO : implement a buffer threshold count? */ + ath6kldev_rx_control(target->dev, true); + + return status; +} + +void htc_flush_rx_buf(struct htc_target *target) +{ + struct htc_endpoint *endpoint; + struct htc_packet *packet, *tmp_pkt; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + endpoint = &target->endpoint[i]; + if (!endpoint->svc_id) + /* not in use.. */ + continue; + + spin_lock_bh(&target->rx_lock); + list_for_each_entry_safe(packet, tmp_pkt, + &endpoint->rx_bufq, list) { + list_del(&packet->list); + spin_unlock_bh(&target->rx_lock); + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "flushing rx pkt:0x%p, len:%d, ep:%d\n", + packet, packet->buf_len, + packet->endpoint); + dev_kfree_skb(packet->pkt_cntxt); + spin_lock_bh(&target->rx_lock); + } + spin_unlock_bh(&target->rx_lock); + } +} + +int htc_conn_service(struct htc_target *target, + struct htc_service_connect_req *conn_req, + struct htc_service_connect_resp *conn_resp) +{ + struct htc_packet *rx_pkt = NULL; + struct htc_packet *tx_pkt = NULL; + struct htc_conn_service_resp *resp_msg; + struct htc_conn_service_msg *conn_msg; + struct htc_endpoint *endpoint; + enum htc_endpoint_id assigned_ep = ENDPOINT_MAX; + unsigned int max_msg_sz = 0; + int status = 0; + + ath6kl_dbg(ATH6KL_DBG_TRC, + "htc_conn_service, target:0x%p service id:0x%X\n", + target, conn_req->svc_id); + + if (conn_req->svc_id == HTC_CTRL_RSVD_SVC) { + /* special case for pseudo control service */ + assigned_ep = ENDPOINT_0; + max_msg_sz = HTC_MAX_CTRL_MSG_LEN; + } else { + /* allocate a packet to send to the target */ + tx_pkt = htc_get_control_buf(target, true); + + if (!tx_pkt) + return -ENOMEM; + + conn_msg = (struct htc_conn_service_msg *)tx_pkt->buf; + memset(conn_msg, 0, sizeof(*conn_msg)); + conn_msg->msg_id = cpu_to_le16(HTC_MSG_CONN_SVC_ID); + conn_msg->svc_id = cpu_to_le16(conn_req->svc_id); + conn_msg->conn_flags = cpu_to_le16(conn_req->conn_flags); + + set_htc_pkt_info(tx_pkt, NULL, (u8 *) conn_msg, + sizeof(*conn_msg) + conn_msg->svc_meta_len, + ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); + + /* we want synchronous operation */ + tx_pkt->completion = NULL; + htc_prep_send_pkt(tx_pkt, 0, 0, 0); + status = htc_issue_send(target, tx_pkt); + + if (status) + goto fail_tx; + + /* wait for response */ + rx_pkt = htc_wait_for_ctrl_msg(target); + + if (!rx_pkt) { + status = -ENOMEM; + goto fail_tx; + } + + resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf; + + if ((le16_to_cpu(resp_msg->msg_id) != HTC_MSG_CONN_SVC_RESP_ID) + || (rx_pkt->act_len < sizeof(*resp_msg))) { + status = -ENOMEM; + goto fail_tx; + } + + conn_resp->resp_code = resp_msg->status; + /* check response status */ + if (resp_msg->status != HTC_SERVICE_SUCCESS) { + ath6kl_err("target failed service 0x%X connect request (status:%d)\n", + resp_msg->svc_id, resp_msg->status); + status = -ENOMEM; + goto fail_tx; + } + + assigned_ep = (enum htc_endpoint_id)resp_msg->eid; + max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz); + } + + if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) { + status = -ENOMEM; + goto fail_tx; + } + + endpoint = &target->endpoint[assigned_ep]; + endpoint->eid = assigned_ep; + if (endpoint->svc_id) { + status = -ENOMEM; + goto fail_tx; + } + + /* return assigned endpoint to caller */ + conn_resp->endpoint = assigned_ep; + conn_resp->len_max = max_msg_sz; + + /* setup the endpoint */ + + /* this marks the endpoint in use */ + endpoint->svc_id = conn_req->svc_id; + + endpoint->max_txq_depth = conn_req->max_txq_depth; + endpoint->len_max = max_msg_sz; + endpoint->ep_cb = conn_req->ep_cb; + endpoint->cred_dist.svc_id = conn_req->svc_id; + endpoint->cred_dist.htc_rsvd = endpoint; + endpoint->cred_dist.endpoint = assigned_ep; + endpoint->cred_dist.cred_sz = target->tgt_cred_sz; + + if (conn_req->max_rxmsg_sz) { + /* + * Override cred_per_msg calculation, this optimizes + * the credit-low indications since the host will actually + * issue smaller messages in the Send path. + */ + if (conn_req->max_rxmsg_sz > max_msg_sz) { + status = -ENOMEM; + goto fail_tx; + } + endpoint->cred_dist.cred_per_msg = + conn_req->max_rxmsg_sz / target->tgt_cred_sz; + } else + endpoint->cred_dist.cred_per_msg = + max_msg_sz / target->tgt_cred_sz; + + if (!endpoint->cred_dist.cred_per_msg) + endpoint->cred_dist.cred_per_msg = 1; + + /* save local connection flags */ + endpoint->conn_flags = conn_req->flags; + +fail_tx: + if (tx_pkt) + htc_reclaim_txctrl_buf(target, tx_pkt); + + if (rx_pkt) { + htc_rxpkt_reset(rx_pkt); + reclaim_rx_ctrl_buf(target, rx_pkt); + } + + return status; +} + +static void reset_ep_state(struct htc_target *target) +{ + struct htc_endpoint *endpoint; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + endpoint = &target->endpoint[i]; + memset(&endpoint->cred_dist, 0, sizeof(endpoint->cred_dist)); + endpoint->svc_id = 0; + endpoint->len_max = 0; + endpoint->max_txq_depth = 0; + memset(&endpoint->ep_st, 0, + sizeof(endpoint->ep_st)); + INIT_LIST_HEAD(&endpoint->rx_bufq); + INIT_LIST_HEAD(&endpoint->txq); + endpoint->target = target; + } + + /* reset distribution list */ + INIT_LIST_HEAD(&target->cred_dist_list); +} + +int htc_get_rxbuf_num(struct htc_target *target, enum htc_endpoint_id endpoint) +{ + int num; + + spin_lock_bh(&target->rx_lock); + num = get_queue_depth(&(target->endpoint[endpoint].rx_bufq)); + spin_unlock_bh(&target->rx_lock); + return num; +} + +static void htc_setup_msg_bndl(struct htc_target *target) +{ + struct hif_dev_scat_sup_info *scat_info = &target->dev->hif_scat_info; + + /* limit what HTC can handle */ + target->msg_per_bndl_max = min(HTC_HOST_MAX_MSG_PER_BUNDLE, + target->msg_per_bndl_max); + + if (ath6kldev_setup_msg_bndl(target->dev, target->msg_per_bndl_max)) { + target->msg_per_bndl_max = 0; + return; + } + + /* limit bundle what the device layer can handle */ + target->msg_per_bndl_max = min(scat_info->max_scat_entries, + target->msg_per_bndl_max); + + ath6kl_dbg(ATH6KL_DBG_TRC, + "htc bundling allowed. max msg per htc bundle: %d\n", + target->msg_per_bndl_max); + + /* Max rx bundle size is limited by the max tx bundle size */ + target->dev->max_rx_bndl_sz = scat_info->max_xfer_szper_scatreq; + /* Max tx bundle size if limited by the extended mbox address range */ + target->dev->max_tx_bndl_sz = min(HIF_MBOX0_EXT_WIDTH, + scat_info->max_xfer_szper_scatreq); + + ath6kl_dbg(ATH6KL_DBG_ANY, "max recv: %d max send: %d\n", + target->dev->max_rx_bndl_sz, target->dev->max_tx_bndl_sz); + + if (target->dev->max_tx_bndl_sz) + target->tx_bndl_enable = true; + + if (target->dev->max_rx_bndl_sz) + target->rx_bndl_enable = true; + + if ((target->tgt_cred_sz % target->dev->block_sz) != 0) { + ath6kl_warn("credit size: %d is not block aligned! Disabling send bundling\n", + target->tgt_cred_sz); + + /* + * Disallow send bundling since the credit size is + * not aligned to a block size the I/O block + * padding will spill into the next credit buffer + * which is fatal. + */ + target->tx_bndl_enable = false; + } +} + +int htc_wait_target(struct htc_target *target) +{ + struct htc_packet *packet = NULL; + struct htc_ready_ext_msg *rdy_msg; + struct htc_service_connect_req connect; + struct htc_service_connect_resp resp; + int status; + + /* we should be getting 1 control message that the target is ready */ + packet = htc_wait_for_ctrl_msg(target); + + if (!packet) + return -ENOMEM; + + /* we controlled the buffer creation so it's properly aligned */ + rdy_msg = (struct htc_ready_ext_msg *)packet->buf; + + if ((le16_to_cpu(rdy_msg->ver2_0_info.msg_id) != HTC_MSG_READY_ID) || + (packet->act_len < sizeof(struct htc_ready_msg))) { + status = -ENOMEM; + goto fail_wait_target; + } + + if (!rdy_msg->ver2_0_info.cred_cnt || !rdy_msg->ver2_0_info.cred_sz) { + status = -ENOMEM; + goto fail_wait_target; + } + + target->tgt_creds = le16_to_cpu(rdy_msg->ver2_0_info.cred_cnt); + target->tgt_cred_sz = le16_to_cpu(rdy_msg->ver2_0_info.cred_sz); + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "target ready: credits: %d credit size: %d\n", + target->tgt_creds, target->tgt_cred_sz); + + /* check if this is an extended ready message */ + if (packet->act_len >= sizeof(struct htc_ready_ext_msg)) { + /* this is an extended message */ + target->htc_tgt_ver = rdy_msg->htc_ver; + target->msg_per_bndl_max = rdy_msg->msg_per_htc_bndl; + } else { + /* legacy */ + target->htc_tgt_ver = HTC_VERSION_2P0; + target->msg_per_bndl_max = 0; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "using htc protocol version : %s (%d)\n", + (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1", + target->htc_tgt_ver); + + if (target->msg_per_bndl_max > 0) + htc_setup_msg_bndl(target); + + /* setup our pseudo HTC control endpoint connection */ + memset(&connect, 0, sizeof(connect)); + memset(&resp, 0, sizeof(resp)); + connect.ep_cb.rx = htc_ctrl_rx; + connect.ep_cb.rx_refill = NULL; + connect.ep_cb.tx_full = NULL; + connect.max_txq_depth = NUM_CONTROL_BUFFERS; + connect.svc_id = HTC_CTRL_RSVD_SVC; + + /* connect fake service */ + status = htc_conn_service((void *)target, &connect, &resp); + + if (status) + ath6kl_hif_cleanup_scatter(target->dev->ar); + +fail_wait_target: + if (packet) { + htc_rxpkt_reset(packet); + reclaim_rx_ctrl_buf(target, packet); + } + + return status; +} + +/* + * Start HTC, enable interrupts and let the target know + * host has finished setup. + */ +int htc_start(struct htc_target *target) +{ + struct htc_packet *packet; + int status; + + /* Disable interrupts at the chip level */ + ath6kldev_disable_intrs(target->dev); + + target->htc_flags = 0; + target->rx_st_flags = 0; + + /* Push control receive buffers into htc control endpoint */ + while ((packet = htc_get_control_buf(target, false)) != NULL) { + status = htc_add_rxbuf(target, packet); + if (status) + return status; + } + + /* NOTE: the first entry in the distribution list is ENDPOINT_0 */ + ath6k_credit_init(target->cred_dist_cntxt, &target->cred_dist_list, + target->tgt_creds); + + dump_cred_dist_stats(target); + + /* Indicate to the target of the setup completion */ + status = htc_setup_tx_complete(target); + + if (status) + return status; + + /* unmask interrupts */ + status = ath6kldev_unmask_intrs(target->dev); + + if (status) + htc_stop(target); + + return status; +} + +/* htc_stop: stop interrupt reception, and flush all queued buffers */ +void htc_stop(struct htc_target *target) +{ + spin_lock_bh(&target->htc_lock); + target->htc_flags |= HTC_OP_STATE_STOPPING; + spin_unlock_bh(&target->htc_lock); + + /* + * Masking interrupts is a synchronous operation, when this + * function returns all pending HIF I/O has completed, we can + * safely flush the queues. + */ + ath6kldev_mask_intrs(target->dev); + + htc_flush_txep_all(target); + + htc_flush_rx_buf(target); + + reset_ep_state(target); +} + +void *htc_create(struct ath6kl *ar) +{ + struct htc_target *target = NULL; + struct htc_packet *packet; + int status = 0, i = 0; + u32 block_size, ctrl_bufsz; + + target = kzalloc(sizeof(*target), GFP_KERNEL); + if (!target) { + ath6kl_err("unable to allocate memory\n"); + return NULL; + } + + target->dev = kzalloc(sizeof(*target->dev), GFP_KERNEL); + if (!target->dev) { + ath6kl_err("unable to allocate memory\n"); + status = -ENOMEM; + goto fail_create_htc; + } + + spin_lock_init(&target->htc_lock); + spin_lock_init(&target->rx_lock); + spin_lock_init(&target->tx_lock); + + INIT_LIST_HEAD(&target->free_ctrl_txbuf); + INIT_LIST_HEAD(&target->free_ctrl_rxbuf); + INIT_LIST_HEAD(&target->cred_dist_list); + + target->dev->ar = ar; + target->dev->htc_cnxt = target; + target->dev->msg_pending = htc_rxmsg_pending_handler; + target->ep_waiting = ENDPOINT_MAX; + + reset_ep_state(target); + + status = ath6kldev_setup(target->dev); + + if (status) + goto fail_create_htc; + + block_size = ar->mbox_info.block_size; + + ctrl_bufsz = (block_size > HTC_MAX_CTRL_MSG_LEN) ? + (block_size + HTC_HDR_LENGTH) : + (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH); + + for (i = 0; i < NUM_CONTROL_BUFFERS; i++) { + packet = kzalloc(sizeof(*packet), GFP_KERNEL); + if (!packet) + break; + + packet->buf_start = kzalloc(ctrl_bufsz, GFP_KERNEL); + if (!packet->buf_start) { + kfree(packet); + break; + } + + packet->buf_len = ctrl_bufsz; + if (i < NUM_CONTROL_RX_BUFFERS) { + packet->act_len = 0; + packet->buf = packet->buf_start; + packet->endpoint = ENDPOINT_0; + list_add_tail(&packet->list, &target->free_ctrl_rxbuf); + } else + list_add_tail(&packet->list, &target->free_ctrl_txbuf); + } + +fail_create_htc: + if (i != NUM_CONTROL_BUFFERS || status) { + if (target) { + htc_cleanup(target); + target = NULL; + } + } + + return target; +} + +/* cleanup the HTC instance */ +void htc_cleanup(struct htc_target *target) +{ + struct htc_packet *packet, *tmp_packet; + + ath6kl_hif_cleanup_scatter(target->dev->ar); + + list_for_each_entry_safe(packet, tmp_packet, + &target->free_ctrl_txbuf, list) { + list_del(&packet->list); + kfree(packet->buf_start); + kfree(packet); + } + + list_for_each_entry_safe(packet, tmp_packet, + &target->free_ctrl_rxbuf, list) { + list_del(&packet->list); + kfree(packet->buf_start); + kfree(packet); + } + + kfree(target->dev); + kfree(target); +} diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h new file mode 100644 index 000000000000..16fa7a84a231 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc.h @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HTC_H +#define HTC_H + +#include "common.h" + +/* frame header flags */ + +/* send direction */ +#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) +#define HTC_FLAGS_SEND_BUNDLE (1 << 1) + +/* receive direction */ +#define HTC_FLG_RX_UNUSED (1 << 0) +#define HTC_FLG_RX_TRAILER (1 << 1) +/* Bundle count maske and shift */ +#define HTC_FLG_RX_BNDL_CNT (0xF0) +#define HTC_FLG_RX_BNDL_CNT_S 4 + +#define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr)) +#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr)) + +/* HTC control message IDs */ + +#define HTC_MSG_READY_ID 1 +#define HTC_MSG_CONN_SVC_ID 2 +#define HTC_MSG_CONN_SVC_RESP_ID 3 +#define HTC_MSG_SETUP_COMPLETE_ID 4 +#define HTC_MSG_SETUP_COMPLETE_EX_ID 5 + +#define HTC_MAX_CTRL_MSG_LEN 256 + +#define HTC_VERSION_2P0 0x00 +#define HTC_VERSION_2P1 0x01 + +#define HTC_SERVICE_META_DATA_MAX_LENGTH 128 + +#define HTC_CONN_FLGS_THRESH_LVL_QUAT 0x0 +#define HTC_CONN_FLGS_THRESH_LVL_HALF 0x1 +#define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT 0x2 +#define HTC_CONN_FLGS_REDUCE_CRED_DRIB 0x4 +#define HTC_CONN_FLGS_THRESH_MASK 0x3 + +/* connect response status codes */ +#define HTC_SERVICE_SUCCESS 0 +#define HTC_SERVICE_NOT_FOUND 1 +#define HTC_SERVICE_FAILED 2 + +/* no resources (i.e. no more endpoints) */ +#define HTC_SERVICE_NO_RESOURCES 3 + +/* specific service is not allowing any more endpoints */ +#define HTC_SERVICE_NO_MORE_EP 4 + +/* report record IDs */ +#define HTC_RECORD_NULL 0 +#define HTC_RECORD_CREDITS 1 +#define HTC_RECORD_LOOKAHEAD 2 +#define HTC_RECORD_LOOKAHEAD_BUNDLE 3 + +#define HTC_SETUP_COMP_FLG_RX_BNDL_EN (1 << 0) + +#define MAKE_SERVICE_ID(group, index) \ + (int)(((int)group << 8) | (int)(index)) + +/* NOTE: service ID of 0x0000 is reserved and should never be used */ +#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1) +#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0) +#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1) +#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2) +#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3) +#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) +#define WMI_MAX_SERVICES 5 + +/* reserved and used to flush ALL packets */ +#define HTC_TX_PACKET_TAG_ALL 0 +#define HTC_SERVICE_TX_PACKET_TAG 1 +#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_SERVICE_TX_PACKET_TAG + 9) + +/* more packets on this endpoint are being fetched */ +#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) + +/* TODO.. for BMI */ +#define ENDPOINT1 0 +/* TODO -remove me, but we have to fix BMI first */ +#define HTC_MAILBOX_NUM_MAX 4 + +/* enable send bundle padding for this endpoint */ +#define HTC_FLGS_TX_BNDL_PAD_EN (1 << 0) +#define HTC_EP_ACTIVE ((u32) (1u << 31)) + +/* HTC operational parameters */ +#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ +#define HTC_TARGET_DEBUG_INTR_MASK 0x01 +#define HTC_TARGET_CREDIT_INTR_MASK 0xF0 + +#define HTC_HOST_MAX_MSG_PER_BUNDLE 8 +#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2 + +/* packet flags */ + +#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0) +#define HTC_RX_PKT_REFRESH_HDR (1 << 1) +#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2) +#define HTC_RX_PKT_NO_RECYCLE (1 << 3) + +/* scatter request flags */ + +#define HTC_SCAT_REQ_FLG_PART_BNDL (1 << 0) + +#define NUM_CONTROL_BUFFERS 8 +#define NUM_CONTROL_TX_BUFFERS 2 +#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS) + +#define HTC_RECV_WAIT_BUFFERS (1 << 0) +#define HTC_OP_STATE_STOPPING (1 << 0) + +/* + * The frame header length and message formats defined herein were selected + * to accommodate optimal alignment for target processing. This reduces + * code size and improves performance. Any changes to the header length may + * alter the alignment and cause exceptions on the target. When adding to + * the messagestructures insure that fields are properly aligned. + */ + +/* HTC frame header + * + * NOTE: do not remove or re-arrange the fields, these are minimally + * required to take advantage of 4-byte lookaheads in some hardware + * implementations. + */ +struct htc_frame_hdr { + u8 eid; + u8 flags; + + /* length of data (including trailer) that follows the header */ + __le16 payld_len; + + /* end of 4-byte lookahead */ + + u8 ctrl[2]; +} __packed; + +/* HTC ready message */ +struct htc_ready_msg { + __le16 msg_id; + __le16 cred_cnt; + __le16 cred_sz; + u8 max_ep; + u8 pad; +} __packed; + +/* extended HTC ready message */ +struct htc_ready_ext_msg { + struct htc_ready_msg ver2_0_info; + u8 htc_ver; + u8 msg_per_htc_bndl; +} __packed; + +/* connect service */ +struct htc_conn_service_msg { + __le16 msg_id; + __le16 svc_id; + __le16 conn_flags; + u8 svc_meta_len; + u8 pad; +} __packed; + +/* connect response */ +struct htc_conn_service_resp { + __le16 msg_id; + __le16 svc_id; + u8 status; + u8 eid; + __le16 max_msg_sz; + u8 svc_meta_len; + u8 pad; +} __packed; + +struct htc_setup_comp_msg { + __le16 msg_id; +} __packed; + +/* extended setup completion message */ +struct htc_setup_comp_ext_msg { + __le16 msg_id; + __le32 flags; + u8 msg_per_rxbndl; + u8 Rsvd[3]; +} __packed; + +struct htc_record_hdr { + u8 rec_id; + u8 len; +} __packed; + +struct htc_credit_report { + u8 eid; + u8 credits; +} __packed; + +/* + * NOTE: The lk_ahd array is guarded by a pre_valid + * and Post Valid guard bytes. The pre_valid bytes must + * equal the inverse of the post_valid byte. + */ +struct htc_lookahead_report { + u8 pre_valid; + u8 lk_ahd[4]; + u8 post_valid; +} __packed; + +struct htc_bundle_lkahd_rpt { + u8 lk_ahd[4]; +} __packed; + +/* Current service IDs */ + +enum htc_service_grp_ids { + RSVD_SERVICE_GROUP = 0, + WMI_SERVICE_GROUP = 1, + + HTC_TEST_GROUP = 254, + HTC_SERVICE_GROUP_LAST = 255 +}; + +/* ------ endpoint IDS ------ */ + +enum htc_endpoint_id { + ENDPOINT_UNUSED = -1, + ENDPOINT_0 = 0, + ENDPOINT_1 = 1, + ENDPOINT_2 = 2, + ENDPOINT_3, + ENDPOINT_4, + ENDPOINT_5, + ENDPOINT_6, + ENDPOINT_7, + ENDPOINT_8, + ENDPOINT_MAX, +}; + +struct htc_tx_packet_info { + u16 tag; + int cred_used; + u8 flags; + int seqno; +}; + +struct htc_rx_packet_info { + u32 exp_hdr; + u32 rx_flags; + u32 indicat_flags; +}; + +struct htc_target; + +/* wrapper around endpoint-specific packets */ +struct htc_packet { + struct list_head list; + + /* caller's per packet specific context */ + void *pkt_cntxt; + + /* + * the true buffer start , the caller can store the real + * buffer start here. In receive callbacks, the HTC layer + * sets buf to the start of the payload past the header. + * This field allows the caller to reset buf when it recycles + * receive packets back to HTC. + */ + u8 *buf_start; + + /* + * Pointer to the start of the buffer. In the transmit + * direction this points to the start of the payload. In the + * receive direction, however, the buffer when queued up + * points to the start of the HTC header but when returned + * to the caller points to the start of the payload + */ + u8 *buf; + u32 buf_len; + + /* actual length of payload */ + u32 act_len; + + /* endpoint that this packet was sent/recv'd from */ + enum htc_endpoint_id endpoint; + + /* completion status */ + + int status; + union { + struct htc_tx_packet_info tx; + struct htc_rx_packet_info rx; + } info; + + void (*completion) (struct htc_target *, struct htc_packet *); + struct htc_target *context; +}; + +enum htc_send_full_action { + HTC_SEND_FULL_KEEP = 0, + HTC_SEND_FULL_DROP = 1, +}; + +struct htc_ep_callbacks { + void (*rx) (struct htc_target *, struct htc_packet *); + void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint); + enum htc_send_full_action (*tx_full) (struct htc_target *, + struct htc_packet *); + struct htc_packet *(*rx_allocthresh) (struct htc_target *, + enum htc_endpoint_id, int); + int rx_alloc_thresh; + int rx_refill_thresh; +}; + +/* service connection information */ +struct htc_service_connect_req { + u16 svc_id; + u16 conn_flags; + struct htc_ep_callbacks ep_cb; + int max_txq_depth; + u32 flags; + unsigned int max_rxmsg_sz; +}; + +/* service connection response information */ +struct htc_service_connect_resp { + u8 buf_len; + u8 act_len; + enum htc_endpoint_id endpoint; + unsigned int len_max; + u8 resp_code; +}; + +/* endpoint distributionstructure */ +struct htc_endpoint_credit_dist { + struct list_head list; + + /* Service ID (set by HTC) */ + u16 svc_id; + + /* endpoint for this distributionstruct (set by HTC) */ + enum htc_endpoint_id endpoint; + + u32 dist_flags; + + /* + * credits for normal operation, anything above this + * indicates the endpoint is over-subscribed. + */ + int cred_norm; + + /* floor for credit distribution */ + int cred_min; + + int cred_assngd; + + /* current credits available */ + int credits; + + /* + * pending credits to distribute on this endpoint, this + * is set by HTC when credit reports arrive. The credit + * distribution functions sets this to zero when it distributes + * the credits. + */ + int cred_to_dist; + + /* + * the number of credits that the current pending TX packet needs + * to transmit. This is set by HTC when endpoint needs credits in + * order to transmit. + */ + int seek_cred; + + /* size in bytes of each credit */ + int cred_sz; + + /* credits required for a maximum sized messages */ + int cred_per_msg; + + /* reserved for HTC use */ + void *htc_rsvd; + + /* + * current depth of TX queue , i.e. messages waiting for credits + * This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE + * or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint + * that has non-zero credits to recover. + */ + int txq_depth; +}; + +/* + * credit distibution code that is passed into the distrbution function, + * there are mandatory and optional codes that must be handled + */ +enum htc_credit_dist_reason { + HTC_CREDIT_DIST_SEND_COMPLETE = 0, + HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, + HTC_CREDIT_DIST_SEEK_CREDITS, +}; + +struct htc_credit_state_info { + int total_avail_credits; + int cur_free_credits; + struct list_head lowestpri_ep_dist; +}; + +/* endpoint statistics */ +struct htc_endpoint_stats { + /* + * number of times the host set the credit-low flag in a send + * message on this endpoint + */ + u32 cred_low_indicate; + + u32 tx_issued; + u32 tx_pkt_bundled; + u32 tx_bundles; + u32 tx_dropped; + + /* running count of total credit reports received for this endpoint */ + u32 tx_cred_rpt; + + /* credit reports received from this endpoint's RX packets */ + u32 cred_rpt_from_rx; + + /* credit reports received from RX packets of other endpoints */ + u32 cred_rpt_from_other; + + /* credit reports received from endpoint 0 RX packets */ + u32 cred_rpt_ep0; + + /* count of credits received via Rx packets on this endpoint */ + u32 cred_from_rx; + + /* count of credits received via another endpoint */ + u32 cred_from_other; + + /* count of credits received via another endpoint */ + u32 cred_from_ep0; + + /* count of consummed credits */ + u32 cred_cosumd; + + /* count of credits returned */ + u32 cred_retnd; + + u32 rx_pkts; + + /* count of lookahead records found in Rx msg */ + u32 rx_lkahds; + + /* count of recv packets received in a bundle */ + u32 rx_bundl; + + /* count of number of bundled lookaheads */ + u32 rx_bundle_lkahd; + + /* count of the number of bundle indications from the HTC header */ + u32 rx_bundle_from_hdr; + + /* the number of times the recv allocation threshold was hit */ + u32 rx_alloc_thresh_hit; + + /* total number of bytes */ + u32 rxalloc_thresh_byte; +}; + +struct htc_endpoint { + enum htc_endpoint_id eid; + u16 svc_id; + struct list_head txq; + struct list_head rx_bufq; + struct htc_endpoint_credit_dist cred_dist; + struct htc_ep_callbacks ep_cb; + int max_txq_depth; + int len_max; + int tx_proc_cnt; + int rx_proc_cnt; + struct htc_target *target; + u8 seqno; + u32 conn_flags; + struct htc_endpoint_stats ep_st; +}; + +struct htc_control_buffer { + struct htc_packet packet; + u8 *buf; +}; + +struct ath6kl_device; + +/* our HTC target state */ +struct htc_target { + struct htc_endpoint endpoint[ENDPOINT_MAX]; + struct list_head cred_dist_list; + struct list_head free_ctrl_txbuf; + struct list_head free_ctrl_rxbuf; + struct htc_credit_state_info *cred_dist_cntxt; + int tgt_creds; + unsigned int tgt_cred_sz; + spinlock_t htc_lock; + spinlock_t rx_lock; + spinlock_t tx_lock; + struct ath6kl_device *dev; + u32 htc_flags; + u32 rx_st_flags; + enum htc_endpoint_id ep_waiting; + u8 htc_tgt_ver; + + /* max messages per bundle for HTC */ + int msg_per_bndl_max; + + bool tx_bndl_enable; + int rx_bndl_enable; +}; + +void *htc_create(struct ath6kl *ar); +void htc_set_credit_dist(struct htc_target *target, + struct htc_credit_state_info *cred_info, + u16 svc_pri_order[], int len); +int htc_wait_target(struct htc_target *target); +int htc_start(struct htc_target *target); +int htc_conn_service(struct htc_target *target, + struct htc_service_connect_req *req, + struct htc_service_connect_resp *resp); +int htc_tx(struct htc_target *target, struct htc_packet *packet); +void htc_stop(struct htc_target *target); +void htc_cleanup(struct htc_target *target); +void htc_flush_txep(struct htc_target *target, + enum htc_endpoint_id endpoint, u16 tag); +void htc_flush_rx_buf(struct htc_target *target); +void htc_indicate_activity_change(struct htc_target *target, + enum htc_endpoint_id endpoint, bool active); +int htc_get_rxbuf_num(struct htc_target *target, enum htc_endpoint_id endpoint); +int htc_add_rxbuf_multiple(struct htc_target *target, struct list_head *pktq); + +static inline void set_htc_pkt_info(struct htc_packet *packet, void *context, + u8 *buf, unsigned int len, + enum htc_endpoint_id eid, u16 tag) +{ + packet->pkt_cntxt = context; + packet->buf = buf; + packet->act_len = len; + packet->endpoint = eid; + packet->info.tx.tag = tag; +} + +static inline void htc_rxpkt_reset(struct htc_packet *packet) +{ + packet->buf = packet->buf_start; + packet->act_len = 0; +} + +static inline void set_htc_rxpkt_info(struct htc_packet *packet, void *context, + u8 *buf, unsigned long len, + enum htc_endpoint_id eid) +{ + packet->pkt_cntxt = context; + packet->buf = buf; + packet->buf_start = buf; + packet->buf_len = len; + packet->endpoint = eid; +} + +static inline int get_queue_depth(struct list_head *queue) +{ + struct list_head *tmp_list; + int depth = 0; + + list_for_each(tmp_list, queue) + depth++; + + return depth; +} + +#endif diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.c b/drivers/net/wireless/ath/ath6kl/htc_hif.c new file mode 100644 index 000000000000..1bcaaec579c5 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc_hif.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2007-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "target.h" +#include "hif-ops.h" +#include "htc_hif.h" +#include "debug.h" + +#define MAILBOX_FOR_BLOCK_SIZE 1 + +#define ATH6KL_TIME_QUANTUM 10 /* in ms */ + +static void ath6kl_add_io_pkt(struct ath6kl_device *dev, + struct htc_packet *packet) +{ + spin_lock_bh(&dev->lock); + list_add_tail(&packet->list, &dev->reg_io); + spin_unlock_bh(&dev->lock); +} + +static struct htc_packet *ath6kl_get_io_pkt(struct ath6kl_device *dev) +{ + struct htc_packet *packet = NULL; + + spin_lock_bh(&dev->lock); + if (!list_empty(&dev->reg_io)) { + packet = list_first_entry(&dev->reg_io, + struct htc_packet, list); + list_del(&packet->list); + } + spin_unlock_bh(&dev->lock); + + return packet; +} + +static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma) +{ + u8 *buf; + int i; + + buf = req->virt_dma_buf; + + for (i = 0; i < req->scat_entries; i++) { + + if (from_dma) + memcpy(req->scat_list[i].buf, buf, + req->scat_list[i].len); + else + memcpy(buf, req->scat_list[i].buf, + req->scat_list[i].len); + + buf += req->scat_list[i].len; + } + + return 0; +} + +int ath6kldev_rw_comp_handler(void *context, int status) +{ + struct htc_packet *packet = context; + + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, + "ath6kldev_rw_comp_handler (pkt:0x%p , status: %d\n", + packet, status); + + packet->status = status; + packet->completion(packet->context, packet); + + return 0; +} + +static int ath6kldev_proc_dbg_intr(struct ath6kl_device *dev) +{ + u32 dummy; + int status; + + ath6kl_err("target debug interrupt\n"); + + ath6kl_target_failure(dev->ar); + + /* + * read counter to clear the interrupt, the debug error interrupt is + * counter 0. + */ + status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS, + (u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC); + if (status) + WARN_ON(1); + + return status; +} + +/* mailbox recv message polling */ +int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, + int timeout) +{ + struct ath6kl_irq_proc_registers *rg; + int status = 0, i; + u8 htc_mbox = 1 << HTC_MAILBOX; + + for (i = timeout / ATH6KL_TIME_QUANTUM; i > 0; i--) { + /* this is the standard HIF way, load the reg table */ + status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS, + (u8 *) &dev->irq_proc_reg, + sizeof(dev->irq_proc_reg), + HIF_RD_SYNC_BYTE_INC); + + if (status) { + ath6kl_err("failed to read reg table\n"); + return status; + } + + /* check for MBOX data and valid lookahead */ + if (dev->irq_proc_reg.host_int_status & htc_mbox) { + if (dev->irq_proc_reg.rx_lkahd_valid & + htc_mbox) { + /* + * Mailbox has a message and the look ahead + * is valid. + */ + rg = &dev->irq_proc_reg; + *lk_ahd = + le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]); + break; + } + } + + /* delay a little */ + mdelay(ATH6KL_TIME_QUANTUM); + ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "retry mbox poll : %d\n", i); + } + + if (i == 0) { + ath6kl_err("timeout waiting for recv message\n"); + status = -ETIME; + /* check if the target asserted */ + if (dev->irq_proc_reg.counter_int_status & + ATH6KL_TARGET_DEBUG_INTR_MASK) + /* + * Target failure handler will be called in case of + * an assert. + */ + ath6kldev_proc_dbg_intr(dev); + } + + return status; +} + +/* + * Disable packet reception (used in case the host runs out of buffers) + * using the interrupt enable registers through the host I/F + */ +int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx) +{ + struct ath6kl_irq_enable_reg regs; + int status = 0; + + /* take the lock to protect interrupt enable shadows */ + spin_lock_bh(&dev->lock); + + if (enable_rx) + dev->irq_en_reg.int_status_en |= + SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01); + else + dev->irq_en_reg.int_status_en &= + ~SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01); + + memcpy(®s, &dev->irq_en_reg, sizeof(regs)); + + spin_unlock_bh(&dev->lock); + + status = hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_en, + sizeof(struct ath6kl_irq_enable_reg), + HIF_WR_SYNC_BYTE_INC); + + return status; +} + +static void ath6kldev_rw_async_handler(struct htc_target *target, + struct htc_packet *packet) +{ + struct ath6kl_device *dev = target->dev; + struct hif_scatter_req *req = packet->pkt_cntxt; + + req->status = packet->status; + + ath6kl_add_io_pkt(dev, packet); + + req->complete(req); +} + +static int ath6kldev_rw_scatter(struct ath6kl *ar, struct hif_scatter_req *req) +{ + struct ath6kl_device *dev = ar->htc_target->dev; + struct htc_packet *packet = NULL; + int status = 0; + u32 request = req->req; + u8 *virt_dma_buf; + + if (!req->len) + return 0; + + if (request & HIF_ASYNCHRONOUS) { + /* use an I/O packet to carry this request */ + packet = ath6kl_get_io_pkt(dev); + if (!packet) { + status = -ENOMEM; + goto out; + } + + packet->pkt_cntxt = req; + packet->completion = ath6kldev_rw_async_handler; + packet->context = ar->htc_target; + } + + virt_dma_buf = req->virt_dma_buf; + + if (request & HIF_ASYNCHRONOUS) + status = hif_write_async(dev->ar, req->addr, virt_dma_buf, + req->len, request, packet); + else + status = hif_read_write_sync(dev->ar, req->addr, virt_dma_buf, + req->len, request); + +out: + if (status) + if (request & HIF_ASYNCHRONOUS) { + if (packet != NULL) + ath6kl_add_io_pkt(dev, packet); + req->status = status; + req->complete(req); + status = 0; + } + + return status; +} + +int ath6kldev_submit_scat_req(struct ath6kl_device *dev, + struct hif_scatter_req *scat_req, bool read) +{ + int status = 0; + + if (read) { + scat_req->req = HIF_RD_SYNC_BLOCK_FIX; + scat_req->addr = dev->ar->mbox_info.htc_addr; + } else { + scat_req->req = HIF_WR_ASYNC_BLOCK_INC; + + scat_req->addr = + (scat_req->len > HIF_MBOX_WIDTH) ? + dev->ar->mbox_info.htc_ext_addr : + dev->ar->mbox_info.htc_addr; + } + + ath6kl_dbg((ATH6KL_DBG_HTC_RECV | ATH6KL_DBG_HTC_SEND), + "ath6kldev_submit_scat_req, entries: %d, total len: %d mbox:0x%X (mode: %s : %s)\n", + scat_req->scat_entries, scat_req->len, + scat_req->addr, !read ? "async" : "sync", + (read) ? "rd" : "wr"); + + if (!read && dev->virt_scat) + status = ath6kldev_cp_scat_dma_buf(scat_req, false); + + if (status) { + if (!read) { + scat_req->status = status; + scat_req->complete(scat_req); + return 0; + } + return status; + } + + status = dev->hif_scat_info.rw_scat_func(dev->ar, scat_req); + + if (read) { + /* in sync mode, we can touch the scatter request */ + scat_req->status = status; + if (!status && dev->virt_scat) + scat_req->status = + ath6kldev_cp_scat_dma_buf(scat_req, true); + } + + return status; +} + +/* + * function to set up virtual scatter support if HIF + * layer has not implemented the interface. + */ +static int ath6kldev_setup_virt_scat_sup(struct ath6kl_device *dev) +{ + struct hif_scatter_req *scat_req; + int buf_sz, scat_req_sz, scat_list_sz; + int i, status = 0; + u8 *virt_dma_buf; + + buf_sz = 2 * L1_CACHE_BYTES + ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER; + + scat_list_sz = (ATH6KL_SCATTER_ENTRIES_PER_REQ - 1) * + sizeof(struct hif_scatter_item); + scat_req_sz = sizeof(*scat_req) + scat_list_sz; + + for (i = 0; i < ATH6KL_SCATTER_REQS; i++) { + scat_req = kzalloc(scat_req_sz, GFP_KERNEL); + + if (!scat_req) { + status = -ENOMEM; + break; + } + + virt_dma_buf = kzalloc(buf_sz, GFP_KERNEL); + if (!virt_dma_buf) { + kfree(scat_req); + status = -ENOMEM; + break; + } + + scat_req->virt_dma_buf = + (u8 *)L1_CACHE_ALIGN((unsigned long)virt_dma_buf); + + /* we emulate a DMA bounce interface */ + hif_scatter_req_add(dev->ar, scat_req); + } + + if (status) + ath6kl_hif_cleanup_scatter(dev->ar); + else { + dev->hif_scat_info.rw_scat_func = ath6kldev_rw_scatter; + dev->hif_scat_info.max_scat_entries = + ATH6KL_SCATTER_ENTRIES_PER_REQ; + dev->hif_scat_info.max_xfer_szper_scatreq = + ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER; + dev->virt_scat = true; + } + + return status; +} + +int ath6kldev_setup_msg_bndl(struct ath6kl_device *dev, int max_msg_per_trans) +{ + int status; + + status = ath6kl_hif_enable_scatter(dev->ar, &dev->hif_scat_info); + + if (status) { + ath6kl_warn("hif does not support scatter requests (%d)\n", + status); + + /* we can try to use a virtual DMA scatter mechanism */ + status = ath6kldev_setup_virt_scat_sup(dev); + } + + if (!status) + ath6kl_dbg(ATH6KL_DBG_ANY, "max scatter items:%d: maxlen:%d\n", + dev->hif_scat_info.max_scat_entries, + dev->hif_scat_info.max_xfer_szper_scatreq); + + return status; +} + +static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev) +{ + u8 counter_int_status; + + ath6kl_dbg(ATH6KL_DBG_IRQ, "counter interrupt\n"); + + counter_int_status = dev->irq_proc_reg.counter_int_status & + dev->irq_en_reg.cntr_int_status_en; + + ath6kl_dbg(ATH6KL_DBG_IRQ, + "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", + counter_int_status); + + /* + * NOTE: other modules like GMBOX may use the counter interrupt for + * credit flow control on other counters, we only need to check for + * the debug assertion counter interrupt. + */ + if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK) + return ath6kldev_proc_dbg_intr(dev); + + return 0; +} + +static int ath6kldev_proc_err_intr(struct ath6kl_device *dev) +{ + int status; + u8 error_int_status; + u8 reg_buf[4]; + + ath6kl_dbg(ATH6KL_DBG_IRQ, "error interrupt\n"); + + error_int_status = dev->irq_proc_reg.error_int_status & 0x0F; + if (!error_int_status) { + WARN_ON(1); + return -EIO; + } + + ath6kl_dbg(ATH6KL_DBG_IRQ, + "valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", + error_int_status); + + if (MS(ERROR_INT_STATUS_WAKEUP, error_int_status)) + ath6kl_dbg(ATH6KL_DBG_IRQ, "error : wakeup\n"); + + if (MS(ERROR_INT_STATUS_RX_UNDERFLOW, error_int_status)) + ath6kl_err("rx underflow\n"); + + if (MS(ERROR_INT_STATUS_TX_OVERFLOW, error_int_status)) + ath6kl_err("tx overflow\n"); + + /* Clear the interrupt */ + dev->irq_proc_reg.error_int_status &= ~error_int_status; + + /* set W1C value to clear the interrupt, this hits the register first */ + reg_buf[0] = error_int_status; + reg_buf[1] = 0; + reg_buf[2] = 0; + reg_buf[3] = 0; + + status = hif_read_write_sync(dev->ar, ERROR_INT_STATUS_ADDRESS, + reg_buf, 4, HIF_WR_SYNC_BYTE_FIX); + + if (status) + WARN_ON(1); + + return status; +} + +static int ath6kldev_proc_cpu_intr(struct ath6kl_device *dev) +{ + int status; + u8 cpu_int_status; + u8 reg_buf[4]; + + ath6kl_dbg(ATH6KL_DBG_IRQ, "cpu interrupt\n"); + + cpu_int_status = dev->irq_proc_reg.cpu_int_status & + dev->irq_en_reg.cpu_int_status_en; + if (!cpu_int_status) { + WARN_ON(1); + return -EIO; + } + + ath6kl_dbg(ATH6KL_DBG_IRQ, + "valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", + cpu_int_status); + + /* Clear the interrupt */ + dev->irq_proc_reg.cpu_int_status &= ~cpu_int_status; + + /* + * Set up the register transfer buffer to hit the register 4 times , + * this is done to make the access 4-byte aligned to mitigate issues + * with host bus interconnects that restrict bus transfer lengths to + * be a multiple of 4-bytes. + */ + + /* set W1C value to clear the interrupt, this hits the register first */ + reg_buf[0] = cpu_int_status; + /* the remaining are set to zero which have no-effect */ + reg_buf[1] = 0; + reg_buf[2] = 0; + reg_buf[3] = 0; + + status = hif_read_write_sync(dev->ar, CPU_INT_STATUS_ADDRESS, + reg_buf, 4, HIF_WR_SYNC_BYTE_FIX); + + if (status) + WARN_ON(1); + + return status; +} + +/* process pending interrupts synchronously */ +static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) +{ + struct ath6kl_irq_proc_registers *rg; + int status = 0; + u8 host_int_status = 0; + u32 lk_ahd = 0; + u8 htc_mbox = 1 << HTC_MAILBOX; + + ath6kl_dbg(ATH6KL_DBG_IRQ, "proc_pending_irqs: (dev: 0x%p)\n", dev); + + /* + * NOTE: HIF implementation guarantees that the context of this + * call allows us to perform SYNCHRONOUS I/O, that is we can block, + * sleep or call any API that can block or switch thread/task + * contexts. This is a fully schedulable context. + */ + + /* + * Process pending intr only when int_status_en is clear, it may + * result in unnecessary bus transaction otherwise. Target may be + * unresponsive at the time. + */ + if (dev->irq_en_reg.int_status_en) { + /* + * Read the first 28 bytes of the HTC register table. This + * will yield us the value of different int status + * registers and the lookahead registers. + * + * length = sizeof(int_status) + sizeof(cpu_int_status) + * + sizeof(error_int_status) + + * sizeof(counter_int_status) + + * sizeof(mbox_frame) + sizeof(rx_lkahd_valid) + * + sizeof(hole) + sizeof(rx_lkahd) + + * sizeof(int_status_en) + + * sizeof(cpu_int_status_en) + + * sizeof(err_int_status_en) + + * sizeof(cntr_int_status_en); + */ + status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS, + (u8 *) &dev->irq_proc_reg, + sizeof(dev->irq_proc_reg), + HIF_RD_SYNC_BYTE_INC); + if (status) + goto out; + + if (AR_DBG_LVL_CHECK(ATH6KL_DBG_IRQ)) + ath6kl_dump_registers(dev, &dev->irq_proc_reg, + &dev->irq_en_reg); + + /* Update only those registers that are enabled */ + host_int_status = dev->irq_proc_reg.host_int_status & + dev->irq_en_reg.int_status_en; + + /* Look at mbox status */ + if (host_int_status & htc_mbox) { + /* + * Mask out pending mbox value, we use "lookAhead as + * the real flag for mbox processing. + */ + host_int_status &= ~htc_mbox; + if (dev->irq_proc_reg.rx_lkahd_valid & + htc_mbox) { + rg = &dev->irq_proc_reg; + lk_ahd = le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]); + if (!lk_ahd) + ath6kl_err("lookAhead is zero!\n"); + } + } + } + + if (!host_int_status && !lk_ahd) { + *done = true; + goto out; + } + + if (lk_ahd) { + int fetched = 0; + + ath6kl_dbg(ATH6KL_DBG_IRQ, + "pending mailbox msg, lk_ahd: 0x%X\n", lk_ahd); + /* + * Mailbox Interrupt, the HTC layer may issue async + * requests to empty the mailbox. When emptying the recv + * mailbox we use the async handler above called from the + * completion routine of the callers read request. This can + * improve performance by reducing context switching when + * we rapidly pull packets. + */ + status = dev->msg_pending(dev->htc_cnxt, &lk_ahd, &fetched); + if (status) + goto out; + + if (!fetched) + /* + * HTC could not pull any messages out due to lack + * of resources. + */ + dev->chk_irq_status_cnt = 0; + } + + /* now handle the rest of them */ + ath6kl_dbg(ATH6KL_DBG_IRQ, + "valid interrupt source(s) for other interrupts: 0x%x\n", + host_int_status); + + if (MS(HOST_INT_STATUS_CPU, host_int_status)) { + /* CPU Interrupt */ + status = ath6kldev_proc_cpu_intr(dev); + if (status) + goto out; + } + + if (MS(HOST_INT_STATUS_ERROR, host_int_status)) { + /* Error Interrupt */ + status = ath6kldev_proc_err_intr(dev); + if (status) + goto out; + } + + if (MS(HOST_INT_STATUS_COUNTER, host_int_status)) + /* Counter Interrupt */ + status = ath6kldev_proc_counter_intr(dev); + +out: + /* + * An optimization to bypass reading the IRQ status registers + * unecessarily which can re-wake the target, if upper layers + * determine that we are in a low-throughput mode, we can rely on + * taking another interrupt rather than re-checking the status + * registers which can re-wake the target. + * + * NOTE : for host interfaces that makes use of detecting pending + * mbox messages at hif can not use this optimization due to + * possible side effects, SPI requires the host to drain all + * messages from the mailbox before exiting the ISR routine. + */ + + ath6kl_dbg(ATH6KL_DBG_IRQ, + "bypassing irq status re-check, forcing done\n"); + + *done = true; + + ath6kl_dbg(ATH6KL_DBG_IRQ, + "proc_pending_irqs: (done:%d, status=%d\n", *done, status); + + return status; +} + +/* interrupt handler, kicks off all interrupt processing */ +int ath6kldev_intr_bh_handler(struct ath6kl *ar) +{ + struct ath6kl_device *dev = ar->htc_target->dev; + int status = 0; + bool done = false; + + /* + * Reset counter used to flag a re-scan of IRQ status registers on + * the target. + */ + dev->chk_irq_status_cnt = 0; + + /* + * IRQ processing is synchronous, interrupt status registers can be + * re-read. + */ + while (!done) { + status = proc_pending_irqs(dev, &done); + if (status) + break; + } + + return status; +} + +static int ath6kldev_enable_intrs(struct ath6kl_device *dev) +{ + struct ath6kl_irq_enable_reg regs; + int status; + + spin_lock_bh(&dev->lock); + + /* Enable all but ATH6KL CPU interrupts */ + dev->irq_en_reg.int_status_en = + SM(INT_STATUS_ENABLE_ERROR, 0x01) | + SM(INT_STATUS_ENABLE_CPU, 0x01) | + SM(INT_STATUS_ENABLE_COUNTER, 0x01); + + /* + * NOTE: There are some cases where HIF can do detection of + * pending mbox messages which is disabled now. + */ + dev->irq_en_reg.int_status_en |= SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01); + + /* Set up the CPU Interrupt status Register */ + dev->irq_en_reg.cpu_int_status_en = 0; + + /* Set up the Error Interrupt status Register */ + dev->irq_en_reg.err_int_status_en = + SM(ERROR_STATUS_ENABLE_RX_UNDERFLOW, 0x01) | + SM(ERROR_STATUS_ENABLE_TX_OVERFLOW, 0x1); + + /* + * Enable Counter interrupt status register to get fatal errors for + * debugging. + */ + dev->irq_en_reg.cntr_int_status_en = SM(COUNTER_INT_STATUS_ENABLE_BIT, + ATH6KL_TARGET_DEBUG_INTR_MASK); + memcpy(®s, &dev->irq_en_reg, sizeof(regs)); + + spin_unlock_bh(&dev->lock); + + status = hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_en, sizeof(regs), + HIF_WR_SYNC_BYTE_INC); + + if (status) + ath6kl_err("failed to update interrupt ctl reg err: %d\n", + status); + + return status; +} + +int ath6kldev_disable_intrs(struct ath6kl_device *dev) +{ + struct ath6kl_irq_enable_reg regs; + + spin_lock_bh(&dev->lock); + /* Disable all interrupts */ + dev->irq_en_reg.int_status_en = 0; + dev->irq_en_reg.cpu_int_status_en = 0; + dev->irq_en_reg.err_int_status_en = 0; + dev->irq_en_reg.cntr_int_status_en = 0; + memcpy(®s, &dev->irq_en_reg, sizeof(regs)); + spin_unlock_bh(&dev->lock); + + return hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_en, sizeof(regs), + HIF_WR_SYNC_BYTE_INC); +} + +/* enable device interrupts */ +int ath6kldev_unmask_intrs(struct ath6kl_device *dev) +{ + int status = 0; + + /* + * Make sure interrupt are disabled before unmasking at the HIF + * layer. The rationale here is that between device insertion + * (where we clear the interrupts the first time) and when HTC + * is finally ready to handle interrupts, other software can perform + * target "soft" resets. The ATH6KL interrupt enables reset back to an + * "enabled" state when this happens. + */ + ath6kldev_disable_intrs(dev); + + /* unmask the host controller interrupts */ + ath6kl_hif_irq_enable(dev->ar); + status = ath6kldev_enable_intrs(dev); + + return status; +} + +/* disable all device interrupts */ +int ath6kldev_mask_intrs(struct ath6kl_device *dev) +{ + /* + * Mask the interrupt at the HIF layer to avoid any stray interrupt + * taken while we zero out our shadow registers in + * ath6kldev_disable_intrs(). + */ + ath6kl_hif_irq_disable(dev->ar); + + return ath6kldev_disable_intrs(dev); +} + +int ath6kldev_setup(struct ath6kl_device *dev) +{ + int status = 0; + int i; + struct htc_packet *packet; + + /* initialize our free list of IO packets */ + INIT_LIST_HEAD(&dev->reg_io); + spin_lock_init(&dev->lock); + + /* carve up register I/O packets (these are for ASYNC register I/O ) */ + for (i = 0; i < ATH6KL_MAX_REG_IO_BUFFERS; i++) { + packet = &dev->reg_io_buf[i].packet; + set_htc_rxpkt_info(packet, dev, dev->reg_io_buf[i].buf, + ATH6KL_REG_IO_BUFFER_SIZE, 0); + ath6kl_add_io_pkt(dev, packet); + } + + /* + * NOTE: we actually get the block size of a mailbox other than 0, + * for SDIO the block size on mailbox 0 is artificially set to 1. + * So we use the block size that is set for the other 3 mailboxes. + */ + dev->block_sz = dev->ar->mbox_info.block_size; + + /* must be a power of 2 */ + if ((dev->block_sz & (dev->block_sz - 1)) != 0) { + WARN_ON(1); + goto fail_setup; + } + + /* assemble mask, used for padding to a block */ + dev->block_mask = dev->block_sz - 1; + + ath6kl_dbg(ATH6KL_DBG_TRC, "block size: %d, mbox addr:0x%X\n", + dev->block_sz, dev->ar->mbox_info.htc_addr); + + ath6kl_dbg(ATH6KL_DBG_TRC, + "hif interrupt processing is sync only\n"); + + status = ath6kldev_disable_intrs(dev); + +fail_setup: + return status; + +} diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.h b/drivers/net/wireless/ath/ath6kl/htc_hif.h new file mode 100644 index 000000000000..d770d4ec612e --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc_hif.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2007-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HTC_HIF_H +#define HTC_HIF_H + +#include "htc.h" +#include "hif.h" + +#define ATH6KL_MAILBOXES 4 + +/* HTC runs over mailbox 0 */ +#define HTC_MAILBOX 0 + +#define ATH6KL_TARGET_DEBUG_INTR_MASK 0x01 + +#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ + INT_STATUS_ENABLE_CPU_MASK | \ + INT_STATUS_ENABLE_COUNTER_MASK) + +#define ATH6KL_REG_IO_BUFFER_SIZE 32 +#define ATH6KL_MAX_REG_IO_BUFFERS 8 +#define ATH6KL_SCATTER_ENTRIES_PER_REQ 16 +#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER (16 * 1024) +#define ATH6KL_SCATTER_REQS 4 + +#ifndef A_CACHE_LINE_PAD +#define A_CACHE_LINE_PAD 128 +#endif +#define ATH6KL_MIN_SCATTER_ENTRIES_PER_REQ 2 +#define ATH6KL_MIN_TRANSFER_SIZE_PER_SCATTER (4 * 1024) + +struct ath6kl_irq_proc_registers { + u8 host_int_status; + u8 cpu_int_status; + u8 error_int_status; + u8 counter_int_status; + u8 mbox_frame; + u8 rx_lkahd_valid; + u8 host_int_status2; + u8 gmbox_rx_avail; + __le32 rx_lkahd[2]; + __le32 rx_gmbox_lkahd_alias[2]; +} __packed; + +struct ath6kl_irq_enable_reg { + u8 int_status_en; + u8 cpu_int_status_en; + u8 err_int_status_en; + u8 cntr_int_status_en; +} __packed; + +/* buffers for ASYNC I/O */ +struct ath6kl_async_reg_io_buffer { + struct htc_packet packet; + u8 pad1[A_CACHE_LINE_PAD]; + /* cache-line safe with pads around */ + u8 buf[ATH6KL_REG_IO_BUFFER_SIZE]; + u8 pad2[A_CACHE_LINE_PAD]; +}; + +struct ath6kl_device { + spinlock_t lock; + u8 pad1[A_CACHE_LINE_PAD]; + struct ath6kl_irq_proc_registers irq_proc_reg; + u8 pad2[A_CACHE_LINE_PAD]; + struct ath6kl_irq_enable_reg irq_en_reg; + u8 pad3[A_CACHE_LINE_PAD]; + u32 block_sz; + u32 block_mask; + struct htc_target *htc_cnxt; + struct list_head reg_io; + struct ath6kl_async_reg_io_buffer reg_io_buf[ATH6KL_MAX_REG_IO_BUFFERS]; + int (*msg_pending) (struct htc_target *target, u32 lk_ahds[], + int *npkts_fetched); + struct hif_dev_scat_sup_info hif_scat_info; + bool virt_scat; + int max_rx_bndl_sz; + int max_tx_bndl_sz; + int chk_irq_status_cnt; + struct ath6kl *ar; +}; + +int ath6kldev_setup(struct ath6kl_device *dev); +int ath6kldev_unmask_intrs(struct ath6kl_device *dev); +int ath6kldev_mask_intrs(struct ath6kl_device *dev); +int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, + u32 *lk_ahd, int timeout); +int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx); +int ath6kldev_disable_intrs(struct ath6kl_device *dev); + +int ath6kldev_rw_comp_handler(void *context, int status); +int ath6kldev_intr_bh_handler(struct ath6kl *ar); + +/* Scatter Function and Definitions */ +int ath6kldev_setup_msg_bndl(struct ath6kl_device *dev, int max_msg_per_xfer); +int ath6kldev_submit_scat_req(struct ath6kl_device *dev, + struct hif_scatter_req *scat_req, bool read); + +#endif /*ATH6KL_H_ */ diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c new file mode 100644 index 000000000000..fe61871e9874 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -0,0 +1,1293 @@ + +/* + * Copyright (c) 2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/mmc/sdio_func.h> +#include "core.h" +#include "cfg80211.h" +#include "target.h" +#include "debug.h" +#include "hif-ops.h" + +unsigned int debug_mask; + +module_param(debug_mask, uint, 0644); + +/* + * Include definitions here that can be used to tune the WLAN module + * behavior. Different customers can tune the behavior as per their needs, + * here. + */ + +/* + * This configuration item enable/disable keepalive support. + * Keepalive support: In the absence of any data traffic to AP, null + * frames will be sent to the AP at periodic interval, to keep the association + * active. This configuration item defines the periodic interval. + * Use value of zero to disable keepalive support + * Default: 60 seconds + */ +#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60 + +/* + * This configuration item sets the value of disconnect timeout + * Firmware delays sending the disconnec event to the host for this + * timeout after is gets disconnected from the current AP. + * If the firmware successly roams within the disconnect timeout + * it sends a new connect event + */ +#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 + +#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 + +enum addr_type { + DATASET_PATCH_ADDR, + APP_LOAD_ADDR, + APP_START_OVERRIDE_ADDR, +}; + +#define ATH6KL_DATA_OFFSET 64 +struct sk_buff *ath6kl_buf_alloc(int size) +{ + struct sk_buff *skb; + u16 reserved; + + /* Add chacheline space at front and back of buffer */ + reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + + sizeof(struct htc_packet); + skb = dev_alloc_skb(size + reserved); + + if (skb) + skb_reserve(skb, reserved - L1_CACHE_BYTES); + return skb; +} + +void ath6kl_init_profile_info(struct ath6kl *ar) +{ + ar->ssid_len = 0; + memset(ar->ssid, 0, sizeof(ar->ssid)); + + ar->dot11_auth_mode = OPEN_AUTH; + ar->auth_mode = NONE_AUTH; + ar->prwise_crypto = NONE_CRYPT; + ar->prwise_crypto_len = 0; + ar->grp_crypto = NONE_CRYPT; + ar->grp_crpto_len = 0; + memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); + memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); + memset(ar->bssid, 0, sizeof(ar->bssid)); + ar->bss_ch = 0; + ar->nw_type = ar->next_mode = INFRA_NETWORK; +} + +static u8 ath6kl_get_fw_iftype(struct ath6kl *ar) +{ + switch (ar->nw_type) { + case INFRA_NETWORK: + return HI_OPTION_FW_MODE_BSS_STA; + case ADHOC_NETWORK: + return HI_OPTION_FW_MODE_IBSS; + case AP_NETWORK: + return HI_OPTION_FW_MODE_AP; + default: + ath6kl_err("Unsupported interface type :%d\n", ar->nw_type); + return 0xff; + } +} + +static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, + u32 item_offset) +{ + u32 addr = 0; + + if (ar->target_type == TARGET_TYPE_AR6003) + addr = ATH6KL_HI_START_ADDR + item_offset; + + return addr; +} + +static int ath6kl_set_host_app_area(struct ath6kl *ar) +{ + u32 address, data; + struct host_app_area host_app_area; + + /* Fetch the address of the host_app_area_s + * instance in the host interest area */ + address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest)); + address = TARG_VTOP(address); + + if (ath6kl_read_reg_diag(ar, &address, &data)) + return -EIO; + + address = TARG_VTOP(data); + host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; + if (ath6kl_access_datadiag(ar, address, + (u8 *)&host_app_area, + sizeof(struct host_app_area), false)) + return -EIO; + + return 0; +} + +static inline void set_ac2_ep_map(struct ath6kl *ar, + u8 ac, + enum htc_endpoint_id ep) +{ + ar->ac2ep_map[ac] = ep; + ar->ep2ac_map[ep] = ac; +} + +/* connect to a service */ +static int ath6kl_connectservice(struct ath6kl *ar, + struct htc_service_connect_req *con_req, + char *desc) +{ + int status; + struct htc_service_connect_resp response; + + memset(&response, 0, sizeof(response)); + + status = htc_conn_service(ar->htc_target, con_req, &response); + if (status) { + ath6kl_err("failed to connect to %s service status:%d\n", + desc, status); + return status; + } + + switch (con_req->svc_id) { + case WMI_CONTROL_SVC: + if (test_bit(WMI_ENABLED, &ar->flag)) + ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint); + ar->ctrl_ep = response.endpoint; + break; + case WMI_DATA_BE_SVC: + set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint); + break; + case WMI_DATA_BK_SVC: + set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint); + break; + case WMI_DATA_VI_SVC: + set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint); + break; + case WMI_DATA_VO_SVC: + set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint); + break; + default: + ath6kl_err("service id is not mapped %d\n", con_req->svc_id); + return -EINVAL; + } + + return 0; +} + +static int ath6kl_init_service_ep(struct ath6kl *ar) +{ + struct htc_service_connect_req connect; + + memset(&connect, 0, sizeof(connect)); + + /* these fields are the same for all service endpoints */ + connect.ep_cb.rx = ath6kl_rx; + connect.ep_cb.rx_refill = ath6kl_rx_refill; + connect.ep_cb.tx_full = ath6kl_tx_queue_full; + + /* + * Set the max queue depth so that our ath6kl_tx_queue_full handler + * gets called. + */ + connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH; + connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4; + if (!connect.ep_cb.rx_refill_thresh) + connect.ep_cb.rx_refill_thresh++; + + /* connect to control service */ + connect.svc_id = WMI_CONTROL_SVC; + if (ath6kl_connectservice(ar, &connect, "WMI CONTROL")) + return -EIO; + + connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN; + + /* + * Limit the HTC message size on the send path, although e can + * receive A-MSDU frames of 4K, we will only send ethernet-sized + * (802.3) frames on the send path. + */ + connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH; + + /* + * To reduce the amount of committed memory for larger A_MSDU + * frames, use the recv-alloc threshold mechanism for larger + * packets. + */ + connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE; + connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf; + + /* + * For the remaining data services set the connection flag to + * reduce dribbling, if configured to do so. + */ + connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB; + connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK; + connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF; + + connect.svc_id = WMI_DATA_BE_SVC; + + if (ath6kl_connectservice(ar, &connect, "WMI DATA BE")) + return -EIO; + + /* connect to back-ground map this to WMI LOW_PRI */ + connect.svc_id = WMI_DATA_BK_SVC; + if (ath6kl_connectservice(ar, &connect, "WMI DATA BK")) + return -EIO; + + /* connect to Video service, map this to to HI PRI */ + connect.svc_id = WMI_DATA_VI_SVC; + if (ath6kl_connectservice(ar, &connect, "WMI DATA VI")) + return -EIO; + + /* + * Connect to VO service, this is currently not mapped to a WMI + * priority stream due to historical reasons. WMI originally + * defined 3 priorities over 3 mailboxes We can change this when + * WMI is reworked so that priorities are not dependent on + * mailboxes. + */ + connect.svc_id = WMI_DATA_VO_SVC; + if (ath6kl_connectservice(ar, &connect, "WMI DATA VO")) + return -EIO; + + return 0; +} + +static void ath6kl_init_control_info(struct ath6kl *ar) +{ + u8 ctr; + + clear_bit(WMI_ENABLED, &ar->flag); + ath6kl_init_profile_info(ar); + ar->def_txkey_index = 0; + memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); + ar->ch_hint = 0; + ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL; + ar->listen_intvl_b = 0; + ar->tx_pwr = 0; + clear_bit(SKIP_SCAN, &ar->flag); + set_bit(WMM_ENABLED, &ar->flag); + ar->intra_bss = 1; + memset(&ar->sc_params, 0, sizeof(ar->sc_params)); + ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT; + ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS; + + memset((u8 *)ar->sta_list, 0, + AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); + + spin_lock_init(&ar->mcastpsq_lock); + + /* Init the PS queues */ + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + spin_lock_init(&ar->sta_list[ctr].psq_lock); + skb_queue_head_init(&ar->sta_list[ctr].psq); + } + + skb_queue_head_init(&ar->mcastpsq); + + memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); +} + +/* + * Set HTC/Mbox operational parameters, this can only be called when the + * target is in the BMI phase. + */ +static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val, + u8 htc_ctrl_buf) +{ + int status; + u32 blk_size; + + blk_size = ar->mbox_info.block_size; + + if (htc_ctrl_buf) + blk_size |= ((u32)htc_ctrl_buf) << 16; + + /* set the host interest area for the block size */ + status = ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_mbox_io_block_sz)), + (u8 *)&blk_size, + 4); + if (status) { + ath6kl_err("bmi_write_memory for IO block size failed\n"); + goto out; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n", + blk_size, + ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz))); + + if (mbox_isr_yield_val) { + /* set the host interest area for the mbox ISR yield limit */ + status = ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_mbox_isr_yield_limit)), + (u8 *)&mbox_isr_yield_val, + 4); + if (status) { + ath6kl_err("bmi_write_memory for yield limit failed\n"); + goto out; + } + } + +out: + return status; +} + +#define REG_DUMP_COUNT_AR6003 60 +#define REGISTER_DUMP_LEN_MAX 60 + +static void ath6kl_dump_target_assert_info(struct ath6kl *ar) +{ + u32 address; + u32 regdump_loc = 0; + int status; + u32 regdump_val[REGISTER_DUMP_LEN_MAX]; + u32 i; + + if (ar->target_type != TARGET_TYPE_AR6003) + return; + + /* the reg dump pointer is copied to the host interest area */ + address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state)); + address = TARG_VTOP(address); + + /* read RAM location through diagnostic window */ + status = ath6kl_read_reg_diag(ar, &address, ®dump_loc); + + if (status || !regdump_loc) { + ath6kl_err("failed to get ptr to register dump area\n"); + return; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n", + regdump_loc); + + regdump_loc = TARG_VTOP(regdump_loc); + + /* fetch register dump data */ + status = ath6kl_access_datadiag(ar, + regdump_loc, + (u8 *)®dump_val[0], + REG_DUMP_COUNT_AR6003 * (sizeof(u32)), + true); + + if (status) { + ath6kl_err("failed to get register dump\n"); + return; + } + ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n"); + + for (i = 0; i < REG_DUMP_COUNT_AR6003; i++) + ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n", + i, regdump_val[i]); + +} + +void ath6kl_target_failure(struct ath6kl *ar) +{ + ath6kl_err("target asserted\n"); + + /* try dumping target assertion information (if any) */ + ath6kl_dump_target_assert_info(ar); + +} + +static int ath6kl_target_config_wlan_params(struct ath6kl *ar) +{ + int status = 0; + + /* + * Configure the device for rx dot11 header rules. "0,0" are the + * default values. Required if checksum offload is needed. Set + * RxMetaVersion to 2. + */ + if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, + ar->rx_meta_ver, 0, 0)) { + ath6kl_err("unable to set the rx frame format\n"); + status = -EIO; + } + + if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN) + if ((ath6kl_wmi_pmparams_cmd(ar->wmi, 0, 1, 0, 0, 1, + IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) { + ath6kl_err("unable to set power save fail event policy\n"); + status = -EIO; + } + + if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER)) + if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, 0, + WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) { + ath6kl_err("unable to set barker preamble policy\n"); + status = -EIO; + } + + if (ath6kl_wmi_set_keepalive_cmd(ar->wmi, + WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) { + ath6kl_err("unable to set keep alive interval\n"); + status = -EIO; + } + + if (ath6kl_wmi_disctimeout_cmd(ar->wmi, + WLAN_CONFIG_DISCONNECT_TIMEOUT)) { + ath6kl_err("unable to set disconnect timeout\n"); + status = -EIO; + } + + if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST)) + if (ath6kl_wmi_set_wmm_txop(ar->wmi, WMI_TXOP_DISABLED)) { + ath6kl_err("unable to set txop bursting\n"); + status = -EIO; + } + + return status; +} + +int ath6kl_configure_target(struct ath6kl *ar) +{ + u32 param, ram_reserved_size; + u8 fw_iftype; + + fw_iftype = ath6kl_get_fw_iftype(ar); + if (fw_iftype == 0xff) + return -EINVAL; + + /* Tell target which HTC version it is used*/ + param = HTC_PROTOCOL_VERSION; + if (ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_app_host_interest)), + (u8 *)¶m, 4) != 0) { + ath6kl_err("bmi_write_memory for htc version failed\n"); + return -EIO; + } + + /* set the firmware mode to STA/IBSS/AP */ + param = 0; + + if (ath6kl_bmi_read(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_option_flag)), + (u8 *)¶m, 4) != 0) { + ath6kl_err("bmi_read_memory for setting fwmode failed\n"); + return -EIO; + } + + param |= (1 << HI_OPTION_NUM_DEV_SHIFT); + param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT); + param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); + param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); + + if (ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_option_flag)), + (u8 *)¶m, + 4) != 0) { + ath6kl_err("bmi_write_memory for setting fwmode failed\n"); + return -EIO; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n"); + + /* + * Hardcode the address use for the extended board data + * Ideally this should be pre-allocate by the OS at boot time + * But since it is a new feature and board data is loaded + * at init time, we have to workaround this from host. + * It is difficult to patch the firmware boot code, + * but possible in theory. + */ + + if (ar->target_type == TARGET_TYPE_AR6003) { + if (ar->version.target_ver == AR6003_REV2_VERSION) { + param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; + ram_reserved_size = AR6003_REV2_RAM_RESERVE_SIZE; + } else { + param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; + ram_reserved_size = AR6003_REV3_RAM_RESERVE_SIZE; + } + + if (ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_ext_data)), + (u8 *)¶m, 4) != 0) { + ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); + return -EIO; + } + if (ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_end_ram_reserve_sz)), + (u8 *)&ram_reserved_size, 4) != 0) { + ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); + return -EIO; + } + } + + /* set the block size for the target */ + if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0)) + /* use default number of control buffers */ + return -EIO; + + return 0; +} + +struct ath6kl *ath6kl_core_alloc(struct device *sdev) +{ + struct net_device *dev; + struct ath6kl *ar; + struct wireless_dev *wdev; + + wdev = ath6kl_cfg80211_init(sdev); + if (!wdev) { + ath6kl_err("ath6kl_cfg80211_init failed\n"); + return NULL; + } + + ar = wdev_priv(wdev); + ar->dev = sdev; + ar->wdev = wdev; + wdev->iftype = NL80211_IFTYPE_STATION; + + dev = alloc_netdev(0, "wlan%d", ether_setup); + if (!dev) { + ath6kl_err("no memory for network device instance\n"); + ath6kl_cfg80211_deinit(ar); + return NULL; + } + + dev->ieee80211_ptr = wdev; + SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); + wdev->netdev = dev; + ar->sme_state = SME_DISCONNECTED; + ar->auto_auth_stage = AUTH_IDLE; + + init_netdev(dev); + + ar->net_dev = dev; + ar->wlan_state = WLAN_ENABLED; + + ar->wlan_pwr_state = WLAN_POWER_STATE_ON; + + spin_lock_init(&ar->lock); + + ath6kl_init_control_info(ar); + init_waitqueue_head(&ar->event_wq); + sema_init(&ar->sem, 1); + clear_bit(DESTROY_IN_PROGRESS, &ar->flag); + + INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); + + setup_timer(&ar->disconnect_timer, disconnect_timer_handler, + (unsigned long) dev); + + return ar; +} + +int ath6kl_unavail_ev(struct ath6kl *ar) +{ + ath6kl_destroy(ar->net_dev, 1); + + return 0; +} + +/* firmware upload */ +static u32 ath6kl_get_load_address(u32 target_ver, enum addr_type type) +{ + WARN_ON(target_ver != AR6003_REV2_VERSION && + target_ver != AR6003_REV3_VERSION); + + switch (type) { + case DATASET_PATCH_ADDR: + return (target_ver == AR6003_REV2_VERSION) ? + AR6003_REV2_DATASET_PATCH_ADDRESS : + AR6003_REV3_DATASET_PATCH_ADDRESS; + case APP_LOAD_ADDR: + return (target_ver == AR6003_REV2_VERSION) ? + AR6003_REV2_APP_LOAD_ADDRESS : + 0x1234; + case APP_START_OVERRIDE_ADDR: + return (target_ver == AR6003_REV2_VERSION) ? + AR6003_REV2_APP_START_OVERRIDE : + AR6003_REV3_APP_START_OVERRIDE; + default: + return 0; + } +} + +static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, + u8 **fw, size_t *fw_len) +{ + const struct firmware *fw_entry; + int ret; + + ret = request_firmware(&fw_entry, filename, ar->dev); + if (ret) + return ret; + + *fw_len = fw_entry->size; + *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); + + if (*fw == NULL) + ret = -ENOMEM; + + release_firmware(fw_entry); + + return ret; +} + +static int ath6kl_fetch_board_file(struct ath6kl *ar) +{ + const char *filename; + int ret; + + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_BOARD_DATA_FILE; + break; + default: + filename = AR6003_REV3_BOARD_DATA_FILE; + break; + } + + ret = ath6kl_get_fw(ar, filename, &ar->fw_board, + &ar->fw_board_len); + if (ret == 0) { + /* managed to get proper board file */ + return 0; + } + + /* there was no proper board file, try to use default instead */ + ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", + filename, ret); + + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE; + break; + default: + filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE; + break; + } + + ret = ath6kl_get_fw(ar, filename, &ar->fw_board, + &ar->fw_board_len); + if (ret) { + ath6kl_err("Failed to get default board file %s: %d\n", + filename, ret); + return ret; + } + + ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n"); + ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n"); + + return 0; +} + + +static int ath6kl_upload_board_file(struct ath6kl *ar) +{ + u32 board_address, board_ext_address, param; + int ret; + + if (ar->fw_board == NULL) { + ret = ath6kl_fetch_board_file(ar); + if (ret) + return ret; + } + + /* Determine where in Target RAM to write Board Data */ + ath6kl_bmi_read(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_data)), + (u8 *) &board_address, 4); + ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n", + board_address); + + /* determine where in target ram to write extended board data */ + ath6kl_bmi_read(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_ext_data)), + (u8 *) &board_ext_address, 4); + + ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n", + board_ext_address); + + if (board_ext_address == 0) { + ath6kl_err("Failed to get board file target address.\n"); + return -EINVAL; + } + + if (ar->fw_board_len == (AR6003_BOARD_DATA_SZ + + AR6003_BOARD_EXT_DATA_SZ)) { + /* write extended board data */ + ret = ath6kl_bmi_write(ar, board_ext_address, + ar->fw_board + AR6003_BOARD_DATA_SZ, + AR6003_BOARD_EXT_DATA_SZ); + + if (ret) { + ath6kl_err("Failed to write extended board data: %d\n", + ret); + return ret; + } + + /* record that extended board data is initialized */ + param = (AR6003_BOARD_EXT_DATA_SZ << 16) | 1; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_ext_data_config)), + (unsigned char *) ¶m, 4); + } + + if (ar->fw_board_len < AR6003_BOARD_DATA_SZ) { + ath6kl_err("Too small board file: %zu\n", ar->fw_board_len); + ret = -EINVAL; + return ret; + } + + ret = ath6kl_bmi_write(ar, board_address, ar->fw_board, + AR6003_BOARD_DATA_SZ); + + if (ret) { + ath6kl_err("Board file bmi write failed: %d\n", ret); + return ret; + } + + /* record the fact that Board Data IS initialized */ + param = 1; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_data_initialized)), + (u8 *)¶m, 4); + + return ret; +} + +static int ath6kl_upload_otp(struct ath6kl *ar) +{ + const char *filename; + u32 address, param; + int ret; + + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_OTP_FILE; + break; + default: + filename = AR6003_REV3_OTP_FILE; + break; + } + + if (ar->fw_otp == NULL) { + ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, + &ar->fw_otp_len); + if (ret) { + ath6kl_err("Failed to get OTP file %s: %d\n", + filename, ret); + return ret; + } + } + + address = ath6kl_get_load_address(ar->version.target_ver, + APP_LOAD_ADDR); + + ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp, + ar->fw_otp_len); + if (ret) { + ath6kl_err("Failed to upload OTP file: %d\n", ret); + return ret; + } + + /* execute the OTP code */ + param = 0; + address = ath6kl_get_load_address(ar->version.target_ver, + APP_START_OVERRIDE_ADDR); + ath6kl_bmi_execute(ar, address, ¶m); + + return ret; +} + +static int ath6kl_upload_firmware(struct ath6kl *ar) +{ + const char *filename; + u32 address; + int ret; + + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_FIRMWARE_FILE; + break; + default: + filename = AR6003_REV3_FIRMWARE_FILE; + break; + } + + if (ar->fw == NULL) { + ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); + if (ret) { + ath6kl_err("Failed to get firmware file %s: %d\n", + filename, ret); + return ret; + } + } + + address = ath6kl_get_load_address(ar->version.target_ver, + APP_LOAD_ADDR); + + ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len); + + if (ret) { + ath6kl_err("Failed to write firmware: %d\n", ret); + return ret; + } + + /* Set starting address for firmware */ + address = ath6kl_get_load_address(ar->version.target_ver, + APP_START_OVERRIDE_ADDR); + ath6kl_bmi_set_app_start(ar, address); + + return ret; +} + +static int ath6kl_upload_patch(struct ath6kl *ar) +{ + const char *filename; + u32 address, param; + int ret; + + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_PATCH_FILE; + break; + default: + filename = AR6003_REV3_PATCH_FILE; + break; + } + + if (ar->fw_patch == NULL) { + ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, + &ar->fw_patch_len); + if (ret) { + ath6kl_err("Failed to get patch file %s: %d\n", + filename, ret); + return ret; + } + } + + address = ath6kl_get_load_address(ar->version.target_ver, + DATASET_PATCH_ADDR); + + ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len); + if (ret) { + ath6kl_err("Failed to write patch file: %d\n", ret); + return ret; + } + + param = address; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_dset_list_head)), + (unsigned char *) ¶m, 4); + + return 0; +} + +static int ath6kl_init_upload(struct ath6kl *ar) +{ + u32 param, options, sleep, address; + int status = 0; + + if (ar->target_type != TARGET_TYPE_AR6003) + return -EINVAL; + + /* temporarily disable system sleep */ + address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; + status = ath6kl_bmi_reg_read(ar, address, ¶m); + if (status) + return status; + + options = param; + + param |= ATH6KL_OPTION_SLEEP_DISABLE; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; + status = ath6kl_bmi_reg_read(ar, address, ¶m); + if (status) + return status; + + sleep = param; + + param |= SM(SYSTEM_SLEEP_DISABLE, 1); + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n", + options, sleep); + + /* program analog PLL register */ + status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER, + 0xF9104001); + if (status) + return status; + + /* Run at 80/88MHz by default */ + param = SM(CPU_CLOCK_STANDARD, 1); + + address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + param = 0; + address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; + param = SM(LPO_CAL_ENABLE, 1); + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + /* WAR to avoid SDIO CRC err */ + if (ar->version.target_ver == AR6003_REV2_VERSION) { + ath6kl_err("temporary war to avoid sdio crc error\n"); + + param = 0x20; + + address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + } + + /* write EEPROM data to Target RAM */ + status = ath6kl_upload_board_file(ar); + if (status) + return status; + + /* transfer One time Programmable data */ + status = ath6kl_upload_otp(ar); + if (status) + return status; + + /* Download Target firmware */ + status = ath6kl_upload_firmware(ar); + if (status) + return status; + + status = ath6kl_upload_patch(ar); + if (status) + return status; + + /* Restore system sleep */ + address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, sleep); + if (status) + return status; + + address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; + param = options | 0x20; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; + + /* Configure GPIO AR6003 UART */ + param = CONFIG_AR600x_DEBUG_UART_TX_PIN; + status = ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_dbg_uart_txpin)), + (u8 *)¶m, 4); + + return status; +} + +static int ath6kl_init(struct net_device *dev) +{ + struct ath6kl *ar = ath6kl_priv(dev); + int status = 0; + s32 timeleft; + + if (!ar) + return -EIO; + + /* Do we need to finish the BMI phase */ + if (ath6kl_bmi_done(ar)) { + status = -EIO; + goto ath6kl_init_done; + } + + /* Indicate that WMI is enabled (although not ready yet) */ + set_bit(WMI_ENABLED, &ar->flag); + ar->wmi = ath6kl_wmi_init((void *) ar); + if (!ar->wmi) { + ath6kl_err("failed to initialize wmi\n"); + status = -EIO; + goto ath6kl_init_done; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); + + /* + * The reason we have to wait for the target here is that the + * driver layer has to init BMI in order to set the host block + * size. + */ + if (htc_wait_target(ar->htc_target)) { + status = -EIO; + goto err_wmi_cleanup; + } + + if (ath6kl_init_service_ep(ar)) { + status = -EIO; + goto err_cleanup_scatter; + } + + /* setup access class priority mappings */ + ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ + ar->ac_stream_pri_map[WMM_AC_BE] = 1; + ar->ac_stream_pri_map[WMM_AC_VI] = 2; + ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ + + /* give our connected endpoints some buffers */ + ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); + ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); + + /* allocate some buffers that handle larger AMSDU frames */ + ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); + + /* setup credit distribution */ + ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info); + + ath6kl_cookie_init(ar); + + /* start HTC */ + status = htc_start(ar->htc_target); + + if (status) { + ath6kl_cookie_cleanup(ar); + goto err_rxbuf_cleanup; + } + + /* Wait for Wmi event to be ready */ + timeleft = wait_event_interruptible_timeout(ar->event_wq, + test_bit(WMI_READY, + &ar->flag), + WMI_TIMEOUT); + + if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { + ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", + ATH6KL_ABI_VERSION, ar->version.abi_ver); + status = -EIO; + goto err_htc_stop; + } + + if (!timeleft || signal_pending(current)) { + ath6kl_err("wmi is not ready or wait was interrupted\n"); + status = -EIO; + goto err_htc_stop; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__); + + /* communicate the wmi protocol verision to the target */ + if ((ath6kl_set_host_app_area(ar)) != 0) + ath6kl_err("unable to set the host app area\n"); + + ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | + ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; + + status = ath6kl_target_config_wlan_params(ar); + if (!status) + goto ath6kl_init_done; + +err_htc_stop: + htc_stop(ar->htc_target); +err_rxbuf_cleanup: + htc_flush_rx_buf(ar->htc_target); + ath6kl_cleanup_amsdu_rxbufs(ar); +err_cleanup_scatter: + ath6kl_hif_cleanup_scatter(ar); +err_wmi_cleanup: + ath6kl_wmi_shutdown(ar->wmi); + clear_bit(WMI_ENABLED, &ar->flag); + ar->wmi = NULL; + +ath6kl_init_done: + return status; +} + +int ath6kl_core_init(struct ath6kl *ar) +{ + int ret = 0; + struct ath6kl_bmi_target_info targ_info; + + ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); + if (!ar->ath6kl_wq) + return -ENOMEM; + + ret = ath6kl_bmi_init(ar); + if (ret) + goto err_wq; + + ret = ath6kl_bmi_get_target_info(ar, &targ_info); + if (ret) + goto err_bmi_cleanup; + + ar->version.target_ver = le32_to_cpu(targ_info.version); + ar->target_type = le32_to_cpu(targ_info.type); + ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version); + + ret = ath6kl_configure_target(ar); + if (ret) + goto err_bmi_cleanup; + + ar->htc_target = htc_create(ar); + + if (!ar->htc_target) { + ret = -ENOMEM; + goto err_bmi_cleanup; + } + + ar->aggr_cntxt = aggr_init(ar->net_dev); + if (!ar->aggr_cntxt) { + ath6kl_err("failed to initialize aggr\n"); + ret = -ENOMEM; + goto err_htc_cleanup; + } + + ret = ath6kl_init_upload(ar); + if (ret) + goto err_htc_cleanup; + + ret = ath6kl_init(ar->net_dev); + if (ret) + goto err_htc_cleanup; + + /* This runs the init function if registered */ + ret = register_netdev(ar->net_dev); + if (ret) { + ath6kl_err("register_netdev failed\n"); + ath6kl_destroy(ar->net_dev, 0); + return ret; + } + + set_bit(NETDEV_REGISTERED, &ar->flag); + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", + __func__, ar->net_dev->name, ar->net_dev, ar); + + return ret; + +err_htc_cleanup: + htc_cleanup(ar->htc_target); +err_bmi_cleanup: + ath6kl_bmi_cleanup(ar); +err_wq: + destroy_workqueue(ar->ath6kl_wq); + return ret; +} + +void ath6kl_stop_txrx(struct ath6kl *ar) +{ + struct net_device *ndev = ar->net_dev; + + if (!ndev) + return; + + set_bit(DESTROY_IN_PROGRESS, &ar->flag); + + if (down_interruptible(&ar->sem)) { + ath6kl_err("down_interruptible failed\n"); + return; + } + + if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR) + ath6kl_stop_endpoint(ndev, false, true); + + ar->wlan_state = WLAN_DISABLED; +} + +/* + * We need to differentiate between the surprise and planned removal of the + * device because of the following consideration: + * + * - In case of surprise removal, the hcd already frees up the pending + * for the device and hence there is no need to unregister the function + * driver inorder to get these requests. For planned removal, the function + * driver has to explicitly unregister itself to have the hcd return all the + * pending requests before the data structures for the devices are freed up. + * Note that as per the current implementation, the function driver will + * end up releasing all the devices since there is no API to selectively + * release a particular device. + * + * - Certain commands issued to the target can be skipped for surprise + * removal since they will anyway not go through. + */ +void ath6kl_destroy(struct net_device *dev, unsigned int unregister) +{ + struct ath6kl *ar; + + if (!dev || !ath6kl_priv(dev)) { + ath6kl_err("failed to get device structure\n"); + return; + } + + ar = ath6kl_priv(dev); + + destroy_workqueue(ar->ath6kl_wq); + + if (ar->htc_target) + htc_cleanup(ar->htc_target); + + aggr_module_destroy(ar->aggr_cntxt); + + ath6kl_cookie_cleanup(ar); + + ath6kl_cleanup_amsdu_rxbufs(ar); + + ath6kl_bmi_cleanup(ar); + + if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) { + unregister_netdev(dev); + clear_bit(NETDEV_REGISTERED, &ar->flag); + } + + free_netdev(dev); + + ath6kl_cfg80211_deinit(ar); +} diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c new file mode 100644 index 000000000000..f325a23dfff0 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -0,0 +1,1337 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "hif-ops.h" +#include "cfg80211.h" +#include "target.h" +#include "debug.h" + +struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 *node_addr) +{ + struct ath6kl_sta *conn = NULL; + u8 i, max_conn; + + max_conn = (ar->nw_type == AP_NETWORK) ? AP_MAX_NUM_STA : 0; + + for (i = 0; i < max_conn; i++) { + if (memcmp(node_addr, ar->sta_list[i].mac, ETH_ALEN) == 0) { + conn = &ar->sta_list[i]; + break; + } + } + + return conn; +} + +struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) +{ + struct ath6kl_sta *conn = NULL; + u8 ctr; + + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + if (ar->sta_list[ctr].aid == aid) { + conn = &ar->sta_list[ctr]; + break; + } + } + return conn; +} + +static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, + u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) +{ + struct ath6kl_sta *sta; + u8 free_slot; + + free_slot = aid - 1; + + sta = &ar->sta_list[free_slot]; + memcpy(sta->mac, mac, ETH_ALEN); + memcpy(sta->wpa_ie, wpaie, ielen); + sta->aid = aid; + sta->keymgmt = keymgmt; + sta->ucipher = ucipher; + sta->auth = auth; + + ar->sta_list_index = ar->sta_list_index | (1 << free_slot); + ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); +} + +static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) +{ + struct ath6kl_sta *sta = &ar->sta_list[i]; + + /* empty the queued pkts in the PS queue if any */ + spin_lock_bh(&sta->psq_lock); + skb_queue_purge(&sta->psq); + spin_unlock_bh(&sta->psq_lock); + + memset(&ar->ap_stats.sta[sta->aid - 1], 0, + sizeof(struct wmi_per_sta_stat)); + memset(sta->mac, 0, ETH_ALEN); + memset(sta->wpa_ie, 0, ATH6KL_MAX_IE); + sta->aid = 0; + sta->sta_flags = 0; + + ar->sta_list_index = ar->sta_list_index & ~(1 << i); + +} + +static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason) +{ + u8 i, removed = 0; + + if (is_zero_ether_addr(mac)) + return removed; + + if (is_broadcast_ether_addr(mac)) { + ath6kl_dbg(ATH6KL_DBG_TRC, "deleting all station\n"); + + for (i = 0; i < AP_MAX_NUM_STA; i++) { + if (!is_zero_ether_addr(ar->sta_list[i].mac)) { + ath6kl_sta_cleanup(ar, i); + removed = 1; + } + } + } else { + for (i = 0; i < AP_MAX_NUM_STA; i++) { + if (memcmp(ar->sta_list[i].mac, mac, ETH_ALEN) == 0) { + ath6kl_dbg(ATH6KL_DBG_TRC, + "deleting station %pM aid=%d reason=%d\n", + mac, ar->sta_list[i].aid, reason); + ath6kl_sta_cleanup(ar, i); + removed = 1; + break; + } + } + } + + return removed; +} + +enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac) +{ + struct ath6kl *ar = devt; + return ar->ac2ep_map[ac]; +} + +struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar) +{ + struct ath6kl_cookie *cookie; + + cookie = ar->cookie_list; + if (cookie != NULL) { + ar->cookie_list = cookie->arc_list_next; + ar->cookie_count--; + } + + return cookie; +} + +void ath6kl_cookie_init(struct ath6kl *ar) +{ + u32 i; + + ar->cookie_list = NULL; + ar->cookie_count = 0; + + memset(ar->cookie_mem, 0, sizeof(ar->cookie_mem)); + + for (i = 0; i < MAX_COOKIE_NUM; i++) + ath6kl_free_cookie(ar, &ar->cookie_mem[i]); +} + +void ath6kl_cookie_cleanup(struct ath6kl *ar) +{ + ar->cookie_list = NULL; + ar->cookie_count = 0; +} + +void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie) +{ + /* Insert first */ + + if (!ar || !cookie) + return; + + cookie->arc_list_next = ar->cookie_list; + ar->cookie_list = cookie; + ar->cookie_count++; +} + +/* set the window address register (using 4-byte register access ). */ +static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) +{ + int status; + u8 addr_val[4]; + s32 i; + + /* + * Write bytes 1,2,3 of the register to set the upper address bytes, + * the LSB is written last to initiate the access cycle + */ + + for (i = 1; i <= 3; i++) { + /* + * Fill the buffer with the address byte value we want to + * hit 4 times. + */ + memset(addr_val, ((u8 *)&addr)[i], 4); + + /* + * Hit each byte of the register address with a 4-byte + * write operation to the same address, this is a harmless + * operation. + */ + status = hif_read_write_sync(ar, reg_addr + i, addr_val, + 4, HIF_WR_SYNC_BYTE_FIX); + if (status) + break; + } + + if (status) { + ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n", + addr, reg_addr); + return status; + } + + /* + * Write the address register again, this time write the whole + * 4-byte value. The effect here is that the LSB write causes the + * cycle to start, the extra 3 byte write to bytes 1,2,3 has no + * effect since we are writing the same values again + */ + status = hif_read_write_sync(ar, reg_addr, (u8 *)(&addr), + 4, HIF_WR_SYNC_BYTE_INC); + + if (status) { + ath6kl_err("failed to write 0x%x to window reg: 0x%X\n", + addr, reg_addr); + return status; + } + + return 0; +} + +/* + * Read from the ATH6KL through its diagnostic window. No cooperation from + * the Target is required for this. + */ +int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data) +{ + int status; + + /* set window register to start read cycle */ + status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, + *address); + + if (status) + return status; + + /* read the data */ + status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data, + sizeof(u32), HIF_RD_SYNC_BYTE_INC); + if (status) { + ath6kl_err("failed to read from window data addr\n"); + return status; + } + + return status; +} + + +/* + * Write to the ATH6KL through its diagnostic window. No cooperation from + * the Target is required for this. + */ +static int ath6kl_write_reg_diag(struct ath6kl *ar, u32 *address, u32 *data) +{ + int status; + + /* set write data */ + status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data, + sizeof(u32), HIF_WR_SYNC_BYTE_INC); + if (status) { + ath6kl_err("failed to write 0x%x to window data addr\n", *data); + return status; + } + + /* set window register, which starts the write cycle */ + return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, + *address); +} + +int ath6kl_access_datadiag(struct ath6kl *ar, u32 address, + u8 *data, u32 length, bool read) +{ + u32 count; + int status = 0; + + for (count = 0; count < length; count += 4, address += 4) { + if (read) { + status = ath6kl_read_reg_diag(ar, &address, + (u32 *) &data[count]); + if (status) + break; + } else { + status = ath6kl_write_reg_diag(ar, &address, + (u32 *) &data[count]); + if (status) + break; + } + } + + return status; +} + +static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, + bool wait_fot_compltn, bool cold_reset) +{ + int status = 0; + u32 address; + u32 data; + + if (target_type != TARGET_TYPE_AR6003) + return; + + data = cold_reset ? RESET_CONTROL_COLD_RST : RESET_CONTROL_MBOX_RST; + + address = RTC_BASE_ADDRESS; + status = ath6kl_write_reg_diag(ar, &address, &data); + + if (status) + ath6kl_err("failed to reset target\n"); +} + +void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile, + bool get_dbglogs) +{ + struct ath6kl *ar = ath6kl_priv(dev); + static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + bool discon_issued; + + netif_stop_queue(dev); + + /* disable the target and the interrupts associated with it */ + if (test_bit(WMI_READY, &ar->flag)) { + discon_issued = (test_bit(CONNECTED, &ar->flag) || + test_bit(CONNECT_PEND, &ar->flag)); + ath6kl_disconnect(ar); + if (!keep_profile) + ath6kl_init_profile_info(ar); + + del_timer(&ar->disconnect_timer); + + clear_bit(WMI_READY, &ar->flag); + ath6kl_wmi_shutdown(ar->wmi); + clear_bit(WMI_ENABLED, &ar->flag); + ar->wmi = NULL; + + /* + * After wmi_shudown all WMI events will be dropped. We + * need to cleanup the buffers allocated in AP mode and + * give disconnect notification to stack, which usually + * happens in the disconnect_event. Simulate the disconnect + * event by calling the function directly. Sometimes + * disconnect_event will be received when the debug logs + * are collected. + */ + if (discon_issued) + ath6kl_disconnect_event(ar, DISCONNECT_CMD, + (ar->nw_type & AP_NETWORK) ? + bcast_mac : ar->bssid, + 0, NULL, 0); + + ar->user_key_ctrl = 0; + + } else { + ath6kl_dbg(ATH6KL_DBG_TRC, + "%s: wmi is not ready 0x%p 0x%p\n", + __func__, ar, ar->wmi); + + /* Shut down WMI if we have started it */ + if (test_bit(WMI_ENABLED, &ar->flag)) { + ath6kl_dbg(ATH6KL_DBG_TRC, + "%s: shut down wmi\n", __func__); + ath6kl_wmi_shutdown(ar->wmi); + clear_bit(WMI_ENABLED, &ar->flag); + ar->wmi = NULL; + } + } + + if (ar->htc_target) { + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__); + htc_stop(ar->htc_target); + } + + /* + * Try to reset the device if we can. The driver may have been + * configure NOT to reset the target during a debug session. + */ + ath6kl_dbg(ATH6KL_DBG_TRC, + "attempting to reset target on instance destroy\n"); + ath6kl_reset_device(ar, ar->target_type, true, true); +} + +static void ath6kl_install_static_wep_keys(struct ath6kl *ar) +{ + u8 index; + u8 keyusage; + + for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { + if (ar->wep_key_list[index].key_len) { + keyusage = GROUP_USAGE; + if (index == ar->def_txkey_index) + keyusage |= TX_USAGE; + + ath6kl_wmi_addkey_cmd(ar->wmi, + index, + WEP_CRYPT, + keyusage, + ar->wep_key_list[index].key_len, + NULL, + ar->wep_key_list[index].key, + KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + } + } +} + +static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, + u16 listen_int, u16 beacon_int, + u8 assoc_resp_len, u8 *assoc_info) +{ + struct net_device *dev = ar->net_dev; + struct station_info sinfo; + struct ath6kl_req_key *ik; + enum crypto_type keyType = NONE_CRYPT; + + if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) { + ik = &ar->ap_mode_bkey; + + switch (ar->auth_mode) { + case NONE_AUTH: + if (ar->prwise_crypto == WEP_CRYPT) + ath6kl_install_static_wep_keys(ar); + break; + case WPA_PSK_AUTH: + case WPA2_PSK_AUTH: + case (WPA_PSK_AUTH|WPA2_PSK_AUTH): + switch (ik->ik_type) { + case ATH6KL_CIPHER_TKIP: + keyType = TKIP_CRYPT; + break; + case ATH6KL_CIPHER_AES_CCM: + keyType = AES_CRYPT; + break; + default: + goto skip_key; + } + ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType, + GROUP_USAGE, ik->ik_keylen, + (u8 *)&ik->ik_keyrsc, + ik->ik_keydata, + KEY_OP_INIT_VAL, ik->ik_macaddr, + SYNC_BOTH_WMIFLAG); + break; + } +skip_key: + set_bit(CONNECTED, &ar->flag); + return; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", + bssid, channel); + + ath6kl_add_new_sta(ar, bssid, channel, assoc_info, assoc_resp_len, + listen_int & 0xFF, beacon_int, + (listen_int >> 8) & 0xFF); + + /* send event to application */ + memset(&sinfo, 0, sizeof(sinfo)); + + /* TODO: sinfo.generation */ + /* TODO: need to deliver (Re)AssocReq IEs somehow.. change in + * cfg80211 needed, e.g., by adding those into sinfo + */ + cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL); + + netif_wake_queue(ar->net_dev); + + return; +} + +/* Functions for Tx credit handling */ +void ath6k_credit_init(struct htc_credit_state_info *cred_info, + struct list_head *ep_list, + int tot_credits) +{ + struct htc_endpoint_credit_dist *cur_ep_dist; + int count; + + cred_info->cur_free_credits = tot_credits; + cred_info->total_avail_credits = tot_credits; + + list_for_each_entry(cur_ep_dist, ep_list, list) { + if (cur_ep_dist->endpoint == ENDPOINT_0) + continue; + + cur_ep_dist->cred_min = cur_ep_dist->cred_per_msg; + + if (tot_credits > 4) + if ((cur_ep_dist->svc_id == WMI_DATA_BK_SVC) || + (cur_ep_dist->svc_id == WMI_DATA_BE_SVC)) { + ath6kl_deposit_credit_to_ep(cred_info, + cur_ep_dist, + cur_ep_dist->cred_min); + cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; + } + + if (cur_ep_dist->svc_id == WMI_CONTROL_SVC) { + ath6kl_deposit_credit_to_ep(cred_info, cur_ep_dist, + cur_ep_dist->cred_min); + /* + * Control service is always marked active, it + * never goes inactive EVER. + */ + cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; + } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC) + /* this is the lowest priority data endpoint */ + cred_info->lowestpri_ep_dist = cur_ep_dist->list; + + /* + * Streams have to be created (explicit | implicit) for all + * kinds of traffic. BE endpoints are also inactive in the + * beginning. When BE traffic starts it creates implicit + * streams that redistributes credits. + * + * Note: all other endpoints have minimums set but are + * initially given NO credits. credits will be distributed + * as traffic activity demands + */ + } + + WARN_ON(cred_info->cur_free_credits <= 0); + + list_for_each_entry(cur_ep_dist, ep_list, list) { + if (cur_ep_dist->endpoint == ENDPOINT_0) + continue; + + if (cur_ep_dist->svc_id == WMI_CONTROL_SVC) + cur_ep_dist->cred_norm = cur_ep_dist->cred_per_msg; + else { + /* + * For the remaining data endpoints, we assume that + * each cred_per_msg are the same. We use a simple + * calculation here, we take the remaining credits + * and determine how many max messages this can + * cover and then set each endpoint's normal value + * equal to 3/4 this amount. + */ + count = (cred_info->cur_free_credits / + cur_ep_dist->cred_per_msg) + * cur_ep_dist->cred_per_msg; + count = (count * 3) >> 2; + count = max(count, cur_ep_dist->cred_per_msg); + cur_ep_dist->cred_norm = count; + + } + } +} + +/* initialize and setup credit distribution */ +int ath6k_setup_credit_dist(void *htc_handle, + struct htc_credit_state_info *cred_info) +{ + u16 servicepriority[5]; + + memset(cred_info, 0, sizeof(struct htc_credit_state_info)); + + servicepriority[0] = WMI_CONTROL_SVC; /* highest */ + servicepriority[1] = WMI_DATA_VO_SVC; + servicepriority[2] = WMI_DATA_VI_SVC; + servicepriority[3] = WMI_DATA_BE_SVC; + servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */ + + /* set priority list */ + htc_set_credit_dist(htc_handle, cred_info, servicepriority, 5); + + return 0; +} + +/* reduce an ep's credits back to a set limit */ +static void ath6k_reduce_credits(struct htc_credit_state_info *cred_info, + struct htc_endpoint_credit_dist *ep_dist, + int limit) +{ + int credits; + + ep_dist->cred_assngd = limit; + + if (ep_dist->credits <= limit) + return; + + credits = ep_dist->credits - limit; + ep_dist->credits -= credits; + cred_info->cur_free_credits += credits; +} + +static void ath6k_credit_update(struct htc_credit_state_info *cred_info, + struct list_head *epdist_list) +{ + struct htc_endpoint_credit_dist *cur_dist_list; + + list_for_each_entry(cur_dist_list, epdist_list, list) { + if (cur_dist_list->endpoint == ENDPOINT_0) + continue; + + if (cur_dist_list->cred_to_dist > 0) { + cur_dist_list->credits += + cur_dist_list->cred_to_dist; + cur_dist_list->cred_to_dist = 0; + if (cur_dist_list->credits > + cur_dist_list->cred_assngd) + ath6k_reduce_credits(cred_info, + cur_dist_list, + cur_dist_list->cred_assngd); + + if (cur_dist_list->credits > + cur_dist_list->cred_norm) + ath6k_reduce_credits(cred_info, cur_dist_list, + cur_dist_list->cred_norm); + + if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) { + if (cur_dist_list->txq_depth == 0) + ath6k_reduce_credits(cred_info, + cur_dist_list, 0); + } + } + } +} + +/* + * HTC has an endpoint that needs credits, ep_dist is the endpoint in + * question. + */ +void ath6k_seek_credits(struct htc_credit_state_info *cred_info, + struct htc_endpoint_credit_dist *ep_dist) +{ + struct htc_endpoint_credit_dist *curdist_list; + int credits = 0; + int need; + + if (ep_dist->svc_id == WMI_CONTROL_SVC) + goto out; + + if ((ep_dist->svc_id == WMI_DATA_VI_SVC) || + (ep_dist->svc_id == WMI_DATA_VO_SVC)) + if ((ep_dist->cred_assngd >= ep_dist->cred_norm)) + goto out; + + /* + * For all other services, we follow a simple algorithm of: + * + * 1. checking the free pool for credits + * 2. checking lower priority endpoints for credits to take + */ + + credits = min(cred_info->cur_free_credits, ep_dist->seek_cred); + + if (credits >= ep_dist->seek_cred) + goto out; + + /* + * We don't have enough in the free pool, try taking away from + * lower priority services The rule for taking away credits: + * + * 1. Only take from lower priority endpoints + * 2. Only take what is allocated above the minimum (never + * starve an endpoint completely) + * 3. Only take what you need. + */ + + list_for_each_entry_reverse(curdist_list, + &cred_info->lowestpri_ep_dist, + list) { + if (curdist_list == ep_dist) + break; + + need = ep_dist->seek_cred - cred_info->cur_free_credits; + + if ((curdist_list->cred_assngd - need) >= + curdist_list->cred_min) { + /* + * The current one has been allocated more than + * it's minimum and it has enough credits assigned + * above it's minimum to fulfill our need try to + * take away just enough to fulfill our need. + */ + ath6k_reduce_credits(cred_info, curdist_list, + curdist_list->cred_assngd - need); + + if (cred_info->cur_free_credits >= + ep_dist->seek_cred) + break; + } + + if (curdist_list->endpoint == ENDPOINT_0) + break; + } + + credits = min(cred_info->cur_free_credits, ep_dist->seek_cred); + +out: + /* did we find some credits? */ + if (credits) + ath6kl_deposit_credit_to_ep(cred_info, ep_dist, credits); + + ep_dist->seek_cred = 0; +} + +/* redistribute credits based on activity change */ +static void ath6k_redistribute_credits(struct htc_credit_state_info *info, + struct list_head *ep_dist_list) +{ + struct htc_endpoint_credit_dist *curdist_list; + + list_for_each_entry(curdist_list, ep_dist_list, list) { + if (curdist_list->endpoint == ENDPOINT_0) + continue; + + if ((curdist_list->svc_id == WMI_DATA_BK_SVC) || + (curdist_list->svc_id == WMI_DATA_BE_SVC)) + curdist_list->dist_flags |= HTC_EP_ACTIVE; + + if ((curdist_list->svc_id != WMI_CONTROL_SVC) && + !(curdist_list->dist_flags & HTC_EP_ACTIVE)) { + if (curdist_list->txq_depth == 0) + ath6k_reduce_credits(info, + curdist_list, 0); + else + ath6k_reduce_credits(info, + curdist_list, + curdist_list->cred_min); + } + } +} + +/* + * + * This function is invoked whenever endpoints require credit + * distributions. A lock is held while this function is invoked, this + * function shall NOT block. The ep_dist_list is a list of distribution + * structures in prioritized order as defined by the call to the + * htc_set_credit_dist() api. + */ +void ath6k_credit_distribute(struct htc_credit_state_info *cred_info, + struct list_head *ep_dist_list, + enum htc_credit_dist_reason reason) +{ + switch (reason) { + case HTC_CREDIT_DIST_SEND_COMPLETE: + ath6k_credit_update(cred_info, ep_dist_list); + break; + case HTC_CREDIT_DIST_ACTIVITY_CHANGE: + ath6k_redistribute_credits(cred_info, ep_dist_list); + break; + default: + break; + } + + WARN_ON(cred_info->cur_free_credits > cred_info->total_avail_credits); + WARN_ON(cred_info->cur_free_credits < 0); +} + +void disconnect_timer_handler(unsigned long ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct ath6kl *ar = ath6kl_priv(dev); + + ath6kl_init_profile_info(ar); + ath6kl_disconnect(ar); +} + +void ath6kl_disconnect(struct ath6kl *ar) +{ + if (test_bit(CONNECTED, &ar->flag) || + test_bit(CONNECT_PEND, &ar->flag)) { + ath6kl_wmi_disconnect_cmd(ar->wmi); + /* + * Disconnect command is issued, clear the connect pending + * flag. The connected flag will be cleared in + * disconnect event notification. + */ + clear_bit(CONNECT_PEND, &ar->flag); + } +} + +/* WMI Event handlers */ + +static const char *get_hw_id_string(u32 id) +{ + switch (id) { + case AR6003_REV1_VERSION: + return "1.0"; + case AR6003_REV2_VERSION: + return "2.0"; + case AR6003_REV3_VERSION: + return "2.1.1"; + default: + return "unknown"; + } +} + +void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) +{ + struct ath6kl *ar = devt; + struct net_device *dev = ar->net_dev; + + memcpy(dev->dev_addr, datap, ETH_ALEN); + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n", + __func__, dev->dev_addr); + + ar->version.wlan_ver = sw_ver; + ar->version.abi_ver = abi_ver; + + snprintf(ar->wdev->wiphy->fw_version, + sizeof(ar->wdev->wiphy->fw_version), + "%u.%u.%u.%u", + (ar->version.wlan_ver & 0xf0000000) >> 28, + (ar->version.wlan_ver & 0x0f000000) >> 24, + (ar->version.wlan_ver & 0x00ff0000) >> 16, + (ar->version.wlan_ver & 0x0000ffff)); + + /* indicate to the waiting thread that the ready event was received */ + set_bit(WMI_READY, &ar->flag); + wake_up(&ar->event_wq); + + ath6kl_info("hw %s fw %s\n", + get_hw_id_string(ar->wdev->wiphy->hw_version), + ar->wdev->wiphy->fw_version); +} + +void ath6kl_scan_complete_evt(struct ath6kl *ar, int status) +{ + ath6kl_cfg80211_scan_complete_event(ar, status); + + if (!ar->usr_bss_filter) + ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); + + ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status); +} + +void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, + u16 listen_int, u16 beacon_int, + enum network_type net_type, u8 beacon_ie_len, + u8 assoc_req_len, u8 assoc_resp_len, + u8 *assoc_info) +{ + unsigned long flags; + + if (ar->nw_type == AP_NETWORK) { + ath6kl_connect_ap_mode(ar, channel, bssid, listen_int, + beacon_int, assoc_resp_len, + assoc_info); + return; + } + + ath6kl_cfg80211_connect_event(ar, channel, bssid, + listen_int, beacon_int, + net_type, beacon_ie_len, + assoc_req_len, assoc_resp_len, + assoc_info); + + memcpy(ar->bssid, bssid, sizeof(ar->bssid)); + ar->bss_ch = channel; + + if ((ar->nw_type == INFRA_NETWORK)) + ath6kl_wmi_listeninterval_cmd(ar->wmi, ar->listen_intvl_t, + ar->listen_intvl_b); + + netif_wake_queue(ar->net_dev); + + /* Update connect & link status atomically */ + spin_lock_irqsave(&ar->lock, flags); + set_bit(CONNECTED, &ar->flag); + clear_bit(CONNECT_PEND, &ar->flag); + netif_carrier_on(ar->net_dev); + spin_unlock_irqrestore(&ar->lock, flags); + + aggr_reset_state(ar->aggr_cntxt); + ar->reconnect_flag = 0; + + if ((ar->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) { + memset(ar->node_map, 0, sizeof(ar->node_map)); + ar->node_num = 0; + ar->next_ep_id = ENDPOINT_2; + } + + if (!ar->usr_bss_filter) + ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); +} + +void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast) +{ + struct ath6kl_sta *sta; + u8 tsc[6]; + /* + * For AP case, keyid will have aid of STA which sent pkt with + * MIC error. Use this aid to get MAC & send it to hostapd. + */ + if (ar->nw_type == AP_NETWORK) { + sta = ath6kl_find_sta_by_aid(ar, (keyid >> 2)); + if (!sta) + return; + + ath6kl_dbg(ATH6KL_DBG_TRC, + "ap tkip mic error received from aid=%d\n", keyid); + + memset(tsc, 0, sizeof(tsc)); /* FIX: get correct TSC */ + cfg80211_michael_mic_failure(ar->net_dev, sta->mac, + NL80211_KEYTYPE_PAIRWISE, keyid, + tsc, GFP_KERNEL); + } else + ath6kl_cfg80211_tkip_micerr_event(ar, keyid, ismcast); + +} + +static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len) +{ + struct wmi_target_stats *tgt_stats = + (struct wmi_target_stats *) ptr; + struct target_stats *stats = &ar->target_stats; + struct tkip_ccmp_stats *ccmp_stats; + struct bss *conn_bss = NULL; + struct cserv_stats *c_stats; + u8 ac; + + if (len < sizeof(*tgt_stats)) + return; + + /* update the RSSI of the connected bss */ + if (test_bit(CONNECTED, &ar->flag)) { + conn_bss = ath6kl_wmi_find_node(ar->wmi, ar->bssid); + if (conn_bss) { + c_stats = &tgt_stats->cserv_stats; + conn_bss->ni_rssi = + a_sle16_to_cpu(c_stats->cs_ave_beacon_rssi); + conn_bss->ni_snr = + tgt_stats->cserv_stats.cs_ave_beacon_snr; + ath6kl_wmi_node_return(ar->wmi, conn_bss); + } + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n"); + + stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt); + stats->tx_byte += le32_to_cpu(tgt_stats->stats.tx.byte); + stats->tx_ucast_pkt += le32_to_cpu(tgt_stats->stats.tx.ucast_pkt); + stats->tx_ucast_byte += le32_to_cpu(tgt_stats->stats.tx.ucast_byte); + stats->tx_mcast_pkt += le32_to_cpu(tgt_stats->stats.tx.mcast_pkt); + stats->tx_mcast_byte += le32_to_cpu(tgt_stats->stats.tx.mcast_byte); + stats->tx_bcast_pkt += le32_to_cpu(tgt_stats->stats.tx.bcast_pkt); + stats->tx_bcast_byte += le32_to_cpu(tgt_stats->stats.tx.bcast_byte); + stats->tx_rts_success_cnt += + le32_to_cpu(tgt_stats->stats.tx.rts_success_cnt); + + for (ac = 0; ac < WMM_NUM_AC; ac++) + stats->tx_pkt_per_ac[ac] += + le32_to_cpu(tgt_stats->stats.tx.pkt_per_ac[ac]); + + stats->tx_err += le32_to_cpu(tgt_stats->stats.tx.err); + stats->tx_fail_cnt += le32_to_cpu(tgt_stats->stats.tx.fail_cnt); + stats->tx_retry_cnt += le32_to_cpu(tgt_stats->stats.tx.retry_cnt); + stats->tx_mult_retry_cnt += + le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt); + stats->tx_rts_fail_cnt += + le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt); + stats->tx_ucast_rate = + ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate)); + + stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt); + stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte); + stats->rx_ucast_pkt += le32_to_cpu(tgt_stats->stats.rx.ucast_pkt); + stats->rx_ucast_byte += le32_to_cpu(tgt_stats->stats.rx.ucast_byte); + stats->rx_mcast_pkt += le32_to_cpu(tgt_stats->stats.rx.mcast_pkt); + stats->rx_mcast_byte += le32_to_cpu(tgt_stats->stats.rx.mcast_byte); + stats->rx_bcast_pkt += le32_to_cpu(tgt_stats->stats.rx.bcast_pkt); + stats->rx_bcast_byte += le32_to_cpu(tgt_stats->stats.rx.bcast_byte); + stats->rx_frgment_pkt += le32_to_cpu(tgt_stats->stats.rx.frgment_pkt); + stats->rx_err += le32_to_cpu(tgt_stats->stats.rx.err); + stats->rx_crc_err += le32_to_cpu(tgt_stats->stats.rx.crc_err); + stats->rx_key_cache_miss += + le32_to_cpu(tgt_stats->stats.rx.key_cache_miss); + stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err); + stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame); + stats->rx_ucast_rate = + ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate)); + + ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats; + + stats->tkip_local_mic_fail += + le32_to_cpu(ccmp_stats->tkip_local_mic_fail); + stats->tkip_cnter_measures_invoked += + le32_to_cpu(ccmp_stats->tkip_cnter_measures_invoked); + stats->tkip_fmt_err += le32_to_cpu(ccmp_stats->tkip_fmt_err); + + stats->ccmp_fmt_err += le32_to_cpu(ccmp_stats->ccmp_fmt_err); + stats->ccmp_replays += le32_to_cpu(ccmp_stats->ccmp_replays); + + stats->pwr_save_fail_cnt += + le32_to_cpu(tgt_stats->pm_stats.pwr_save_failure_cnt); + stats->noise_floor_calib = + a_sle32_to_cpu(tgt_stats->noise_floor_calib); + + stats->cs_bmiss_cnt += + le32_to_cpu(tgt_stats->cserv_stats.cs_bmiss_cnt); + stats->cs_low_rssi_cnt += + le32_to_cpu(tgt_stats->cserv_stats.cs_low_rssi_cnt); + stats->cs_connect_cnt += + le16_to_cpu(tgt_stats->cserv_stats.cs_connect_cnt); + stats->cs_discon_cnt += + le16_to_cpu(tgt_stats->cserv_stats.cs_discon_cnt); + + stats->cs_ave_beacon_rssi = + a_sle16_to_cpu(tgt_stats->cserv_stats.cs_ave_beacon_rssi); + + stats->cs_last_roam_msec = + tgt_stats->cserv_stats.cs_last_roam_msec; + stats->cs_snr = tgt_stats->cserv_stats.cs_snr; + stats->cs_rssi = a_sle16_to_cpu(tgt_stats->cserv_stats.cs_rssi); + + stats->lq_val = le32_to_cpu(tgt_stats->lq_val); + + stats->wow_pkt_dropped += + le32_to_cpu(tgt_stats->wow_stats.wow_pkt_dropped); + stats->wow_host_pkt_wakeups += + tgt_stats->wow_stats.wow_host_pkt_wakeups; + stats->wow_host_evt_wakeups += + tgt_stats->wow_stats.wow_host_evt_wakeups; + stats->wow_evt_discarded += + le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded); + + if (test_bit(STATS_UPDATE_PEND, &ar->flag)) { + clear_bit(STATS_UPDATE_PEND, &ar->flag); + wake_up(&ar->event_wq); + } +} + +static void ath6kl_add_le32(__le32 *var, __le32 val) +{ + *var = cpu_to_le32(le32_to_cpu(*var) + le32_to_cpu(val)); +} + +void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len) +{ + struct wmi_ap_mode_stat *p = (struct wmi_ap_mode_stat *) ptr; + struct wmi_ap_mode_stat *ap = &ar->ap_stats; + struct wmi_per_sta_stat *st_ap, *st_p; + u8 ac; + + if (ar->nw_type == AP_NETWORK) { + if (len < sizeof(*p)) + return; + + for (ac = 0; ac < AP_MAX_NUM_STA; ac++) { + st_ap = &ap->sta[ac]; + st_p = &p->sta[ac]; + + ath6kl_add_le32(&st_ap->tx_bytes, st_p->tx_bytes); + ath6kl_add_le32(&st_ap->tx_pkts, st_p->tx_pkts); + ath6kl_add_le32(&st_ap->tx_error, st_p->tx_error); + ath6kl_add_le32(&st_ap->tx_discard, st_p->tx_discard); + ath6kl_add_le32(&st_ap->rx_bytes, st_p->rx_bytes); + ath6kl_add_le32(&st_ap->rx_pkts, st_p->rx_pkts); + ath6kl_add_le32(&st_ap->rx_error, st_p->rx_error); + ath6kl_add_le32(&st_ap->rx_discard, st_p->rx_discard); + } + + } else { + ath6kl_update_target_stats(ar, ptr, len); + } +} + +void ath6kl_wakeup_event(void *dev) +{ + struct ath6kl *ar = (struct ath6kl *) dev; + + wake_up(&ar->event_wq); +} + +void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr) +{ + struct ath6kl *ar = (struct ath6kl *) devt; + + ar->tx_pwr = tx_pwr; + wake_up(&ar->event_wq); +} + +void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid) +{ + struct ath6kl_sta *conn; + struct sk_buff *skb; + bool psq_empty = false; + + conn = ath6kl_find_sta_by_aid(ar, aid); + + if (!conn) + return; + /* + * Send out a packet queued on ps queue. When the ps queue + * becomes empty update the PVB for this station. + */ + spin_lock_bh(&conn->psq_lock); + psq_empty = skb_queue_empty(&conn->psq); + spin_unlock_bh(&conn->psq_lock); + + if (psq_empty) + /* TODO: Send out a NULL data frame */ + return; + + spin_lock_bh(&conn->psq_lock); + skb = skb_dequeue(&conn->psq); + spin_unlock_bh(&conn->psq_lock); + + conn->sta_flags |= STA_PS_POLLED; + ath6kl_data_tx(skb, ar->net_dev); + conn->sta_flags &= ~STA_PS_POLLED; + + spin_lock_bh(&conn->psq_lock); + psq_empty = skb_queue_empty(&conn->psq); + spin_unlock_bh(&conn->psq_lock); + + if (psq_empty) + ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0); +} + +void ath6kl_dtimexpiry_event(struct ath6kl *ar) +{ + bool mcastq_empty = false; + struct sk_buff *skb; + + /* + * If there are no associated STAs, ignore the DTIM expiry event. + * There can be potential race conditions where the last associated + * STA may disconnect & before the host could clear the 'Indicate + * DTIM' request to the firmware, the firmware would have just + * indicated a DTIM expiry event. The race is between 'clear DTIM + * expiry cmd' going from the host to the firmware & the DTIM + * expiry event happening from the firmware to the host. + */ + if (!ar->sta_list_index) + return; + + spin_lock_bh(&ar->mcastpsq_lock); + mcastq_empty = skb_queue_empty(&ar->mcastpsq); + spin_unlock_bh(&ar->mcastpsq_lock); + + if (mcastq_empty) + return; + + /* set the STA flag to dtim_expired for the frame to go out */ + set_bit(DTIM_EXPIRED, &ar->flag); + + spin_lock_bh(&ar->mcastpsq_lock); + while ((skb = skb_dequeue(&ar->mcastpsq)) != NULL) { + spin_unlock_bh(&ar->mcastpsq_lock); + + ath6kl_data_tx(skb, ar->net_dev); + + spin_lock_bh(&ar->mcastpsq_lock); + } + spin_unlock_bh(&ar->mcastpsq_lock); + + clear_bit(DTIM_EXPIRED, &ar->flag); + + /* clear the LSB of the BitMapCtl field of the TIM IE */ + ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0); +} + +void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, + u8 assoc_resp_len, u8 *assoc_info, + u16 prot_reason_status) +{ + struct bss *wmi_ssid_node = NULL; + unsigned long flags; + + if (ar->nw_type == AP_NETWORK) { + if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) + return; + + /* if no more associated STAs, empty the mcast PS q */ + if (ar->sta_list_index == 0) { + spin_lock_bh(&ar->mcastpsq_lock); + skb_queue_purge(&ar->mcastpsq); + spin_unlock_bh(&ar->mcastpsq_lock); + + /* clear the LSB of the TIM IE's BitMapCtl field */ + if (test_bit(WMI_READY, &ar->flag)) + ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0); + } + + if (!is_broadcast_ether_addr(bssid)) { + /* send event to application */ + cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL); + } + + clear_bit(CONNECTED, &ar->flag); + return; + } + + ath6kl_cfg80211_disconnect_event(ar, reason, bssid, + assoc_resp_len, assoc_info, + prot_reason_status); + + aggr_reset_state(ar->aggr_cntxt); + + del_timer(&ar->disconnect_timer); + + ath6kl_dbg(ATH6KL_DBG_WLAN_CONNECT, + "disconnect reason is %d\n", reason); + + /* + * If the event is due to disconnect cmd from the host, only they + * the target would stop trying to connect. Under any other + * condition, target would keep trying to connect. + */ + if (reason == DISCONNECT_CMD) { + if (!ar->usr_bss_filter && test_bit(WMI_READY, &ar->flag)) + ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); + } else { + set_bit(CONNECT_PEND, &ar->flag); + if (((reason == ASSOC_FAILED) && + (prot_reason_status == 0x11)) || + ((reason == ASSOC_FAILED) && (prot_reason_status == 0x0) + && (ar->reconnect_flag == 1))) { + set_bit(CONNECTED, &ar->flag); + return; + } + } + + if ((reason == NO_NETWORK_AVAIL) && test_bit(WMI_READY, &ar->flag)) { + ath6kl_wmi_node_free(ar->wmi, bssid); + + /* + * In case any other same SSID nodes are present remove it, + * since those nodes also not available now. + */ + do { + /* + * Find the nodes based on SSID and remove it + * + * Note: This case will not work out for + * Hidden-SSID + */ + wmi_ssid_node = ath6kl_wmi_find_ssid_node(ar->wmi, + ar->ssid, + ar->ssid_len, + false, + true); + + if (wmi_ssid_node) + ath6kl_wmi_node_free(ar->wmi, + wmi_ssid_node->ni_macaddr); + + } while (wmi_ssid_node); + } + + /* update connect & link status atomically */ + spin_lock_irqsave(&ar->lock, flags); + clear_bit(CONNECTED, &ar->flag); + netif_carrier_off(ar->net_dev); + spin_unlock_irqrestore(&ar->lock, flags); + + if ((reason != CSERV_DISCONNECT) || (ar->reconnect_flag != 1)) + ar->reconnect_flag = 0; + + if (reason != CSERV_DISCONNECT) + ar->user_key_ctrl = 0; + + netif_stop_queue(ar->net_dev); + memset(ar->bssid, 0, sizeof(ar->bssid)); + ar->bss_ch = 0; + + ath6kl_tx_data_cleanup(ar); +} + +static int ath6kl_open(struct net_device *dev) +{ + struct ath6kl *ar = ath6kl_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&ar->lock, flags); + + ar->wlan_state = WLAN_ENABLED; + + if (test_bit(CONNECTED, &ar->flag)) { + netif_carrier_on(dev); + netif_wake_queue(dev); + } else + netif_carrier_off(dev); + + spin_unlock_irqrestore(&ar->lock, flags); + + return 0; +} + +static int ath6kl_close(struct net_device *dev) +{ + struct ath6kl *ar = ath6kl_priv(dev); + + netif_stop_queue(dev); + + ath6kl_disconnect(ar); + + if (test_bit(WMI_READY, &ar->flag)) { + if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, + 0, 0, 0)) + return -EIO; + + ar->wlan_state = WLAN_DISABLED; + } + + ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED); + + return 0; +} + +static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) +{ + struct ath6kl *ar = ath6kl_priv(dev); + + return &ar->net_stats; +} + +static struct net_device_ops ath6kl_netdev_ops = { + .ndo_open = ath6kl_open, + .ndo_stop = ath6kl_close, + .ndo_start_xmit = ath6kl_data_tx, + .ndo_get_stats = ath6kl_get_stats, +}; + +void init_netdev(struct net_device *dev) +{ + dev->netdev_ops = &ath6kl_netdev_ops; + dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; + + dev->needed_headroom = ETH_HLEN; + dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + + sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH + + WMI_MAX_TX_META_SZ; + + return; +} diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c new file mode 100644 index 000000000000..b0f9ba2e463c --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/node.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" +#include "wmi.h" +#include "debug.h" + +struct bss *wlan_node_alloc(int wh_size) +{ + struct bss *ni; + + ni = kzalloc(sizeof(struct bss), GFP_ATOMIC); + + if ((ni != NULL) && wh_size) { + ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC); + if (ni->ni_buf == NULL) { + kfree(ni); + return NULL; + } + } + + return ni; +} + +void wlan_node_free(struct bss *ni) +{ + kfree(ni->ni_buf); + kfree(ni); +} + +void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, + const u8 *mac_addr) +{ + int hash; + + memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN); + hash = ATH6KL_NODE_HASH(mac_addr); + ni->ni_refcnt = 1; + + ni->ni_tstamp = jiffies_to_msecs(jiffies); + ni->ni_actcnt = WLAN_NODE_INACT_CNT; + + spin_lock_bh(&nt->nt_nodelock); + + /* insert at the end of the node list */ + ni->ni_list_next = NULL; + ni->ni_list_prev = nt->nt_node_last; + if (nt->nt_node_last != NULL) + nt->nt_node_last->ni_list_next = ni; + + nt->nt_node_last = ni; + if (nt->nt_node_first == NULL) + nt->nt_node_first = ni; + + /* insert into the hash list */ + ni->ni_hash_next = nt->nt_hash[hash]; + if (ni->ni_hash_next != NULL) + nt->nt_hash[hash]->ni_hash_prev = ni; + + ni->ni_hash_prev = NULL; + nt->nt_hash[hash] = ni; + + spin_unlock_bh(&nt->nt_nodelock); +} + +struct bss *wlan_find_node(struct ath6kl_node_table *nt, + const u8 *mac_addr) +{ + struct bss *ni, *found_ni = NULL; + int hash; + + spin_lock_bh(&nt->nt_nodelock); + + hash = ATH6KL_NODE_HASH(mac_addr); + for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { + if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) { + ni->ni_refcnt++; + found_ni = ni; + break; + } + } + + spin_unlock_bh(&nt->nt_nodelock); + + return found_ni; +} + +void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni) +{ + int hash; + + spin_lock_bh(&nt->nt_nodelock); + + if (ni->ni_list_prev == NULL) + /* fix list head */ + nt->nt_node_first = ni->ni_list_next; + else + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + + if (ni->ni_list_next == NULL) + /* fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + else + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + + if (ni->ni_hash_prev == NULL) { + /* first in list so fix the list head */ + hash = ATH6KL_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } else { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if (ni->ni_hash_next != NULL) + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + + wlan_node_free(ni); + + spin_unlock_bh(&nt->nt_nodelock); +} + +static void wlan_node_dec_free(struct bss *ni) +{ + if ((ni->ni_refcnt--) == 1) + wlan_node_free(ni); +} + +void wlan_free_allnodes(struct ath6kl_node_table *nt) +{ + struct bss *ni; + + while ((ni = nt->nt_node_first) != NULL) + wlan_node_reclaim(nt, ni); +} + +void wlan_iterate_nodes(struct ath6kl_node_table *nt, + void (*f) (void *arg, struct bss *), void *arg) +{ + struct bss *ni; + + spin_lock_bh(&nt->nt_nodelock); + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + ni->ni_refcnt++; + (*f) (arg, ni); + wlan_node_dec_free(ni); + } + spin_unlock_bh(&nt->nt_nodelock); +} + +void wlan_node_table_init(void *wmi, struct ath6kl_node_table *nt) +{ + ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n", + (unsigned long)nt); + + memset(nt, 0, sizeof(struct ath6kl_node_table)); + + spin_lock_init(&nt->nt_nodelock); + + nt->nt_wmi = wmi; + nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC; +} + +void wlan_refresh_inactive_nodes(struct ath6kl_node_table *nt) +{ + struct bss *bss; + u8 my_bssid[ETH_ALEN]; + u32 now; + + ath6kl_wmi_get_current_bssid(nt->nt_wmi, my_bssid); + + now = jiffies_to_msecs(jiffies); + bss = nt->nt_node_first; + while (bss != NULL) { + /* refresh all nodes except the current bss */ + if (memcmp(my_bssid, bss->ni_macaddr, sizeof(my_bssid)) != 0) { + if (((now - bss->ni_tstamp) > nt->nt_node_age) + || --bss->ni_actcnt == 0) { + wlan_node_reclaim(nt, bss); + } + } + bss = bss->ni_list_next; + } +} + +void wlan_node_table_cleanup(struct ath6kl_node_table *nt) +{ + wlan_free_allnodes(nt); +} + +struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid, + u32 ssid_len, bool is_wpa2, bool match_ssid) +{ + struct bss *ni, *found_ni = NULL; + u8 *ie_ssid; + + spin_lock_bh(&nt->nt_nodelock); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + + ie_ssid = ni->ni_cie.ie_ssid; + + if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && + (memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) { + + if (match_ssid || + (is_wpa2 && ni->ni_cie.ie_rsn != NULL) || + (!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) { + ni->ni_refcnt++; + found_ni = ni; + break; + } + } + } + + spin_unlock_bh(&nt->nt_nodelock); + + return found_ni; +} + +void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni) +{ + spin_lock_bh(&nt->nt_nodelock); + wlan_node_dec_free(ni); + spin_unlock_bh(&nt->nt_nodelock); +} diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c new file mode 100644 index 000000000000..b38732aaf41a --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/mmc/card.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/host.h> +#include <linux/mmc/sdio_func.h> +#include <linux/mmc/sdio_ids.h> +#include <linux/mmc/sdio.h> +#include <linux/mmc/sd.h> +#include "htc_hif.h" +#include "hif-ops.h" +#include "target.h" +#include "debug.h" + +struct ath6kl_sdio { + struct sdio_func *func; + + spinlock_t lock; + + /* free list */ + struct list_head bus_req_freeq; + + /* available bus requests */ + struct bus_request bus_req[BUS_REQUEST_MAX_NUM]; + + struct ath6kl *ar; + u8 *dma_buffer; + + /* scatter request list head */ + struct list_head scat_req; + + spinlock_t scat_lock; + bool is_disabled; + atomic_t irq_handling; + const struct sdio_device_id *id; + struct work_struct wr_async_work; + struct list_head wr_asyncq; + spinlock_t wr_async_lock; +}; + +#define CMD53_ARG_READ 0 +#define CMD53_ARG_WRITE 1 +#define CMD53_ARG_BLOCK_BASIS 1 +#define CMD53_ARG_FIXED_ADDRESS 0 +#define CMD53_ARG_INCR_ADDRESS 1 + +static inline struct ath6kl_sdio *ath6kl_sdio_priv(struct ath6kl *ar) +{ + return ar->hif_priv; +} + +/* + * Macro to check if DMA buffer is WORD-aligned and DMA-able. + * Most host controllers assume the buffer is DMA'able and will + * bug-check otherwise (i.e. buffers on the stack). virt_addr_valid + * check fails on stack memory. + */ +static inline bool buf_needs_bounce(u8 *buf) +{ + return ((unsigned long) buf & 0x3) || !virt_addr_valid(buf); +} + +static void ath6kl_sdio_set_mbox_info(struct ath6kl *ar) +{ + struct ath6kl_mbox_info *mbox_info = &ar->mbox_info; + + /* EP1 has an extended range */ + mbox_info->htc_addr = HIF_MBOX_BASE_ADDR; + mbox_info->htc_ext_addr = HIF_MBOX0_EXT_BASE_ADDR; + mbox_info->htc_ext_sz = HIF_MBOX0_EXT_WIDTH; + mbox_info->block_size = HIF_MBOX_BLOCK_SIZE; + mbox_info->gmbox_addr = HIF_GMBOX_BASE_ADDR; + mbox_info->gmbox_sz = HIF_GMBOX_WIDTH; +} + +static inline void ath6kl_sdio_set_cmd53_arg(u32 *arg, u8 rw, u8 func, + u8 mode, u8 opcode, u32 addr, + u16 blksz) +{ + *arg = (((rw & 1) << 31) | + ((func & 0x7) << 28) | + ((mode & 1) << 27) | + ((opcode & 1) << 26) | + ((addr & 0x1FFFF) << 9) | + (blksz & 0x1FF)); +} + +static inline void ath6kl_sdio_set_cmd52_arg(u32 *arg, u8 write, u8 raw, + unsigned int address, + unsigned char val) +{ + const u8 func = 0; + + *arg = ((write & 1) << 31) | + ((func & 0x7) << 28) | + ((raw & 1) << 27) | + (1 << 26) | + ((address & 0x1FFFF) << 9) | + (1 << 8) | + (val & 0xFF); +} + +static int ath6kl_sdio_func0_cmd52_wr_byte(struct mmc_card *card, + unsigned int address, + unsigned char byte) +{ + struct mmc_command io_cmd; + + memset(&io_cmd, 0, sizeof(io_cmd)); + ath6kl_sdio_set_cmd52_arg(&io_cmd.arg, 1, 0, address, byte); + io_cmd.opcode = SD_IO_RW_DIRECT; + io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + + return mmc_wait_for_cmd(card->host, &io_cmd, 0); +} + +static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio) +{ + struct bus_request *bus_req; + unsigned long flag; + + spin_lock_irqsave(&ar_sdio->lock, flag); + + if (list_empty(&ar_sdio->bus_req_freeq)) { + spin_unlock_irqrestore(&ar_sdio->lock, flag); + return NULL; + } + + bus_req = list_first_entry(&ar_sdio->bus_req_freeq, + struct bus_request, list); + list_del(&bus_req->list); + + spin_unlock_irqrestore(&ar_sdio->lock, flag); + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req); + + return bus_req; +} + +static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio, + struct bus_request *bus_req) +{ + unsigned long flag; + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req); + + spin_lock_irqsave(&ar_sdio->lock, flag); + list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq); + spin_unlock_irqrestore(&ar_sdio->lock, flag); +} + +static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req, + struct hif_scatter_req_priv *s_req_priv, + struct mmc_data *data) +{ + struct scatterlist *sg; + int i; + + data->blksz = HIF_MBOX_BLOCK_SIZE; + data->blocks = scat_req->len / HIF_MBOX_BLOCK_SIZE; + + ath6kl_dbg(ATH6KL_DBG_SCATTER, + "hif-scatter: (%s) addr: 0x%X, (block len: %d, block count: %d) , (tot:%d,sg:%d)\n", + (scat_req->req & HIF_WRITE) ? "WR" : "RD", scat_req->addr, + data->blksz, data->blocks, scat_req->len, + scat_req->scat_entries); + + data->flags = (scat_req->req & HIF_WRITE) ? MMC_DATA_WRITE : + MMC_DATA_READ; + + /* fill SG entries */ + sg = s_req_priv->sgentries; + sg_init_table(sg, scat_req->scat_entries); + + /* assemble SG list */ + for (i = 0; i < scat_req->scat_entries; i++, sg++) { + if ((unsigned long)scat_req->scat_list[i].buf & 0x3) + /* + * Some scatter engines can handle unaligned + * buffers, print this as informational only. + */ + ath6kl_dbg(ATH6KL_DBG_SCATTER, + "(%s) scatter buffer is unaligned 0x%p\n", + scat_req->req & HIF_WRITE ? "WR" : "RD", + scat_req->scat_list[i].buf); + + ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n", + i, scat_req->scat_list[i].buf, + scat_req->scat_list[i].len); + + sg_set_buf(sg, scat_req->scat_list[i].buf, + scat_req->scat_list[i].len); + } + + /* set scatter-gather table for request */ + data->sg = s_req_priv->sgentries; + data->sg_len = scat_req->scat_entries; +} + +static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio, + struct bus_request *req) +{ + struct mmc_request mmc_req; + struct mmc_command cmd; + struct mmc_data data; + struct hif_scatter_req *scat_req; + u8 opcode, rw; + int status; + + scat_req = req->scat_req; + + memset(&mmc_req, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + ath6kl_sdio_setup_scat_data(scat_req, scat_req->req_priv, &data); + + opcode = (scat_req->req & HIF_FIXED_ADDRESS) ? + CMD53_ARG_FIXED_ADDRESS : CMD53_ARG_INCR_ADDRESS; + + rw = (scat_req->req & HIF_WRITE) ? CMD53_ARG_WRITE : CMD53_ARG_READ; + + /* Fixup the address so that the last byte will fall on MBOX EOM */ + if (scat_req->req & HIF_WRITE) { + if (scat_req->addr == HIF_MBOX_BASE_ADDR) + scat_req->addr += HIF_MBOX_WIDTH - scat_req->len; + else + /* Uses extended address range */ + scat_req->addr += HIF_MBOX0_EXT_WIDTH - scat_req->len; + } + + /* set command argument */ + ath6kl_sdio_set_cmd53_arg(&cmd.arg, rw, ar_sdio->func->num, + CMD53_ARG_BLOCK_BASIS, opcode, scat_req->addr, + data.blocks); + + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + mmc_req.cmd = &cmd; + mmc_req.data = &data; + + mmc_set_data_timeout(&data, ar_sdio->func->card); + /* synchronous call to process request */ + mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req); + + status = cmd.error ? cmd.error : data.error; + scat_req->status = status; + + if (scat_req->status) + ath6kl_err("Scatter write request failed:%d\n", + scat_req->status); + + if (scat_req->req & HIF_ASYNCHRONOUS) + scat_req->complete(scat_req); + + return status; +} + + +/* callback to issue a read-write scatter request */ +static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar, + struct hif_scatter_req *scat_req) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + struct hif_scatter_req_priv *req_priv = scat_req->req_priv; + u32 request = scat_req->req; + int status = 0; + unsigned long flags; + + if (!scat_req->len) + return -EINVAL; + + ath6kl_dbg(ATH6KL_DBG_SCATTER, + "hif-scatter: total len: %d scatter entries: %d\n", + scat_req->len, scat_req->scat_entries); + + if (request & HIF_SYNCHRONOUS) { + sdio_claim_host(ar_sdio->func); + status = ath6kl_sdio_scat_rw(ar_sdio, req_priv->busrequest); + sdio_release_host(ar_sdio->func); + } else { + spin_lock_irqsave(&ar_sdio->wr_async_lock, flags); + list_add_tail(&req_priv->busrequest->list, &ar_sdio->wr_asyncq); + spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags); + queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work); + } + + return status; +} + +/* clean up scatter support */ +static void ath6kl_sdio_cleanup_scat_resource(struct ath6kl_sdio *ar_sdio) +{ + struct hif_scatter_req *s_req, *tmp_req; + unsigned long flag; + + /* empty the free list */ + spin_lock_irqsave(&ar_sdio->scat_lock, flag); + list_for_each_entry_safe(s_req, tmp_req, &ar_sdio->scat_req, list) { + list_del(&s_req->list); + spin_unlock_irqrestore(&ar_sdio->scat_lock, flag); + + if (s_req->req_priv && s_req->req_priv->busrequest) + ath6kl_sdio_free_bus_req(ar_sdio, + s_req->req_priv->busrequest); + kfree(s_req->virt_dma_buf); + kfree(s_req->req_priv); + kfree(s_req); + + spin_lock_irqsave(&ar_sdio->scat_lock, flag); + } + spin_unlock_irqrestore(&ar_sdio->scat_lock, flag); +} + +/* setup of HIF scatter resources */ +static int ath6kl_sdio_setup_scat_resource(struct ath6kl_sdio *ar_sdio, + struct hif_dev_scat_sup_info *pinfo) +{ + struct hif_scatter_req *s_req; + struct bus_request *bus_req; + int i, scat_req_sz, scat_list_sz; + + /* check if host supports scatter and it meets our requirements */ + if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { + ath6kl_err("hif-scatter: host only supports scatter of : %d entries, need: %d\n", + ar_sdio->func->card->host->max_segs, + MAX_SCATTER_ENTRIES_PER_REQ); + return -EINVAL; + } + + ath6kl_dbg(ATH6KL_DBG_ANY, + "hif-scatter enabled: max scatter req : %d entries: %d\n", + MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ); + + scat_list_sz = (MAX_SCATTER_ENTRIES_PER_REQ - 1) * + sizeof(struct hif_scatter_item); + scat_req_sz = sizeof(*s_req) + scat_list_sz; + + for (i = 0; i < MAX_SCATTER_REQUESTS; i++) { + /* allocate the scatter request */ + s_req = kzalloc(scat_req_sz, GFP_KERNEL); + if (!s_req) + goto fail_setup_scat; + + /* allocate the private request blob */ + s_req->req_priv = kzalloc(sizeof(*s_req->req_priv), GFP_KERNEL); + + if (!s_req->req_priv) { + kfree(s_req); + goto fail_setup_scat; + } + + /* allocate a bus request for this scatter request */ + bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); + if (!bus_req) { + kfree(s_req->req_priv); + kfree(s_req); + goto fail_setup_scat; + } + + /* assign the scatter request to this bus request */ + bus_req->scat_req = s_req; + s_req->req_priv->busrequest = bus_req; + /* add it to the scatter pool */ + hif_scatter_req_add(ar_sdio->ar, s_req); + } + + /* set scatter function pointers */ + pinfo->rw_scat_func = ath6kl_sdio_async_rw_scatter; + pinfo->max_scat_entries = MAX_SCATTER_ENTRIES_PER_REQ; + pinfo->max_xfer_szper_scatreq = MAX_SCATTER_REQ_TRANSFER_SIZE; + + return 0; + +fail_setup_scat: + ath6kl_err("hif-scatter: failed to alloc scatter resources !\n"); + ath6kl_sdio_cleanup_scat_resource(ar_sdio); + + return -ENOMEM; +} + +static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, + u32 len, u32 request) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + u8 *tbuf = NULL; + int ret; + bool bounced = false; + + if (request & HIF_BLOCK_BASIS) + len = round_down(len, HIF_MBOX_BLOCK_SIZE); + + if (buf_needs_bounce(buf)) { + if (!ar_sdio->dma_buffer) + return -ENOMEM; + tbuf = ar_sdio->dma_buffer; + memcpy(tbuf, buf, len); + bounced = true; + } else + tbuf = buf; + + sdio_claim_host(ar_sdio->func); + if (request & HIF_WRITE) { + if (addr >= HIF_MBOX_BASE_ADDR && + addr <= HIF_MBOX_END_ADDR) + addr += (HIF_MBOX_WIDTH - len); + + if (addr == HIF_MBOX0_EXT_BASE_ADDR) + addr += HIF_MBOX0_EXT_WIDTH - len; + + if (request & HIF_FIXED_ADDRESS) + ret = sdio_writesb(ar_sdio->func, addr, tbuf, len); + else + ret = sdio_memcpy_toio(ar_sdio->func, addr, tbuf, len); + } else { + if (request & HIF_FIXED_ADDRESS) + ret = sdio_readsb(ar_sdio->func, tbuf, addr, len); + else + ret = sdio_memcpy_fromio(ar_sdio->func, tbuf, + addr, len); + if (bounced) + memcpy(buf, tbuf, len); + } + sdio_release_host(ar_sdio->func); + + return ret; +} + +static void __ath6kl_sdio_write_async(struct ath6kl_sdio *ar_sdio, + struct bus_request *req) +{ + if (req->scat_req) + ath6kl_sdio_scat_rw(ar_sdio, req); + else { + void *context; + int status; + + status = ath6kl_sdio_read_write_sync(ar_sdio->ar, req->address, + req->buffer, req->length, + req->request); + context = req->packet; + ath6kl_sdio_free_bus_req(ar_sdio, req); + ath6kldev_rw_comp_handler(context, status); + } +} + +static void ath6kl_sdio_write_async_work(struct work_struct *work) +{ + struct ath6kl_sdio *ar_sdio; + unsigned long flags; + struct bus_request *req, *tmp_req; + + ar_sdio = container_of(work, struct ath6kl_sdio, wr_async_work); + sdio_claim_host(ar_sdio->func); + + spin_lock_irqsave(&ar_sdio->wr_async_lock, flags); + list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) { + list_del(&req->list); + spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags); + __ath6kl_sdio_write_async(ar_sdio, req); + spin_lock_irqsave(&ar_sdio->wr_async_lock, flags); + } + spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags); + + sdio_release_host(ar_sdio->func); +} + +static void ath6kl_sdio_irq_handler(struct sdio_func *func) +{ + int status; + struct ath6kl_sdio *ar_sdio; + + ar_sdio = sdio_get_drvdata(func); + atomic_set(&ar_sdio->irq_handling, 1); + + /* + * Release the host during interrups so we can pick it back up when + * we process commands. + */ + sdio_release_host(ar_sdio->func); + + status = ath6kldev_intr_bh_handler(ar_sdio->ar); + sdio_claim_host(ar_sdio->func); + atomic_set(&ar_sdio->irq_handling, 0); + WARN_ON(status && status != -ECANCELED); +} + +static int ath6kl_sdio_power_on(struct ath6kl_sdio *ar_sdio) +{ + struct sdio_func *func = ar_sdio->func; + int ret = 0; + + if (!ar_sdio->is_disabled) + return 0; + + sdio_claim_host(func); + + ret = sdio_enable_func(func); + if (ret) { + ath6kl_err("Unable to enable sdio func: %d)\n", ret); + sdio_release_host(func); + return ret; + } + + sdio_release_host(func); + + /* + * Wait for hardware to initialise. It should take a lot less than + * 10 ms but let's be conservative here. + */ + msleep(10); + + ar_sdio->is_disabled = false; + + return ret; +} + +static int ath6kl_sdio_power_off(struct ath6kl_sdio *ar_sdio) +{ + int ret; + + if (ar_sdio->is_disabled) + return 0; + + /* Disable the card */ + sdio_claim_host(ar_sdio->func); + ret = sdio_disable_func(ar_sdio->func); + sdio_release_host(ar_sdio->func); + + if (ret) + return ret; + + ar_sdio->is_disabled = true; + + return ret; +} + +static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer, + u32 length, u32 request, + struct htc_packet *packet) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + struct bus_request *bus_req; + unsigned long flags; + + bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); + + if (!bus_req) + return -ENOMEM; + + bus_req->address = address; + bus_req->buffer = buffer; + bus_req->length = length; + bus_req->request = request; + bus_req->packet = packet; + + spin_lock_irqsave(&ar_sdio->wr_async_lock, flags); + list_add_tail(&bus_req->list, &ar_sdio->wr_asyncq); + spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags); + queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work); + + return 0; +} + +static void ath6kl_sdio_irq_enable(struct ath6kl *ar) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + int ret; + + sdio_claim_host(ar_sdio->func); + + /* Register the isr */ + ret = sdio_claim_irq(ar_sdio->func, ath6kl_sdio_irq_handler); + if (ret) + ath6kl_err("Failed to claim sdio irq: %d\n", ret); + + sdio_release_host(ar_sdio->func); +} + +static void ath6kl_sdio_irq_disable(struct ath6kl *ar) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + int ret; + + sdio_claim_host(ar_sdio->func); + + /* Mask our function IRQ */ + while (atomic_read(&ar_sdio->irq_handling)) { + sdio_release_host(ar_sdio->func); + schedule_timeout(HZ / 10); + sdio_claim_host(ar_sdio->func); + } + + ret = sdio_release_irq(ar_sdio->func); + if (ret) + ath6kl_err("Failed to release sdio irq: %d\n", ret); + + sdio_release_host(ar_sdio->func); +} + +static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + struct hif_scatter_req *node = NULL; + unsigned long flag; + + spin_lock_irqsave(&ar_sdio->scat_lock, flag); + + if (!list_empty(&ar_sdio->scat_req)) { + node = list_first_entry(&ar_sdio->scat_req, + struct hif_scatter_req, list); + list_del(&node->list); + } + + spin_unlock_irqrestore(&ar_sdio->scat_lock, flag); + + return node; +} + +static void ath6kl_sdio_scatter_req_add(struct ath6kl *ar, + struct hif_scatter_req *s_req) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + unsigned long flag; + + spin_lock_irqsave(&ar_sdio->scat_lock, flag); + + list_add_tail(&s_req->list, &ar_sdio->scat_req); + + spin_unlock_irqrestore(&ar_sdio->scat_lock, flag); + +} + +static int ath6kl_sdio_enable_scatter(struct ath6kl *ar, + struct hif_dev_scat_sup_info *info) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + int ret; + + ret = ath6kl_sdio_setup_scat_resource(ar_sdio, info); + + return ret; +} + +static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + + ath6kl_sdio_cleanup_scat_resource(ar_sdio); +} + +static const struct ath6kl_hif_ops ath6kl_sdio_ops = { + .read_write_sync = ath6kl_sdio_read_write_sync, + .write_async = ath6kl_sdio_write_async, + .irq_enable = ath6kl_sdio_irq_enable, + .irq_disable = ath6kl_sdio_irq_disable, + .scatter_req_get = ath6kl_sdio_scatter_req_get, + .scatter_req_add = ath6kl_sdio_scatter_req_add, + .enable_scatter = ath6kl_sdio_enable_scatter, + .cleanup_scatter = ath6kl_sdio_cleanup_scatter, +}; + +static int ath6kl_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret; + struct ath6kl_sdio *ar_sdio; + struct ath6kl *ar; + int count; + + ath6kl_dbg(ATH6KL_DBG_TRC, + "%s: func: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n", + __func__, func->num, func->vendor, + func->device, func->max_blksize, func->cur_blksize); + + ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL); + if (!ar_sdio) + return -ENOMEM; + + ar_sdio->dma_buffer = kzalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); + if (!ar_sdio->dma_buffer) { + ret = -ENOMEM; + goto err_hif; + } + + ar_sdio->func = func; + sdio_set_drvdata(func, ar_sdio); + + ar_sdio->id = id; + ar_sdio->is_disabled = true; + + spin_lock_init(&ar_sdio->lock); + spin_lock_init(&ar_sdio->scat_lock); + spin_lock_init(&ar_sdio->wr_async_lock); + + INIT_LIST_HEAD(&ar_sdio->scat_req); + INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); + INIT_LIST_HEAD(&ar_sdio->wr_asyncq); + + INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work); + + for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) + ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]); + + ar = ath6kl_core_alloc(&ar_sdio->func->dev); + if (!ar) { + ath6kl_err("Failed to alloc ath6kl core\n"); + ret = -ENOMEM; + goto err_dma; + } + + ar_sdio->ar = ar; + ar->hif_priv = ar_sdio; + ar->hif_ops = &ath6kl_sdio_ops; + + ath6kl_sdio_set_mbox_info(ar); + + sdio_claim_host(func); + + if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >= + MANUFACTURER_ID_AR6003_BASE) { + /* enable 4-bit ASYNC interrupt on AR6003 or later */ + ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card, + CCCR_SDIO_IRQ_MODE_REG, + SDIO_IRQ_MODE_ASYNC_4BIT_IRQ); + if (ret) { + ath6kl_err("Failed to enable 4-bit async irq mode %d\n", + ret); + sdio_release_host(func); + goto err_dma; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "4-bit async irq mode enabled\n"); + } + + /* give us some time to enable, in ms */ + func->enable_timeout = 100; + + sdio_release_host(func); + + ret = ath6kl_sdio_power_on(ar_sdio); + if (ret) + goto err_dma; + + sdio_claim_host(func); + + ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); + if (ret) { + ath6kl_err("Set sdio block size %d failed: %d)\n", + HIF_MBOX_BLOCK_SIZE, ret); + sdio_release_host(func); + goto err_off; + } + + sdio_release_host(func); + + ret = ath6kl_core_init(ar); + if (ret) { + ath6kl_err("Failed to init ath6kl core\n"); + goto err_off; + } + + return ret; + +err_off: + ath6kl_sdio_power_off(ar_sdio); +err_dma: + kfree(ar_sdio->dma_buffer); +err_hif: + kfree(ar_sdio); + + return ret; +} + +static void ath6kl_sdio_remove(struct sdio_func *func) +{ + struct ath6kl_sdio *ar_sdio; + + ar_sdio = sdio_get_drvdata(func); + + ath6kl_stop_txrx(ar_sdio->ar); + cancel_work_sync(&ar_sdio->wr_async_work); + + ath6kl_unavail_ev(ar_sdio->ar); + + ath6kl_sdio_power_off(ar_sdio); + + kfree(ar_sdio->dma_buffer); + kfree(ar_sdio); +} + +static const struct sdio_device_id ath6kl_sdio_devices[] = { + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0))}, + {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))}, + {}, +}; + +MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); + +static struct sdio_driver ath6kl_sdio_driver = { + .name = "ath6kl_sdio", + .id_table = ath6kl_sdio_devices, + .probe = ath6kl_sdio_probe, + .remove = ath6kl_sdio_remove, +}; + +static int __init ath6kl_sdio_init(void) +{ + int ret; + + ret = sdio_register_driver(&ath6kl_sdio_driver); + if (ret) + ath6kl_err("sdio driver registration failed: %d\n", ret); + + return ret; +} + +static void __exit ath6kl_sdio_exit(void) +{ + sdio_unregister_driver(&ath6kl_sdio_driver); +} + +module_init(ath6kl_sdio_init); +module_exit(ath6kl_sdio_exit); + +MODULE_AUTHOR("Atheros Communications, Inc."); +MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); +MODULE_LICENSE("Dual BSD/GPL"); + +MODULE_FIRMWARE(AR6003_REV2_OTP_FILE); +MODULE_FIRMWARE(AR6003_REV2_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6003_REV2_PATCH_FILE); +MODULE_FIRMWARE(AR6003_REV2_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6003_REV2_DEFAULT_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6003_REV3_OTP_FILE); +MODULE_FIRMWARE(AR6003_REV3_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6003_REV3_PATCH_FILE); +MODULE_FIRMWARE(AR6003_REV3_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6003_REV3_DEFAULT_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h new file mode 100644 index 000000000000..519a013c9991 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/target.h @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef TARGET_H +#define TARGET_H + +#define AR6003_BOARD_DATA_SZ 1024 +#define AR6003_BOARD_EXT_DATA_SZ 768 + +#define RESET_CONTROL_ADDRESS 0x00000000 +#define RESET_CONTROL_COLD_RST 0x00000100 +#define RESET_CONTROL_MBOX_RST 0x00000004 + +#define CPU_CLOCK_STANDARD_S 0 +#define CPU_CLOCK_STANDARD 0x00000003 +#define CPU_CLOCK_ADDRESS 0x00000020 + +#define CLOCK_CONTROL_ADDRESS 0x00000028 +#define CLOCK_CONTROL_LF_CLK32_S 2 +#define CLOCK_CONTROL_LF_CLK32 0x00000004 + +#define SYSTEM_SLEEP_ADDRESS 0x000000c4 +#define SYSTEM_SLEEP_DISABLE_S 0 +#define SYSTEM_SLEEP_DISABLE 0x00000001 + +#define LPO_CAL_ADDRESS 0x000000e0 +#define LPO_CAL_ENABLE_S 20 +#define LPO_CAL_ENABLE 0x00100000 + +#define GPIO_PIN10_ADDRESS 0x00000050 +#define GPIO_PIN11_ADDRESS 0x00000054 +#define GPIO_PIN12_ADDRESS 0x00000058 +#define GPIO_PIN13_ADDRESS 0x0000005c + +#define HOST_INT_STATUS_ADDRESS 0x00000400 +#define HOST_INT_STATUS_ERROR_S 7 +#define HOST_INT_STATUS_ERROR 0x00000080 + +#define HOST_INT_STATUS_CPU_S 6 +#define HOST_INT_STATUS_CPU 0x00000040 + +#define HOST_INT_STATUS_COUNTER_S 4 +#define HOST_INT_STATUS_COUNTER 0x00000010 + +#define CPU_INT_STATUS_ADDRESS 0x00000401 + +#define ERROR_INT_STATUS_ADDRESS 0x00000402 +#define ERROR_INT_STATUS_WAKEUP_S 2 +#define ERROR_INT_STATUS_WAKEUP 0x00000004 + +#define ERROR_INT_STATUS_RX_UNDERFLOW_S 1 +#define ERROR_INT_STATUS_RX_UNDERFLOW 0x00000002 + +#define ERROR_INT_STATUS_TX_OVERFLOW_S 0 +#define ERROR_INT_STATUS_TX_OVERFLOW 0x00000001 + +#define COUNTER_INT_STATUS_ADDRESS 0x00000403 +#define COUNTER_INT_STATUS_COUNTER_S 0 +#define COUNTER_INT_STATUS_COUNTER 0x000000ff + +#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405 + +#define INT_STATUS_ENABLE_ADDRESS 0x00000418 +#define INT_STATUS_ENABLE_ERROR_S 7 +#define INT_STATUS_ENABLE_ERROR 0x00000080 + +#define INT_STATUS_ENABLE_CPU_S 6 +#define INT_STATUS_ENABLE_CPU 0x00000040 + +#define INT_STATUS_ENABLE_INT_S 5 +#define INT_STATUS_ENABLE_INT 0x00000020 +#define INT_STATUS_ENABLE_COUNTER_S 4 +#define INT_STATUS_ENABLE_COUNTER 0x00000010 + +#define INT_STATUS_ENABLE_MBOX_DATA_S 0 +#define INT_STATUS_ENABLE_MBOX_DATA 0x0000000f + +#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419 +#define CPU_INT_STATUS_ENABLE_BIT_S 0 +#define CPU_INT_STATUS_ENABLE_BIT 0x000000ff + +#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_S 1 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW 0x00000002 + +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_S 0 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW 0x00000001 + +#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b +#define COUNTER_INT_STATUS_ENABLE_BIT_S 0 +#define COUNTER_INT_STATUS_ENABLE_BIT 0x000000ff + +#define COUNT_ADDRESS 0x00000420 + +#define COUNT_DEC_ADDRESS 0x00000440 + +#define WINDOW_DATA_ADDRESS 0x00000474 +#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478 +#define WINDOW_READ_ADDR_ADDRESS 0x0000047c +#define CPU_DBG_SEL_ADDRESS 0x00000483 +#define CPU_DBG_ADDRESS 0x00000484 + +#define LOCAL_SCRATCH_ADDRESS 0x000000c0 +#define ATH6KL_OPTION_SLEEP_DISABLE 0x08 + +#define RTC_BASE_ADDRESS 0x00004000 +#define GPIO_BASE_ADDRESS 0x00014000 +#define MBOX_BASE_ADDRESS 0x00018000 +#define ANALOG_INTF_BASE_ADDRESS 0x0001c000 + +/* real name of the register is unknown */ +#define ATH6KL_ANALOG_PLL_REGISTER (ANALOG_INTF_BASE_ADDRESS + 0x284) + +#define SM(f, v) (((v) << f##_S) & f) +#define MS(f, v) (((v) & f) >> f##_S) + +/* + * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the + * host_interest structure. + * + * Host Interest is shared between Host and Target in order to coordinate + * between the two, and is intended to remain constant (with additions only + * at the end). + */ +#define ATH6KL_HI_START_ADDR 0x00540600 + +/* + * These are items that the Host may need to access + * via BMI or via the Diagnostic Window. The position + * of items in this structure must remain constant. + * across firmware revisions! + * + * Types for each item must be fixed size across target and host platforms. + * The structure is used only to calculate offset for each register with + * HI_ITEM() macro, no values are stored to it. + * + * More items may be added at the end. + */ +struct host_interest { + /* + * Pointer to application-defined area, if any. + * Set by Target application during startup. + */ + u32 hi_app_host_interest; /* 0x00 */ + + /* Pointer to register dump area, valid after Target crash. */ + u32 hi_failure_state; /* 0x04 */ + + /* Pointer to debug logging header */ + u32 hi_dbglog_hdr; /* 0x08 */ + + u32 hi_unused1; /* 0x0c */ + + /* + * General-purpose flag bits, similar to ATH6KL_OPTION_* flags. + * Can be used by application rather than by OS. + */ + u32 hi_option_flag; /* 0x10 */ + + /* + * Boolean that determines whether or not to + * display messages on the serial port. + */ + u32 hi_serial_enable; /* 0x14 */ + + /* Start address of DataSet index, if any */ + u32 hi_dset_list_head; /* 0x18 */ + + /* Override Target application start address */ + u32 hi_app_start; /* 0x1c */ + + /* Clock and voltage tuning */ + u32 hi_skip_clock_init; /* 0x20 */ + u32 hi_core_clock_setting; /* 0x24 */ + u32 hi_cpu_clock_setting; /* 0x28 */ + u32 hi_system_sleep_setting; /* 0x2c */ + u32 hi_xtal_control_setting; /* 0x30 */ + u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */ + u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */ + u32 hi_ref_voltage_trim_setting; /* 0x3c */ + u32 hi_clock_info; /* 0x40 */ + + /* + * Flash configuration overrides, used only + * when firmware is not executing from flash. + * (When using flash, modify the global variables + * with equivalent names.) + */ + u32 hi_bank0_addr_value; /* 0x44 */ + u32 hi_bank0_read_value; /* 0x48 */ + u32 hi_bank0_write_value; /* 0x4c */ + u32 hi_bank0_config_value; /* 0x50 */ + + /* Pointer to Board Data */ + u32 hi_board_data; /* 0x54 */ + u32 hi_board_data_initialized; /* 0x58 */ + + u32 hi_dset_ram_index_tbl; /* 0x5c */ + + u32 hi_desired_baud_rate; /* 0x60 */ + u32 hi_dbglog_config; /* 0x64 */ + u32 hi_end_ram_reserve_sz; /* 0x68 */ + u32 hi_mbox_io_block_sz; /* 0x6c */ + + u32 hi_num_bpatch_streams; /* 0x70 -- unused */ + u32 hi_mbox_isr_yield_limit; /* 0x74 */ + + u32 hi_refclk_hz; /* 0x78 */ + u32 hi_ext_clk_detected; /* 0x7c */ + u32 hi_dbg_uart_txpin; /* 0x80 */ + u32 hi_dbg_uart_rxpin; /* 0x84 */ + u32 hi_hci_uart_baud; /* 0x88 */ + u32 hi_hci_uart_pin_assignments; /* 0x8C */ + /* + * NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts + * pin + */ + u32 hi_hci_uart_baud_scale_val; /* 0x90 */ + u32 hi_hci_uart_baud_step_val; /* 0x94 */ + + u32 hi_allocram_start; /* 0x98 */ + u32 hi_allocram_sz; /* 0x9c */ + u32 hi_hci_bridge_flags; /* 0xa0 */ + u32 hi_hci_uart_support_pins; /* 0xa4 */ + /* + * NOTE: byte [0] = RESET pin (bit 7 is polarity), + * bytes[1]..bytes[3] are for future use + */ + u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */ + /* + * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high + * [31:16]: wakeup timeout in ms + */ + + /* Pointer to extended board data */ + u32 hi_board_ext_data; /* 0xac */ + u32 hi_board_ext_data_config; /* 0xb0 */ + + /* + * Bit [0] : valid + * Bit[31:16: size + */ + /* + * hi_reset_flag is used to do some stuff when target reset. + * such as restore app_start after warm reset or + * preserve host Interest area, or preserve ROM data, literals etc. + */ + u32 hi_reset_flag; /* 0xb4 */ + /* indicate hi_reset_flag is valid */ + u32 hi_reset_flag_valid; /* 0xb8 */ + u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */ + /* + * 0xbc - [31:0]: idle timeout in ms + */ + /* ACS flags */ + u32 hi_acs_flags; /* 0xc0 */ + u32 hi_console_flags; /* 0xc4 */ + u32 hi_nvram_state; /* 0xc8 */ + u32 hi_option_flag2; /* 0xcc */ + + /* If non-zero, override values sent to Host in WMI_READY event. */ + u32 hi_sw_version_override; /* 0xd0 */ + u32 hi_abi_version_override; /* 0xd4 */ + + /* + * Percentage of high priority RX traffic to total expected RX traffic - + * applicable only to ar6004 + */ + u32 hi_hp_rx_traffic_ratio; /* 0xd8 */ + + /* test applications flags */ + u32 hi_test_apps_related ; /* 0xdc */ + /* location of test script */ + u32 hi_ota_testscript; /* 0xe0 */ + /* location of CAL data */ + u32 hi_cal_data; /* 0xe4 */ + /* Number of packet log buffers */ + u32 hi_pktlog_num_buffers; /* 0xe8 */ + +} __packed; + +#define HI_ITEM(item) offsetof(struct host_interest, item) + +#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3 + +#define HI_OPTION_FW_MODE_IBSS 0x0 +#define HI_OPTION_FW_MODE_BSS_STA 0x1 +#define HI_OPTION_FW_MODE_AP 0x2 + +#define HI_OPTION_NUM_DEV_SHIFT 0x9 + +#define HI_OPTION_FW_BRIDGE_SHIFT 0x04 + +/* Fw Mode/SubMode Mask +|------------------------------------------------------------------------------| +| SUB | SUB | SUB | SUB | | | | +| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0| +| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) +|------------------------------------------------------------------------------| +*/ +#define HI_OPTION_FW_MODE_SHIFT 0xC + +/* Convert a Target virtual address into a Target physical address */ +#define TARG_VTOP(vaddr) (vaddr & 0x001fffff) + +#define AR6003_REV2_APP_START_OVERRIDE 0x944C00 +#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 +#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 +#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 +#define AR6003_REV2_RAM_RESERVE_SIZE 6912 + +#define AR6003_REV3_APP_START_OVERRIDE 0x945d00 +#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 +#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 +#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 +#define AR6003_REV3_RAM_RESERVE_SIZE 512 + +#endif diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c new file mode 100644 index 000000000000..615b46d388f6 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -0,0 +1,1452 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "debug.h" + +static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, + u32 *map_no) +{ + struct ath6kl *ar = ath6kl_priv(dev); + struct ethhdr *eth_hdr; + u32 i, ep_map = -1; + u8 *datap; + + *map_no = 0; + datap = skb->data; + eth_hdr = (struct ethhdr *) (datap + sizeof(struct wmi_data_hdr)); + + if (is_multicast_ether_addr(eth_hdr->h_dest)) + return ENDPOINT_2; + + for (i = 0; i < ar->node_num; i++) { + if (memcmp(eth_hdr->h_dest, ar->node_map[i].mac_addr, + ETH_ALEN) == 0) { + *map_no = i + 1; + ar->node_map[i].tx_pend++; + return ar->node_map[i].ep_id; + } + + if ((ep_map == -1) && !ar->node_map[i].tx_pend) + ep_map = i; + } + + if (ep_map == -1) { + ep_map = ar->node_num; + ar->node_num++; + if (ar->node_num > MAX_NODE_NUM) + return ENDPOINT_UNUSED; + } + + memcpy(ar->node_map[ep_map].mac_addr, eth_hdr->h_dest, ETH_ALEN); + + for (i = ENDPOINT_2; i <= ENDPOINT_5; i++) { + if (!ar->tx_pending[i]) { + ar->node_map[ep_map].ep_id = i; + break; + } + + /* + * No free endpoint is available, start redistribution on + * the inuse endpoints. + */ + if (i == ENDPOINT_5) { + ar->node_map[ep_map].ep_id = ar->next_ep_id; + ar->next_ep_id++; + if (ar->next_ep_id > ENDPOINT_5) + ar->next_ep_id = ENDPOINT_2; + } + } + + *map_no = ep_map + 1; + ar->node_map[ep_map].tx_pend++; + + return ar->node_map[ep_map].ep_id; +} + +static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb, + bool *more_data) +{ + struct ethhdr *datap = (struct ethhdr *) skb->data; + struct ath6kl_sta *conn = NULL; + bool ps_queued = false, is_psq_empty = false; + + if (is_multicast_ether_addr(datap->h_dest)) { + u8 ctr = 0; + bool q_mcast = false; + + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + if (ar->sta_list[ctr].sta_flags & STA_PS_SLEEP) { + q_mcast = true; + break; + } + } + + if (q_mcast) { + /* + * If this transmit is not because of a Dtim Expiry + * q it. + */ + if (!test_bit(DTIM_EXPIRED, &ar->flag)) { + bool is_mcastq_empty = false; + + spin_lock_bh(&ar->mcastpsq_lock); + is_mcastq_empty = + skb_queue_empty(&ar->mcastpsq); + skb_queue_tail(&ar->mcastpsq, skb); + spin_unlock_bh(&ar->mcastpsq_lock); + + /* + * If this is the first Mcast pkt getting + * queued indicate to the target to set the + * BitmapControl LSB of the TIM IE. + */ + if (is_mcastq_empty) + ath6kl_wmi_set_pvb_cmd(ar->wmi, + MCAST_AID, 1); + + ps_queued = true; + } else { + /* + * This transmit is because of Dtim expiry. + * Determine if MoreData bit has to be set. + */ + spin_lock_bh(&ar->mcastpsq_lock); + if (!skb_queue_empty(&ar->mcastpsq)) + *more_data = true; + spin_unlock_bh(&ar->mcastpsq_lock); + } + } + } else { + conn = ath6kl_find_sta(ar, datap->h_dest); + if (!conn) { + dev_kfree_skb(skb); + + /* Inform the caller that the skb is consumed */ + return true; + } + + if (conn->sta_flags & STA_PS_SLEEP) { + if (!(conn->sta_flags & STA_PS_POLLED)) { + /* Queue the frames if the STA is sleeping */ + spin_lock_bh(&conn->psq_lock); + is_psq_empty = skb_queue_empty(&conn->psq); + skb_queue_tail(&conn->psq, skb); + spin_unlock_bh(&conn->psq_lock); + + /* + * If this is the first pkt getting queued + * for this STA, update the PVB for this + * STA. + */ + if (is_psq_empty) + ath6kl_wmi_set_pvb_cmd(ar->wmi, + conn->aid, 1); + + ps_queued = true; + } else { + /* + * This tx is because of a PsPoll. + * Determine if MoreData bit has to be set. + */ + spin_lock_bh(&conn->psq_lock); + if (!skb_queue_empty(&conn->psq)) + *more_data = true; + spin_unlock_bh(&conn->psq_lock); + } + } + } + + return ps_queued; +} + +/* Tx functions */ + +int ath6kl_control_tx(void *devt, struct sk_buff *skb, + enum htc_endpoint_id eid) +{ + struct ath6kl *ar = devt; + int status = 0; + struct ath6kl_cookie *cookie = NULL; + + spin_lock_bh(&ar->lock); + + ath6kl_dbg(ATH6KL_DBG_WLAN_TX, + "%s: skb=0x%p, len=0x%x eid =%d\n", __func__, + skb, skb->len, eid); + + if (test_bit(WMI_CTRL_EP_FULL, &ar->flag) && (eid == ar->ctrl_ep)) { + /* + * Control endpoint is full, don't allocate resources, we + * are just going to drop this packet. + */ + cookie = NULL; + ath6kl_err("wmi ctrl ep full, dropping pkt : 0x%p, len:%d\n", + skb, skb->len); + } else + cookie = ath6kl_alloc_cookie(ar); + + if (cookie == NULL) { + spin_unlock_bh(&ar->lock); + status = -ENOMEM; + goto fail_ctrl_tx; + } + + ar->tx_pending[eid]++; + + if (eid != ar->ctrl_ep) + ar->total_tx_data_pend++; + + spin_unlock_bh(&ar->lock); + + cookie->skb = skb; + cookie->map_no = 0; + set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, + eid, ATH6KL_CONTROL_PKT_TAG); + + /* + * This interface is asynchronous, if there is an error, cleanup + * will happen in the TX completion callback. + */ + htc_tx(ar->htc_target, &cookie->htc_pkt); + + return 0; + +fail_ctrl_tx: + dev_kfree_skb(skb); + return status; +} + +int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_cookie *cookie = NULL; + enum htc_endpoint_id eid = ENDPOINT_UNUSED; + u32 map_no = 0; + u16 htc_tag = ATH6KL_DATA_PKT_TAG; + u8 ac = 99 ; /* initialize to unmapped ac */ + bool chk_adhoc_ps_mapping = false, more_data = false; + struct wmi_tx_meta_v2 meta_v2; + int ret; + + ath6kl_dbg(ATH6KL_DBG_WLAN_TX, + "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, + skb, skb->data, skb->len); + + /* If target is not associated */ + if (!test_bit(CONNECTED, &ar->flag)) { + dev_kfree_skb(skb); + return 0; + } + + if (!test_bit(WMI_READY, &ar->flag)) + goto fail_tx; + + /* AP mode Power saving processing */ + if (ar->nw_type == AP_NETWORK) { + if (ath6kl_powersave_ap(ar, skb, &more_data)) + return 0; + } + + if (test_bit(WMI_ENABLED, &ar->flag)) { + memset(&meta_v2, 0, sizeof(meta_v2)); + + if (skb_headroom(skb) < dev->needed_headroom) { + WARN_ON(1); + goto fail_tx; + } + + if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) { + ath6kl_err("ath6kl_wmi_dix_2_dot3 failed\n"); + goto fail_tx; + } + + if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE, + more_data, 0, 0, NULL)) { + ath6kl_err("wmi_data_hdr_add failed\n"); + goto fail_tx; + } + + if ((ar->nw_type == ADHOC_NETWORK) && + ar->ibss_ps_enable && test_bit(CONNECTED, &ar->flag)) + chk_adhoc_ps_mapping = true; + else { + /* get the stream mapping */ + ret = ath6kl_wmi_implicit_create_pstream(ar->wmi, skb, + 0, test_bit(WMM_ENABLED, &ar->flag), &ac); + if (ret) + goto fail_tx; + } + } else + goto fail_tx; + + spin_lock_bh(&ar->lock); + + if (chk_adhoc_ps_mapping) + eid = ath6kl_ibss_map_epid(skb, dev, &map_no); + else + eid = ar->ac2ep_map[ac]; + + if (eid == 0 || eid == ENDPOINT_UNUSED) { + ath6kl_err("eid %d is not mapped!\n", eid); + spin_unlock_bh(&ar->lock); + goto fail_tx; + } + + /* allocate resource for this packet */ + cookie = ath6kl_alloc_cookie(ar); + + if (!cookie) { + spin_unlock_bh(&ar->lock); + goto fail_tx; + } + + /* update counts while the lock is held */ + ar->tx_pending[eid]++; + ar->total_tx_data_pend++; + + spin_unlock_bh(&ar->lock); + + cookie->skb = skb; + cookie->map_no = map_no; + set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, + eid, htc_tag); + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len); + + /* + * HTC interface is asynchronous, if this fails, cleanup will + * happen in the ath6kl_tx_complete callback. + */ + htc_tx(ar->htc_target, &cookie->htc_pkt); + + return 0; + +fail_tx: + dev_kfree_skb(skb); + + ar->net_stats.tx_dropped++; + ar->net_stats.tx_aborted_errors++; + + return 0; +} + +/* indicate tx activity or inactivity on a WMI stream */ +void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active) +{ + struct ath6kl *ar = devt; + enum htc_endpoint_id eid; + int i; + + eid = ar->ac2ep_map[traffic_class]; + + if (!test_bit(WMI_ENABLED, &ar->flag)) + goto notify_htc; + + spin_lock_bh(&ar->lock); + + ar->ac_stream_active[traffic_class] = active; + + if (active) { + /* + * Keep track of the active stream with the highest + * priority. + */ + if (ar->ac_stream_pri_map[traffic_class] > + ar->hiac_stream_active_pri) + /* set the new highest active priority */ + ar->hiac_stream_active_pri = + ar->ac_stream_pri_map[traffic_class]; + + } else { + /* + * We may have to search for the next active stream + * that is the highest priority. + */ + if (ar->hiac_stream_active_pri == + ar->ac_stream_pri_map[traffic_class]) { + /* + * The highest priority stream just went inactive + * reset and search for the "next" highest "active" + * priority stream. + */ + ar->hiac_stream_active_pri = 0; + + for (i = 0; i < WMM_NUM_AC; i++) { + if (ar->ac_stream_active[i] && + (ar->ac_stream_pri_map[i] > + ar->hiac_stream_active_pri)) + /* + * Set the new highest active + * priority. + */ + ar->hiac_stream_active_pri = + ar->ac_stream_pri_map[i]; + } + } + } + + spin_unlock_bh(&ar->lock); + +notify_htc: + /* notify HTC, this may cause credit distribution changes */ + htc_indicate_activity_change(ar->htc_target, eid, active); +} + +enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, + struct htc_packet *packet) +{ + struct ath6kl *ar = target->dev->ar; + enum htc_endpoint_id endpoint = packet->endpoint; + + if (endpoint == ar->ctrl_ep) { + /* + * Under normal WMI if this is getting full, then something + * is running rampant the host should not be exhausting the + * WMI queue with too many commands the only exception to + * this is during testing using endpointping. + */ + spin_lock_bh(&ar->lock); + set_bit(WMI_CTRL_EP_FULL, &ar->flag); + spin_unlock_bh(&ar->lock); + ath6kl_err("wmi ctrl ep is full\n"); + return HTC_SEND_FULL_KEEP; + } + + if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG) + return HTC_SEND_FULL_KEEP; + + if (ar->nw_type == ADHOC_NETWORK) + /* + * In adhoc mode, we cannot differentiate traffic + * priorities so there is no need to continue, however we + * should stop the network. + */ + goto stop_net_queues; + + /* + * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for + * the highest active stream. + */ + if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < + ar->hiac_stream_active_pri && + ar->cookie_count <= MAX_HI_COOKIE_NUM) + /* + * Give preference to the highest priority stream by + * dropping the packets which overflowed. + */ + return HTC_SEND_FULL_DROP; + +stop_net_queues: + spin_lock_bh(&ar->lock); + set_bit(NETQ_STOPPED, &ar->flag); + spin_unlock_bh(&ar->lock); + netif_stop_queue(ar->net_dev); + + return HTC_SEND_FULL_KEEP; +} + +/* TODO this needs to be looked at */ +static void ath6kl_tx_clear_node_map(struct ath6kl *ar, + enum htc_endpoint_id eid, u32 map_no) +{ + u32 i; + + if (ar->nw_type != ADHOC_NETWORK) + return; + + if (!ar->ibss_ps_enable) + return; + + if (eid == ar->ctrl_ep) + return; + + if (map_no == 0) + return; + + map_no--; + ar->node_map[map_no].tx_pend--; + + if (ar->node_map[map_no].tx_pend) + return; + + if (map_no != (ar->node_num - 1)) + return; + + for (i = ar->node_num; i > 0; i--) { + if (ar->node_map[i - 1].tx_pend) + break; + + memset(&ar->node_map[i - 1], 0, + sizeof(struct ath6kl_node_mapping)); + ar->node_num--; + } +} + +void ath6kl_tx_complete(void *context, struct list_head *packet_queue) +{ + struct ath6kl *ar = context; + struct sk_buff_head skb_queue; + struct htc_packet *packet; + struct sk_buff *skb; + struct ath6kl_cookie *ath6kl_cookie; + u32 map_no = 0; + int status; + enum htc_endpoint_id eid; + bool wake_event = false; + bool flushing = false; + + skb_queue_head_init(&skb_queue); + + /* lock the driver as we update internal state */ + spin_lock_bh(&ar->lock); + + /* reap completed packets */ + while (!list_empty(packet_queue)) { + + packet = list_first_entry(packet_queue, struct htc_packet, + list); + list_del(&packet->list); + + ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt; + if (!ath6kl_cookie) + goto fatal; + + status = packet->status; + skb = ath6kl_cookie->skb; + eid = packet->endpoint; + map_no = ath6kl_cookie->map_no; + + if (!skb || !skb->data) + goto fatal; + + packet->buf = skb->data; + + __skb_queue_tail(&skb_queue, skb); + + if (!status && (packet->act_len != skb->len)) + goto fatal; + + ar->tx_pending[eid]--; + + if (eid != ar->ctrl_ep) + ar->total_tx_data_pend--; + + if (eid == ar->ctrl_ep) { + if (test_bit(WMI_CTRL_EP_FULL, &ar->flag)) + clear_bit(WMI_CTRL_EP_FULL, &ar->flag); + + if (ar->tx_pending[eid] == 0) + wake_event = true; + } + + if (status) { + if (status == -ECANCELED) + /* a packet was flushed */ + flushing = true; + + ar->net_stats.tx_errors++; + + if (status != -ENOSPC) + ath6kl_err("tx error, status: 0x%x\n", status); + ath6kl_dbg(ATH6KL_DBG_WLAN_TX, + "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n", + __func__, skb, packet->buf, packet->act_len, + eid, "error!"); + } else { + ath6kl_dbg(ATH6KL_DBG_WLAN_TX, + "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n", + __func__, skb, packet->buf, packet->act_len, + eid, "OK"); + + flushing = false; + ar->net_stats.tx_packets++; + ar->net_stats.tx_bytes += skb->len; + } + + ath6kl_tx_clear_node_map(ar, eid, map_no); + + ath6kl_free_cookie(ar, ath6kl_cookie); + + if (test_bit(NETQ_STOPPED, &ar->flag)) + clear_bit(NETQ_STOPPED, &ar->flag); + } + + spin_unlock_bh(&ar->lock); + + __skb_queue_purge(&skb_queue); + + if (test_bit(CONNECTED, &ar->flag)) { + if (!flushing) + netif_wake_queue(ar->net_dev); + } + + if (wake_event) + wake_up(&ar->event_wq); + + return; + +fatal: + WARN_ON(1); + spin_unlock_bh(&ar->lock); + return; +} + +void ath6kl_tx_data_cleanup(struct ath6kl *ar) +{ + int i; + + /* flush all the data (non-control) streams */ + for (i = 0; i < WMM_NUM_AC; i++) + htc_flush_txep(ar->htc_target, ar->ac2ep_map[i], + ATH6KL_DATA_PKT_TAG); +} + +/* Rx functions */ + +static void ath6kl_deliver_frames_to_nw_stack(struct net_device *dev, + struct sk_buff *skb) +{ + if (!skb) + return; + + skb->dev = dev; + + if (!(skb->dev->flags & IFF_UP)) { + dev_kfree_skb(skb); + return; + } + + skb->protocol = eth_type_trans(skb, skb->dev); + + netif_rx_ni(skb); +} + +static void ath6kl_alloc_netbufs(struct sk_buff_head *q, u16 num) +{ + struct sk_buff *skb; + + while (num) { + skb = ath6kl_buf_alloc(ATH6KL_BUFFER_SIZE); + if (!skb) { + ath6kl_err("netbuf allocation failed\n"); + return; + } + skb_queue_tail(q, skb); + num--; + } +} + +static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr) +{ + struct sk_buff *skb = NULL; + + if (skb_queue_len(&p_aggr->free_q) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) + ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); + + skb = skb_dequeue(&p_aggr->free_q); + + return skb; +} + +void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint) +{ + struct ath6kl *ar = target->dev->ar; + struct sk_buff *skb; + int rx_buf; + int n_buf_refill; + struct htc_packet *packet; + struct list_head queue; + + n_buf_refill = ATH6KL_MAX_RX_BUFFERS - + htc_get_rxbuf_num(ar->htc_target, endpoint); + + if (n_buf_refill <= 0) + return; + + INIT_LIST_HEAD(&queue); + + ath6kl_dbg(ATH6KL_DBG_WLAN_RX, + "%s: providing htc with %d buffers at eid=%d\n", + __func__, n_buf_refill, endpoint); + + for (rx_buf = 0; rx_buf < n_buf_refill; rx_buf++) { + skb = ath6kl_buf_alloc(ATH6KL_BUFFER_SIZE); + if (!skb) + break; + + packet = (struct htc_packet *) skb->head; + set_htc_rxpkt_info(packet, skb, skb->data, + ATH6KL_BUFFER_SIZE, endpoint); + list_add_tail(&packet->list, &queue); + } + + if (!list_empty(&queue)) + htc_add_rxbuf_multiple(ar->htc_target, &queue); +} + +void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count) +{ + struct htc_packet *packet; + struct sk_buff *skb; + + while (count) { + skb = ath6kl_buf_alloc(ATH6KL_AMSDU_BUFFER_SIZE); + if (!skb) + return; + + packet = (struct htc_packet *) skb->head; + set_htc_rxpkt_info(packet, skb, skb->data, + ATH6KL_AMSDU_BUFFER_SIZE, 0); + spin_lock_bh(&ar->lock); + list_add_tail(&packet->list, &ar->amsdu_rx_buffer_queue); + spin_unlock_bh(&ar->lock); + count--; + } +} + +/* + * Callback to allocate a receive buffer for a pending packet. We use a + * pre-allocated list of buffers of maximum AMSDU size (4K). + */ +struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target, + enum htc_endpoint_id endpoint, + int len) +{ + struct ath6kl *ar = target->dev->ar; + struct htc_packet *packet = NULL; + struct list_head *pkt_pos; + int refill_cnt = 0, depth = 0; + + ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: eid=%d, len:%d\n", + __func__, endpoint, len); + + if ((len <= ATH6KL_BUFFER_SIZE) || + (len > ATH6KL_AMSDU_BUFFER_SIZE)) + return NULL; + + spin_lock_bh(&ar->lock); + + if (list_empty(&ar->amsdu_rx_buffer_queue)) { + spin_unlock_bh(&ar->lock); + refill_cnt = ATH6KL_MAX_AMSDU_RX_BUFFERS; + goto refill_buf; + } + + packet = list_first_entry(&ar->amsdu_rx_buffer_queue, + struct htc_packet, list); + list_del(&packet->list); + list_for_each(pkt_pos, &ar->amsdu_rx_buffer_queue) + depth++; + + refill_cnt = ATH6KL_MAX_AMSDU_RX_BUFFERS - depth; + spin_unlock_bh(&ar->lock); + + /* set actual endpoint ID */ + packet->endpoint = endpoint; + +refill_buf: + if (refill_cnt >= ATH6KL_AMSDU_REFILL_THRESHOLD) + ath6kl_refill_amsdu_rxbufs(ar, refill_cnt); + + return packet; +} + +static void aggr_slice_amsdu(struct aggr_info *p_aggr, + struct rxtid *rxtid, struct sk_buff *skb) +{ + struct sk_buff *new_skb; + struct ethhdr *hdr; + u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len; + u8 *framep; + + mac_hdr_len = sizeof(struct ethhdr); + framep = skb->data + mac_hdr_len; + amsdu_len = skb->len - mac_hdr_len; + + while (amsdu_len > mac_hdr_len) { + hdr = (struct ethhdr *) framep; + payload_8023_len = ntohs(hdr->h_proto); + + if (payload_8023_len < MIN_MSDU_SUBFRAME_PAYLOAD_LEN || + payload_8023_len > MAX_MSDU_SUBFRAME_PAYLOAD_LEN) { + ath6kl_err("802.3 AMSDU frame bound check failed. len %d\n", + payload_8023_len); + break; + } + + frame_8023_len = payload_8023_len + mac_hdr_len; + new_skb = aggr_get_free_skb(p_aggr); + if (!new_skb) { + ath6kl_err("no buffer available\n"); + break; + } + + memcpy(new_skb->data, framep, frame_8023_len); + skb_put(new_skb, frame_8023_len); + if (ath6kl_wmi_dot3_2_dix(new_skb)) { + ath6kl_err("dot3_2_dix error\n"); + dev_kfree_skb(new_skb); + break; + } + + skb_queue_tail(&rxtid->q, new_skb); + + /* Is this the last subframe within this aggregate ? */ + if ((amsdu_len - frame_8023_len) == 0) + break; + + /* Add the length of A-MSDU subframe padding bytes - + * Round to nearest word. + */ + frame_8023_len = ALIGN(frame_8023_len + 3, 3); + + framep += frame_8023_len; + amsdu_len -= frame_8023_len; + } + + dev_kfree_skb(skb); +} + +static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, + u16 seq_no, u8 order) +{ + struct sk_buff *skb; + struct rxtid *rxtid; + struct skb_hold_q *node; + u16 idx, idx_end, seq_end; + struct rxtid_stats *stats; + + if (!p_aggr) + return; + + rxtid = &p_aggr->rx_tid[tid]; + stats = &p_aggr->stat[tid]; + + idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); + + /* + * idx_end is typically the last possible frame in the window, + * but changes to 'the' seq_no, when BAR comes. If seq_no + * is non-zero, we will go up to that and stop. + * Note: last seq no in current window will occupy the same + * index position as index that is just previous to start. + * An imp point : if win_sz is 7, for seq_no space of 4095, + * then, there would be holes when sequence wrap around occurs. + * Target should judiciously choose the win_sz, based on + * this condition. For 4095, (TID_WINDOW_SZ = 2 x win_sz + * 2, 4, 8, 16 win_sz works fine). + * We must deque from "idx" to "idx_end", including both. + */ + seq_end = seq_no ? seq_no : rxtid->seq_next; + idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); + + spin_lock_bh(&rxtid->lock); + + do { + node = &rxtid->hold_q[idx]; + if ((order == 1) && (!node->skb)) + break; + + if (node->skb) { + if (node->is_amsdu) + aggr_slice_amsdu(p_aggr, rxtid, node->skb); + else + skb_queue_tail(&rxtid->q, node->skb); + node->skb = NULL; + } else + stats->num_hole++; + + rxtid->seq_next = ATH6KL_NEXT_SEQ_NO(rxtid->seq_next); + idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); + } while (idx != idx_end); + + spin_unlock_bh(&rxtid->lock); + + stats->num_delivered += skb_queue_len(&rxtid->q); + + while ((skb = skb_dequeue(&rxtid->q))) + ath6kl_deliver_frames_to_nw_stack(p_aggr->dev, skb); +} + +static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, + u16 seq_no, + bool is_amsdu, struct sk_buff *frame) +{ + struct rxtid *rxtid; + struct rxtid_stats *stats; + struct sk_buff *skb; + struct skb_hold_q *node; + u16 idx, st, cur, end; + bool is_queued = false; + u16 extended_end; + + rxtid = &agg_info->rx_tid[tid]; + stats = &agg_info->stat[tid]; + + stats->num_into_aggr++; + + if (!rxtid->aggr) { + if (is_amsdu) { + aggr_slice_amsdu(agg_info, rxtid, frame); + is_queued = true; + stats->num_amsdu++; + while ((skb = skb_dequeue(&rxtid->q))) + ath6kl_deliver_frames_to_nw_stack(agg_info->dev, + skb); + } + return is_queued; + } + + /* Check the incoming sequence no, if it's in the window */ + st = rxtid->seq_next; + cur = seq_no; + end = (st + rxtid->hold_q_sz-1) & ATH6KL_MAX_SEQ_NO; + + if (((st < end) && (cur < st || cur > end)) || + ((st > end) && (cur > end) && (cur < st))) { + extended_end = (end + rxtid->hold_q_sz - 1) & + ATH6KL_MAX_SEQ_NO; + + if (((end < extended_end) && + (cur < end || cur > extended_end)) || + ((end > extended_end) && (cur > extended_end) && + (cur < end))) { + aggr_deque_frms(agg_info, tid, 0, 0); + if (cur >= rxtid->hold_q_sz - 1) + rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); + else + rxtid->seq_next = ATH6KL_MAX_SEQ_NO - + (rxtid->hold_q_sz - 2 - cur); + } else { + /* + * Dequeue only those frames that are outside the + * new shifted window. + */ + if (cur >= rxtid->hold_q_sz - 1) + st = cur - (rxtid->hold_q_sz - 1); + else + st = ATH6KL_MAX_SEQ_NO - + (rxtid->hold_q_sz - 2 - cur); + + aggr_deque_frms(agg_info, tid, st, 0); + } + + stats->num_oow++; + } + + idx = AGGR_WIN_IDX(seq_no, rxtid->hold_q_sz); + + node = &rxtid->hold_q[idx]; + + spin_lock_bh(&rxtid->lock); + + /* + * Is the cur frame duplicate or something beyond our window(hold_q + * -> which is 2x, already)? + * + * 1. Duplicate is easy - drop incoming frame. + * 2. Not falling in current sliding window. + * 2a. is the frame_seq_no preceding current tid_seq_no? + * -> drop the frame. perhaps sender did not get our ACK. + * this is taken care of above. + * 2b. is the frame_seq_no beyond window(st, TID_WINDOW_SZ); + * -> Taken care of it above, by moving window forward. + */ + dev_kfree_skb(node->skb); + stats->num_dups++; + + node->skb = frame; + is_queued = true; + node->is_amsdu = is_amsdu; + node->seq_no = seq_no; + + if (node->is_amsdu) + stats->num_amsdu++; + else + stats->num_mpdu++; + + spin_unlock_bh(&rxtid->lock); + + aggr_deque_frms(agg_info, tid, 0, 1); + + if (agg_info->timer_scheduled) + rxtid->progress = true; + else + for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { + if (rxtid->hold_q[idx].skb) { + /* + * There is a frame in the queue and no + * timer so start a timer to ensure that + * the frame doesn't remain stuck + * forever. + */ + agg_info->timer_scheduled = true; + mod_timer(&agg_info->timer, + (jiffies + + HZ * (AGGR_RX_TIMEOUT) / 1000)); + rxtid->progress = false; + rxtid->timer_mon = true; + break; + } + } + + return is_queued; +} + +void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) +{ + struct ath6kl *ar = target->dev->ar; + struct sk_buff *skb = packet->pkt_cntxt; + struct wmi_rx_meta_v2 *meta; + struct wmi_data_hdr *dhdr; + int min_hdr_len; + u8 meta_type, dot11_hdr = 0; + int status = packet->status; + enum htc_endpoint_id ept = packet->endpoint; + bool is_amsdu, prev_ps, ps_state = false; + struct ath6kl_sta *conn = NULL; + struct sk_buff *skb1 = NULL; + struct ethhdr *datap = NULL; + u16 seq_no, offset; + u8 tid; + + ath6kl_dbg(ATH6KL_DBG_WLAN_RX, + "%s: ar=0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d", + __func__, ar, ept, skb, packet->buf, + packet->act_len, status); + + if (status || !(skb->data + HTC_HDR_LENGTH)) { + ar->net_stats.rx_errors++; + dev_kfree_skb(skb); + return; + } + + /* + * Take lock to protect buffer counts and adaptive power throughput + * state. + */ + spin_lock_bh(&ar->lock); + + ar->net_stats.rx_packets++; + ar->net_stats.rx_bytes += packet->act_len; + + skb_put(skb, packet->act_len + HTC_HDR_LENGTH); + skb_pull(skb, HTC_HDR_LENGTH); + + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len); + + spin_unlock_bh(&ar->lock); + + skb->dev = ar->net_dev; + + if (!test_bit(WMI_ENABLED, &ar->flag)) { + if (EPPING_ALIGNMENT_PAD > 0) + skb_pull(skb, EPPING_ALIGNMENT_PAD); + ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); + return; + } + + if (ept == ar->ctrl_ep) { + ath6kl_wmi_control_rx(ar->wmi, skb); + return; + } + + min_hdr_len = sizeof(struct ethhdr); + min_hdr_len += sizeof(struct wmi_data_hdr) + + sizeof(struct ath6kl_llc_snap_hdr); + + dhdr = (struct wmi_data_hdr *) skb->data; + + /* + * In the case of AP mode we may receive NULL data frames + * that do not have LLC hdr. They are 16 bytes in size. + * Allow these frames in the AP mode. + */ + if (ar->nw_type != AP_NETWORK && + ((packet->act_len < min_hdr_len) || + (packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) { + ath6kl_info("frame len is too short or too long\n"); + ar->net_stats.rx_errors++; + ar->net_stats.rx_length_errors++; + dev_kfree_skb(skb); + return; + } + + /* Get the Power save state of the STA */ + if (ar->nw_type == AP_NETWORK) { + meta_type = wmi_data_hdr_get_meta(dhdr); + + ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) & + WMI_DATA_HDR_PS_MASK); + + offset = sizeof(struct wmi_data_hdr); + + switch (meta_type) { + case 0: + break; + case WMI_META_VERSION_1: + offset += sizeof(struct wmi_rx_meta_v1); + break; + case WMI_META_VERSION_2: + offset += sizeof(struct wmi_rx_meta_v2); + break; + default: + break; + } + + datap = (struct ethhdr *) (skb->data + offset); + conn = ath6kl_find_sta(ar, datap->h_source); + + if (!conn) { + dev_kfree_skb(skb); + return; + } + + /* + * If there is a change in PS state of the STA, + * take appropriate steps: + * + * 1. If Sleep-->Awake, flush the psq for the STA + * Clear the PVB for the STA. + * 2. If Awake-->Sleep, Starting queueing frames + * the STA. + */ + prev_ps = !!(conn->sta_flags & STA_PS_SLEEP); + + if (ps_state) + conn->sta_flags |= STA_PS_SLEEP; + else + conn->sta_flags &= ~STA_PS_SLEEP; + + if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) { + if (!(conn->sta_flags & STA_PS_SLEEP)) { + struct sk_buff *skbuff = NULL; + + spin_lock_bh(&conn->psq_lock); + while ((skbuff = skb_dequeue(&conn->psq)) + != NULL) { + spin_unlock_bh(&conn->psq_lock); + ath6kl_data_tx(skbuff, ar->net_dev); + spin_lock_bh(&conn->psq_lock); + } + spin_unlock_bh(&conn->psq_lock); + /* Clear the PVB for this STA */ + ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0); + } + } + + /* drop NULL data frames here */ + if ((packet->act_len < min_hdr_len) || + (packet->act_len > + WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH)) { + dev_kfree_skb(skb); + return; + } + } + + is_amsdu = wmi_data_hdr_is_amsdu(dhdr) ? true : false; + tid = wmi_data_hdr_get_up(dhdr); + seq_no = wmi_data_hdr_get_seqno(dhdr); + meta_type = wmi_data_hdr_get_meta(dhdr); + dot11_hdr = wmi_data_hdr_get_dot11(dhdr); + + ath6kl_wmi_data_hdr_remove(ar->wmi, skb); + + switch (meta_type) { + case WMI_META_VERSION_1: + skb_pull(skb, sizeof(struct wmi_rx_meta_v1)); + break; + case WMI_META_VERSION_2: + meta = (struct wmi_rx_meta_v2 *) skb->data; + if (meta->csum_flags & 0x1) { + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = (__force __wsum) meta->csum; + } + skb_pull(skb, sizeof(struct wmi_rx_meta_v2)); + break; + default: + break; + } + + if (dot11_hdr) + status = ath6kl_wmi_dot11_hdr_remove(ar->wmi, skb); + else if (!is_amsdu) + status = ath6kl_wmi_dot3_2_dix(skb); + + if (status) { + /* + * Drop frames that could not be processed (lack of + * memory, etc.) + */ + dev_kfree_skb(skb); + return; + } + + if (!(ar->net_dev->flags & IFF_UP)) { + dev_kfree_skb(skb); + return; + } + + if (ar->nw_type == AP_NETWORK) { + datap = (struct ethhdr *) skb->data; + if (is_multicast_ether_addr(datap->h_dest)) + /* + * Bcast/Mcast frames should be sent to the + * OS stack as well as on the air. + */ + skb1 = skb_copy(skb, GFP_ATOMIC); + else { + /* + * Search for a connected STA with dstMac + * as the Mac address. If found send the + * frame to it on the air else send the + * frame up the stack. + */ + struct ath6kl_sta *conn = NULL; + conn = ath6kl_find_sta(ar, datap->h_dest); + + if (conn && ar->intra_bss) { + skb1 = skb; + skb = NULL; + } else if (conn && !ar->intra_bss) { + dev_kfree_skb(skb); + skb = NULL; + } + } + if (skb1) + ath6kl_data_tx(skb1, ar->net_dev); + } + + if (!aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, + is_amsdu, skb)) + ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); +} + +static void aggr_timeout(unsigned long arg) +{ + u8 i, j; + struct aggr_info *p_aggr = (struct aggr_info *) arg; + struct rxtid *rxtid; + struct rxtid_stats *stats; + + for (i = 0; i < NUM_OF_TIDS; i++) { + rxtid = &p_aggr->rx_tid[i]; + stats = &p_aggr->stat[i]; + + if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) + continue; + + stats->num_timeouts++; + ath6kl_err("aggr timeout (st %d end %d)\n", + rxtid->seq_next, + ((rxtid->seq_next + rxtid->hold_q_sz-1) & + ATH6KL_MAX_SEQ_NO)); + aggr_deque_frms(p_aggr, i, 0, 0); + } + + p_aggr->timer_scheduled = false; + + for (i = 0; i < NUM_OF_TIDS; i++) { + rxtid = &p_aggr->rx_tid[i]; + + if (rxtid->aggr && rxtid->hold_q) { + for (j = 0; j < rxtid->hold_q_sz; j++) { + if (rxtid->hold_q[j].skb) { + p_aggr->timer_scheduled = true; + rxtid->timer_mon = true; + rxtid->progress = false; + break; + } + } + + if (j >= rxtid->hold_q_sz) + rxtid->timer_mon = false; + } + } + + if (p_aggr->timer_scheduled) + mod_timer(&p_aggr->timer, + jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT)); +} + +static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) +{ + struct rxtid *rxtid; + struct rxtid_stats *stats; + + if (!p_aggr || tid >= NUM_OF_TIDS) + return; + + rxtid = &p_aggr->rx_tid[tid]; + stats = &p_aggr->stat[tid]; + + if (rxtid->aggr) + aggr_deque_frms(p_aggr, tid, 0, 0); + + rxtid->aggr = false; + rxtid->progress = false; + rxtid->timer_mon = false; + rxtid->win_sz = 0; + rxtid->seq_next = 0; + rxtid->hold_q_sz = 0; + + kfree(rxtid->hold_q); + rxtid->hold_q = NULL; + + memset(stats, 0, sizeof(struct rxtid_stats)); +} + +void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, u8 win_sz) +{ + struct aggr_info *p_aggr = ar->aggr_cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + u16 hold_q_size; + + if (!p_aggr) + return; + + rxtid = &p_aggr->rx_tid[tid]; + stats = &p_aggr->stat[tid]; + + if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) + ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n", + __func__, win_sz, tid); + + if (rxtid->aggr) + aggr_delete_tid_state(p_aggr, tid); + + rxtid->seq_next = seq_no; + hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q); + rxtid->hold_q = kzalloc(hold_q_size, GFP_KERNEL); + if (!rxtid->hold_q) + return; + + rxtid->win_sz = win_sz; + rxtid->hold_q_sz = TID_WINDOW_SZ(win_sz); + if (!skb_queue_empty(&rxtid->q)) + return; + + rxtid->aggr = true; +} + +struct aggr_info *aggr_init(struct net_device *dev) +{ + struct aggr_info *p_aggr = NULL; + struct rxtid *rxtid; + u8 i; + + p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); + if (!p_aggr) { + ath6kl_err("failed to alloc memory for aggr_node\n"); + return NULL; + } + + p_aggr->aggr_sz = AGGR_SZ_DEFAULT; + p_aggr->dev = dev; + init_timer(&p_aggr->timer); + p_aggr->timer.function = aggr_timeout; + p_aggr->timer.data = (unsigned long) p_aggr; + + p_aggr->timer_scheduled = false; + skb_queue_head_init(&p_aggr->free_q); + + ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); + + for (i = 0; i < NUM_OF_TIDS; i++) { + rxtid = &p_aggr->rx_tid[i]; + rxtid->aggr = false; + rxtid->progress = false; + rxtid->timer_mon = false; + skb_queue_head_init(&rxtid->q); + spin_lock_init(&rxtid->lock); + } + + return p_aggr; +} + +void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid) +{ + struct aggr_info *p_aggr = ar->aggr_cntxt; + struct rxtid *rxtid; + + if (!p_aggr) + return; + + rxtid = &p_aggr->rx_tid[tid]; + + if (rxtid->aggr) + aggr_delete_tid_state(p_aggr, tid); +} + +void aggr_reset_state(struct aggr_info *aggr_info) +{ + u8 tid; + + for (tid = 0; tid < NUM_OF_TIDS; tid++) + aggr_delete_tid_state(aggr_info, tid); +} + +/* clean up our amsdu buffer list */ +void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar) +{ + struct htc_packet *packet, *tmp_pkt; + + spin_lock_bh(&ar->lock); + if (list_empty(&ar->amsdu_rx_buffer_queue)) { + spin_unlock_bh(&ar->lock); + return; + } + + list_for_each_entry_safe(packet, tmp_pkt, &ar->amsdu_rx_buffer_queue, + list) { + list_del(&packet->list); + spin_unlock_bh(&ar->lock); + dev_kfree_skb(packet->pkt_cntxt); + spin_lock_bh(&ar->lock); + } + + spin_unlock_bh(&ar->lock); +} + +void aggr_module_destroy(struct aggr_info *aggr_info) +{ + struct rxtid *rxtid; + u8 i, k; + + if (!aggr_info) + return; + + if (aggr_info->timer_scheduled) { + del_timer(&aggr_info->timer); + aggr_info->timer_scheduled = false; + } + + for (i = 0; i < NUM_OF_TIDS; i++) { + rxtid = &aggr_info->rx_tid[i]; + if (rxtid->hold_q) { + for (k = 0; k < rxtid->hold_q_sz; k++) + dev_kfree_skb(rxtid->hold_q[k].skb); + kfree(rxtid->hold_q); + } + + skb_queue_purge(&rxtid->q); + } + + skb_queue_purge(&aggr_info->free_q); + kfree(aggr_info); +} diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c new file mode 100644 index 000000000000..a52d7d201fbd --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -0,0 +1,2762 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/ip.h> +#include "core.h" +#include "debug.h" + +static int ath6kl_wmi_sync_point(struct wmi *wmi); + +static const s32 wmi_rate_tbl[][2] = { + /* {W/O SGI, with SGI} */ + {1000, 1000}, + {2000, 2000}, + {5500, 5500}, + {11000, 11000}, + {6000, 6000}, + {9000, 9000}, + {12000, 12000}, + {18000, 18000}, + {24000, 24000}, + {36000, 36000}, + {48000, 48000}, + {54000, 54000}, + {6500, 7200}, + {13000, 14400}, + {19500, 21700}, + {26000, 28900}, + {39000, 43300}, + {52000, 57800}, + {58500, 65000}, + {65000, 72200}, + {13500, 15000}, + {27000, 30000}, + {40500, 45000}, + {54000, 60000}, + {81000, 90000}, + {108000, 120000}, + {121500, 135000}, + {135000, 150000}, + {0, 0} +}; + +/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ +static const u8 up_to_ac[] = { + WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO, +}; + +void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id) +{ + if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX)) + return; + + wmi->ep_id = ep_id; +} + +enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi) +{ + return wmi->ep_id; +} + +/* Performs DIX to 802.3 encapsulation for transmit packets. + * Assumes the entire DIX header is contigous and that there is + * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. + */ +int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb) +{ + struct ath6kl_llc_snap_hdr *llc_hdr; + struct ethhdr *eth_hdr; + size_t new_len; + __be16 type; + u8 *datap; + u16 size; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr); + if (skb_headroom(skb) < size) + return -ENOMEM; + + eth_hdr = (struct ethhdr *) skb->data; + type = eth_hdr->h_proto; + + if (!is_ethertype(be16_to_cpu(type))) { + ath6kl_dbg(ATH6KL_DBG_WMI, + "%s: pkt is already in 802.3 format\n", __func__); + return 0; + } + + new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr); + + skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr)); + datap = skb->data; + + eth_hdr->h_proto = cpu_to_be16(new_len); + + memcpy(datap, eth_hdr, sizeof(*eth_hdr)); + + llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr)); + llc_hdr->dsap = 0xAA; + llc_hdr->ssap = 0xAA; + llc_hdr->cntl = 0x03; + llc_hdr->org_code[0] = 0x0; + llc_hdr->org_code[1] = 0x0; + llc_hdr->org_code[2] = 0x0; + llc_hdr->eth_type = type; + + return 0; +} + +static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, + u8 *version, void *tx_meta_info) +{ + struct wmi_tx_meta_v1 *v1; + struct wmi_tx_meta_v2 *v2; + + if (WARN_ON(skb == NULL || version == NULL)) + return -EINVAL; + + switch (*version) { + case WMI_META_VERSION_1: + skb_push(skb, WMI_MAX_TX_META_SZ); + v1 = (struct wmi_tx_meta_v1 *) skb->data; + v1->pkt_id = 0; + v1->rate_plcy_id = 0; + *version = WMI_META_VERSION_1; + break; + case WMI_META_VERSION_2: + skb_push(skb, WMI_MAX_TX_META_SZ); + v2 = (struct wmi_tx_meta_v2 *) skb->data; + memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info, + sizeof(struct wmi_tx_meta_v2)); + break; + } + + return 0; +} + +int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, + u8 msg_type, bool more_data, + enum wmi_data_hdr_data_type data_type, + u8 meta_ver, void *tx_meta_info) +{ + struct wmi_data_hdr *data_hdr; + int ret; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); + if (ret) + return ret; + + skb_push(skb, sizeof(struct wmi_data_hdr)); + + data_hdr = (struct wmi_data_hdr *)skb->data; + memset(data_hdr, 0, sizeof(struct wmi_data_hdr)); + + data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; + data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; + + if (more_data) + data_hdr->info |= + WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; + + data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); + data_hdr->info3 = 0; + + return 0; +} + +static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) +{ + struct iphdr *ip_hdr = (struct iphdr *) pkt; + u8 ip_pri; + + /* + * Determine IPTOS priority + * + * IP-TOS - 8bits + * : DSCP(6-bits) ECN(2-bits) + * : DSCP - P2 P1 P0 X X X + * where (P2 P1 P0) form 802.1D + */ + ip_pri = ip_hdr->tos >> 5; + ip_pri &= 0x7; + + if ((layer2_pri & 0x7) > ip_pri) + return (u8) layer2_pri & 0x7; + else + return ip_pri; +} + +int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb, + u32 layer2_priority, bool wmm_enabled, + u8 *ac) +{ + struct wmi_data_hdr *data_hdr; + struct ath6kl_llc_snap_hdr *llc_hdr; + struct wmi_create_pstream_cmd cmd; + u32 meta_size, hdr_size; + u16 ip_type = IP_ETHERTYPE; + u8 stream_exist, usr_pri; + u8 traffic_class = WMM_AC_BE; + u8 *datap; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + datap = skb->data; + data_hdr = (struct wmi_data_hdr *) datap; + + meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) & + WMI_DATA_HDR_META_MASK) ? WMI_MAX_TX_META_SZ : 0; + + if (!wmm_enabled) { + /* If WMM is disabled all traffic goes as BE traffic */ + usr_pri = 0; + } else { + hdr_size = sizeof(struct ethhdr); + + llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + + sizeof(struct + wmi_data_hdr) + + meta_size + hdr_size); + + if (llc_hdr->eth_type == htons(ip_type)) { + /* + * Extract the endpoint info from the TOS field + * in the IP header. + */ + usr_pri = + ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) + + sizeof(struct ath6kl_llc_snap_hdr), + layer2_priority); + } else + usr_pri = layer2_priority & 0x7; + } + + /* workaround for WMM S5 */ + if ((wmi->traffic_class == WMM_AC_VI) && + ((usr_pri == 5) || (usr_pri == 4))) + usr_pri = 1; + + /* Convert user priority to traffic class */ + traffic_class = up_to_ac[usr_pri & 0x7]; + + wmi_data_hdr_set_up(data_hdr, usr_pri); + + spin_lock_bh(&wmi->lock); + stream_exist = wmi->fat_pipe_exist; + spin_unlock_bh(&wmi->lock); + + if (!(stream_exist & (1 << traffic_class))) { + memset(&cmd, 0, sizeof(cmd)); + cmd.traffic_class = traffic_class; + cmd.user_pri = usr_pri; + cmd.inactivity_int = + cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT); + /* Implicit streams are created with TSID 0xFF */ + cmd.tsid = WMI_IMPLICIT_PSTREAM; + ath6kl_wmi_create_pstream_cmd(wmi, &cmd); + } + + *ac = traffic_class; + + return 0; +} + +int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb) +{ + struct ieee80211_hdr_3addr *pwh, wh; + struct ath6kl_llc_snap_hdr *llc_hdr; + struct ethhdr eth_hdr; + u32 hdr_size; + u8 *datap; + __le16 sub_type; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + datap = skb->data; + pwh = (struct ieee80211_hdr_3addr *) datap; + + sub_type = pwh->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); + + memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr)); + + /* Strip off the 802.11 header */ + if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { + hdr_size = roundup(sizeof(struct ieee80211_qos_hdr), + sizeof(u32)); + skb_pull(skb, hdr_size); + } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA)) + skb_pull(skb, sizeof(struct ieee80211_hdr_3addr)); + + datap = skb->data; + llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap); + + eth_hdr.h_proto = llc_hdr->eth_type; + memset(eth_hdr.h_dest, 0, sizeof(eth_hdr.h_dest)); + memset(eth_hdr.h_source, 0, sizeof(eth_hdr.h_source)); + + switch ((le16_to_cpu(wh.frame_control)) & + (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { + case 0: + memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN); + memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN); + break; + case IEEE80211_FCTL_TODS: + memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN); + memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN); + break; + case IEEE80211_FCTL_FROMDS: + memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN); + memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN); + break; + case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: + break; + } + + skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr)); + skb_push(skb, sizeof(eth_hdr)); + + datap = skb->data; + + memcpy(datap, ð_hdr, sizeof(eth_hdr)); + + return 0; +} + +/* + * Performs 802.3 to DIX encapsulation for received packets. + * Assumes the entire 802.3 header is contigous. + */ +int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb) +{ + struct ath6kl_llc_snap_hdr *llc_hdr; + struct ethhdr eth_hdr; + u8 *datap; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + datap = skb->data; + + memcpy(ð_hdr, datap, sizeof(eth_hdr)); + + llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr)); + eth_hdr.h_proto = llc_hdr->eth_type; + + skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr)); + datap = skb->data; + + memcpy(datap, ð_hdr, sizeof(eth_hdr)); + + return 0; +} + +int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb) +{ + if (WARN_ON(skb == NULL)) + return -EINVAL; + + skb_pull(skb, sizeof(struct wmi_data_hdr)); + + return 0; +} + +void ath6kl_wmi_iterate_nodes(struct wmi *wmi, + void (*f) (void *arg, struct bss *), + void *arg) +{ + wlan_iterate_nodes(&wmi->scan_table, f, arg); +} + +static void ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(struct sk_buff *skb, + u8 *datap) +{ + struct wmi_bss_info_hdr2 bih2; + struct wmi_bss_info_hdr *bih; + + memcpy(&bih2, datap, sizeof(struct wmi_bss_info_hdr2)); + + skb_push(skb, 4); + bih = (struct wmi_bss_info_hdr *) skb->data; + + bih->ch = bih2.ch; + bih->frame_type = bih2.frame_type; + bih->snr = bih2.snr; + bih->rssi = a_cpu_to_sle16(bih2.snr - 95); + bih->ie_mask = cpu_to_le32(le16_to_cpu(bih2.ie_mask)); + memcpy(bih->bssid, bih2.bssid, ETH_ALEN); +} + +static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) +{ + struct tx_complete_msg_v1 *msg_v1; + struct wmi_tx_complete_event *evt; + int index; + u16 size; + + evt = (struct wmi_tx_complete_event *) datap; + + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + + if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI)) + return 0; + + for (index = 0; index < evt->num_msg; index++) { + size = sizeof(struct wmi_tx_complete_event) + + (index * sizeof(struct tx_complete_msg_v1)); + msg_v1 = (struct tx_complete_msg_v1 *)(datap + size); + + ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n", + msg_v1->status, msg_v1->pkt_id, + msg_v1->rate_idx, msg_v1->ack_failures); + } + + return 0; +} + +static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) +{ + struct sk_buff *skb; + + skb = ath6kl_buf_alloc(size); + if (!skb) + return NULL; + + skb_put(skb, size); + if (size) + memset(skb->data, 0, size); + + return skb; +} + +/* Send a "simple" wmi command -- one with no arguments */ +static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id) +{ + struct sk_buff *skb; + int ret; + + skb = ath6kl_wmi_get_new_buf(0); + if (!skb) + return -ENOMEM; + + ret = ath6kl_wmi_cmd_send(wmi, skb, cmd_id, NO_SYNC_WMIFLAG); + + return ret; +} + +static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap; + + if (len < sizeof(struct wmi_ready_event_2)) + return -EINVAL; + + wmi->ready = true; + ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, + le32_to_cpu(ev->sw_version), + le32_to_cpu(ev->abi_version)); + + return 0; +} + +static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_connect_event *ev; + u8 *pie, *peie; + + if (len < sizeof(struct wmi_connect_event)) + return -EINVAL; + + ev = (struct wmi_connect_event *) datap; + + ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n", + __func__, ev->ch, ev->bssid); + + memcpy(wmi->bssid, ev->bssid, ETH_ALEN); + + /* Start of assoc rsp IEs */ + pie = ev->assoc_info + ev->beacon_ie_len + + ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */ + + /* End of assoc rsp IEs */ + peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len + + ev->assoc_resp_len; + + while (pie < peie) { + switch (*pie) { + case WLAN_EID_VENDOR_SPECIFIC: + if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 && + pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) { + /* WMM OUT (00:50:F2) */ + if (pie[1] > 5 + && pie[6] == WMM_PARAM_OUI_SUBTYPE) + wmi->is_wmm_enabled = true; + } + break; + } + + if (wmi->is_wmm_enabled) + break; + + pie += pie[1] + 2; + } + + ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid, + le16_to_cpu(ev->listen_intvl), + le16_to_cpu(ev->beacon_intvl), + le32_to_cpu(ev->nw_type), + ev->beacon_ie_len, ev->assoc_req_len, + ev->assoc_resp_len, ev->assoc_info); + + return 0; +} + +static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_disconnect_event *ev; + wmi->traffic_class = 100; + + if (len < sizeof(struct wmi_disconnect_event)) + return -EINVAL; + + ev = (struct wmi_disconnect_event *) datap; + memset(wmi->bssid, 0, sizeof(wmi->bssid)); + + wmi->is_wmm_enabled = false; + wmi->pair_crypto_type = NONE_CRYPT; + wmi->grp_crypto_type = NONE_CRYPT; + + ath6kl_disconnect_event(wmi->parent_dev, ev->disconn_reason, + ev->bssid, ev->assoc_resp_len, ev->assoc_info, + le16_to_cpu(ev->proto_reason_status)); + + return 0; +} + +static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_peer_node_event *ev; + + if (len < sizeof(struct wmi_peer_node_event)) + return -EINVAL; + + ev = (struct wmi_peer_node_event *) datap; + + if (ev->event_code == PEER_NODE_JOIN_EVENT) + ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n", + ev->peer_mac_addr); + else if (ev->event_code == PEER_NODE_LEAVE_EVENT) + ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n", + ev->peer_mac_addr); + + return 0; +} + +static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_tkip_micerr_event *ev; + + if (len < sizeof(struct wmi_tkip_micerr_event)) + return -EINVAL; + + ev = (struct wmi_tkip_micerr_event *) datap; + + ath6kl_tkip_micerr_event(wmi->parent_dev, ev->key_id, ev->is_mcast); + + return 0; +} + +static int ath6kl_wlan_parse_beacon(u8 *buf, int frame_len, + struct ath6kl_common_ie *cie) +{ + u8 *frm, *efrm; + u8 elemid_ssid = false; + + frm = buf; + efrm = (u8 *) (frm + frame_len); + + /* + * beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid + * [tlv] supported rates + * [tlv] country information + * [tlv] parameter set (FH/DS) + * [tlv] erp information + * [tlv] extended supported rates + * [tlv] WMM + * [tlv] WPA or RSN + * [tlv] Atheros Advanced Capabilities + */ + if ((efrm - frm) < 12) + return -EINVAL; + + memset(cie, 0, sizeof(*cie)); + + cie->ie_tstamp = frm; + frm += 8; + cie->ie_beaconInt = *(u16 *) frm; + frm += 2; + cie->ie_capInfo = *(u16 *) frm; + frm += 2; + cie->ie_chan = 0; + + while (frm < efrm) { + switch (*frm) { + case WLAN_EID_SSID: + if (!elemid_ssid) { + cie->ie_ssid = frm; + elemid_ssid = true; + } + break; + case WLAN_EID_SUPP_RATES: + cie->ie_rates = frm; + break; + case WLAN_EID_COUNTRY: + cie->ie_country = frm; + break; + case WLAN_EID_FH_PARAMS: + break; + case WLAN_EID_DS_PARAMS: + cie->ie_chan = frm[2]; + break; + case WLAN_EID_TIM: + cie->ie_tim = frm; + break; + case WLAN_EID_IBSS_PARAMS: + break; + case WLAN_EID_EXT_SUPP_RATES: + cie->ie_xrates = frm; + break; + case WLAN_EID_ERP_INFO: + if (frm[1] != 1) + return -EINVAL; + + cie->ie_erp = frm[2]; + break; + case WLAN_EID_RSN: + cie->ie_rsn = frm; + break; + case WLAN_EID_HT_CAPABILITY: + cie->ie_htcap = frm; + break; + case WLAN_EID_HT_INFORMATION: + cie->ie_htop = frm; + break; + case WLAN_EID_VENDOR_SPECIFIC: + if (frm[1] > 3 && frm[2] == 0x00 && frm[3] == 0x50 && + frm[4] == 0xf2) { + /* OUT Type (00:50:F2) */ + + if (frm[5] == WPA_OUI_TYPE) { + /* WPA OUT */ + cie->ie_wpa = frm; + } else if (frm[5] == WMM_OUI_TYPE) { + /* WMM OUT */ + cie->ie_wmm = frm; + } else if (frm[5] == WSC_OUT_TYPE) { + /* WSC OUT */ + cie->ie_wsc = frm; + } + + } else if (frm[1] > 3 && frm[2] == 0x00 + && frm[3] == 0x03 && frm[4] == 0x7f + && frm[5] == ATH_OUI_TYPE) { + /* Atheros OUI (00:03:7f) */ + cie->ie_ath = frm; + } + break; + default: + break; + } + frm += frm[1] + 2; + } + + if ((cie->ie_rates == NULL) + || (cie->ie_rates[1] > ATH6KL_RATE_MAXSIZE)) + return -EINVAL; + + if ((cie->ie_ssid == NULL) + || (cie->ie_ssid[1] > IEEE80211_MAX_SSID_LEN)) + return -EINVAL; + + return 0; +} + +static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct bss *bss = NULL; + struct wmi_bss_info_hdr *bih; + u8 cached_ssid_len = 0; + u8 cached_ssid[IEEE80211_MAX_SSID_LEN] = { 0 }; + u8 beacon_ssid_len = 0; + u8 *buf, *ie_ssid; + u8 *ni_buf; + int buf_len; + + int ret; + + if (len <= sizeof(struct wmi_bss_info_hdr)) + return -EINVAL; + + bih = (struct wmi_bss_info_hdr *) datap; + bss = wlan_find_node(&wmi->scan_table, bih->bssid); + + if (a_sle16_to_cpu(bih->rssi) > 0) { + if (bss == NULL) + return 0; + else + bih->rssi = a_cpu_to_sle16(bss->ni_rssi); + } + + buf = datap + sizeof(struct wmi_bss_info_hdr); + len -= sizeof(struct wmi_bss_info_hdr); + + ath6kl_dbg(ATH6KL_DBG_WMI, + "bss info evt - ch %u, rssi %02x, bssid \"%pM\"\n", + bih->ch, a_sle16_to_cpu(bih->rssi), bih->bssid); + + if (bss != NULL) { + /* + * Free up the node. We are about to allocate a new node. + * In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so cache the probe-resp-ssid if already present. + */ + if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE)) { + ie_ssid = bss->ni_cie.ie_ssid; + if (ie_ssid && (ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && + (ie_ssid[2] != 0)) { + cached_ssid_len = ie_ssid[1]; + memcpy(cached_ssid, ie_ssid + 2, + cached_ssid_len); + } + } + + /* + * Use the current average rssi of associated AP base on + * assumption + * 1. Most os with GUI will update RSSI by + * ath6kl_wmi_get_stats_cmd() periodically. + * 2. ath6kl_wmi_get_stats_cmd(..) will be called when calling + * ath6kl_wmi_startscan_cmd(...) + * The average value of RSSI give end-user better feeling for + * instance value of scan result. It also sync up RSSI info + * in GUI between scan result and RSSI signal icon. + */ + if (memcmp(wmi->bssid, bih->bssid, ETH_ALEN) == 0) { + bih->rssi = a_cpu_to_sle16(bss->ni_rssi); + bih->snr = bss->ni_snr; + } + + wlan_node_reclaim(&wmi->scan_table, bss); + } + + /* + * beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid + */ + beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; + + /* + * If ssid is cached for this hidden AP, then change + * buffer len accordingly. + */ + if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && + (cached_ssid_len != 0) && + (beacon_ssid_len == 0 || (cached_ssid_len > beacon_ssid_len && + buf[SSID_IE_LEN_INDEX + 1] == 0))) { + + len += (cached_ssid_len - beacon_ssid_len); + } + + bss = wlan_node_alloc(len); + if (!bss) + return -ENOMEM; + + bss->ni_snr = bih->snr; + bss->ni_rssi = a_sle16_to_cpu(bih->rssi); + + if (WARN_ON(!bss->ni_buf)) + return -EINVAL; + + /* + * In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so place the cached-ssid(probe-resp) in the bss info. + */ + if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && + (cached_ssid_len != 0) && + (beacon_ssid_len == 0 || (beacon_ssid_len && + buf[SSID_IE_LEN_INDEX + 1] == 0))) { + ni_buf = bss->ni_buf; + buf_len = len; + + /* + * Copy the first 14 bytes: + * time-stamp(8), beacon-interval(2), + * cap-info(2), ssid-id(1), ssid-len(1). + */ + memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); + + ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; + ni_buf += (SSID_IE_LEN_INDEX + 1); + + buf += (SSID_IE_LEN_INDEX + 1); + buf_len -= (SSID_IE_LEN_INDEX + 1); + + memcpy(ni_buf, cached_ssid, cached_ssid_len); + ni_buf += cached_ssid_len; + + buf += beacon_ssid_len; + buf_len -= beacon_ssid_len; + + if (cached_ssid_len > beacon_ssid_len) + buf_len -= (cached_ssid_len - beacon_ssid_len); + + memcpy(ni_buf, buf, buf_len); + } else + memcpy(bss->ni_buf, buf, len); + + bss->ni_framelen = len; + + ret = ath6kl_wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie); + if (ret) { + wlan_node_free(bss); + return -EINVAL; + } + + /* + * Update the frequency in ie_chan, overwriting of channel number + * which is done in ath6kl_wlan_parse_beacon + */ + bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); + wlan_setup_node(&wmi->scan_table, bss, bih->bssid); + + return 0; +} + +static int ath6kl_wmi_opt_frame_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct bss *bss; + struct wmi_opt_rx_info_hdr *bih; + u8 *buf; + + if (len <= sizeof(struct wmi_opt_rx_info_hdr)) + return -EINVAL; + + bih = (struct wmi_opt_rx_info_hdr *) datap; + buf = datap + sizeof(struct wmi_opt_rx_info_hdr); + len -= sizeof(struct wmi_opt_rx_info_hdr); + + ath6kl_dbg(ATH6KL_DBG_WMI, "opt frame event %2.2x:%2.2x\n", + bih->bssid[4], bih->bssid[5]); + + bss = wlan_find_node(&wmi->scan_table, bih->bssid); + if (bss != NULL) { + /* Free up the node. We are about to allocate a new node. */ + wlan_node_reclaim(&wmi->scan_table, bss); + } + + bss = wlan_node_alloc(len); + if (!bss) + return -ENOMEM; + + bss->ni_snr = bih->snr; + bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); + + if (WARN_ON(!bss->ni_buf)) + return -EINVAL; + + memcpy(bss->ni_buf, buf, len); + wlan_setup_node(&wmi->scan_table, bss, bih->bssid); + + return 0; +} + +/* Inactivity timeout of a fatpipe(pstream) at the target */ +static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap, + int len) +{ + struct wmi_pstream_timeout_event *ev; + + if (len < sizeof(struct wmi_pstream_timeout_event)) + return -EINVAL; + + ev = (struct wmi_pstream_timeout_event *) datap; + + /* + * When the pstream (fat pipe == AC) timesout, it means there were + * no thinStreams within this pstream & it got implicitly created + * due to data flow on this AC. We start the inactivity timer only + * for implicitly created pstream. Just reset the host state. + */ + spin_lock_bh(&wmi->lock); + wmi->stream_exist_for_ac[ev->traffic_class] = 0; + wmi->fat_pipe_exist &= ~(1 << ev->traffic_class); + spin_unlock_bh(&wmi->lock); + + /* Indicate inactivity to driver layer for this fatpipe (pstream) */ + ath6kl_indicate_tx_activity(wmi->parent_dev, ev->traffic_class, false); + + return 0; +} + +static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_bit_rate_reply *reply; + s32 rate; + u32 sgi, index; + + if (len < sizeof(struct wmi_bit_rate_reply)) + return -EINVAL; + + reply = (struct wmi_bit_rate_reply *) datap; + + ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index); + + if (reply->rate_index == (s8) RATE_AUTO) { + rate = RATE_AUTO; + } else { + index = reply->rate_index & 0x7f; + sgi = (reply->rate_index & 0x80) ? 1 : 0; + rate = wmi_rate_tbl[index][sgi]; + } + + ath6kl_wakeup_event(wmi->parent_dev); + + return 0; +} + +static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) +{ + if (len < sizeof(struct wmi_fix_rates_reply)) + return -EINVAL; + + ath6kl_wakeup_event(wmi->parent_dev); + + return 0; +} + +static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len) +{ + if (len < sizeof(struct wmi_channel_list_reply)) + return -EINVAL; + + ath6kl_wakeup_event(wmi->parent_dev); + + return 0; +} + +static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_tx_pwr_reply *reply; + + if (len < sizeof(struct wmi_tx_pwr_reply)) + return -EINVAL; + + reply = (struct wmi_tx_pwr_reply *) datap; + ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM); + + return 0; +} + +static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len) +{ + if (len < sizeof(struct wmi_get_keepalive_cmd)) + return -EINVAL; + + ath6kl_wakeup_event(wmi->parent_dev); + + return 0; +} + +static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_scan_complete_event *ev; + + ev = (struct wmi_scan_complete_event *) datap; + + if (a_sle32_to_cpu(ev->status) == 0) + wlan_refresh_inactive_nodes(&wmi->scan_table); + + ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status)); + wmi->is_probe_ssid = false; + + return 0; +} + +/* + * Target is reporting a programming error. This is for + * developer aid only. Target only checks a few common violations + * and it is responsibility of host to do all error checking. + * Behavior of target after wmi error event is undefined. + * A reset is recommended. + */ +static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + const char *type = "unknown error"; + struct wmi_cmd_error_event *ev; + ev = (struct wmi_cmd_error_event *) datap; + + switch (ev->err_code) { + case INVALID_PARAM: + type = "invalid parameter"; + break; + case ILLEGAL_STATE: + type = "invalid state"; + break; + case INTERNAL_ERROR: + type = "internal error"; + break; + } + + ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n", + ev->cmd_id, type); + + return 0; +} + +static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + ath6kl_tgt_stats_event(wmi->parent_dev, datap, len); + + return 0; +} + +static u8 ath6kl_wmi_get_upper_threshold(s16 rssi, + struct sq_threshold_params *sq_thresh, + u32 size) +{ + u32 index; + u8 threshold = (u8) sq_thresh->upper_threshold[size - 1]; + + /* The list is already in sorted order. Get the next lower value */ + for (index = 0; index < size; index++) { + if (rssi < sq_thresh->upper_threshold[index]) { + threshold = (u8) sq_thresh->upper_threshold[index]; + break; + } + } + + return threshold; +} + +static u8 ath6kl_wmi_get_lower_threshold(s16 rssi, + struct sq_threshold_params *sq_thresh, + u32 size) +{ + u32 index; + u8 threshold = (u8) sq_thresh->lower_threshold[size - 1]; + + /* The list is already in sorted order. Get the next lower value */ + for (index = 0; index < size; index++) { + if (rssi > sq_thresh->lower_threshold[index]) { + threshold = (u8) sq_thresh->lower_threshold[index]; + break; + } + } + + return threshold; +} + +static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi, + struct wmi_rssi_threshold_params_cmd *rssi_cmd) +{ + struct sk_buff *skb; + struct wmi_rssi_threshold_params_cmd *cmd; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data; + memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd)); + + return ath6kl_wmi_cmd_send(wmi, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG); +} + +static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap, + int len) +{ + struct wmi_rssi_threshold_event *reply; + struct wmi_rssi_threshold_params_cmd cmd; + struct sq_threshold_params *sq_thresh; + enum wmi_rssi_threshold_val new_threshold; + u8 upper_rssi_threshold, lower_rssi_threshold; + s16 rssi; + int ret; + + if (len < sizeof(struct wmi_rssi_threshold_event)) + return -EINVAL; + + reply = (struct wmi_rssi_threshold_event *) datap; + new_threshold = (enum wmi_rssi_threshold_val) reply->range; + rssi = a_sle16_to_cpu(reply->rssi); + + sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI]; + + /* + * Identify the threshold breached and communicate that to the app. + * After that install a new set of thresholds based on the signal + * quality reported by the target + */ + if (new_threshold) { + /* Upper threshold breached */ + if (rssi < sq_thresh->upper_threshold[0]) { + ath6kl_dbg(ATH6KL_DBG_WMI, + "spurious upper rssi threshold event: %d\n", + rssi); + } else if ((rssi < sq_thresh->upper_threshold[1]) && + (rssi >= sq_thresh->upper_threshold[0])) { + new_threshold = WMI_RSSI_THRESHOLD1_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[2]) && + (rssi >= sq_thresh->upper_threshold[1])) { + new_threshold = WMI_RSSI_THRESHOLD2_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[3]) && + (rssi >= sq_thresh->upper_threshold[2])) { + new_threshold = WMI_RSSI_THRESHOLD3_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[4]) && + (rssi >= sq_thresh->upper_threshold[3])) { + new_threshold = WMI_RSSI_THRESHOLD4_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[5]) && + (rssi >= sq_thresh->upper_threshold[4])) { + new_threshold = WMI_RSSI_THRESHOLD5_ABOVE; + } else if (rssi >= sq_thresh->upper_threshold[5]) { + new_threshold = WMI_RSSI_THRESHOLD6_ABOVE; + } + } else { + /* Lower threshold breached */ + if (rssi > sq_thresh->lower_threshold[0]) { + ath6kl_dbg(ATH6KL_DBG_WMI, + "spurious lower rssi threshold event: %d %d\n", + rssi, sq_thresh->lower_threshold[0]); + } else if ((rssi > sq_thresh->lower_threshold[1]) && + (rssi <= sq_thresh->lower_threshold[0])) { + new_threshold = WMI_RSSI_THRESHOLD6_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[2]) && + (rssi <= sq_thresh->lower_threshold[1])) { + new_threshold = WMI_RSSI_THRESHOLD5_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[3]) && + (rssi <= sq_thresh->lower_threshold[2])) { + new_threshold = WMI_RSSI_THRESHOLD4_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[4]) && + (rssi <= sq_thresh->lower_threshold[3])) { + new_threshold = WMI_RSSI_THRESHOLD3_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[5]) && + (rssi <= sq_thresh->lower_threshold[4])) { + new_threshold = WMI_RSSI_THRESHOLD2_BELOW; + } else if (rssi <= sq_thresh->lower_threshold[5]) { + new_threshold = WMI_RSSI_THRESHOLD1_BELOW; + } + } + + /* Calculate and install the next set of thresholds */ + lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh, + sq_thresh->lower_threshold_valid_count); + upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh, + sq_thresh->upper_threshold_valid_count); + + /* Issue a wmi command to install the thresholds */ + cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold); + cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold); + cmd.weight = sq_thresh->weight; + cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval); + + ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd); + if (ret) { + ath6kl_err("unable to configure rssi thresholds\n"); + return -EIO; + } + + return 0; +} + +static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_cac_event *reply; + struct ieee80211_tspec_ie *ts; + u16 active_tsids, tsinfo; + u8 tsid, index; + u8 ts_id; + + if (len < sizeof(struct wmi_cac_event)) + return -EINVAL; + + reply = (struct wmi_cac_event *) datap; + + if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && + (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) { + + ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion); + tsinfo = le16_to_cpu(ts->tsinfo); + tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) & + IEEE80211_WMM_IE_TSPEC_TID_MASK; + + ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, tsid); + } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { + /* + * Following assumes that there is only one outstanding + * ADDTS request when this event is received + */ + spin_lock_bh(&wmi->lock); + active_tsids = wmi->stream_exist_for_ac[reply->ac]; + spin_unlock_bh(&wmi->lock); + + for (index = 0; index < sizeof(active_tsids) * 8; index++) { + if ((active_tsids >> index) & 1) + break; + } + if (index < (sizeof(active_tsids) * 8)) + ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, index); + } + + /* + * Clear active tsids and Add missing handling + * for delete qos stream from AP + */ + else if (reply->cac_indication == CAC_INDICATION_DELETE) { + + ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion); + tsinfo = le16_to_cpu(ts->tsinfo); + ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) & + IEEE80211_WMM_IE_TSPEC_TID_MASK); + + spin_lock_bh(&wmi->lock); + wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id); + active_tsids = wmi->stream_exist_for_ac[reply->ac]; + spin_unlock_bh(&wmi->lock); + + /* Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if (!active_tsids) { + ath6kl_indicate_tx_activity(wmi->parent_dev, reply->ac, + false); + wmi->fat_pipe_exist &= ~(1 << reply->ac); + } + } + + return 0; +} + +static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi, + struct wmi_snr_threshold_params_cmd *snr_cmd) +{ + struct sk_buff *skb; + struct wmi_snr_threshold_params_cmd *cmd; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_snr_threshold_params_cmd *) skb->data; + memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd)); + + return ath6kl_wmi_cmd_send(wmi, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG); +} + +static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap, + int len) +{ + struct wmi_snr_threshold_event *reply; + struct sq_threshold_params *sq_thresh; + struct wmi_snr_threshold_params_cmd cmd; + enum wmi_snr_threshold_val new_threshold; + u8 upper_snr_threshold, lower_snr_threshold; + s16 snr; + int ret; + + if (len < sizeof(struct wmi_snr_threshold_event)) + return -EINVAL; + + reply = (struct wmi_snr_threshold_event *) datap; + + new_threshold = (enum wmi_snr_threshold_val) reply->range; + snr = reply->snr; + + sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR]; + + /* + * Identify the threshold breached and communicate that to the app. + * After that install a new set of thresholds based on the signal + * quality reported by the target. + */ + if (new_threshold) { + /* Upper threshold breached */ + if (snr < sq_thresh->upper_threshold[0]) { + ath6kl_dbg(ATH6KL_DBG_WMI, + "spurious upper snr threshold event: %d\n", + snr); + } else if ((snr < sq_thresh->upper_threshold[1]) && + (snr >= sq_thresh->upper_threshold[0])) { + new_threshold = WMI_SNR_THRESHOLD1_ABOVE; + } else if ((snr < sq_thresh->upper_threshold[2]) && + (snr >= sq_thresh->upper_threshold[1])) { + new_threshold = WMI_SNR_THRESHOLD2_ABOVE; + } else if ((snr < sq_thresh->upper_threshold[3]) && + (snr >= sq_thresh->upper_threshold[2])) { + new_threshold = WMI_SNR_THRESHOLD3_ABOVE; + } else if (snr >= sq_thresh->upper_threshold[3]) { + new_threshold = WMI_SNR_THRESHOLD4_ABOVE; + } + } else { + /* Lower threshold breached */ + if (snr > sq_thresh->lower_threshold[0]) { + ath6kl_dbg(ATH6KL_DBG_WMI, + "spurious lower snr threshold event: %d\n", + sq_thresh->lower_threshold[0]); + } else if ((snr > sq_thresh->lower_threshold[1]) && + (snr <= sq_thresh->lower_threshold[0])) { + new_threshold = WMI_SNR_THRESHOLD4_BELOW; + } else if ((snr > sq_thresh->lower_threshold[2]) && + (snr <= sq_thresh->lower_threshold[1])) { + new_threshold = WMI_SNR_THRESHOLD3_BELOW; + } else if ((snr > sq_thresh->lower_threshold[3]) && + (snr <= sq_thresh->lower_threshold[2])) { + new_threshold = WMI_SNR_THRESHOLD2_BELOW; + } else if (snr <= sq_thresh->lower_threshold[3]) { + new_threshold = WMI_SNR_THRESHOLD1_BELOW; + } + } + + /* Calculate and install the next set of thresholds */ + lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh, + sq_thresh->lower_threshold_valid_count); + upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh, + sq_thresh->upper_threshold_valid_count); + + /* Issue a wmi command to install the thresholds */ + cmd.thresh_above1_val = upper_snr_threshold; + cmd.thresh_below1_val = lower_snr_threshold; + cmd.weight = sq_thresh->weight; + cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval); + + ath6kl_dbg(ATH6KL_DBG_WMI, + "snr: %d, threshold: %d, lower: %d, upper: %d\n", + snr, new_threshold, + lower_snr_threshold, upper_snr_threshold); + + ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd); + if (ret) { + ath6kl_err("unable to configure snr threshold\n"); + return -EIO; + } + + return 0; +} + +static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + u16 ap_info_entry_size; + struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap; + struct wmi_ap_info_v1 *ap_info_v1; + u8 index; + + if (len < sizeof(struct wmi_aplist_event) || + ev->ap_list_ver != APLIST_VER1) + return -EINVAL; + + ap_info_entry_size = sizeof(struct wmi_ap_info_v1); + ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list; + + ath6kl_dbg(ATH6KL_DBG_WMI, + "number of APs in aplist event: %d\n", ev->num_ap); + + if (len < (int) (sizeof(struct wmi_aplist_event) + + (ev->num_ap - 1) * ap_info_entry_size)) + return -EINVAL; + + /* AP list version 1 contents */ + for (index = 0; index < ev->num_ap; index++) { + ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n", + index, ap_info_v1->bssid, ap_info_v1->channel); + ap_info_v1++; + } + + return 0; +} + +int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, + enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag) +{ + struct wmi_cmd_hdr *cmd_hdr; + enum htc_endpoint_id ep_id = wmi->ep_id; + int ret; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + if (sync_flag >= END_WMIFLAG) { + dev_kfree_skb(skb); + return -EINVAL; + } + + if ((sync_flag == SYNC_BEFORE_WMIFLAG) || + (sync_flag == SYNC_BOTH_WMIFLAG)) { + /* + * Make sure all data currently queued is transmitted before + * the cmd execution. Establish a new sync point. + */ + ath6kl_wmi_sync_point(wmi); + } + + skb_push(skb, sizeof(struct wmi_cmd_hdr)); + + cmd_hdr = (struct wmi_cmd_hdr *) skb->data; + cmd_hdr->cmd_id = cpu_to_le16(cmd_id); + cmd_hdr->info1 = 0; /* added for virtual interface */ + + /* Only for OPT_TX_CMD, use BE endpoint. */ + if (cmd_id == WMI_OPT_TX_FRAME_CMDID) { + ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE, + false, false, 0, NULL); + if (ret) { + dev_kfree_skb(skb); + return ret; + } + ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, WMM_AC_BE); + } + + ath6kl_control_tx(wmi->parent_dev, skb, ep_id); + + if ((sync_flag == SYNC_AFTER_WMIFLAG) || + (sync_flag == SYNC_BOTH_WMIFLAG)) { + /* + * Make sure all new data queued waits for the command to + * execute. Establish a new sync point. + */ + ath6kl_wmi_sync_point(wmi); + } + + return 0; +} + +int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type, + enum dot11_auth_mode dot11_auth_mode, + enum auth_mode auth_mode, + enum crypto_type pairwise_crypto, + u8 pairwise_crypto_len, + enum crypto_type group_crypto, + u8 group_crypto_len, int ssid_len, u8 *ssid, + u8 *bssid, u16 channel, u32 ctrl_flags) +{ + struct sk_buff *skb; + struct wmi_connect_cmd *cc; + int ret; + + wmi->traffic_class = 100; + + if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT)) + return -EINVAL; + + if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT)) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd)); + if (!skb) + return -ENOMEM; + + cc = (struct wmi_connect_cmd *) skb->data; + + if (ssid_len) + memcpy(cc->ssid, ssid, ssid_len); + + cc->ssid_len = ssid_len; + cc->nw_type = nw_type; + cc->dot11_auth_mode = dot11_auth_mode; + cc->auth_mode = auth_mode; + cc->prwise_crypto_type = pairwise_crypto; + cc->prwise_crypto_len = pairwise_crypto_len; + cc->grp_crypto_type = group_crypto; + cc->grp_crypto_len = group_crypto_len; + cc->ch = cpu_to_le16(channel); + cc->ctrl_flags = cpu_to_le32(ctrl_flags); + + if (bssid != NULL) + memcpy(cc->bssid, bssid, ETH_ALEN); + + wmi->pair_crypto_type = pairwise_crypto; + wmi->grp_crypto_type = group_crypto; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG); + + return ret; +} + +int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel) +{ + struct sk_buff *skb; + struct wmi_reconnect_cmd *cc; + int ret; + + wmi->traffic_class = 100; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd)); + if (!skb) + return -ENOMEM; + + cc = (struct wmi_reconnect_cmd *) skb->data; + cc->channel = cpu_to_le16(channel); + + if (bssid != NULL) + memcpy(cc->bssid, bssid, ETH_ALEN); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RECONNECT_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + +int ath6kl_wmi_disconnect_cmd(struct wmi *wmi) +{ + int ret; + + wmi->traffic_class = 100; + + /* Disconnect command does not need to do a SYNC before. */ + ret = ath6kl_wmi_simple_cmd(wmi, WMI_DISCONNECT_CMDID); + + return ret; +} + +int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, + u32 force_fgscan, u32 is_legacy, + u32 home_dwell_time, u32 force_scan_interval, + s8 num_chan, u16 *ch_list) +{ + struct sk_buff *skb; + struct wmi_start_scan_cmd *sc; + s8 size; + int ret; + + size = sizeof(struct wmi_start_scan_cmd); + + if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN)) + return -EINVAL; + + if (num_chan > WMI_MAX_CHANNELS) + return -EINVAL; + + if (num_chan) + size += sizeof(u16) * (num_chan - 1); + + skb = ath6kl_wmi_get_new_buf(size); + if (!skb) + return -ENOMEM; + + sc = (struct wmi_start_scan_cmd *) skb->data; + sc->scan_type = scan_type; + sc->force_fg_scan = cpu_to_le32(force_fgscan); + sc->is_legacy = cpu_to_le32(is_legacy); + sc->home_dwell_time = cpu_to_le32(home_dwell_time); + sc->force_scan_intvl = cpu_to_le32(force_scan_interval); + sc->num_ch = num_chan; + + if (num_chan) + memcpy(sc->ch_list, ch_list, num_chan * sizeof(u16)); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + +int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec, + u16 fg_end_sec, u16 bg_sec, + u16 minact_chdw_msec, u16 maxact_chdw_msec, + u16 pas_chdw_msec, u8 short_scan_ratio, + u8 scan_ctrl_flag, u32 max_dfsch_act_time, + u16 maxact_scan_per_ssid) +{ + struct sk_buff *skb; + struct wmi_scan_params_cmd *sc; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*sc)); + if (!skb) + return -ENOMEM; + + sc = (struct wmi_scan_params_cmd *) skb->data; + sc->fg_start_period = cpu_to_le16(fg_start_sec); + sc->fg_end_period = cpu_to_le16(fg_end_sec); + sc->bg_period = cpu_to_le16(bg_sec); + sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec); + sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec); + sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec); + sc->short_scan_ratio = short_scan_ratio; + sc->scan_ctrl_flags = scan_ctrl_flag; + sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time); + sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_SCAN_PARAMS_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask) +{ + struct sk_buff *skb; + struct wmi_bss_filter_cmd *cmd; + int ret; + + if (filter >= LAST_BSS_FILTER) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_bss_filter_cmd *) skb->data; + cmd->bss_filter = filter; + cmd->ie_mask = cpu_to_le32(ie_mask); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_BSS_FILTER_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag, + u8 ssid_len, u8 *ssid) +{ + struct sk_buff *skb; + struct wmi_probed_ssid_cmd *cmd; + int ret; + + if (index > MAX_PROBED_SSID_INDEX) + return -EINVAL; + + if (ssid_len > sizeof(cmd->ssid)) + return -EINVAL; + + if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0)) + return -EINVAL; + + if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len) + return -EINVAL; + + if (flag & SPECIFIC_SSID_FLAG) + wmi->is_probe_ssid = true; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_probed_ssid_cmd *) skb->data; + cmd->entry_index = index; + cmd->flag = flag; + cmd->ssid_len = ssid_len; + memcpy(cmd->ssid, ssid, ssid_len); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PROBED_SSID_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval, + u16 listen_beacons) +{ + struct sk_buff *skb; + struct wmi_listen_int_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_listen_int_cmd *) skb->data; + cmd->listen_intvl = cpu_to_le16(listen_interval); + cmd->num_beacons = cpu_to_le16(listen_beacons); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LISTEN_INT_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode) +{ + struct sk_buff *skb; + struct wmi_power_mode_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_power_mode_cmd *) skb->data; + cmd->pwr_mode = pwr_mode; + wmi->pwr_mode = pwr_mode; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_MODE_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period, + u16 ps_poll_num, u16 dtim_policy, + u16 tx_wakeup_policy, u16 num_tx_to_wakeup, + u16 ps_fail_event_policy) +{ + struct sk_buff *skb; + struct wmi_power_params_cmd *pm; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*pm)); + if (!skb) + return -ENOMEM; + + pm = (struct wmi_power_params_cmd *)skb->data; + pm->idle_period = cpu_to_le16(idle_period); + pm->pspoll_number = cpu_to_le16(ps_poll_num); + pm->dtim_policy = cpu_to_le16(dtim_policy); + pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy); + pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup); + pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_PARAMS_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout) +{ + struct sk_buff *skb; + struct wmi_disc_timeout_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_disc_timeout_cmd *) skb->data; + cmd->discon_timeout = timeout; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, + enum crypto_type key_type, + u8 key_usage, u8 key_len, + u8 *key_rsc, u8 *key_material, + u8 key_op_ctrl, u8 *mac_addr, + enum wmi_sync_flag sync_flag) +{ + struct sk_buff *skb; + struct wmi_add_cipher_key_cmd *cmd; + int ret; + + if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || + (key_material == NULL)) + return -EINVAL; + + if ((WEP_CRYPT != key_type) && (NULL == key_rsc)) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_add_cipher_key_cmd *) skb->data; + cmd->key_index = key_index; + cmd->key_type = key_type; + cmd->key_usage = key_usage; + cmd->key_len = key_len; + memcpy(cmd->key, key_material, key_len); + + if (key_rsc != NULL) + memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc)); + + cmd->key_op_ctrl = key_op_ctrl; + + if (mac_addr) + memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_CIPHER_KEY_CMDID, + sync_flag); + + return ret; +} + +int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk) +{ + struct sk_buff *skb; + struct wmi_add_krk_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_add_krk_cmd *) skb->data; + memcpy(cmd->krk, krk, WMI_KRK_LEN); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG); + + return ret; +} + +int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index) +{ + struct sk_buff *skb; + struct wmi_delete_cipher_key_cmd *cmd; + int ret; + + if (key_index > WMI_MAX_KEY_INDEX) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_delete_cipher_key_cmd *) skb->data; + cmd->key_index = key_index; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_CIPHER_KEY_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + +int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid, + const u8 *pmkid, bool set) +{ + struct sk_buff *skb; + struct wmi_setpmkid_cmd *cmd; + int ret; + + if (bssid == NULL) + return -EINVAL; + + if (set && pmkid == NULL) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_setpmkid_cmd *) skb->data; + memcpy(cmd->bssid, bssid, ETH_ALEN); + if (set) { + memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid)); + cmd->enable = PMKID_ENABLE; + } else { + memset(cmd->pmkid, 0, sizeof(cmd->pmkid)); + cmd->enable = PMKID_DISABLE; + } + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PMKID_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + +static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb, + enum htc_endpoint_id ep_id) +{ + struct wmi_data_hdr *data_hdr; + int ret; + + if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) + return -EINVAL; + + skb_push(skb, sizeof(struct wmi_data_hdr)); + + data_hdr = (struct wmi_data_hdr *) skb->data; + data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT; + data_hdr->info3 = 0; + + ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id); + + return ret; +} + +static int ath6kl_wmi_sync_point(struct wmi *wmi) +{ + struct sk_buff *skb; + struct wmi_sync_cmd *cmd; + struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC]; + enum htc_endpoint_id ep_id; + u8 index, num_pri_streams = 0; + int ret = 0; + + memset(data_sync_bufs, 0, sizeof(data_sync_bufs)); + + spin_lock_bh(&wmi->lock); + + for (index = 0; index < WMM_NUM_AC; index++) { + if (wmi->fat_pipe_exist & (1 << index)) { + num_pri_streams++; + data_sync_bufs[num_pri_streams - 1].traffic_class = + index; + } + } + + spin_unlock_bh(&wmi->lock); + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) { + ret = -ENOMEM; + goto free_skb; + } + + cmd = (struct wmi_sync_cmd *) skb->data; + + /* + * In the SYNC cmd sent on the control Ep, send a bitmap + * of the data eps on which the Data Sync will be sent + */ + cmd->data_sync_map = wmi->fat_pipe_exist; + + for (index = 0; index < num_pri_streams; index++) { + data_sync_bufs[index].skb = ath6kl_buf_alloc(0); + if (data_sync_bufs[index].skb == NULL) { + ret = -ENOMEM; + break; + } + } + + /* + * If buffer allocation for any of the dataSync fails, + * then do not send the Synchronize cmd on the control ep + */ + if (ret) + goto free_skb; + + /* + * Send sync cmd followed by sync data messages on all + * endpoints being used + */ + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SYNCHRONIZE_CMDID, + NO_SYNC_WMIFLAG); + + if (ret) + goto free_skb; + + /* cmd buffer sent, we no longer own it */ + skb = NULL; + + for (index = 0; index < num_pri_streams; index++) { + + if (WARN_ON(!data_sync_bufs[index].skb)) + break; + + ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, + data_sync_bufs[index]. + traffic_class); + ret = + ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb, + ep_id); + + if (ret) + break; + + data_sync_bufs[index].skb = NULL; + } + +free_skb: + /* free up any resources left over (possibly due to an error) */ + if (skb) + dev_kfree_skb(skb); + + for (index = 0; index < num_pri_streams; index++) { + if (data_sync_bufs[index].skb != NULL) { + dev_kfree_skb((struct sk_buff *)data_sync_bufs[index]. + skb); + } + } + + return ret; +} + +int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, + struct wmi_create_pstream_cmd *params) +{ + struct sk_buff *skb; + struct wmi_create_pstream_cmd *cmd; + u8 fatpipe_exist_for_ac = 0; + s32 min_phy = 0; + s32 nominal_phy = 0; + int ret; + + if (!((params->user_pri < 8) && + (params->user_pri <= 0x7) && + (up_to_ac[params->user_pri & 0x7] == params->traffic_class) && + (params->traffic_direc == UPLINK_TRAFFIC || + params->traffic_direc == DNLINK_TRAFFIC || + params->traffic_direc == BIDIR_TRAFFIC) && + (params->traffic_type == TRAFFIC_TYPE_APERIODIC || + params->traffic_type == TRAFFIC_TYPE_PERIODIC) && + (params->voice_psc_cap == DISABLE_FOR_THIS_AC || + params->voice_psc_cap == ENABLE_FOR_THIS_AC || + params->voice_psc_cap == ENABLE_FOR_ALL_AC) && + (params->tsid == WMI_IMPLICIT_PSTREAM || + params->tsid <= WMI_MAX_THINSTREAM))) { + return -EINVAL; + } + + /* + * Check nominal PHY rate is >= minimalPHY, + * so that DUT can allow TSRS IE + */ + + /* Get the physical rate (units of bps) */ + min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000); + + /* Check minimal phy < nominal phy rate */ + if (params->nominal_phy >= min_phy) { + /* unit of 500 kbps */ + nominal_phy = (params->nominal_phy * 1000) / 500; + ath6kl_dbg(ATH6KL_DBG_WMI, + "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n", + min_phy, nominal_phy); + + params->nominal_phy = nominal_phy; + } else { + params->nominal_phy = 0; + } + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + ath6kl_dbg(ATH6KL_DBG_WMI, + "sending create_pstream_cmd: ac=%d tsid:%d\n", + params->traffic_class, params->tsid); + + cmd = (struct wmi_create_pstream_cmd *) skb->data; + memcpy(cmd, params, sizeof(*cmd)); + + /* This is an implicitly created Fat pipe */ + if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) { + spin_lock_bh(&wmi->lock); + fatpipe_exist_for_ac = (wmi->fat_pipe_exist & + (1 << params->traffic_class)); + wmi->fat_pipe_exist |= (1 << params->traffic_class); + spin_unlock_bh(&wmi->lock); + } else { + /* explicitly created thin stream within a fat pipe */ + spin_lock_bh(&wmi->lock); + fatpipe_exist_for_ac = (wmi->fat_pipe_exist & + (1 << params->traffic_class)); + wmi->stream_exist_for_ac[params->traffic_class] |= + (1 << params->tsid); + /* + * If a thinstream becomes active, the fat pipe automatically + * becomes active + */ + wmi->fat_pipe_exist |= (1 << params->traffic_class); + spin_unlock_bh(&wmi->lock); + } + + /* + * Indicate activty change to driver layer only if this is the + * first TSID to get created in this AC explicitly or an implicit + * fat pipe is getting created. + */ + if (!fatpipe_exist_for_ac) + ath6kl_indicate_tx_activity(wmi->parent_dev, + params->traffic_class, true); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CREATE_PSTREAM_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid) +{ + struct sk_buff *skb; + struct wmi_delete_pstream_cmd *cmd; + u16 active_tsids = 0; + int ret; + + if (traffic_class > 3) { + ath6kl_err("invalid traffic class: %d\n", traffic_class); + return -EINVAL; + } + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_delete_pstream_cmd *) skb->data; + cmd->traffic_class = traffic_class; + cmd->tsid = tsid; + + spin_lock_bh(&wmi->lock); + active_tsids = wmi->stream_exist_for_ac[traffic_class]; + spin_unlock_bh(&wmi->lock); + + if (!(active_tsids & (1 << tsid))) { + dev_kfree_skb(skb); + ath6kl_dbg(ATH6KL_DBG_WMI, + "TSID %d doesn't exist for traffic class: %d\n", + tsid, traffic_class); + return -ENODATA; + } + + ath6kl_dbg(ATH6KL_DBG_WMI, + "sending delete_pstream_cmd: traffic class: %d tsid=%d\n", + traffic_class, tsid); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_PSTREAM_CMDID, + SYNC_BEFORE_WMIFLAG); + + spin_lock_bh(&wmi->lock); + wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid); + active_tsids = wmi->stream_exist_for_ac[traffic_class]; + spin_unlock_bh(&wmi->lock); + + /* + * Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if (!active_tsids) { + ath6kl_indicate_tx_activity(wmi->parent_dev, + traffic_class, false); + wmi->fat_pipe_exist &= ~(1 << traffic_class); + } + + return ret; +} + +int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) +{ + struct sk_buff *skb; + struct wmi_set_ip_cmd *cmd; + int ret; + + /* Multicast address are not valid */ + if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || + (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_ip_cmd *) skb->data; + memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG); + return ret; +} + +static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap, + int len) +{ + if (len < sizeof(struct wmi_get_wow_list_reply)) + return -EINVAL; + + return 0; +} + +static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb, + enum wmix_command_id cmd_id, + enum wmi_sync_flag sync_flag) +{ + struct wmix_cmd_hdr *cmd_hdr; + int ret; + + skb_push(skb, sizeof(struct wmix_cmd_hdr)); + + cmd_hdr = (struct wmix_cmd_hdr *) skb->data; + cmd_hdr->cmd_id = cpu_to_le32(cmd_id); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_EXTENSION_CMDID, sync_flag); + + return ret; +} + +int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source) +{ + struct sk_buff *skb; + struct wmix_hb_challenge_resp_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data; + cmd->cookie = cpu_to_le32(cookie); + cmd->source = cpu_to_le32(source); + + ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_get_stats_cmd(struct wmi *wmi) +{ + return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID); +} + +int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM) +{ + struct sk_buff *skb; + struct wmi_set_tx_pwr_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_tx_pwr_cmd *) skb->data; + cmd->dbM = dbM; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_TX_PWR_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + +int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi) +{ + return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID); +} + +void ath6kl_wmi_get_current_bssid(struct wmi *wmi, u8 *bssid) +{ + if (bssid) + memcpy(bssid, wmi->bssid, ETH_ALEN); +} + +int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy) +{ + struct sk_buff *skb; + struct wmi_set_lpreamble_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_lpreamble_cmd *) skb->data; + cmd->status = status; + cmd->preamble_policy = preamble_policy; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LPREAMBLE_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold) +{ + struct sk_buff *skb; + struct wmi_set_rts_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_rts_cmd *) skb->data; + cmd->threshold = cpu_to_le16(threshold); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_RTS_CMDID, NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg) +{ + struct sk_buff *skb; + struct wmi_set_wmm_txop_cmd *cmd; + int ret; + + if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED))) + return -EINVAL; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_wmm_txop_cmd *) skb->data; + cmd->txop_enable = cfg; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_WMM_TXOP_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl) +{ + struct sk_buff *skb; + struct wmi_set_keepalive_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_keepalive_cmd *) skb->data; + cmd->keep_alive_intvl = keep_alive_intvl; + wmi->keep_alive_intvl = keep_alive_intvl; + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + +s32 ath6kl_wmi_get_rate(s8 rate_index) +{ + if (rate_index == RATE_AUTO) + return 0; + + return wmi_rate_tbl[(u32) rate_index][0]; +} + +void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss) +{ + if (bss) + wlan_node_return(&wmi->scan_table, bss); +} + +struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 * ssid, + u32 ssid_len, bool is_wpa2, + bool match_ssid) +{ + struct bss *node = NULL; + + node = wlan_find_ssid_node(&wmi->scan_table, ssid, + ssid_len, is_wpa2, match_ssid); + return node; +} + +struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 * mac_addr) +{ + struct bss *ni = NULL; + + ni = wlan_find_node(&wmi->scan_table, mac_addr); + + return ni; +} + +void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr) +{ + struct bss *ni = NULL; + + ni = wlan_find_node(&wmi->scan_table, mac_addr); + if (ni != NULL) + wlan_node_reclaim(&wmi->scan_table, ni); + + return; +} + +static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, + u32 len) +{ + struct wmi_pmkid_list_reply *reply; + u32 expected_len; + + if (len < sizeof(struct wmi_pmkid_list_reply)) + return -EINVAL; + + reply = (struct wmi_pmkid_list_reply *)datap; + expected_len = sizeof(reply->num_pmkid) + + le32_to_cpu(reply->num_pmkid) * WMI_PMKID_LEN; + + if (len < expected_len) + return -EINVAL; + + return 0; +} + +static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap; + + aggr_recv_addba_req_evt(wmi->parent_dev, cmd->tid, + le16_to_cpu(cmd->st_seq_no), cmd->win_sz); + + return 0; +} + +static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap; + + aggr_recv_delba_req_evt(wmi->parent_dev, cmd->tid); + + return 0; +} + +/* AP mode functions */ +static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct wmi_pspoll_event *ev; + + if (len < sizeof(struct wmi_pspoll_event)) + return -EINVAL; + + ev = (struct wmi_pspoll_event *) datap; + + ath6kl_pspoll_event(wmi->parent_dev, le16_to_cpu(ev->aid)); + + return 0; +} + +static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + ath6kl_dtimexpiry_event(wmi->parent_dev); + + return 0; +} + +int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag) +{ + struct sk_buff *skb; + struct wmi_ap_set_pvb_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_ap_set_pvb_cmd *) skb->data; + cmd->aid = cpu_to_le16(aid); + cmd->flag = cpu_to_le32(flag); + + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID, + NO_SYNC_WMIFLAG); + + return 0; +} + +int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver, + bool rx_dot11_hdr, bool defrag_on_host) +{ + struct sk_buff *skb; + struct wmi_rx_frame_format_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_rx_frame_format_cmd *) skb->data; + cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0; + cmd->defrag_on_host = defrag_on_host ? 1 : 0; + cmd->meta_ver = rx_meta_ver; + + /* Delete the local aggr state, on host */ + ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RX_FRAME_FORMAT_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + +static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) +{ + struct wmix_cmd_hdr *cmd; + u32 len; + u16 id; + u8 *datap; + int ret = 0; + + if (skb->len < sizeof(struct wmix_cmd_hdr)) { + ath6kl_err("bad packet 1\n"); + wmi->stat.cmd_len_err++; + return -EINVAL; + } + + cmd = (struct wmix_cmd_hdr *) skb->data; + id = le32_to_cpu(cmd->cmd_id); + + skb_pull(skb, sizeof(struct wmix_cmd_hdr)); + + datap = skb->data; + len = skb->len; + + switch (id) { + case WMIX_HB_CHALLENGE_RESP_EVENTID: + break; + case WMIX_DBGLOG_EVENTID: + break; + default: + ath6kl_err("unknown cmd id 0x%x\n", id); + wmi->stat.cmd_id_err++; + ret = -EINVAL; + break; + } + + return ret; +} + +/* Control Path */ +int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) +{ + struct wmi_cmd_hdr *cmd; + u32 len; + u16 id; + u8 *datap; + int ret = 0; + + if (WARN_ON(skb == NULL)) + return -EINVAL; + + if (skb->len < sizeof(struct wmi_cmd_hdr)) { + ath6kl_err("bad packet 1\n"); + dev_kfree_skb(skb); + wmi->stat.cmd_len_err++; + return -EINVAL; + } + + cmd = (struct wmi_cmd_hdr *) skb->data; + id = le16_to_cpu(cmd->cmd_id); + + skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + + datap = skb->data; + len = skb->len; + + ath6kl_dbg(ATH6KL_DBG_WMI, "%s: wmi id: %d\n", __func__, id); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "msg payload ", datap, len); + + switch (id) { + case WMI_GET_BITRATE_CMDID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n"); + ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len); + break; + case WMI_GET_CHANNEL_LIST_CMDID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n"); + ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len); + break; + case WMI_GET_TX_PWR_CMDID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n"); + ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len); + break; + case WMI_READY_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n"); + ret = ath6kl_wmi_ready_event_rx(wmi, datap, len); + break; + case WMI_CONNECT_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n"); + ret = ath6kl_wmi_connect_event_rx(wmi, datap, len); + break; + case WMI_DISCONNECT_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n"); + ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len); + break; + case WMI_PEER_NODE_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n"); + ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len); + break; + case WMI_TKIP_MICERR_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n"); + ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len); + break; + case WMI_BSSINFO_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n"); + ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(skb, datap); + ret = ath6kl_wmi_bssinfo_event_rx(wmi, skb->data, skb->len); + break; + case WMI_REGDOMAIN_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); + break; + case WMI_PSTREAM_TIMEOUT_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); + ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len); + break; + case WMI_NEIGHBOR_REPORT_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n"); + break; + case WMI_SCAN_COMPLETE_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n"); + ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len); + break; + case WMI_CMDERROR_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n"); + ret = ath6kl_wmi_error_event_rx(wmi, datap, len); + break; + case WMI_REPORT_STATISTICS_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n"); + ret = ath6kl_wmi_stats_event_rx(wmi, datap, len); + break; + case WMI_RSSI_THRESHOLD_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n"); + ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len); + break; + case WMI_ERROR_REPORT_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n"); + break; + case WMI_OPT_RX_FRAME_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n"); + ret = ath6kl_wmi_opt_frame_event_rx(wmi, datap, len); + break; + case WMI_REPORT_ROAM_TBL_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n"); + break; + case WMI_EXTENSION_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n"); + ret = ath6kl_wmi_control_rx_xtnd(wmi, skb); + break; + case WMI_CAC_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n"); + ret = ath6kl_wmi_cac_event_rx(wmi, datap, len); + break; + case WMI_CHANNEL_CHANGE_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n"); + break; + case WMI_REPORT_ROAM_DATA_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n"); + break; + case WMI_GET_FIXRATES_CMDID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); + ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len); + break; + case WMI_TX_RETRY_ERR_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n"); + break; + case WMI_SNR_THRESHOLD_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n"); + ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len); + break; + case WMI_LQ_THRESHOLD_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n"); + break; + case WMI_APLIST_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n"); + ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len); + break; + case WMI_GET_KEEPALIVE_CMDID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n"); + ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len); + break; + case WMI_GET_WOW_LIST_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n"); + ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len); + break; + case WMI_GET_PMKID_LIST_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n"); + ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len); + break; + case WMI_PSPOLL_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n"); + ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len); + break; + case WMI_DTIMEXPIRY_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n"); + ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len); + break; + case WMI_SET_PARAMS_REPLY_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n"); + break; + case WMI_ADDBA_REQ_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n"); + ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len); + break; + case WMI_ADDBA_RESP_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n"); + break; + case WMI_DELBA_REQ_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n"); + ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len); + break; + case WMI_REPORT_BTCOEX_CONFIG_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, + "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n"); + break; + case WMI_REPORT_BTCOEX_STATS_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, + "WMI_REPORT_BTCOEX_STATS_EVENTID\n"); + break; + case WMI_TX_COMPLETE_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); + ret = ath6kl_wmi_tx_complete_event_rx(datap, len); + break; + default: + ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); + wmi->stat.cmd_id_err++; + ret = -EINVAL; + break; + } + + dev_kfree_skb(skb); + + return ret; +} + +static void ath6kl_wmi_qos_state_init(struct wmi *wmi) +{ + if (!wmi) + return; + + spin_lock_bh(&wmi->lock); + + wmi->fat_pipe_exist = 0; + memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac)); + + spin_unlock_bh(&wmi->lock); +} + +void *ath6kl_wmi_init(void *dev) +{ + struct wmi *wmi; + + wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL); + if (!wmi) + return NULL; + + spin_lock_init(&wmi->lock); + + wmi->parent_dev = dev; + + wlan_node_table_init(wmi, &wmi->scan_table); + ath6kl_wmi_qos_state_init(wmi); + + wmi->pwr_mode = REC_POWER; + wmi->phy_mode = WMI_11G_MODE; + + wmi->pair_crypto_type = NONE_CRYPT; + wmi->grp_crypto_type = NONE_CRYPT; + + wmi->ht_allowed[A_BAND_24GHZ] = 1; + wmi->ht_allowed[A_BAND_5GHZ] = 1; + + return wmi; +} + +void ath6kl_wmi_shutdown(struct wmi *wmi) +{ + if (!wmi) + return; + + wlan_node_table_cleanup(&wmi->scan_table); + kfree(wmi); +} diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h new file mode 100644 index 000000000000..bbaa7049f4a8 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -0,0 +1,2024 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file contains the definitions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all the + * commands and events. Commands are messages from the host to the WM. + * Events and Replies are messages from the WM to the host. + */ + +#ifndef WMI_H +#define WMI_H + +#include <linux/ieee80211.h> + +#include "htc.h" + +#define HTC_PROTOCOL_VERSION 0x0002 +#define WMI_PROTOCOL_VERSION 0x0002 +#define WMI_CONTROL_MSG_MAX_LEN 256 +#define is_ethertype(type_or_len) ((type_or_len) >= 0x0600) + +#define IP_ETHERTYPE 0x0800 + +#define WMI_IMPLICIT_PSTREAM 0xFF +#define WMI_MAX_THINSTREAM 15 + +#define SSID_IE_LEN_INDEX 13 + +/* Host side link management data structures */ +#define SIG_QUALITY_THRESH_LVLS 6 +#define SIG_QUALITY_UPPER_THRESH_LVLS SIG_QUALITY_THRESH_LVLS +#define SIG_QUALITY_LOWER_THRESH_LVLS SIG_QUALITY_THRESH_LVLS + +#define A_BAND_24GHZ 0 +#define A_BAND_5GHZ 1 +#define A_NUM_BANDS 2 + +/* in ms */ +#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 + +/* + * There are no signed versions of __le16 and __le32, so for a temporary + * solution come up with our own version. The idea is from fs/ntfs/types.h. + * + * Use a_ prefix so that it doesn't conflict if we get proper support to + * linux/types.h. + */ +typedef __s16 __bitwise a_sle16; +typedef __s32 __bitwise a_sle32; + +static inline a_sle32 a_cpu_to_sle32(s32 val) +{ + return (__force a_sle32) cpu_to_le32(val); +} + +static inline s32 a_sle32_to_cpu(a_sle32 val) +{ + return le32_to_cpu((__force __le32) val); +} + +static inline a_sle16 a_cpu_to_sle16(s16 val) +{ + return (__force a_sle16) cpu_to_le16(val); +} + +static inline s16 a_sle16_to_cpu(a_sle16 val) +{ + return le16_to_cpu((__force __le16) val); +} + +struct sq_threshold_params { + s16 upper_threshold[SIG_QUALITY_UPPER_THRESH_LVLS]; + s16 lower_threshold[SIG_QUALITY_LOWER_THRESH_LVLS]; + u32 upper_threshold_valid_count; + u32 lower_threshold_valid_count; + u32 polling_interval; + u8 weight; + u8 last_rssi; + u8 last_rssi_poll_event; +}; + +struct wmi_stats { + u32 cmd_len_err; + u32 cmd_id_err; +}; + +struct wmi_data_sync_bufs { + u8 traffic_class; + struct sk_buff *skb; +}; + +/* WMM stream classes */ +#define WMM_NUM_AC 4 +#define WMM_AC_BE 0 /* best effort */ +#define WMM_AC_BK 1 /* background */ +#define WMM_AC_VI 2 /* video */ +#define WMM_AC_VO 3 /* voice */ + +struct wmi { + bool ready; + u16 stream_exist_for_ac[WMM_NUM_AC]; + u8 fat_pipe_exist; + void *parent_dev; + struct wmi_stats stat; + struct ath6kl_node_table scan_table; + u8 bssid[ETH_ALEN]; + u8 pwr_mode; + u8 phy_mode; + u8 keep_alive_intvl; + spinlock_t lock; + enum htc_endpoint_id ep_id; + struct sq_threshold_params + sq_threshld[SIGNAL_QUALITY_METRICS_NUM_MAX]; + enum crypto_type pair_crypto_type; + enum crypto_type grp_crypto_type; + bool is_wmm_enabled; + u8 ht_allowed[A_NUM_BANDS]; + u8 traffic_class; + bool is_probe_ssid; +}; + +struct host_app_area { + u32 wmi_protocol_ver; +}; + +enum wmi_msg_type { + DATA_MSGTYPE = 0x0, + CNTL_MSGTYPE, + SYNC_MSGTYPE, + OPT_MSGTYPE, +}; + +/* + * Macros for operating on WMI_DATA_HDR (info) field + */ + +#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03 +#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0 +#define WMI_DATA_HDR_UP_MASK 0x07 +#define WMI_DATA_HDR_UP_SHIFT 2 + +/* In AP mode, the same bit (b5) is used to indicate Power save state in + * the Rx dir and More data bit state in the tx direction. + */ +#define WMI_DATA_HDR_PS_MASK 0x1 +#define WMI_DATA_HDR_PS_SHIFT 5 + +#define WMI_DATA_HDR_MORE_MASK 0x1 +#define WMI_DATA_HDR_MORE_SHIFT 5 + +enum wmi_data_hdr_data_type { + WMI_DATA_HDR_DATA_TYPE_802_3 = 0, + WMI_DATA_HDR_DATA_TYPE_802_11, + + /* used to be used for the PAL */ + WMI_DATA_HDR_DATA_TYPE_ACL, +}; + +#define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 +#define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 + +/* Macros for operating on WMI_DATA_HDR (info2) field */ +#define WMI_DATA_HDR_SEQNO_MASK 0xFFF +#define WMI_DATA_HDR_SEQNO_SHIFT 0 + +#define WMI_DATA_HDR_AMSDU_MASK 0x1 +#define WMI_DATA_HDR_AMSDU_SHIFT 12 + +#define WMI_DATA_HDR_META_MASK 0x7 +#define WMI_DATA_HDR_META_SHIFT 13 + +struct wmi_data_hdr { + s8 rssi; + + /* + * usage of 'info' field(8-bit): + * + * b1:b0 - WMI_MSG_TYPE + * b4:b3:b2 - UP(tid) + * b5 - Used in AP mode. + * More-data in tx dir, PS in rx. + * b7:b6 - Dot3 header(0), + * Dot11 Header(1), + * ACL data(2) + */ + u8 info; + + /* + * usage of 'info2' field(16-bit): + * + * b11:b0 - seq_no + * b12 - A-MSDU? + * b15:b13 - META_DATA_VERSION 0 - 7 + */ + __le16 info2; + __le16 info3; +} __packed; + +static inline u8 wmi_data_hdr_get_up(struct wmi_data_hdr *dhdr) +{ + return (dhdr->info >> WMI_DATA_HDR_UP_SHIFT) & WMI_DATA_HDR_UP_MASK; +} + +static inline void wmi_data_hdr_set_up(struct wmi_data_hdr *dhdr, + u8 usr_pri) +{ + dhdr->info &= ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT); + dhdr->info |= usr_pri << WMI_DATA_HDR_UP_SHIFT; +} + +static inline u8 wmi_data_hdr_get_dot11(struct wmi_data_hdr *dhdr) +{ + u8 data_type; + + data_type = (dhdr->info >> WMI_DATA_HDR_DATA_TYPE_SHIFT) & + WMI_DATA_HDR_DATA_TYPE_MASK; + return (data_type == WMI_DATA_HDR_DATA_TYPE_802_11); +} + +static inline u16 wmi_data_hdr_get_seqno(struct wmi_data_hdr *dhdr) +{ + return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_SEQNO_SHIFT) & + WMI_DATA_HDR_SEQNO_MASK; +} + +static inline u8 wmi_data_hdr_is_amsdu(struct wmi_data_hdr *dhdr) +{ + return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_AMSDU_SHIFT) & + WMI_DATA_HDR_AMSDU_MASK; +} + +static inline u8 wmi_data_hdr_get_meta(struct wmi_data_hdr *dhdr) +{ + return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_META_SHIFT) & + WMI_DATA_HDR_META_MASK; +} + +/* Tx meta version definitions */ +#define WMI_MAX_TX_META_SZ 12 +#define WMI_META_VERSION_1 0x01 +#define WMI_META_VERSION_2 0x02 + +struct wmi_tx_meta_v1 { + /* packet ID to identify the tx request */ + u8 pkt_id; + + /* rate policy to be used for the tx of this frame */ + u8 rate_plcy_id; +} __packed; + +struct wmi_tx_meta_v2 { + /* + * Offset from start of the WMI header for csum calculation to + * begin. + */ + u8 csum_start; + + /* offset from start of WMI header where final csum goes */ + u8 csum_dest; + + /* no of bytes over which csum is calculated */ + u8 csum_flags; +} __packed; + +struct wmi_rx_meta_v1 { + u8 status; + + /* rate index mapped to rate at which this packet was received. */ + u8 rix; + + /* rssi of packet */ + u8 rssi; + + /* rf channel during packet reception */ + u8 channel; + + __le16 flags; +} __packed; + +struct wmi_rx_meta_v2 { + __le16 csum; + + /* bit 0 set -partial csum valid bit 1 set -test mode */ + u8 csum_flags; +} __packed; + +/* Control Path */ +struct wmi_cmd_hdr { + __le16 cmd_id; + + /* info1 - 16 bits + * b03:b00 - id + * b15:b04 - unused */ + __le16 info1; + + /* for alignment */ + __le16 reserved; +} __packed; + +/* List of WMI commands */ +enum wmi_cmd_id { + WMI_CONNECT_CMDID = 0x0001, + WMI_RECONNECT_CMDID, + WMI_DISCONNECT_CMDID, + WMI_SYNCHRONIZE_CMDID, + WMI_CREATE_PSTREAM_CMDID, + WMI_DELETE_PSTREAM_CMDID, + WMI_START_SCAN_CMDID, + WMI_SET_SCAN_PARAMS_CMDID, + WMI_SET_BSS_FILTER_CMDID, + WMI_SET_PROBED_SSID_CMDID, /* 10 */ + WMI_SET_LISTEN_INT_CMDID, + WMI_SET_BMISS_TIME_CMDID, + WMI_SET_DISC_TIMEOUT_CMDID, + WMI_GET_CHANNEL_LIST_CMDID, + WMI_SET_BEACON_INT_CMDID, + WMI_GET_STATISTICS_CMDID, + WMI_SET_CHANNEL_PARAMS_CMDID, + WMI_SET_POWER_MODE_CMDID, + WMI_SET_IBSS_PM_CAPS_CMDID, + WMI_SET_POWER_PARAMS_CMDID, /* 20 */ + WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, + WMI_ADD_CIPHER_KEY_CMDID, + WMI_DELETE_CIPHER_KEY_CMDID, + WMI_ADD_KRK_CMDID, + WMI_DELETE_KRK_CMDID, + WMI_SET_PMKID_CMDID, + WMI_SET_TX_PWR_CMDID, + WMI_GET_TX_PWR_CMDID, + WMI_SET_ASSOC_INFO_CMDID, + WMI_ADD_BAD_AP_CMDID, /* 30 */ + WMI_DELETE_BAD_AP_CMDID, + WMI_SET_TKIP_COUNTERMEASURES_CMDID, + WMI_RSSI_THRESHOLD_PARAMS_CMDID, + WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, + WMI_SET_ACCESS_PARAMS_CMDID, + WMI_SET_RETRY_LIMITS_CMDID, + WMI_SET_OPT_MODE_CMDID, + WMI_OPT_TX_FRAME_CMDID, + WMI_SET_VOICE_PKT_SIZE_CMDID, + WMI_SET_MAX_SP_LEN_CMDID, /* 40 */ + WMI_SET_ROAM_CTRL_CMDID, + WMI_GET_ROAM_TBL_CMDID, + WMI_GET_ROAM_DATA_CMDID, + WMI_ENABLE_RM_CMDID, + WMI_SET_MAX_OFFHOME_DURATION_CMDID, + WMI_EXTENSION_CMDID, /* Non-wireless extensions */ + WMI_SNR_THRESHOLD_PARAMS_CMDID, + WMI_LQ_THRESHOLD_PARAMS_CMDID, + WMI_SET_LPREAMBLE_CMDID, + WMI_SET_RTS_CMDID, /* 50 */ + WMI_CLR_RSSI_SNR_CMDID, + WMI_SET_FIXRATES_CMDID, + WMI_GET_FIXRATES_CMDID, + WMI_SET_AUTH_MODE_CMDID, + WMI_SET_REASSOC_MODE_CMDID, + WMI_SET_WMM_CMDID, + WMI_SET_WMM_TXOP_CMDID, + WMI_TEST_CMDID, + + /* COEX AR6002 only */ + WMI_SET_BT_STATUS_CMDID, + WMI_SET_BT_PARAMS_CMDID, /* 60 */ + + WMI_SET_KEEPALIVE_CMDID, + WMI_GET_KEEPALIVE_CMDID, + WMI_SET_APPIE_CMDID, + WMI_GET_APPIE_CMDID, + WMI_SET_WSC_STATUS_CMDID, + + /* Wake on Wireless */ + WMI_SET_HOST_SLEEP_MODE_CMDID, + WMI_SET_WOW_MODE_CMDID, + WMI_GET_WOW_LIST_CMDID, + WMI_ADD_WOW_PATTERN_CMDID, + WMI_DEL_WOW_PATTERN_CMDID, /* 70 */ + + WMI_SET_FRAMERATES_CMDID, + WMI_SET_AP_PS_CMDID, + WMI_SET_QOS_SUPP_CMDID, + + /* WMI_THIN_RESERVED_... mark the start and end + * values for WMI_THIN_RESERVED command IDs. These + * command IDs can be found in wmi_thin.h */ + WMI_THIN_RESERVED_START = 0x8000, + WMI_THIN_RESERVED_END = 0x8fff, + + /* Developer commands starts at 0xF000 */ + WMI_SET_BITRATE_CMDID = 0xF000, + WMI_GET_BITRATE_CMDID, + WMI_SET_WHALPARAM_CMDID, + WMI_SET_MAC_ADDRESS_CMDID, + WMI_SET_AKMP_PARAMS_CMDID, + WMI_SET_PMKID_LIST_CMDID, + WMI_GET_PMKID_LIST_CMDID, + WMI_ABORT_SCAN_CMDID, + WMI_SET_TARGET_EVENT_REPORT_CMDID, + + /* Unused */ + WMI_UNUSED1, + WMI_UNUSED2, + + /* AP mode commands */ + WMI_AP_HIDDEN_SSID_CMDID, + WMI_AP_SET_NUM_STA_CMDID, + WMI_AP_ACL_POLICY_CMDID, + WMI_AP_ACL_MAC_LIST_CMDID, + WMI_AP_CONFIG_COMMIT_CMDID, + WMI_AP_SET_MLME_CMDID, + WMI_AP_SET_PVB_CMDID, + WMI_AP_CONN_INACT_CMDID, + WMI_AP_PROT_SCAN_TIME_CMDID, + WMI_AP_SET_COUNTRY_CMDID, + WMI_AP_SET_DTIM_CMDID, + WMI_AP_MODE_STAT_CMDID, + + WMI_SET_IP_CMDID, + WMI_SET_PARAMS_CMDID, + WMI_SET_MCAST_FILTER_CMDID, + WMI_DEL_MCAST_FILTER_CMDID, + + WMI_ALLOW_AGGR_CMDID, + WMI_ADDBA_REQ_CMDID, + WMI_DELBA_REQ_CMDID, + WMI_SET_HT_CAP_CMDID, + WMI_SET_HT_OP_CMDID, + WMI_SET_TX_SELECT_RATES_CMDID, + WMI_SET_TX_SGI_PARAM_CMDID, + WMI_SET_RATE_POLICY_CMDID, + + WMI_HCI_CMD_CMDID, + WMI_RX_FRAME_FORMAT_CMDID, + WMI_SET_THIN_MODE_CMDID, + WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, + + WMI_AP_SET_11BG_RATESET_CMDID, + WMI_SET_PMK_CMDID, + WMI_MCAST_FILTER_CMDID, + + /* COEX CMDID AR6003 */ + WMI_SET_BTCOEX_FE_ANT_CMDID, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, + WMI_SET_BTCOEX_SCO_CONFIG_CMDID, + WMI_SET_BTCOEX_A2DP_CONFIG_CMDID, + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, + WMI_SET_BTCOEX_DEBUG_CMDID, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID, + WMI_GET_BTCOEX_STATS_CMDID, + WMI_GET_BTCOEX_CONFIG_CMDID, + + WMI_SET_DFS_ENABLE_CMDID, /* F034 */ + WMI_SET_DFS_MINRSSITHRESH_CMDID, + WMI_SET_DFS_MAXPULSEDUR_CMDID, + WMI_DFS_RADAR_DETECTED_CMDID, + + /* P2P commands */ + WMI_P2P_SET_CONFIG_CMDID, /* F038 */ + WMI_WPS_SET_CONFIG_CMDID, + WMI_SET_REQ_DEV_ATTR_CMDID, + WMI_P2P_FIND_CMDID, + WMI_P2P_STOP_FIND_CMDID, + WMI_P2P_GO_NEG_START_CMDID, + WMI_P2P_LISTEN_CMDID, + + WMI_CONFIG_TX_MAC_RULES_CMDID, /* F040 */ + WMI_SET_PROMISCUOUS_MODE_CMDID, + WMI_RX_FRAME_FILTER_CMDID, + WMI_SET_CHANNEL_CMDID, + + /* WAC commands */ + WMI_ENABLE_WAC_CMDID, + WMI_WAC_SCAN_REPLY_CMDID, + WMI_WAC_CTRL_REQ_CMDID, + WMI_SET_DIV_PARAMS_CMDID, + + WMI_GET_PMK_CMDID, + WMI_SET_PASSPHRASE_CMDID, + WMI_SEND_ASSOC_RES_CMDID, + WMI_SET_ASSOC_REQ_RELAY_CMDID, + WMI_GET_RFKILL_MODE_CMDID, + + /* ACS command, consists of sub-commands */ + WMI_ACS_CTRL_CMDID, + + /* Ultra low power store / recall commands */ + WMI_STORERECALL_CONFIGURE_CMDID, + WMI_STORERECALL_RECALL_CMDID, + WMI_STORERECALL_HOST_READY_CMDID, + WMI_FORCE_TARGET_ASSERT_CMDID, + WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, +}; + +/* WMI_CONNECT_CMDID */ +enum network_type { + INFRA_NETWORK = 0x01, + ADHOC_NETWORK = 0x02, + ADHOC_CREATOR = 0x04, + AP_NETWORK = 0x10, +}; + +enum dot11_auth_mode { + OPEN_AUTH = 0x01, + SHARED_AUTH = 0x02, + + /* different from IEEE_AUTH_MODE definitions */ + LEAP_AUTH = 0x04, +}; + +enum { + AUTH_IDLE, + AUTH_OPEN_IN_PROGRESS, +}; + +enum auth_mode { + NONE_AUTH = 0x01, + WPA_AUTH = 0x02, + WPA2_AUTH = 0x04, + WPA_PSK_AUTH = 0x08, + WPA2_PSK_AUTH = 0x10, + WPA_AUTH_CCKM = 0x20, + WPA2_AUTH_CCKM = 0x40, +}; + +#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT +#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1) + +#define WMI_MIN_KEY_INDEX 0 +#define WMI_MAX_KEY_INDEX 3 + +#define WMI_MAX_KEY_LEN 32 + +/* + * NB: these values are ordered carefully; there are lots of + * of implications in any reordering. In particular beware + * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY. + */ +#define ATH6KL_CIPHER_WEP 0 +#define ATH6KL_CIPHER_TKIP 1 +#define ATH6KL_CIPHER_AES_OCB 2 +#define ATH6KL_CIPHER_AES_CCM 3 +#define ATH6KL_CIPHER_CKIP 5 +#define ATH6KL_CIPHER_CCKM_KRK 6 +#define ATH6KL_CIPHER_NONE 7 /* pseudo value */ + +/* + * 802.11 rate set. + */ +#define ATH6KL_RATE_MAXSIZE 15 /* max rates we'll handle */ + +#define ATH_OUI_TYPE 0x01 +#define WPA_OUI_TYPE 0x01 +#define WMM_PARAM_OUI_SUBTYPE 0x01 +#define WMM_OUI_TYPE 0x02 +#define WSC_OUT_TYPE 0x04 + +enum wmi_connect_ctrl_flags_bits { + CONNECT_ASSOC_POLICY_USER = 0x0001, + CONNECT_SEND_REASSOC = 0x0002, + CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, + CONNECT_PROFILE_MATCH_DONE = 0x0008, + CONNECT_IGNORE_AAC_BEACON = 0x0010, + CONNECT_CSA_FOLLOW_BSS = 0x0020, + CONNECT_DO_WPA_OFFLOAD = 0x0040, + CONNECT_DO_NOT_DEAUTH = 0x0080, +}; + +struct wmi_connect_cmd { + u8 nw_type; + u8 dot11_auth_mode; + u8 auth_mode; + u8 prwise_crypto_type; + u8 prwise_crypto_len; + u8 grp_crypto_type; + u8 grp_crypto_len; + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + __le16 ch; + u8 bssid[ETH_ALEN]; + __le32 ctrl_flags; +} __packed; + +/* WMI_RECONNECT_CMDID */ +struct wmi_reconnect_cmd { + /* channel hint */ + __le16 channel; + + /* mandatory if set */ + u8 bssid[ETH_ALEN]; +} __packed; + +/* WMI_ADD_CIPHER_KEY_CMDID */ +enum key_usage { + PAIRWISE_USAGE = 0x00, + GROUP_USAGE = 0x01, + + /* default Tx Key - static WEP only */ + TX_USAGE = 0x02, +}; + +/* + * Bit Flag + * Bit 0 - Initialise TSC - default is Initialize + */ +#define KEY_OP_INIT_TSC 0x01 +#define KEY_OP_INIT_RSC 0x02 + +/* default initialise the TSC & RSC */ +#define KEY_OP_INIT_VAL 0x03 +#define KEY_OP_VALID_MASK 0x03 + +struct wmi_add_cipher_key_cmd { + u8 key_index; + u8 key_type; + + /* enum key_usage */ + u8 key_usage; + + u8 key_len; + + /* key replay sequence counter */ + u8 key_rsc[8]; + + u8 key[WLAN_MAX_KEY_LEN]; + + /* additional key control info */ + u8 key_op_ctrl; + + u8 key_mac_addr[ETH_ALEN]; +} __packed; + +/* WMI_DELETE_CIPHER_KEY_CMDID */ +struct wmi_delete_cipher_key_cmd { + u8 key_index; +} __packed; + +#define WMI_KRK_LEN 16 + +/* WMI_ADD_KRK_CMDID */ +struct wmi_add_krk_cmd { + u8 krk[WMI_KRK_LEN]; +} __packed; + +/* WMI_SETPMKID_CMDID */ + +#define WMI_PMKID_LEN 16 + +enum pmkid_enable_flg { + PMKID_DISABLE = 0, + PMKID_ENABLE = 1, +}; + +struct wmi_setpmkid_cmd { + u8 bssid[ETH_ALEN]; + + /* enum pmkid_enable_flg */ + u8 enable; + + u8 pmkid[WMI_PMKID_LEN]; +} __packed; + +/* WMI_START_SCAN_CMD */ +enum wmi_scan_type { + WMI_LONG_SCAN = 0, + WMI_SHORT_SCAN = 1, +}; + +struct wmi_start_scan_cmd { + __le32 force_fg_scan; + + /* for legacy cisco AP compatibility */ + __le32 is_legacy; + + /* max duration in the home channel(msec) */ + __le32 home_dwell_time; + + /* time interval between scans (msec) */ + __le32 force_scan_intvl; + + /* enum wmi_scan_type */ + u8 scan_type; + + /* how many channels follow */ + u8 num_ch; + + /* channels in Mhz */ + __le16 ch_list[1]; +} __packed; + +/* WMI_SET_SCAN_PARAMS_CMDID */ +#define WMI_SHORTSCANRATIO_DEFAULT 3 + +/* + * Warning: scan control flag value of 0xFF is used to disable + * all flags in WMI_SCAN_PARAMS_CMD. Do not add any more + * flags here + */ +enum wmi_scan_ctrl_flags_bits { + + /* set if can scan in the connect cmd */ + CONNECT_SCAN_CTRL_FLAGS = 0x01, + + /* set if scan for the SSID it is already connected to */ + SCAN_CONNECTED_CTRL_FLAGS = 0x02, + + /* set if enable active scan */ + ACTIVE_SCAN_CTRL_FLAGS = 0x04, + + /* set if enable roam scan when bmiss and lowrssi */ + ROAM_SCAN_CTRL_FLAGS = 0x08, + + /* set if follows customer BSSINFO reporting rule */ + REPORT_BSSINFO_CTRL_FLAGS = 0x10, + + /* if disabled, target doesn't scan after a disconnect event */ + ENABLE_AUTO_CTRL_FLAGS = 0x20, + + /* + * Scan complete event with canceled status will be generated when + * a scan is prempted before it gets completed. + */ + ENABLE_SCAN_ABORT_EVENT = 0x40 +}; + +#define DEFAULT_SCAN_CTRL_FLAGS \ + (CONNECT_SCAN_CTRL_FLAGS | \ + SCAN_CONNECTED_CTRL_FLAGS | \ + ACTIVE_SCAN_CTRL_FLAGS | \ + ROAM_SCAN_CTRL_FLAGS | \ + ENABLE_AUTO_CTRL_FLAGS) + +struct wmi_scan_params_cmd { + /* sec */ + __le16 fg_start_period; + + /* sec */ + __le16 fg_end_period; + + /* sec */ + __le16 bg_period; + + /* msec */ + __le16 maxact_chdwell_time; + + /* msec */ + __le16 pas_chdwell_time; + + /* how many shorts scan for one long */ + u8 short_scan_ratio; + + u8 scan_ctrl_flags; + + /* msec */ + __le16 minact_chdwell_time; + + /* max active scans per ssid */ + __le16 maxact_scan_per_ssid; + + /* msecs */ + __le32 max_dfsch_act_time; +} __packed; + +/* WMI_SET_BSS_FILTER_CMDID */ +enum wmi_bss_filter { + /* no beacons forwarded */ + NONE_BSS_FILTER = 0x0, + + /* all beacons forwarded */ + ALL_BSS_FILTER, + + /* only beacons matching profile */ + PROFILE_FILTER, + + /* all but beacons matching profile */ + ALL_BUT_PROFILE_FILTER, + + /* only beacons matching current BSS */ + CURRENT_BSS_FILTER, + + /* all but beacons matching BSS */ + ALL_BUT_BSS_FILTER, + + /* beacons matching probed ssid */ + PROBED_SSID_FILTER, + + /* marker only */ + LAST_BSS_FILTER, +}; + +struct wmi_bss_filter_cmd { + /* see, enum wmi_bss_filter */ + u8 bss_filter; + + /* for alignment */ + u8 reserved1; + + /* for alignment */ + __le16 reserved2; + + __le32 ie_mask; +} __packed; + +/* WMI_SET_PROBED_SSID_CMDID */ +#define MAX_PROBED_SSID_INDEX 9 + +enum wmi_ssid_flag { + /* disables entry */ + DISABLE_SSID_FLAG = 0, + + /* probes specified ssid */ + SPECIFIC_SSID_FLAG = 0x01, + + /* probes for any ssid */ + ANY_SSID_FLAG = 0x02, +}; + +struct wmi_probed_ssid_cmd { + /* 0 to MAX_PROBED_SSID_INDEX */ + u8 entry_index; + + /* see, enum wmi_ssid_flg */ + u8 flag; + + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; +} __packed; + +/* + * WMI_SET_LISTEN_INT_CMDID + * The Listen interval is between 15 and 3000 TUs + */ +struct wmi_listen_int_cmd { + __le16 listen_intvl; + __le16 num_beacons; +} __packed; + +/* WMI_SET_POWER_MODE_CMDID */ +enum wmi_power_mode { + REC_POWER = 0x01, + MAX_PERF_POWER, +}; + +struct wmi_power_mode_cmd { + /* see, enum wmi_power_mode */ + u8 pwr_mode; +} __packed; + +/* + * Policy to determnine whether power save failure event should be sent to + * host during scanning + */ +enum power_save_fail_event_policy { + SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1, + IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2, +}; + +struct wmi_power_params_cmd { + /* msec */ + __le16 idle_period; + + __le16 pspoll_number; + __le16 dtim_policy; + __le16 tx_wakeup_policy; + __le16 num_tx_to_wakeup; + __le16 ps_fail_event_policy; +} __packed; + +/* WMI_SET_DISC_TIMEOUT_CMDID */ +struct wmi_disc_timeout_cmd { + /* seconds */ + u8 discon_timeout; +} __packed; + +enum dir_type { + UPLINK_TRAFFIC = 0, + DNLINK_TRAFFIC = 1, + BIDIR_TRAFFIC = 2, +}; + +enum voiceps_cap_type { + DISABLE_FOR_THIS_AC = 0, + ENABLE_FOR_THIS_AC = 1, + ENABLE_FOR_ALL_AC = 2, +}; + +enum traffic_type { + TRAFFIC_TYPE_APERIODIC = 0, + TRAFFIC_TYPE_PERIODIC = 1, +}; + +/* WMI_SYNCHRONIZE_CMDID */ +struct wmi_sync_cmd { + u8 data_sync_map; +} __packed; + +/* WMI_CREATE_PSTREAM_CMDID */ +struct wmi_create_pstream_cmd { + /* msec */ + __le32 min_service_int; + + /* msec */ + __le32 max_service_int; + + /* msec */ + __le32 inactivity_int; + + /* msec */ + __le32 suspension_int; + + __le32 service_start_time; + + /* in bps */ + __le32 min_data_rate; + + /* in bps */ + __le32 mean_data_rate; + + /* in bps */ + __le32 peak_data_rate; + + __le32 max_burst_size; + __le32 delay_bound; + + /* in bps */ + __le32 min_phy_rate; + + __le32 sba; + __le32 medium_time; + + /* in octects */ + __le16 nominal_msdu; + + /* in octects */ + __le16 max_msdu; + + u8 traffic_class; + + /* see, enum dir_type */ + u8 traffic_direc; + + u8 rx_queue_num; + + /* see, enum traffic_type */ + u8 traffic_type; + + /* see, enum voiceps_cap_type */ + u8 voice_psc_cap; + u8 tsid; + + /* 802.1D user priority */ + u8 user_pri; + + /* nominal phy rate */ + u8 nominal_phy; +} __packed; + +/* WMI_DELETE_PSTREAM_CMDID */ +struct wmi_delete_pstream_cmd { + u8 tx_queue_num; + u8 rx_queue_num; + u8 traffic_direc; + u8 traffic_class; + u8 tsid; +} __packed; + +/* WMI_SET_CHANNEL_PARAMS_CMDID */ +enum wmi_phy_mode { + WMI_11A_MODE = 0x1, + WMI_11G_MODE = 0x2, + WMI_11AG_MODE = 0x3, + WMI_11B_MODE = 0x4, + WMI_11GONLY_MODE = 0x5, +}; + +#define WMI_MAX_CHANNELS 32 + +/* + * WMI_RSSI_THRESHOLD_PARAMS_CMDID + * Setting the polltime to 0 would disable polling. Threshold values are + * in the ascending order, and should agree to: + * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal + * < highThreshold_upperVal) + */ + +struct wmi_rssi_threshold_params_cmd { + /* polling time as a factor of LI */ + __le32 poll_time; + + /* lowest of upper */ + a_sle16 thresh_above1_val; + + a_sle16 thresh_above2_val; + a_sle16 thresh_above3_val; + a_sle16 thresh_above4_val; + a_sle16 thresh_above5_val; + + /* highest of upper */ + a_sle16 thresh_above6_val; + + /* lowest of bellow */ + a_sle16 thresh_below1_val; + + a_sle16 thresh_below2_val; + a_sle16 thresh_below3_val; + a_sle16 thresh_below4_val; + a_sle16 thresh_below5_val; + + /* highest of bellow */ + a_sle16 thresh_below6_val; + + /* "alpha" */ + u8 weight; + + u8 reserved[3]; +} __packed; + +/* + * WMI_SNR_THRESHOLD_PARAMS_CMDID + * Setting the polltime to 0 would disable polling. + */ + +struct wmi_snr_threshold_params_cmd { + /* polling time as a factor of LI */ + __le32 poll_time; + + /* "alpha" */ + u8 weight; + + /* lowest of uppper */ + u8 thresh_above1_val; + + u8 thresh_above2_val; + u8 thresh_above3_val; + + /* highest of upper */ + u8 thresh_above4_val; + + /* lowest of bellow */ + u8 thresh_below1_val; + + u8 thresh_below2_val; + u8 thresh_below3_val; + + /* highest of bellow */ + u8 thresh_below4_val; + + u8 reserved[3]; +} __packed; + +enum wmi_preamble_policy { + WMI_IGNORE_BARKER_IN_ERP = 0, + WMI_DONOT_IGNORE_BARKER_IN_ERP +}; + +struct wmi_set_lpreamble_cmd { + u8 status; + u8 preamble_policy; +} __packed; + +struct wmi_set_rts_cmd { + __le16 threshold; +} __packed; + +/* WMI_SET_TX_PWR_CMDID */ +struct wmi_set_tx_pwr_cmd { + /* in dbM units */ + u8 dbM; +} __packed; + +struct wmi_tx_pwr_reply { + /* in dbM units */ + u8 dbM; +} __packed; + +struct wmi_report_sleep_state_event { + __le32 sleep_state; +}; + +enum wmi_report_sleep_status { + WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP = 0, + WMI_REPORT_SLEEP_STATUS_IS_AWAKE +}; +enum target_event_report_config { + /* default */ + DISCONN_EVT_IN_RECONN = 0, + + NO_DISCONN_EVT_IN_RECONN +}; + +/* Command Replies */ + +/* WMI_GET_CHANNEL_LIST_CMDID reply */ +struct wmi_channel_list_reply { + u8 reserved; + + /* number of channels in reply */ + u8 num_ch; + + /* channel in Mhz */ + __le16 ch_list[1]; +} __packed; + +/* List of Events (target to host) */ +enum wmi_event_id { + WMI_READY_EVENTID = 0x1001, + WMI_CONNECT_EVENTID, + WMI_DISCONNECT_EVENTID, + WMI_BSSINFO_EVENTID, + WMI_CMDERROR_EVENTID, + WMI_REGDOMAIN_EVENTID, + WMI_PSTREAM_TIMEOUT_EVENTID, + WMI_NEIGHBOR_REPORT_EVENTID, + WMI_TKIP_MICERR_EVENTID, + WMI_SCAN_COMPLETE_EVENTID, /* 0x100a */ + WMI_REPORT_STATISTICS_EVENTID, + WMI_RSSI_THRESHOLD_EVENTID, + WMI_ERROR_REPORT_EVENTID, + WMI_OPT_RX_FRAME_EVENTID, + WMI_REPORT_ROAM_TBL_EVENTID, + WMI_EXTENSION_EVENTID, + WMI_CAC_EVENTID, + WMI_SNR_THRESHOLD_EVENTID, + WMI_LQ_THRESHOLD_EVENTID, + WMI_TX_RETRY_ERR_EVENTID, /* 0x1014 */ + WMI_REPORT_ROAM_DATA_EVENTID, + WMI_TEST_EVENTID, + WMI_APLIST_EVENTID, + WMI_GET_WOW_LIST_EVENTID, + WMI_GET_PMKID_LIST_EVENTID, + WMI_CHANNEL_CHANGE_EVENTID, + WMI_PEER_NODE_EVENTID, + WMI_PSPOLL_EVENTID, + WMI_DTIMEXPIRY_EVENTID, + WMI_WLAN_VERSION_EVENTID, + WMI_SET_PARAMS_REPLY_EVENTID, + WMI_ADDBA_REQ_EVENTID, /*0x1020 */ + WMI_ADDBA_RESP_EVENTID, + WMI_DELBA_REQ_EVENTID, + WMI_TX_COMPLETE_EVENTID, + WMI_HCI_EVENT_EVENTID, + WMI_ACL_DATA_EVENTID, + WMI_REPORT_SLEEP_STATE_EVENTID, + WMI_REPORT_BTCOEX_STATS_EVENTID, + WMI_REPORT_BTCOEX_CONFIG_EVENTID, + WMI_GET_PMK_EVENTID, + + /* DFS Events */ + WMI_DFS_HOST_ATTACH_EVENTID, + WMI_DFS_HOST_INIT_EVENTID, + WMI_DFS_RESET_DELAYLINES_EVENTID, + WMI_DFS_RESET_RADARQ_EVENTID, + WMI_DFS_RESET_AR_EVENTID, + WMI_DFS_RESET_ARQ_EVENTID, + WMI_DFS_SET_DUR_MULTIPLIER_EVENTID, + WMI_DFS_SET_BANGRADAR_EVENTID, + WMI_DFS_SET_DEBUGLEVEL_EVENTID, + WMI_DFS_PHYERR_EVENTID, + + /* CCX Evants */ + WMI_CCX_RM_STATUS_EVENTID, + + /* P2P Events */ + WMI_P2P_GO_NEG_RESULT_EVENTID, + + WMI_WAC_SCAN_DONE_EVENTID, + WMI_WAC_REPORT_BSS_EVENTID, + WMI_WAC_START_WPS_EVENTID, + WMI_WAC_CTRL_REQ_REPLY_EVENTID, + + /* RFKILL Events */ + WMI_RFKILL_STATE_CHANGE_EVENTID, + WMI_RFKILL_GET_MODE_CMD_EVENTID, + WMI_THIN_RESERVED_START_EVENTID = 0x8000, + + /* + * Events in this range are reserved for thinmode + * See wmi_thin.h for actual definitions + */ + WMI_THIN_RESERVED_END_EVENTID = 0x8fff, + + WMI_SET_CHANNEL_EVENTID, + WMI_ASSOC_REQ_EVENTID, + + /* Generic ACS event */ + WMI_ACS_EVENTID, + WMI_REPORT_WMM_PARAMS_EVENTID +}; + +struct wmi_ready_event_2 { + __le32 sw_version; + __le32 abi_version; + u8 mac_addr[ETH_ALEN]; + u8 phy_cap; +} __packed; + +/* Connect Event */ +struct wmi_connect_event { + __le16 ch; + u8 bssid[ETH_ALEN]; + __le16 listen_intvl; + __le16 beacon_intvl; + __le32 nw_type; + u8 beacon_ie_len; + u8 assoc_req_len; + u8 assoc_resp_len; + u8 assoc_info[1]; +} __packed; + +/* Disconnect Event */ +enum wmi_disconnect_reason { + NO_NETWORK_AVAIL = 0x01, + + /* bmiss */ + LOST_LINK = 0x02, + + DISCONNECT_CMD = 0x03, + BSS_DISCONNECTED = 0x04, + AUTH_FAILED = 0x05, + ASSOC_FAILED = 0x06, + NO_RESOURCES_AVAIL = 0x07, + CSERV_DISCONNECT = 0x08, + INVALID_PROFILE = 0x0a, + DOT11H_CHANNEL_SWITCH = 0x0b, + PROFILE_MISMATCH = 0x0c, + CONNECTION_EVICTED = 0x0d, + IBSS_MERGE = 0xe, +}; + +struct wmi_disconnect_event { + /* reason code, see 802.11 spec. */ + __le16 proto_reason_status; + + /* set if known */ + u8 bssid[ETH_ALEN]; + + /* see WMI_DISCONNECT_REASON */ + u8 disconn_reason; + + u8 assoc_resp_len; + u8 assoc_info[1]; +} __packed; + +/* + * BSS Info Event. + * Mechanism used to inform host of the presence and characteristic of + * wireless networks present. Consists of bss info header followed by + * the beacon or probe-response frame body. The 802.11 header is no included. + */ +enum wmi_bi_ftype { + BEACON_FTYPE = 0x1, + PROBERESP_FTYPE, + ACTION_MGMT_FTYPE, + PROBEREQ_FTYPE, +}; + +struct wmi_bss_info_hdr { + __le16 ch; + + /* see, enum wmi_bi_ftype */ + u8 frame_type; + + u8 snr; + a_sle16 rssi; + u8 bssid[ETH_ALEN]; + __le32 ie_mask; +} __packed; + +/* + * BSS INFO HDR version 2.0 + * With 6 bytes HTC header and 6 bytes of WMI header + * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management + * header space. + * - Reduce the ie_mask to 2 bytes as only two bit flags are used + * - Remove rssi and compute it on the host. rssi = snr - 95 + */ +struct wmi_bss_info_hdr2 { + __le16 ch; + + /* see, enum wmi_bi_ftype */ + u8 frame_type; + + u8 snr; + u8 bssid[ETH_ALEN]; + __le16 ie_mask; +} __packed; + +/* Command Error Event */ +enum wmi_error_code { + INVALID_PARAM = 0x01, + ILLEGAL_STATE = 0x02, + INTERNAL_ERROR = 0x03, +}; + +struct wmi_cmd_error_event { + __le16 cmd_id; + u8 err_code; +} __packed; + +struct wmi_pstream_timeout_event { + u8 tx_queue_num; + u8 rx_queue_num; + u8 traffic_direc; + u8 traffic_class; +} __packed; + +/* + * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform + * the host of BSS's it has found that matches the current profile. + * It can be used by the host to cache PMKs and/to initiate pre-authentication + * if the BSS supports it. The first bssid is always the current associated + * BSS. + * The bssid and bssFlags information repeats according to the number + * or APs reported. + */ +enum wmi_bss_flags { + WMI_DEFAULT_BSS_FLAGS = 0x00, + WMI_PREAUTH_CAPABLE_BSS = 0x01, + WMI_PMKID_VALID_BSS = 0x02, +}; + +/* TKIP MIC Error Event */ +struct wmi_tkip_micerr_event { + u8 key_id; + u8 is_mcast; +} __packed; + +/* WMI_SCAN_COMPLETE_EVENTID */ +struct wmi_scan_complete_event { + a_sle32 status; +} __packed; + +#define MAX_OPT_DATA_LEN 1400 + +/* + * Special frame receive Event. + * Mechanism used to inform host of the receiption of the special frames. + * Consists of special frame info header followed by special frame body. + * The 802.11 header is not included. + */ +struct wmi_opt_rx_info_hdr { + __le16 ch; + u8 frame_type; + s8 snr; + u8 src_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; +} __packed; + +/* Reporting statistic */ +struct tx_stats { + __le32 pkt; + __le32 byte; + __le32 ucast_pkt; + __le32 ucast_byte; + __le32 mcast_pkt; + __le32 mcast_byte; + __le32 bcast_pkt; + __le32 bcast_byte; + __le32 rts_success_cnt; + __le32 pkt_per_ac[4]; + __le32 err_per_ac[4]; + + __le32 err; + __le32 fail_cnt; + __le32 retry_cnt; + __le32 mult_retry_cnt; + __le32 rts_fail_cnt; + a_sle32 ucast_rate; +} __packed; + +struct rx_stats { + __le32 pkt; + __le32 byte; + __le32 ucast_pkt; + __le32 ucast_byte; + __le32 mcast_pkt; + __le32 mcast_byte; + __le32 bcast_pkt; + __le32 bcast_byte; + __le32 frgment_pkt; + + __le32 err; + __le32 crc_err; + __le32 key_cache_miss; + __le32 decrypt_err; + __le32 dupl_frame; + a_sle32 ucast_rate; +} __packed; + +struct tkip_ccmp_stats { + __le32 tkip_local_mic_fail; + __le32 tkip_cnter_measures_invoked; + __le32 tkip_replays; + __le32 tkip_fmt_err; + __le32 ccmp_fmt_err; + __le32 ccmp_replays; +} __packed; + +struct pm_stats { + __le32 pwr_save_failure_cnt; + __le16 stop_tx_failure_cnt; + __le16 atim_tx_failure_cnt; + __le16 atim_rx_failure_cnt; + __le16 bcn_rx_failure_cnt; +} __packed; + +struct cserv_stats { + __le32 cs_bmiss_cnt; + __le32 cs_low_rssi_cnt; + __le16 cs_connect_cnt; + __le16 cs_discon_cnt; + a_sle16 cs_ave_beacon_rssi; + __le16 cs_roam_count; + a_sle16 cs_rssi; + u8 cs_snr; + u8 cs_ave_beacon_snr; + u8 cs_last_roam_msec; +} __packed; + +struct wlan_net_stats { + struct tx_stats tx; + struct rx_stats rx; + struct tkip_ccmp_stats tkip_ccmp_stats; +} __packed; + +struct arp_stats { + __le32 arp_received; + __le32 arp_matched; + __le32 arp_replied; +} __packed; + +struct wlan_wow_stats { + __le32 wow_pkt_dropped; + __le16 wow_evt_discarded; + u8 wow_host_pkt_wakeups; + u8 wow_host_evt_wakeups; +} __packed; + +struct wmi_target_stats { + __le32 lq_val; + a_sle32 noise_floor_calib; + struct pm_stats pm_stats; + struct wlan_net_stats stats; + struct wlan_wow_stats wow_stats; + struct arp_stats arp_stats; + struct cserv_stats cserv_stats; +} __packed; + +/* + * WMI_RSSI_THRESHOLD_EVENTID. + * Indicate the RSSI events to host. Events are indicated when we breach a + * thresold value. + */ +enum wmi_rssi_threshold_val { + WMI_RSSI_THRESHOLD1_ABOVE = 0, + WMI_RSSI_THRESHOLD2_ABOVE, + WMI_RSSI_THRESHOLD3_ABOVE, + WMI_RSSI_THRESHOLD4_ABOVE, + WMI_RSSI_THRESHOLD5_ABOVE, + WMI_RSSI_THRESHOLD6_ABOVE, + WMI_RSSI_THRESHOLD1_BELOW, + WMI_RSSI_THRESHOLD2_BELOW, + WMI_RSSI_THRESHOLD3_BELOW, + WMI_RSSI_THRESHOLD4_BELOW, + WMI_RSSI_THRESHOLD5_BELOW, + WMI_RSSI_THRESHOLD6_BELOW +}; + +struct wmi_rssi_threshold_event { + a_sle16 rssi; + u8 range; +} __packed; + +enum wmi_snr_threshold_val { + WMI_SNR_THRESHOLD1_ABOVE = 1, + WMI_SNR_THRESHOLD1_BELOW, + WMI_SNR_THRESHOLD2_ABOVE, + WMI_SNR_THRESHOLD2_BELOW, + WMI_SNR_THRESHOLD3_ABOVE, + WMI_SNR_THRESHOLD3_BELOW, + WMI_SNR_THRESHOLD4_ABOVE, + WMI_SNR_THRESHOLD4_BELOW +}; + +struct wmi_snr_threshold_event { + /* see, enum wmi_snr_threshold_val */ + u8 range; + + u8 snr; +} __packed; + +/* WMI_REPORT_ROAM_TBL_EVENTID */ +#define MAX_ROAM_TBL_CAND 5 + +struct wmi_bss_roam_info { + a_sle32 roam_util; + u8 bssid[ETH_ALEN]; + s8 rssi; + s8 rssidt; + s8 last_rssi; + s8 util; + s8 bias; + + /* for alignment */ + u8 reserved; +} __packed; + +/* WMI_CAC_EVENTID */ +enum cac_indication { + CAC_INDICATION_ADMISSION = 0x00, + CAC_INDICATION_ADMISSION_RESP = 0x01, + CAC_INDICATION_DELETE = 0x02, + CAC_INDICATION_NO_RESP = 0x03, +}; + +#define WMM_TSPEC_IE_LEN 63 + +struct wmi_cac_event { + u8 ac; + u8 cac_indication; + u8 status_code; + u8 tspec_suggestion[WMM_TSPEC_IE_LEN]; +} __packed; + +/* WMI_APLIST_EVENTID */ + +enum aplist_ver { + APLIST_VER1 = 1, +}; + +struct wmi_ap_info_v1 { + u8 bssid[ETH_ALEN]; + __le16 channel; +} __packed; + +union wmi_ap_info { + struct wmi_ap_info_v1 ap_info_v1; +} __packed; + +struct wmi_aplist_event { + u8 ap_list_ver; + u8 num_ap; + union wmi_ap_info ap_list[1]; +} __packed; + +/* Developer Commands */ + +/* + * WMI_SET_BITRATE_CMDID + * + * Get bit rate cmd uses same definition as set bit rate cmd + */ +enum wmi_bit_rate { + RATE_AUTO = -1, + RATE_1Mb = 0, + RATE_2Mb = 1, + RATE_5_5Mb = 2, + RATE_11Mb = 3, + RATE_6Mb = 4, + RATE_9Mb = 5, + RATE_12Mb = 6, + RATE_18Mb = 7, + RATE_24Mb = 8, + RATE_36Mb = 9, + RATE_48Mb = 10, + RATE_54Mb = 11, + RATE_MCS_0_20 = 12, + RATE_MCS_1_20 = 13, + RATE_MCS_2_20 = 14, + RATE_MCS_3_20 = 15, + RATE_MCS_4_20 = 16, + RATE_MCS_5_20 = 17, + RATE_MCS_6_20 = 18, + RATE_MCS_7_20 = 19, + RATE_MCS_0_40 = 20, + RATE_MCS_1_40 = 21, + RATE_MCS_2_40 = 22, + RATE_MCS_3_40 = 23, + RATE_MCS_4_40 = 24, + RATE_MCS_5_40 = 25, + RATE_MCS_6_40 = 26, + RATE_MCS_7_40 = 27, +}; + +struct wmi_bit_rate_reply { + /* see, enum wmi_bit_rate */ + s8 rate_index; +} __packed; + +/* + * WMI_SET_FIXRATES_CMDID + * + * Get fix rates cmd uses same definition as set fix rates cmd + */ +struct wmi_fix_rates_reply { + /* see wmi_bit_rate */ + __le32 fix_rate_mask; +} __packed; + +enum roam_data_type { + /* get the roam time data */ + ROAM_DATA_TIME = 1, +}; + +struct wmi_target_roam_time { + __le32 disassoc_time; + __le32 no_txrx_time; + __le32 assoc_time; + __le32 allow_txrx_time; + u8 disassoc_bssid[ETH_ALEN]; + s8 disassoc_bss_rssi; + u8 assoc_bssid[ETH_ALEN]; + s8 assoc_bss_rssi; +} __packed; + +enum wmi_txop_cfg { + WMI_TXOP_DISABLED = 0, + WMI_TXOP_ENABLED +}; + +struct wmi_set_wmm_txop_cmd { + u8 txop_enable; +} __packed; + +struct wmi_set_keepalive_cmd { + u8 keep_alive_intvl; +} __packed; + +struct wmi_get_keepalive_cmd { + __le32 configured; + u8 keep_alive_intvl; +} __packed; + +/* Notify the WSC registration status to the target */ +#define WSC_REG_ACTIVE 1 +#define WSC_REG_INACTIVE 0 + +#define WOW_MAX_FILTER_LISTS 1 +#define WOW_MAX_FILTERS_PER_LIST 4 +#define WOW_PATTERN_SIZE 64 +#define WOW_MASK_SIZE 64 + +#define MAC_MAX_FILTERS_PER_LIST 4 + +struct wow_filter { + u8 wow_valid_filter; + u8 wow_filter_id; + u8 wow_filter_size; + u8 wow_filter_offset; + u8 wow_filter_mask[WOW_MASK_SIZE]; + u8 wow_filter_pattern[WOW_PATTERN_SIZE]; +} __packed; + +#define MAX_IP_ADDRS 2 + +struct wmi_set_ip_cmd { + /* IP in network byte order */ + __le32 ips[MAX_IP_ADDRS]; +} __packed; + +/* WMI_GET_WOW_LIST_CMD reply */ +struct wmi_get_wow_list_reply { + /* number of patterns in reply */ + u8 num_filters; + + /* this is filter # x of total num_filters */ + u8 this_filter_num; + + u8 wow_mode; + u8 host_mode; + struct wow_filter wow_filters[1]; +} __packed; + +/* WMI_SET_AKMP_PARAMS_CMD */ + +struct wmi_pmkid { + u8 pmkid[WMI_PMKID_LEN]; +} __packed; + +/* WMI_GET_PMKID_LIST_CMD Reply */ +struct wmi_pmkid_list_reply { + __le32 num_pmkid; + u8 bssid_list[ETH_ALEN][1]; + struct wmi_pmkid pmkid_list[1]; +} __packed; + +/* WMI_ADDBA_REQ_EVENTID */ +struct wmi_addba_req_event { + u8 tid; + u8 win_sz; + __le16 st_seq_no; + + /* f/w response for ADDBA Req; OK (0) or failure (!=0) */ + u8 status; +} __packed; + +/* WMI_ADDBA_RESP_EVENTID */ +struct wmi_addba_resp_event { + u8 tid; + + /* OK (0), failure (!=0) */ + u8 status; + + /* three values: not supported(0), 3839, 8k */ + __le16 amsdu_sz; +} __packed; + +/* WMI_DELBA_EVENTID + * f/w received a DELBA for peer and processed it. + * Host is notified of this + */ +struct wmi_delba_event { + u8 tid; + u8 is_peer_initiator; + __le16 reason_code; +} __packed; + +#define PEER_NODE_JOIN_EVENT 0x00 +#define PEER_NODE_LEAVE_EVENT 0x01 +#define PEER_FIRST_NODE_JOIN_EVENT 0x10 +#define PEER_LAST_NODE_LEAVE_EVENT 0x11 + +struct wmi_peer_node_event { + u8 event_code; + u8 peer_mac_addr[ETH_ALEN]; +} __packed; + +/* Transmit complete event data structure(s) */ + +/* version 1 of tx complete msg */ +struct tx_complete_msg_v1 { +#define TX_COMPLETE_STATUS_SUCCESS 0 +#define TX_COMPLETE_STATUS_RETRIES 1 +#define TX_COMPLETE_STATUS_NOLINK 2 +#define TX_COMPLETE_STATUS_TIMEOUT 3 +#define TX_COMPLETE_STATUS_OTHER 4 + + u8 status; + + /* packet ID to identify parent packet */ + u8 pkt_id; + + /* rate index on successful transmission */ + u8 rate_idx; + + /* number of ACK failures in tx attempt */ + u8 ack_failures; +} __packed; + +struct wmi_tx_complete_event { + /* no of tx comp msgs following this struct */ + u8 num_msg; + + /* length in bytes for each individual msg following this struct */ + u8 msg_len; + + /* version of tx complete msg data following this struct */ + u8 msg_type; + + /* individual messages follow this header */ + u8 reserved; +} __packed; + +/* + * ------- AP Mode definitions -------------- + */ + +/* + * !!! Warning !!! + * -Changing the following values needs compilation of both driver and firmware + */ +#define AP_MAX_NUM_STA 8 + +/* Spl. AID used to set DTIM flag in the beacons */ +#define MCAST_AID 0xFF + +#define DEF_AP_COUNTRY_CODE "US " + +/* Used with WMI_AP_SET_NUM_STA_CMDID */ + +struct wmi_ap_set_pvb_cmd { + __le32 flag; + __le16 aid; +} __packed; + +struct wmi_rx_frame_format_cmd { + /* version of meta data for rx packets <0 = default> (0-7 = valid) */ + u8 meta_ver; + + /* + * 1 == leave .11 header intact, + * 0 == replace .11 header with .3 <default> + */ + u8 dot11_hdr; + + /* + * 1 == defragmentation is performed by host, + * 0 == performed by target <default> + */ + u8 defrag_on_host; + + /* for alignment */ + u8 reserved[1]; +} __packed; + +/* AP mode events */ + +/* WMI_PS_POLL_EVENT */ +struct wmi_pspoll_event { + __le16 aid; +} __packed; + +struct wmi_per_sta_stat { + __le32 tx_bytes; + __le32 tx_pkts; + __le32 tx_error; + __le32 tx_discard; + __le32 rx_bytes; + __le32 rx_pkts; + __le32 rx_error; + __le32 rx_discard; + __le32 aid; +} __packed; + +struct wmi_ap_mode_stat { + __le32 action; + struct wmi_per_sta_stat sta[AP_MAX_NUM_STA + 1]; +} __packed; + +/* End of AP mode definitions */ + +/* Extended WMI (WMIX) + * + * Extended WMIX commands are encapsulated in a WMI message with + * cmd=WMI_EXTENSION_CMD. + * + * Extended WMI commands are those that are needed during wireless + * operation, but which are not really wireless commands. This allows, + * for instance, platform-specific commands. Extended WMI commands are + * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID. + * Extended WMI events are similarly embedded in a WMI event message with + * WMI_EVENT_ID=WMI_EXTENSION_EVENTID. + */ +struct wmix_cmd_hdr { + __le32 cmd_id; +} __packed; + +enum wmix_command_id { + WMIX_DSETOPEN_REPLY_CMDID = 0x2001, + WMIX_DSETDATA_REPLY_CMDID, + WMIX_GPIO_OUTPUT_SET_CMDID, + WMIX_GPIO_INPUT_GET_CMDID, + WMIX_GPIO_REGISTER_SET_CMDID, + WMIX_GPIO_REGISTER_GET_CMDID, + WMIX_GPIO_INTR_ACK_CMDID, + WMIX_HB_CHALLENGE_RESP_CMDID, + WMIX_DBGLOG_CFG_MODULE_CMDID, + WMIX_PROF_CFG_CMDID, /* 0x200a */ + WMIX_PROF_ADDR_SET_CMDID, + WMIX_PROF_START_CMDID, + WMIX_PROF_STOP_CMDID, + WMIX_PROF_COUNT_GET_CMDID, +}; + +enum wmix_event_id { + WMIX_DSETOPENREQ_EVENTID = 0x3001, + WMIX_DSETCLOSE_EVENTID, + WMIX_DSETDATAREQ_EVENTID, + WMIX_GPIO_INTR_EVENTID, + WMIX_GPIO_DATA_EVENTID, + WMIX_GPIO_ACK_EVENTID, + WMIX_HB_CHALLENGE_RESP_EVENTID, + WMIX_DBGLOG_EVENTID, + WMIX_PROF_COUNT_EVENTID, +}; + +/* + * ------Error Detection support------- + */ + +/* + * WMIX_HB_CHALLENGE_RESP_CMDID + * Heartbeat Challenge Response command + */ +struct wmix_hb_challenge_resp_cmd { + __le32 cookie; + __le32 source; +} __packed; + +/* End of Extended WMI (WMIX) */ + +enum wmi_sync_flag { + NO_SYNC_WMIFLAG = 0, + + /* transmit all queued data before cmd */ + SYNC_BEFORE_WMIFLAG, + + /* any new data waits until cmd execs */ + SYNC_AFTER_WMIFLAG, + + SYNC_BOTH_WMIFLAG, + + /* end marker */ + END_WMIFLAG +}; + +enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi); +void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id); +int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb); +int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, + u8 msg_type, bool more_data, + enum wmi_data_hdr_data_type data_type, + u8 meta_ver, void *tx_meta_info); + +int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb); +int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb); +int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb); +int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb, + u32 layer2_priority, bool wmm_enabled, + u8 *ac); + +int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb); +void ath6kl_wmi_iterate_nodes(struct wmi *wmi, + void (*f) (void *arg, struct bss *), + void *arg); +struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 *mac_addr); +void ath6kl_wmi_node_free(struct wmi *wmi, const u8 *mac_addr); + +int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, + enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag); + +int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type, + enum dot11_auth_mode dot11_auth_mode, + enum auth_mode auth_mode, + enum crypto_type pairwise_crypto, + u8 pairwise_crypto_len, + enum crypto_type group_crypto, + u8 group_crypto_len, int ssid_len, u8 *ssid, + u8 *bssid, u16 channel, u32 ctrl_flags); + +int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel); +int ath6kl_wmi_disconnect_cmd(struct wmi *wmi); +int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, + u32 force_fgscan, u32 is_legacy, + u32 home_dwell_time, u32 force_scan_interval, + s8 num_chan, u16 *ch_list); +int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec, + u16 fg_end_sec, u16 bg_sec, + u16 minact_chdw_msec, u16 maxact_chdw_msec, + u16 pas_chdw_msec, u8 short_scan_ratio, + u8 scan_ctrl_flag, u32 max_dfsch_act_time, + u16 maxact_scan_per_ssid); +int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask); +int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag, + u8 ssid_len, u8 *ssid); +int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval, + u16 listen_beacons); +int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode); +int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period, + u16 ps_poll_num, u16 dtim_policy, + u16 tx_wakup_policy, u16 num_tx_to_wakeup, + u16 ps_fail_event_policy); +int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout); +int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, + struct wmi_create_pstream_cmd *pstream); +int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid); + +int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold); +int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, + u8 preamble_policy); + +int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source); + +int ath6kl_wmi_get_stats_cmd(struct wmi *wmi); +int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, + enum crypto_type key_type, + u8 key_usage, u8 key_len, + u8 *key_rsc, u8 *key_material, + u8 key_op_ctrl, u8 *mac_addr, + enum wmi_sync_flag sync_flag); +int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk); +int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index); +int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid, + const u8 *pmkid, bool set); +int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM); +int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi); +void ath6kl_wmi_get_current_bssid(struct wmi *wmi, u8 *bssid); + +int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg); +int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl); + +s32 ath6kl_wmi_get_rate(s8 rate_index); + +int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); + +struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 *ssid, + u32 ssid_len, bool is_wpa2, + bool match_ssid); + +void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss); + +/* AP mode */ +int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag); + +int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version, + bool rx_dot11_hdr, bool defrag_on_host); + +void *ath6kl_wmi_init(void *devt); +void ath6kl_wmi_shutdown(struct wmi *wmi); + +#endif /* WMI_H */ diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 0fa466a91bf4..565ab525db33 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -91,3 +91,5 @@ config PCI_IOAPIC config PCI_LABEL def_bool y if (DMI || ACPI) select NLS + +source "drivers/pci/pcie/Kconfig" diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index 55fc066e636d..1cc50da4c9c2 100755 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -102,6 +102,7 @@ static int udc_suspend(struct fsl_udc *udc); static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state); static int fsl_udc_resume(struct platform_device *pdev); static void fsl_ep_fifo_flush(struct usb_ep *_ep); +static void gadget_wait_line_to_se0(void); #ifdef CONFIG_USB_OTG /* Get platform resource from OTG driver */ @@ -294,6 +295,23 @@ static void nuke(struct fsl_ep *ep, int status) /*------------------------------------------------------------------ Internal Hardware related function ------------------------------------------------------------------*/ +static void dr_discharge_dp(struct fsl_usb2_platform_data *pdata) +{ + /* enable pulldown dp */ + if (pdata->gadget_discharge_dp) + pdata->gadget_discharge_dp(true); + /* + * Some boards are very slow change line state from J to SE0 for DP, + * So, we need to discharge DP, otherwise there is a wakeup interrupt + * after we enable the wakeup function. + */ + gadget_wait_line_to_se0(); + + /* Disable pulldown dp */ + if (pdata->gadget_discharge_dp) + pdata->gadget_discharge_dp(false); +} + static inline void dr_wake_up_enable(struct fsl_udc *udc, bool enable) { @@ -381,6 +399,8 @@ static int dr_controller_setup(struct fsl_udc *udc) if (pdata->es) tmp |= USB_MODE_ES; fsl_writel(tmp, &dr_regs->usbmode); + /* wait dp to 0v */ + dr_discharge_dp(pdata); fsl_platform_set_device_mode(pdata); @@ -2026,6 +2046,7 @@ static void suspend_irq(struct fsl_udc *udc) udc->resume_state = udc->usb_state; udc->usb_state = USB_STATE_SUSPENDED; + /* report suspend to the driver, serial.c does not support this */ if (udc->driver->suspend) udc->driver->suspend(&udc->gadget); @@ -2147,12 +2168,9 @@ static void fsl_gadget_disconnect_event(struct work_struct *work) u32 tmp; pdata = udc->pdata; - /* - * Some boards are very slow change line state from J to SE0 for DP, - * So, we need to discharge DP, otherwise there is a wakeup interrupt - * after we enable the wakeup function. - */ - gadget_wait_line_to_se0(); + + /* wait dp to 0v */ + dr_discharge_dp(pdata); /* * Wait class drivers finish, an well-behaviour class driver should @@ -2211,7 +2229,6 @@ bool try_wake_up_udc(struct fsl_udc *udc) fsl_writel(tmp | USB_CMD_RUN_STOP, &dr_regs->usbcmd); printk(KERN_DEBUG "%s: udc out low power mode\n", __func__); } else { - printk(KERN_INFO "USB device disconnected\n"); fsl_writel(tmp & ~USB_CMD_RUN_STOP, &dr_regs->usbcmd); /* here we need disable B_SESSION_IRQ, after * schedule_work finished, it need to be enabled again. diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index d34e7deb8b24..99ba497f5f5a 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 MontaVista Software - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -521,9 +521,6 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; - /* overwrite the default wakeup strategy */ - device_set_wakeup_enable(&hcd->self.root_hub->dev, false); - /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + @@ -553,6 +550,19 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) return retval; } +/* called after hcd send port_reset cmd */ +static int ehci_fsl_reset_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + struct fsl_usb2_platform_data *pdata; + + pdata = hcd->self.controller->platform_data; + + if (pdata->hsic_device_connected) + pdata->hsic_device_connected(); + + return 0; +} + static const struct hc_driver ehci_fsl_hc_driver = { .description = hcd_name, .product_desc = "Freescale On-Chip EHCI Host Controller", @@ -596,6 +606,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { .port_handed_over = ehci_port_handed_over, .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, + .reset_device = ehci_fsl_reset_device, }; static int ehci_fsl_drv_probe(struct platform_device *pdev) diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c index bb34f239215f..6172c0fa0775 100644 --- a/drivers/video/mxc/ldb.c +++ b/drivers/video/mxc/ldb.c @@ -532,7 +532,7 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, } /* clock setting */ - if (cpu_is_mx6q() && + if ((cpu_is_mx6q() || cpu_is_mx6dl()) && ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) ldb_clk[6] += lvds_channel; else @@ -582,7 +582,7 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, } setting_idx = 1; - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { setting->dev_id = plat_data->sec_ipu_id; setting->disp_id = plat_data->sec_disp_id; } else { @@ -628,7 +628,7 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, writel(reg, ldb->control_reg); /* clock setting */ - if (cpu_is_mx6q()) + if (cpu_is_mx6q() || cpu_is_mx6dl()) ldb_clk[6] += lvds_channel; else ldb_clk[6] += setting->disp_id; @@ -653,7 +653,7 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, ldb->setting[setting_idx].ch_mask = ch_mask; ldb->setting[setting_idx].ch_val = ch_val; - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { if ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)) { reg = readl(ldb->control_reg); reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); diff --git a/drivers/video/mxc/mipi_dsi.c b/drivers/video/mxc/mipi_dsi.c index c236ee7434ec..fa00ce177608 100644 --- a/drivers/video/mxc/mipi_dsi.c +++ b/drivers/video/mxc/mipi_dsi.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -454,6 +454,10 @@ static int mipi_dsi_power_on(struct mxc_dispdrv_handle *disp) if (!mipi_dsi->dsi_power_on) { clk_enable(mipi_dsi->dphy_clk); mipi_dsi_enable_controller(mipi_dsi, false); + mipi_dsi_set_mode(mipi_dsi, false); + /* host send pclk/hsync/vsync for two frames before sleep-out */ + msleep((1000/mipi_dsi->mode->refresh + 1) << 1); + mipi_dsi_set_mode(mipi_dsi, true); err = mipi_dsi_dcs_cmd(mipi_dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); if (err) { @@ -880,7 +884,6 @@ static struct mxc_dispdrv_driver mipi_dsi_drv = { .name = DISPDRV_MIPI, .init = mipi_dsi_disp_init, .deinit = mipi_dsi_disp_deinit, - .enable = mipi_dsi_power_on, .disable = mipi_dsi_power_off, }; diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c index 2fa655d345c5..e8a2b9761b65 100644 --- a/drivers/video/mxc/mxc_edid.c +++ b/drivers/video/mxc/mxc_edid.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -313,6 +313,42 @@ int mxc_edid_parse_ext_blk(unsigned char *edid, break; } case 0x1: /*Audio data block*/ + { + u8 audio_format, max_ch, byte1, byte2, byte3; + + i = 0; + cfg->max_channels = 0; + cfg->sample_rates = 0; + cfg->sample_sizes = 0; + + while (i < blklen) { + byte1 = edid[index + 1]; + byte2 = edid[index + 2]; + byte3 = edid[index + 3]; + index += 3; + i += 3; + + audio_format = byte1 >> 3; + max_ch = (byte1 & 0x07) + 1; + + DPRINTK("Audio Format Descriptor : %2d\n", audio_format); + DPRINTK("Max Number of Channels : %2d\n", max_ch); + DPRINTK("Sample Rates : %02x\n", byte2); + + /* ALSA can't specify specific compressed + * formats, so only care about PCM for now. */ + if (audio_format == AUDIO_CODING_TYPE_LPCM) { + if (max_ch > cfg->max_channels) + cfg->max_channels = max_ch; + + cfg->sample_rates |= byte2; + cfg->sample_sizes |= byte3 & 0x7; + DPRINTK("Sample Sizes : %02x\n", + byte3 & 0x7); + } + } + break; + } case 0x4: /*Speaker allocation block*/ case 0x7: /*User extended block*/ default: diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c index 0f4f15ede3da..eaa3032fc2e9 100644 --- a/drivers/video/mxc/mxc_ipuv3_fb.c +++ b/drivers/video/mxc/mxc_ipuv3_fb.c @@ -451,6 +451,15 @@ static int mxcfb_set_par(struct fb_info *fbi) ipu_enable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch); + if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->enable) { + retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv); + if (retval < 0) { + dev_err(fbi->device, "enable error, dispdrv:%s.\n", + mxc_fbi->dispdrv->drv->name); + return -EINVAL; + } + } + return retval; } diff --git a/drivers/video/mxc/mxcfb_hx8369_wvga.c b/drivers/video/mxc/mxcfb_hx8369_wvga.c index d8771fd3c1a3..ed6ffbc37530 100644 --- a/drivers/video/mxc/mxcfb_hx8369_wvga.c +++ b/drivers/video/mxc/mxcfb_hx8369_wvga.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -317,7 +317,10 @@ int mipid_hx8369_lcd_setup(struct mipi_dsi_info *mipi_dsi) buf[0] = MIPI_DCS_EXIT_SLEEP_MODE; mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM, buf, 0); - + /* To allow time for the supply voltages + * and clock circuits to stabilize. + */ + msleep(5); buf[0] = MIPI_DCS_SET_DISPLAY_ON; mipi_dsi_pkt_write(mipi_dsi, MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM, buf, 0); diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c index 6572c1b8e41e..0462f09a8fee 100644 --- a/drivers/video/mxc_hdmi.c +++ b/drivers/video/mxc_hdmi.c @@ -180,6 +180,8 @@ struct mxc_hdmi { struct i2c_client *hdmi_i2c; +static bool hdmi_inited; + extern const struct fb_videomode mxc_cea_mode[64]; #ifdef DEBUG @@ -1362,6 +1364,9 @@ static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi) if (ret < 0) return HDMI_EDID_FAIL; + /* Save edid cfg for audio driver */ + hdmi_set_edid_cfg(&hdmi->edid_cfg); + if (!memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN)) { dev_info(&hdmi->pdev->dev, "same edid\n"); return HDMI_EDID_SAME; @@ -1693,6 +1698,19 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__); } +static int mxc_hdmi_power_on(struct mxc_dispdrv_handle *disp) +{ + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp); + mxc_hdmi_phy_init(hdmi); + return 0; +} + +static void mxc_hdmi_power_off(struct mxc_dispdrv_handle *disp) +{ + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp); + mxc_hdmi_phy_disable(hdmi); +} + static void mxc_hdmi_cable_disconnected(struct mxc_hdmi *hdmi) { dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); @@ -2084,6 +2102,13 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp, dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); + /* Check hdmi disp init once */ + if (hdmi_inited) { + dev_err(&hdmi->pdev->dev, + "Error only one HDMI output support now!\n"); + return -1; + } + if (!plat || irq < 0) return -ENODEV; @@ -2208,6 +2233,8 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp, dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__); + hdmi_inited = true; + return ret; efbclient: @@ -2250,6 +2277,8 @@ static void mxc_hdmi_disp_deinit(struct mxc_dispdrv_handle *disp) platform_device_unregister(hdmi->pdev); + hdmi_inited = false; + kfree(hdmi); } @@ -2257,6 +2286,8 @@ static struct mxc_dispdrv_driver mxc_hdmi_drv = { .name = DISPDRV_HDMI, .init = mxc_hdmi_disp_init, .deinit = mxc_hdmi_disp_deinit, + .enable = mxc_hdmi_power_on, + .disable = mxc_hdmi_power_off, }; static int __devinit mxc_hdmi_probe(struct platform_device *pdev) @@ -2285,6 +2316,8 @@ static int __devinit mxc_hdmi_probe(struct platform_device *pdev) goto ecore; } + hdmi_inited = false; + hdmi->disp_mxc_hdmi = mxc_dispdrv_register(&mxc_hdmi_drv); if (IS_ERR(hdmi->disp_mxc_hdmi)) { dev_err(&pdev->dev, "Failed to register dispdrv - 0x%x\n", diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 395ddc7f0f96..e96cca48cbf8 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -123,6 +123,8 @@ struct fsl_usb2_platform_data { enum usb_wakeup_event (*is_wakeup_event)(struct fsl_usb2_platform_data *); void (*wakeup_handler)(struct fsl_usb2_platform_data *); void (*hsic_post_ops)(void); + void (*hsic_device_connected)(void); + void (*gadget_discharge_dp) (bool); struct fsl_usb2_wakeup_platform_data *wakeup_pdata; struct platform_device *pdev; diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index bf56b6f78270..233ca3b60ecf 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1445,6 +1445,43 @@ enum ieee80211_sa_query_action { #define WLAN_PMKID_LEN 16 +/* + * WMM/802.11e Tspec Element + */ +#define IEEE80211_WMM_IE_TSPEC_TID_MASK 0x0F +#define IEEE80211_WMM_IE_TSPEC_TID_SHIFT 1 + +enum ieee80211_tspec_status_code { + IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED = 0, + IEEE80211_TSPEC_STATUS_ADDTS_INVAL_PARAMS = 0x1, +}; + +struct ieee80211_tspec_ie { + u8 element_id; + u8 len; + u8 oui[3]; + u8 oui_type; + u8 oui_subtype; + u8 version; + __le16 tsinfo; + u8 tsinfo_resvd; + __le16 nominal_msdu; + __le16 max_msdu; + __le32 min_service_int; + __le32 max_service_int; + __le32 inactivity_int; + __le32 suspension_int; + __le32 service_start_time; + __le32 min_data_rate; + __le32 mean_data_rate; + __le32 peak_data_rate; + __le32 max_burst_size; + __le32 delay_bound; + __le32 min_phy_rate; + __le16 sba; + __le16 medium_time; +} __packed; + /** * ieee80211_get_qos_ctl - get pointer to qos control bytes * @hdr: the frame diff --git a/include/linux/mfd/mxc-hdmi-core.h b/include/linux/mfd/mxc-hdmi-core.h index 8c6ce456ddad..b607feec147a 100644 --- a/include/linux/mfd/mxc-hdmi-core.h +++ b/include/linux/mfd/mxc-hdmi-core.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,8 @@ #ifndef __LINUX_MXC_HDMI_CORE_H_ #define __LINUX_MXC_HDMI_CORE_H_ +#include <mach/mxc_edid.h> + #define IRQ_DISABLE_SUCCEED 0 #define IRQ_DISABLE_FAIL 1 @@ -38,6 +40,9 @@ void hdmi_set_sample_rate(unsigned int rate); void hdmi_init_clk_regenerator(void); void hdmi_clk_regenerator_update_pixel_clock(void); +void hdmi_set_edid_cfg(struct mxc_edid_cfg *cfg); +void hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg); + extern int mxc_hdmi_ipu_id; extern int mxc_hdmi_disp_id; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 686434404651..b8ed8398240b 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -401,7 +401,7 @@ struct mmc_driver { struct device_driver drv; int (*probe)(struct mmc_card *); void (*remove)(struct mmc_card *); - int (*suspend)(struct mmc_card *, pm_message_t); + int (*suspend)(struct mmc_card *); int (*resume)(struct mmc_card *); }; diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h index 69b6dbf46b5e..6659446591ec 100644 --- a/include/linux/mtd/gpmi-nand.h +++ b/include/linux/mtd/gpmi-nand.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,6 +51,7 @@ * @partitions: An optional pointer to an array of partition * descriptions. * @partition_count: The number of elements in the partitions array. + * @enable_bbt: Enable the BBT or not. */ struct gpmi_nand_platform_data { /* SoC hardware information. */ @@ -64,5 +65,6 @@ struct gpmi_nand_platform_data { /* Medium information. */ struct mtd_partition *partitions; unsigned partition_count; + unsigned int enable_bbt:1; }; #endif diff --git a/include/linux/mxc_v4l2.h b/include/linux/mxc_v4l2.h index e83e5923c2a4..dd106ff31265 100644 --- a/include/linux/mxc_v4l2.h +++ b/include/linux/mxc_v4l2.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -29,7 +29,8 @@ #define V4L2_CID_MXC_ROT (V4L2_CID_PRIVATE_BASE + 0) #define V4L2_CID_MXC_FLASH (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_MXC_VF_ROT (V4L2_CID_PRIVATE_BASE + 2) -#define V4L2_CID_MXC_MOTION (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_MXC_MOTION (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_MXC_SWITCH_CAM (V4L2_CID_PRIVATE_BASE + 6) #define V4L2_MXC_ROTATE_NONE 0 #define V4L2_MXC_ROTATE_VERT_FLIP 1 diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/include/linux/mxs-dma.h index 203d7c4a3e11..9186f908d207 100644 --- a/arch/arm/mach-mxs/include/mach/dma.h +++ b/include/linux/mxs-dma.h @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/include/linux/pxp_dma.h b/include/linux/pxp_dma.h index 8ae29b4ede8b..bf63bf3570e5 100644 --- a/include/linux/pxp_dma.h +++ b/include/linux/pxp_dma.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -109,6 +109,7 @@ struct rect { struct pxp_layer_param { unsigned short width; unsigned short height; + unsigned short stride; /* aka pitch */ unsigned int pixel_fmt; /* layers combining parameters diff --git a/sound/soc/codecs/cs42888.c b/sound/soc/codecs/cs42888.c index f2480cc1490f..bc88a719df6f 100644 --- a/sound/soc/codecs/cs42888.c +++ b/sound/soc/codecs/cs42888.c @@ -1,6 +1,6 @@ /* * cs42888.c -- CS42888 ALSA SoC Audio Driver - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* * The code contained herein is licensed under the GNU General Public @@ -807,7 +807,7 @@ static int cs42888_probe(struct snd_soc_codec *codec) dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } - if (cpu_is_mx6q()) { + if (cpu_is_mx6q() || cpu_is_mx6dl()) { for (i = 0; i < ARRAY_SIZE(cs42888->supplies); i++) cs42888->supplies[i].supply = cs42888_supply_names[i]; diff --git a/sound/soc/codecs/mxc_hdmi.c b/sound/soc/codecs/mxc_hdmi.c index c6a6bcbdbfd9..70c9b8c9bfe0 100644 --- a/sound/soc/codecs/mxc_hdmi.c +++ b/sound/soc/codecs/mxc_hdmi.c @@ -1,7 +1,7 @@ /* * MXC HDMI ALSA Soc Codec Driver * - * Copyright (C) 2011 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. */ /* @@ -42,6 +42,7 @@ #include <mach/hardware.h> #include <linux/mfd/mxc-hdmi-core.h> +#include <mach/mxc_edid.h> #include <mach/mxc_hdmi.h> #include "../imx/imx-hdmi.h" @@ -53,6 +54,16 @@ struct mxc_hdmi_priv { struct clk *iahb_clk; }; +static struct mxc_edid_cfg edid_cfg; + +static unsigned int playback_rates[HDMI_MAX_RATES]; +static unsigned int playback_sample_size[HDMI_MAX_SAMPLE_SIZE]; +static unsigned int playback_channels[HDMI_MAX_CHANNEL_CONSTRAINTS]; + +static struct snd_pcm_hw_constraint_list playback_constraint_rates; +static struct snd_pcm_hw_constraint_list playback_constraint_bits; +static struct snd_pcm_hw_constraint_list playback_constraint_channels; + #ifdef DEBUG static void dumpregs(void) { @@ -100,19 +111,126 @@ static void hdmi_set_audio_infoframe(void) hdmi_writeb(0x00, HDMI_FC_AUDICONF2); } -static unsigned int hdmi_playback_rates[] = { 32000, 44100, 48000, 88200, 96000 }; - -static struct snd_pcm_hw_constraint_list playback_rate_constraints = { - .count = ARRAY_SIZE(hdmi_playback_rates), - .list = hdmi_playback_rates, - .mask = 0, +static int cea_audio_rates[HDMI_MAX_RATES] = { + 32000, + 44100, + 48000, + 88200, + 96000, + 176400, + 192000, }; +static void mxc_hdmi_get_playback_rates(void) +{ + int i, count = 0; + u8 rates; + + /* always assume basic audio support */ + rates = edid_cfg.sample_rates | 0x7; + + for (i = 0 ; i < HDMI_MAX_RATES ; i++) + if ((rates & (1 << i)) != 0) + playback_rates[count++] = cea_audio_rates[i]; + + playback_constraint_rates.list = playback_rates; + playback_constraint_rates.count = count; + +#ifdef DEBUG + for (i = 0 ; i < playback_constraint_rates.count ; i++) + pr_debug("%s: constraint = %d Hz\n", __func__, + playback_rates[i]); +#endif +} + +static void mxc_hdmi_get_playback_sample_size(void) +{ + int i = 0; + + /* always assume basic audio support */ + playback_sample_size[i++] = 16; + + if (edid_cfg.sample_sizes & 0x2) + playback_sample_size[i++] = 20; + + if (edid_cfg.sample_sizes & 0x4) + playback_sample_size[i++] = 24; + + playback_constraint_bits.list = playback_sample_size; + playback_constraint_bits.count = i; + +#ifdef DEBUG + for (i = 0 ; i < playback_constraint_bits.count ; i++) + pr_debug("%s: constraint = %d bits\n", __func__, + playback_sample_size[i]); +#endif +} + +static void mxc_hdmi_get_playback_channels(void) +{ + int channels = 2, i = 0; + + /* always assume basic audio support */ + playback_channels[i++] = channels; + channels += 2; + + while ((i < HDMI_MAX_CHANNEL_CONSTRAINTS) && + (channels <= edid_cfg.max_channels)) { + playback_channels[i++] = channels; + channels += 2; + } + + playback_constraint_channels.list = playback_channels; + playback_constraint_channels.count = i; + +#ifdef DEBUG + for (i = 0 ; i < playback_constraint_channels.count ; i++) + pr_debug("%s: constraint = %d channels\n", __func__, + playback_channels[i]); +#endif +} + +static int mxc_hdmi_update_constraints(struct mxc_hdmi_priv *priv, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + hdmi_get_edid_cfg(&edid_cfg); + + mxc_hdmi_get_playback_rates(); + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &playback_constraint_rates); + if (ret < 0) + return ret; + + mxc_hdmi_get_playback_sample_size(); + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + &playback_constraint_bits); + if (ret < 0) + return ret; + + mxc_hdmi_get_playback_channels(); + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &playback_constraint_channels); + if (ret < 0) + return ret; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + return 0; +} + static int mxc_hdmi_codec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct mxc_hdmi_priv *hdmi_priv = snd_soc_dai_get_drvdata(dai); - struct snd_pcm_runtime *runtime = substream->runtime; int ret; clk_enable(hdmi_priv->isfr_clk); @@ -122,14 +240,7 @@ static int mxc_hdmi_codec_startup(struct snd_pcm_substream *substream, (int)clk_get_rate(hdmi_priv->isfr_clk), (int)clk_get_rate(hdmi_priv->iahb_clk)); - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &playback_rate_constraints); - if (ret < 0) - return ret; - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); + ret = mxc_hdmi_update_constraints(hdmi_priv, substream); if (ret < 0) return ret; diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 7ba4e8ad7bd6..07153b90d13e 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -24,5 +24,6 @@ obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o +obj-$(CONFIG_SND_SOC_IMX_CS42888) += snd-soc-imx-cs42888.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o diff --git a/sound/soc/imx/imx-cs42888.c b/sound/soc/imx/imx-cs42888.c index 4e97ec246792..26745d35b936 100644 --- a/sound/soc/imx/imx-cs42888.c +++ b/sound/soc/imx/imx-cs42888.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -117,7 +117,7 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, pr_info("Rate not support.\n"); return -EINVAL;; } - } else if (cpu_is_mx6q()) { + } else if (cpu_is_mx6q() || cpu_is_mx6dl()) { switch (rate) { case 32000: lrclk_ratio = 5; @@ -163,7 +163,7 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, if (cpu_is_mx53()) { snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL, mclk_freq, SND_SOC_CLOCK_OUT); - } else if (cpu_is_mx6q()) { + } else if (cpu_is_mx6q() || cpu_is_mx6dl()) { snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL_DIV, mclk_freq, SND_SOC_CLOCK_OUT); } @@ -171,14 +171,14 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1); if (cpu_is_mx53()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0); - else if (cpu_is_mx6q()) + else if (cpu_is_mx6q() || cpu_is_mx6dl()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 2); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1); if (cpu_is_mx53()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0); - else if (cpu_is_mx6q()) + else if (cpu_is_mx6q() || cpu_is_mx6dl()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 2); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio); diff --git a/sound/soc/imx/imx-hdmi-dma.c b/sound/soc/imx/imx-hdmi-dma.c index 9ce99efccc1b..d0c4d52e9c56 100644 --- a/sound/soc/imx/imx-hdmi-dma.c +++ b/sound/soc/imx/imx-hdmi-dma.c @@ -649,14 +649,6 @@ static struct snd_pcm_hardware snd_imx_hardware = { .fifo_size = 0, }; -static unsigned int hw_channels[] = {2, 4, 6, 8}; - -static struct snd_pcm_hw_constraint_list hw_constraint_channels = { - .count = ARRAY_SIZE(hw_channels), - .list = hw_channels, - .mask = 0, -}; - static void hdmi_dma_irq_enable(struct imx_hdmi_dma_runtime_data *rtd) { unsigned long flags; @@ -712,12 +704,6 @@ static int hdmi_dma_open(struct snd_pcm_substream *substream) if (ret < 0) return ret; - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraint_channels); - if (ret < 0) - return ret; - snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); hdmi_dma_irq_enable(hdmi_dma_priv); diff --git a/sound/soc/imx/imx-hdmi.h b/sound/soc/imx/imx-hdmi.h index 52c58dd516d5..11737579af31 100644 --- a/sound/soc/imx/imx-hdmi.h +++ b/sound/soc/imx/imx-hdmi.h @@ -1,7 +1,7 @@ /* * MXC HDMI ALSA Soc Codec Driver * - * Copyright (C) 2011 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. */ /* @@ -31,11 +31,17 @@ struct imx_hdmi { struct platform_device *soc_platform_pdev; }; +#define HDMI_MAX_RATES 7 +#define HDMI_MAX_SAMPLE_SIZE 3 +#define HDMI_MAX_CHANNEL_CONSTRAINTS 4 + #define MXC_HDMI_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \ SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | \ SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000) + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | \ + SNDRV_PCM_RATE_192000) #define MXC_HDMI_FORMATS_PLAYBACK (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_LE) |
