diff options
Diffstat (limited to 'arch')
180 files changed, 30988 insertions, 2170 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 36586dba6fa..2e1b250151a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -73,6 +73,10 @@ config KTIME_SCALAR bool default y +config KTIME_SCALAR + bool + default y + config HAVE_TCM bool select GENERIC_ALLOCATOR @@ -933,9 +937,11 @@ config ARCH_U8500 select GENERIC_CLOCKEVENTS select CLKDEV_LOOKUP select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK select ARCH_HAS_CPUFREQ select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 + select NOMADIK_GPIO help Support for ST-Ericsson's Ux500 architecture @@ -1609,7 +1615,7 @@ config LOCAL_TIMERS config ARCH_NR_GPIO int default 1024 if ARCH_SHMOBILE || ARCH_TEGRA - default 355 if ARCH_U8500 + default 366 if ARCH_U8500 default 264 if MACH_H4700 default 0 help @@ -1756,7 +1762,9 @@ source "mm/Kconfig" config FORCE_MAX_ZONEORDER int "Maximum zone order" if ARCH_SHMOBILE range 11 64 if ARCH_SHMOBILE + depends on SA1111 || UX500_SOC_DB8500 default "9" if SA1111 + default "12" if UX500_SOC_DB8500 default "11" help The kernel memory allocator divides physically contiguous memory @@ -2071,6 +2079,13 @@ config KEXEC initially work for you. It may help to enable device hotplugging support. +config CRASH_SWRESET + bool "Perform a software reset at a panic (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on KEXEC + help + If no crash kernel has been loaded, perform a SW reset as plan B. + config ATAGS_PROC bool "Export atags in procfs" depends on KEXEC diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 85348a09d65..6ca82db8d21 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -318,6 +318,15 @@ config EARLY_PRINTK kernel low-level debugging functions. Add earlyprintk to your kernel parameters to enable this console. +config PRINTK_LL + bool "Use printascii in printk" + depends on DEBUG_LL + help + Say Y here if you want to have printk send its output via the + kernel low-level debugging functions. This is useful if you + are debugging code that executes before the earlyprintk console + is initialized. + config OC_ETM bool "On-chip ETM and ETB" depends on ARM_AMBA diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 215816f1775..d5b5aa2fe3c 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_ARCH_IXP2000) += uengine.o obj-$(CONFIG_ARCH_IXP23XX) += uengine.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o +obj-$(CONFIG_BOOTTIME) += boottime.o diff --git a/arch/arm/common/boottime.c b/arch/arm/common/boottime.c new file mode 100644 index 00000000000..73e9e04ed37 --- /dev/null +++ b/arch/arm/common/boottime.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) ST-Ericsson SA 2009-2010 + * + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + * License terms: GNU General Public License (GPL) version 2 + * + * Store boot times measured during for example u-boot startup. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/boottime.h> +#include <linux/string.h> +#include <asm/setup.h> + +static u32 bootloader_idle; +static u32 bootloader_total; + +static int __init boottime_parse_tag(const struct tag *tag) +{ + int i; + char buff[BOOTTIME_MAX_NAME_LEN]; + + bootloader_idle = tag->u.boottime.idle; + bootloader_total = tag->u.boottime.total; + + for (i = 0; i < tag->u.boottime.num; i++) { + snprintf(buff, BOOTTIME_MAX_NAME_LEN, "%s+0x0/0x0", + tag->u.boottime.entry[i].name); + buff[BOOTTIME_MAX_NAME_LEN - 1] = '\0'; + boottime_mark_wtime(buff, tag->u.boottime.entry[i].time); + } + + return 0; +} + +__tagtable(ATAG_BOOTTIME, boottime_parse_tag); + +int boottime_bootloader_idle(void) +{ + if (bootloader_total == 0) + return 0; + + return (int) ((bootloader_idle) / (bootloader_total / 100)); +} diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig new file mode 100644 index 00000000000..62d360df4f4 --- /dev/null +++ b/arch/arm/configs/u8500_android_defconfig @@ -0,0 +1,344 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_PROFILING=y +CONFIG_BOOTTIME=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_BLKDEV_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_DEFAULT_DEADLINE=y +CONFIG_ARCH_U8500=y +CONFIG_UX500_SOC_DB8500=y +CONFIG_MACH_HREFV60=y +CONFIG_MACH_U8520=y +CONFIG_MACH_SNOWBALL=y +CONFIG_MACH_U9540=y +CONFIG_UX500_GPIO_KEYS=y +CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_DB8500_PWR_TEST=y +# CONFIG_UX500_USECASE_GOVERNOR is not set +CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y +CONFIG_DB8500_MLOADER=y +CONFIG_PCCARD=y +# CONFIG_PCMCIA is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" +CONFIG_KEXEC=y +CONFIG_CRASH_SWRESET=y +CONFIG_CRASH_DUMP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y +CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 +CONFIG_UX500_CPUIDLE_DEBUG=y +CONFIG_FPE_NWFPE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_WAKELOCK=y +CONFIG_PM_RUNTIME=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_LRO is not set +CONFIG_IPV6=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_IPV6_SIT is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_TPROXY=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_PHONET=y +CONFIG_NET_SCHED=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_REGULATOR=y +CONFIG_RFKILL_GPIO=y +CONFIG_NET_9P=y +CONFIG_CAIF=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=73728 +CONFIG_AB8500_PWM=y +CONFIG_SENSORS_BH1780=y +CONFIG_STE_TRACE_MODEM=y +CONFIG_DISPDEV=y +CONFIG_U8500_SIM_DETECT=y +CONFIG_STM_TRACE=y +CONFIG_STM_DEFAULT_MASTERS_MODES=0x20 +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_NETDEVICES=y +CONFIG_TUN=y +CONFIG_CAIF_TTY=m +CONFIG_CAIF_HSI=m +CONFIG_SMSC911X=y +CONFIG_SMSC_PHY=y +CONFIG_PPP=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_ASYNC=y +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_NOMADIK_SKE=y +CONFIG_KEYBOARD_TC3589X=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_CYTTSP_CORE=y +CONFIG_TOUCHSCREEN_CYTTSP_SPI=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AB8500_ACCDET=y +CONFIG_INPUT_AB8500_PONKEY=y +CONFIG_INPUT_UINPUT=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_NOMADIK=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_NOMADIK=y +CONFIG_SPI=y +CONFIG_SPI_PL022=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_TC3589X=y +CONFIG_GPIO_AB8500=y +CONFIG_POWER_SUPPLY=y +CONFIG_AB8500_BM=y +CONFIG_SENSORS_AB8500=y +CONFIG_SENSORS_DBX500=y +CONFIG_SENSORS_LSM303DLH=y +CONFIG_SENSORS_LSM303DLHC=y +CONFIG_SENSORS_L3G4200D=y +CONFIG_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_UX500_WATCHDOG_DEBUG=y +CONFIG_MFD_TC3589X=y +CONFIG_AB5500_CORE=y +CONFIG_AB8500_CORE=y +CONFIG_MFD_DB8500_PRCMU=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_DB8500_PRCMU=y +CONFIG_REGULATOR_AB8500_DEBUG=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_RADIO_CG2900=y +CONFIG_GPU_MALI=y +CONFIG_FB=y +CONFIG_FB_MCDE=y +CONFIG_MCDE_FB_AVOID_REALLOC=y +CONFIG_MCDE_DISPLAY_GENERIC_DSI=y +CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y +CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y +CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE=y +CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_FB_B2R2=y +CONFIG_B2R2_PLUG_CONF=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_UX500_AB5500=y +CONFIG_SND_SOC_UX500_AB8500=y +CONFIG_SND_SOC_UX500_CG29XX=y +CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_HIDRAW=y +CONFIG_USB=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_MON=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_UX500=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_G_ANDROID=y +CONFIG_AB8500_USB=y +CONFIG_MMC=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_MMC_ARMMMCI=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_LM3530=y +CONFIG_LEDS_LP5521=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AB=y +CONFIG_RTC_DRV_AB8500=y +CONFIG_DMADEVICES=y +CONFIG_STE_DMA40=y +CONFIG_STAGING=y +CONFIG_AB5500_SIM=y +CONFIG_CG2900=y +CONFIG_CG2900_CHIP=y +CONFIG_STLC2690_CHIP=y +CONFIG_CG2900_UART=y +CONFIG_CG2900_AUDIO=y +CONFIG_CG2900_TEST=y +CONFIG_BT_CG2900=y +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_RAM_CONSOLE=y +CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_CW1200=m +CONFIG_CW1200_USE_GPIO_IRQ=y +CONFIG_CW1200_DEBUGFS=y +CONFIG_U8500_MMIO=y +CONFIG_U8500_CM=y +CONFIG_U8500_FLASH=y +CONFIG_HSEM_U8500=y +CONFIG_MODEM_U8500=y +CONFIG_U8500_SHRM=y +CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HFS_FS=m +CONFIG_BEFS_FS=m +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_9P_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_INFO=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_FUNCTION_TRACER=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_USER=y +CONFIG_KEYS=y +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DEV_UX500=y +CONFIG_CRYPTO_DEV_UX500_HASH=y +CONFIG_CRC7=y +CONFIG_LIBCRC32C=m diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 7e84f453e8a..30e88eb8985 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,117 +1,322 @@ CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_PROFILING=y +CONFIG_BOOTTIME=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -# CONFIG_LBDAF is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_BLKDEV_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_DEFAULT_DEADLINE=y CONFIG_ARCH_U8500=y +CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y +CONFIG_MACH_U8520=y CONFIG_MACH_SNOWBALL=y -CONFIG_MACH_U5500=y +CONFIG_MACH_U9540=y +CONFIG_MACH_U8500_SNOWBALL=y CONFIG_MACH_UX500_DT=y +CONFIG_UX500_GPIO_KEYS=y +CONFIG_DBX500_PRCMU_DEBUG=y +CONFIG_DB8500_PWR_TEST=y +CONFIG_DB8500_MLOADER=y +CONFIG_PCCARD=y +# CONFIG_PCMCIA is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y +CONFIG_SCHED_MC=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_AEABI=y -CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" +# CONFIG_OABI_COMPAT is not set +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" +CONFIG_KEXEC=y +CONFIG_CRASH_SWRESET=y +CONFIG_CRASH_DUMP=y CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM_RUNTIME=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_LRO is not set +CONFIG_IPV6=y +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_IPV6_SIT is not set +CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_NETFILTER=y +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_TPROXY=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y CONFIG_PHONET=y -# CONFIG_WIRELESS is not set +CONFIG_NET_SCHED=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=y CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_BLK_DEV_RAM_SIZE=73728 CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y +CONFIG_STE_TRACE_MODEM=y +CONFIG_DISPDEV=y +CONFIG_U8500_SIM_DETECT=y +CONFIG_STM_TRACE=y +CONFIG_STM_DEFAULT_MASTERS_MODES=0x20 +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y +CONFIG_TUN=y +CONFIG_CAIF_TTY=m +CONFIG_CAIF_HSI=m CONFIG_SMSC911X=y CONFIG_SMSC_PHY=y +CONFIG_PPP=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_ASYNC=y # CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +# CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_GPIO=y -CONFIG_KEYBOARD_NOMADIK=y -CONFIG_KEYBOARD_STMPE=y +CONFIG_KEYBOARD_NOMADIK_SKE=y CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_BU21013=y +CONFIG_TOUCHSCREEN_CYTTSP_CORE=y +CONFIG_TOUCHSCREEN_CYTTSP_SPI=y CONFIG_INPUT_MISC=y +CONFIG_INPUT_AB8500_ACCDET=y CONFIG_INPUT_AB8500_PONKEY=y -# CONFIG_SERIO is not set +CONFIG_INPUT_UINPUT=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_NOMADIK=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_NOMADIK=y CONFIG_SPI=y CONFIG_SPI_PL022=y -CONFIG_GPIO_STMPE=y +CONFIG_GPIO_SYSFS=y CONFIG_GPIO_TC3589X=y +CONFIG_GPIO_AB8500=y CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y -CONFIG_MFD_STMPE=y +CONFIG_SENSORS_AB8500=y +CONFIG_SENSORS_DBX500=y +CONFIG_SENSORS_LSM303DLH=y +CONFIG_SENSORS_LSM303DLHC=y +CONFIG_SENSORS_L3G4200D=y +CONFIG_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_UX500_WATCHDOG_DEBUG=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y +CONFIG_MFD_DB8500_PRCMU=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y CONFIG_REGULATOR_AB8500=y -# CONFIG_HID_SUPPORT is not set +CONFIG_REGULATOR_DB8500_PRCMU=y +CONFIG_REGULATOR_AB8500_DEBUG=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +# CONFIG_VIDEO_CAPTURE_DRIVERS is not set +CONFIG_RADIO_CG2900=y +CONFIG_DRM=y +CONFIG_GPU_MALI=y +CONFIG_FB=y +CONFIG_FB_MCDE=y +CONFIG_MCDE_FB_AVOID_REALLOC=y +CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0=y +CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI=y +CONFIG_MCDE_DISPLAY_AV8100=y +# CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE is not set +CONFIG_AV8100_HWTRIG_I2SDAT3=y +CONFIG_FB_B2R2=y +CONFIG_B2R2_PLUG_CONF=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_UX500_AB5500=y +CONFIG_SND_SOC_UX500_AB8500=y +CONFIG_SND_SOC_UX500_CG29XX=y +CONFIG_SND_SOC_UX500_AV8100=y +CONFIG_HIDRAW=y +CONFIG_USB=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +CONFIG_USB_MON=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_UX500=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_FILE_STORAGE=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_MULTI=m +# CONFIG_USB_G_MULTI_RNDIS is not set +CONFIG_USB_G_HID=m CONFIG_AB8500_USB=y CONFIG_MMC=y -CONFIG_MMC_CLKGATE=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y -CONFIG_LEDS_LM3530=y -CONFIG_LEDS_LP5521=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AB=y CONFIG_RTC_DRV_AB8500=y -CONFIG_RTC_DRV_PL031=y CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y +CONFIG_AB5500_SIM=y +CONFIG_CG2900=y +CONFIG_CG2900_CHIP=y +CONFIG_STLC2690_CHIP=y +CONFIG_CG2900_UART=y +CONFIG_CG2900_AUDIO=y +CONFIG_CG2900_TEST=y +CONFIG_BT_CG2900=y CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y +CONFIG_CW1200=m +CONFIG_CW1200_USE_GPIO_IRQ=y +CONFIG_CW1200_DEBUGFS=y +CONFIG_U8500_MMIO=y +CONFIG_U8500_CM=y +CONFIG_U8500_FLASH=y CONFIG_HSEM_U8500=y +CONFIG_MODEM_U8500=y +CONFIG_U8500_SHRM=y +CONFIG_U8500_SHRM_MODEM_SILENT_RESET=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -CONFIG_CONFIGFS_FS=m -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y +CONFIG_9P_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y -# CONFIG_SCHED_DEBUG is not set +CONFIG_UNUSED_SYMBOLS=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y # CONFIG_DEBUG_PREEMPT is not set CONFIG_DEBUG_INFO=y -# CONFIG_FTRACE is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_FUNCTION_TRACER=y +CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_USER=y +CONFIG_KEYS=y +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DEV_UX500=y +CONFIG_CRYPTO_DEV_UX500_HASH=y +CONFIG_CRC7=y diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index d5d8d5c7268..a4bf3199819 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -84,6 +84,14 @@ * - kaddr - page address * - size - region size * + * clean_dcache_all() + * + * Cleans the entire d-cache. + * + * flush_dcache_all() + * + * Flushes the entire d-cache. + * * DMA Cache Coherency * =================== * @@ -104,6 +112,9 @@ struct cpu_cache_fns { void (*coherent_user_range)(unsigned long, unsigned long); void (*flush_kern_dcache_area)(void *, size_t); + void (*clean_dcache_all)(void); + void (*flush_dcache_all)(void); + void (*dma_map_area)(const void *, size_t, int); void (*dma_unmap_area)(const void *, size_t, int); @@ -124,6 +135,8 @@ extern struct cpu_cache_fns cpu_cache; #define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range #define __cpuc_coherent_user_range cpu_cache.coherent_user_range #define __cpuc_flush_dcache_area cpu_cache.flush_kern_dcache_area +#define __cpuc_clean_dcache_all cpu_cache.clean_dcache_all +#define __cpuc_flush_dcache_all cpu_cache.flush_dcache_all /* * These are private to the dma-mapping API. Do not use directly. @@ -144,6 +157,8 @@ extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); extern void __cpuc_coherent_user_range(unsigned long, unsigned long); extern void __cpuc_flush_dcache_area(void *, size_t); +extern void __cpuc_clean_dcache_all(void); +extern void __cpuc_flush_dcache_all(void); /* * These are private to the dma-mapping API. Do not use directly. diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index b2deda18154..91063a3976f 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -8,7 +8,7 @@ #include <asm/param.h> /* HZ */ -extern void __delay(int loops); +extern void __delay(unsigned long loops); /* * This function intentionally does not exist; if you see references to @@ -40,5 +40,14 @@ extern void __const_udelay(unsigned long); __const_udelay((n) * ((2199023U*HZ)>>11))) : \ __udelay(n)) +extern void (*delay_fn)(unsigned long); + +static inline void set_delay_fn(void (*fn)(unsigned long)) +{ + delay_fn = fn; +} + +extern void read_current_timer_delay_loop(unsigned long loops); + #endif /* defined(_ARM_DELAY_H) */ diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index 38050b1c480..cd644aade4c 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -96,8 +96,8 @@ struct elf32_hdr; /* * This is used to ensure we don't load something for the wrong architecture. */ -extern int elf_check_arch(const struct elf32_hdr *); -#define elf_check_arch elf_check_arch +extern int arm_elf_check_arch(const struct elf32_hdr *); +#define elf_check_arch(x) arm_elf_check_arch((const struct elf32_hdr *)(x)) #define vmcore_elf64_check_arch(x) (0) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 9af5563dd3e..d9a9a19cb68 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -63,6 +63,12 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define MT_DEVICE_CACHED 2 #define MT_DEVICE_WC 3 /* + * NOTE : U8500 v1.0/ED cut specific hack. + * look at the commit message for more details + */ +#define MT_BACKUP_RAM 4 + +/* * types 4 onwards can be found in asm/mach/map.h and are undefined * for ioremap */ diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 53426c66352..e76b9eae8e4 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -33,6 +33,8 @@ struct outer_cache_fns { #ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void); #endif + void (*prefetch_enable)(void); + void (*prefetch_disable)(void); void (*set_debug)(unsigned long); void (*resume)(void); }; @@ -81,6 +83,18 @@ static inline void outer_resume(void) outer_cache.resume(); } +static inline void outer_prefetch_enable(void) +{ + if (outer_cache.prefetch_enable) + outer_cache.prefetch_enable(); +} + +static inline void outer_prefetch_disable(void) +{ + if (outer_cache.prefetch_disable) + outer_cache.prefetch_disable(); +} + #else static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 23ebc0c82a3..ea1384fea05 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -143,6 +143,23 @@ struct tag_memclk { __u32 fmemclk; }; +/* for automatic boot timing testcases */ +#define ATAG_BOOTTIME 0x41000403 +#define BOOTTIME_MAX_NAME_LEN 64 +#define BOOTTIME_MAX 10 + +struct boottime_entry { + u32 time; /* in us */ + u8 name[BOOTTIME_MAX_NAME_LEN]; +}; + +struct tag_boottime { + struct boottime_entry entry[BOOTTIME_MAX]; + u32 idle; /* in us */ + u32 total; /* in us */ + u8 num; +}; + struct tag { struct tag_header hdr; union { @@ -165,6 +182,10 @@ struct tag { * DC21285 specific */ struct tag_memclk memclk; + /* + * Boot time + */ + struct tag_boottime boottime; } u; }; diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index 0f01f4677bd..e0faaeb30ea 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h @@ -42,4 +42,12 @@ static inline void twd_local_timer_of_register(void) } #endif +#if defined(CONFIG_HOTPLUG) || defined(CONFIG_CPU_IDLE) +void twd_save(void); +void twd_restore(void); +#else +static inline void twd_save(void) { } +static inline void twd_restore(void) { } +#endif + #endif diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index b57c75e0b01..f1a50f37efd 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -48,10 +48,6 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); - /* platform dependent support */ -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__const_udelay); - /* networking */ EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_from_user); diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index d0d1e83150c..6602eae1527 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c @@ -5,11 +5,13 @@ #include <linux/elf.h> #include <asm/system_info.h> -int elf_check_arch(const struct elf32_hdr *x) +int arm_elf_check_arch(const struct elf32_hdr *x) { unsigned int eflags; /* Make sure it's an ARM executable */ + if (x->e_ident[EI_CLASS] != ELF_CLASS) + return 0; if (x->e_machine != EM_ARM) return 0; @@ -36,7 +38,7 @@ int elf_check_arch(const struct elf32_hdr *x) } return 1; } -EXPORT_SYMBOL(elf_check_arch); +EXPORT_SYMBOL(arm_elf_check_arch); void elf_set_personality(const struct elf32_hdr *x) { diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ba386bd9410..180dd9f5b19 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -853,6 +853,25 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, return ret; } +static int hw_breakpoint_undef(struct pt_regs *regs, unsigned int instr) +{ + int reg = (instr >> 12) & 15; + + /* Fake sticky power-down cleared */ + regs->uregs[reg] = 0; + regs->ARM_pc += 4; + + return 0; +} + +static struct undef_hook hw_breakpoint_hook = { + .instr_mask = 0xffff0fff, + .instr_val = 0xee110e95, + .cpsr_mask = MODE_MASK, + .cpsr_val = SVC_MODE, + .fn = hw_breakpoint_undef, +}; + /* * One-time initialisation. */ @@ -899,6 +918,10 @@ static void reset_ctrl_regs(void *unused) /* * Ensure sticky power-down is clear (i.e. debug logic is * powered up). + * + * This could raise an undefined instruction exception. If it + * does, it is fixed up with an undef hook which constructs + * a fake value with the sticky power-down bit cleared. */ asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power)); if ((dbg_power & 0x1) == 0) @@ -986,6 +1009,8 @@ static int __init arch_hw_breakpoint_init(void) */ register_undef_hook(&debug_reg_hook); + register_undef_hook(&hw_breakpoint_hook); + /* * Reset the breakpoint resources. We assume that a halting * debugger will leave the world in a nice state for us. diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index dfcdb9f7c12..4f868fc5174 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -47,6 +47,7 @@ void machine_crash_nonpanic_core(void *unused) printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n", smp_processor_id()); crash_save_cpu(®s, smp_processor_id()); + atomic_notifier_call_chain(&crash_percpu_notifier_list, 0, NULL); flush_cache_all(); atomic_dec(&waiting_for_crash_ipi); @@ -83,6 +84,8 @@ void machine_crash_shutdown(struct pt_regs *regs) local_irq_disable(); + atomic_notifier_call_chain(&crash_percpu_notifier_list, 0, NULL); + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); smp_call_function(machine_crash_nonpanic_core, NULL, false); msecs = 1000; /* Wait at most a second for the other cpus to stop */ @@ -138,3 +141,13 @@ void machine_kexec(struct kimage *image) soft_restart(reboot_code_buffer_phys); } + +void machine_crash_swreset(void) +{ + printk(KERN_INFO "Software reset on panic!\n"); + + flush_cache_all(); + outer_flush_all(); + outer_disable(); + arm_pm_restart(0, NULL); +} diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 2b7b017a20c..5b644d3e831 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -212,8 +212,17 @@ void cpu_idle(void) leds_event(led_idle_start); while (!need_resched()) { #ifdef CONFIG_HOTPLUG_CPU - if (cpu_is_offline(smp_processor_id())) + if (cpu_is_offline(smp_processor_id())) { + + /* NOTE : preempt_count() should be 0 for dying CPU + * as the CPU will use this very thread when + * it is alive + */ + if (preempt_count()) + preempt_enable_no_resched(); + cpu_die(); + } #endif /* diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index 8085417555d..0697db65efa 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -58,10 +58,6 @@ void *return_address(unsigned int level) #else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */ -#if defined(CONFIG_ARM_UNWIND) -#warning "TODO: return_address should use unwind tables" -#endif - void *return_address(unsigned int level) { return NULL; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8f464465977..d0029d1ef7e 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -275,8 +275,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) notify_cpu_starting(cpu); - calibrate_delay(); - smp_store_cpu_info(cpu); /* @@ -423,7 +421,7 @@ static void ipi_timer(void) } #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST -static void smp_timer_broadcast(const struct cpumask *mask) +void smp_timer_broadcast(const struct cpumask *mask) { smp_cross_call(mask, IPI_TIMER); } diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index fef42b21cec..33e4a0456c3 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -33,6 +33,9 @@ static void __iomem *twd_base; static struct clk *twd_clk; static unsigned long twd_timer_rate; +static DEFINE_PER_CPU(u32, twd_ctrl); +static DEFINE_PER_CPU(u32, twd_load); + static struct clock_event_device __percpu **twd_evt; static int twd_ppi; @@ -345,3 +348,24 @@ out: WARN(err, "twd_local_timer_of_register failed (%d)\n", err); } #endif + +#if defined(CONFIG_HOTPLUG) || defined(CONFIG_CPU_IDLE) +void twd_save(void) +{ + int this_cpu = smp_processor_id(); + + per_cpu(twd_ctrl, this_cpu) = __raw_readl(twd_base + TWD_TIMER_CONTROL); + per_cpu(twd_load, this_cpu) = __raw_readl(twd_base + TWD_TIMER_LOAD); + +} + +void twd_restore(void) +{ + int this_cpu = smp_processor_id(); + + __raw_writel(per_cpu(twd_ctrl, this_cpu), + twd_base + TWD_TIMER_CONTROL); + __raw_writel(per_cpu(twd_load, this_cpu), + twd_base + TWD_TIMER_LOAD); +} +#endif diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S deleted file mode 100644 index 3c9a05c8d20..00000000000 --- a/arch/arm/lib/delay.S +++ /dev/null @@ -1,69 +0,0 @@ -/* - * linux/arch/arm/lib/delay.S - * - * Copyright (C) 1995, 1996 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/linkage.h> -#include <asm/assembler.h> -#include <asm/param.h> - .text - -.LC0: .word loops_per_jiffy -.LC1: .word (2199023*HZ)>>11 - -/* - * r0 <= 2000 - * lpj <= 0x01ffffff (max. 3355 bogomips) - * HZ <= 1000 - */ - -ENTRY(__udelay) - ldr r2, .LC1 - mul r0, r2, r0 -ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 - mov r1, #-1 - ldr r2, .LC0 - ldr r2, [r2] @ max = 0x01ffffff - add r0, r0, r1, lsr #32-14 - mov r0, r0, lsr #14 @ max = 0x0001ffff - add r2, r2, r1, lsr #32-10 - mov r2, r2, lsr #10 @ max = 0x00007fff - mul r0, r2, r0 @ max = 2^32-1 - add r0, r0, r1, lsr #32-6 - movs r0, r0, lsr #6 - moveq pc, lr - -/* - * loops = r0 * HZ * loops_per_jiffy / 1000000 - * - * Oh, if only we had a cycle counter... - */ - -@ Delay routine -ENTRY(__delay) - subs r0, r0, #1 -#if 0 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 - movls pc, lr - subs r0, r0, #1 -#endif - bhi __delay - mov pc, lr -ENDPROC(__udelay) -ENDPROC(__const_udelay) -ENDPROC(__delay) diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c new file mode 100644 index 00000000000..b8d636e8ef8 --- /dev/null +++ b/arch/arm/lib/delay.c @@ -0,0 +1,81 @@ +/* + * Originally from linux/arch/arm/lib/delay.S + * + * Copyright (C) 1995, 1996 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/timex.h> + +/* + * Oh, if only we had a cycle counter... + */ +static void delay_loop(unsigned long loops) +{ + asm volatile( + "1: subs %0, %0, #1 \n" + " bhi 1b \n" + : /* No output */ + : "r" (loops) + ); +} + +#ifdef ARCH_HAS_READ_CURRENT_TIMER +/* + * Assumes read_current_timer() is monotonically increasing + * across calls and wraps at most once within MAX_UDELAY_MS. + */ +void read_current_timer_delay_loop(unsigned long loops) +{ + unsigned long bclock, now; + + read_current_timer(&bclock); + do { + read_current_timer(&now); + } while ((now - bclock) < loops); +} +#endif + +void (*delay_fn)(unsigned long) = delay_loop; + +/* + * loops = usecs * HZ * loops_per_jiffy / 1000000 + */ +void __delay(unsigned long loops) +{ + delay_fn(loops); +} +EXPORT_SYMBOL(__delay); + +/* + * 0 <= xloops <= 0x7fffff06 + * loops_per_jiffy <= 0x01ffffff (max. 3355 bogomips) + */ +void __const_udelay(unsigned long xloops) +{ + unsigned long lpj; + unsigned long loops; + + xloops >>= 14; /* max = 0x01ffffff */ + lpj = loops_per_jiffy >> 10; /* max = 0x0001ffff */ + loops = lpj * xloops; /* max = 0x00007fff */ + loops >>= 6; /* max = 2^32-1 */ + + if (likely(loops)) + __delay(loops); +} +EXPORT_SYMBOL(__const_udelay); + +/* + * usecs <= 2000 + * HZ <= 1000 + */ +void __udelay(unsigned long usecs) +{ + __const_udelay(usecs * ((2199023UL*HZ)>>11)); +} +EXPORT_SYMBOL(__udelay); diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index ef7099eea0f..1527359d2bf 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -4,18 +4,26 @@ config UX500_SOC_COMMON bool default y select ARM_GIC - select HAS_MTU + select NOMADIK_GPIO select PL310_ERRATA_753970 select ARM_ERRATA_754322 select ARM_ERRATA_764369 select CACHE_L2X0 + select HAS_MTU + +config UX500_SOC_DBX500 + depends on UX500_SOC_DB5500 || UX500_SOC_DB8500 + bool config UX500_SOC_DB5500 bool select MFD_DB5500_PRCMU + select REGULATOR_DB5500_PRCMU + select UX500_SOC_DBX500 config UX500_SOC_DB8500 bool + select UX500_SOC_DBX500 select MFD_DB8500_PRCMU select REGULATOR select REGULATOR_DB8500_PRCMU @@ -39,6 +47,13 @@ config MACH_HREFV60 Include support for the HREFv60 new development platform. Includes HREFv70, v71 etc. +config MACH_U8520 + bool "U8520 Development platform" + depends on UX500_SOC_DB8500 + select MACH_U8500 + help + Include support for the 8520 development platform. + config MACH_SNOWBALL bool "U8500 Snowball platform" select MACH_MOP500 @@ -51,6 +66,13 @@ config MACH_U5500 help Include support for the U5500 development platform. +config MACH_U9540 + bool "U9540 Development platform" + depends on UX500_SOC_DB8500 + select MACH_U8500 + help + Include support for the U9540 development platform. + config UX500_AUTO_PLATFORM def_bool y depends on !MACH_U5500 @@ -67,6 +89,50 @@ config MACH_UX500_DT endmenu +choice + prompt "Ux500 UIB Keylayout" + default KEYLAYOUT_LAYOUT1 + +config KEYLAYOUT_LAYOUT1 + bool "UIB Keylayout 1; for generic users" + help + Supported keylayout for some numerics, power/call buttons, + volume control etc + +config KEYLAYOUT_LAYOUT2 + bool "UIB Keylayout 2; for connectivity users" + help + Supports keylayout numerics 0-9, left/right/up/down/back/ + enter keys and special character "."(dot) + +endchoice + +choice + prompt "DBx500 sched_clock" + +config DBX500_SCHED_CLOCK_PRCMU + bool "PRCMU Timer sched_clock" + depends on CLKSRC_DBX500_PRCMU + select CLKSRC_DBX500_PRCMU_SCHED_CLOCK + help + Use the always on PRCMU Timer as sched_clock + +config DB5500_MTIMER_SCHED_CLOCK + bool "MTIMER sched_clock" + depends on CLKSRC_DB5500_MTIMER + select CLKSRC_DB5500_MTIMER_SCHED_CLOCK + help + Use the always on MTIMER as sched_clock + +config DBX500_MTU_SCHED_CLOCK + bool "MTU sched_clock" + depends on HAS_MTU + select NOMADIK_MTU_SCHED_CLOCK + help + Use the Multi Timer Unit as the sched_clock. + +endchoice + config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" default 2 @@ -74,6 +140,12 @@ config UX500_DEBUG_UART Choose the UART on which kernel low-level debug messages should be output. +config UX500_GPIO_KEYS + bool "Use gpio-keys for proximity and hal sensors" + depends on KEYBOARD_GPIO + help + Add proximity and hal sensors as a gpio keyboard. + config U5500_MODEM_IRQ bool "Modem IRQ support" depends on UX500_SOC_DB5500 @@ -81,11 +153,73 @@ config U5500_MODEM_IRQ help Add support for handling IRQ:s from modem side -config U5500_MBOX - bool "Mailbox support" - depends on U5500_MODEM_IRQ +config DBX500_PRCMU_DEBUG + bool "DBX500 PRCMU debug" + depends on ((MFD_DB5500_PRCMU || MFD_DB8500_PRCMU) && DEBUG_FS) + help + Add support for PRCMU debug + +config TEE_UX500 + bool "Trusted Execution Environment (TEE) ux500 hardware support" + depends on TEE_SUPPORT + default y + help + Adds TEE hardware support for ux500 platforms. + +config TEE_SVP + bool "Trusted Execution Environment (TEE) ux500 SVP support" + depends on TEE_SUPPORT && UX500_SVP + default y + help + Adds TEE support for SVP in ux500 platforms. + +config UX500_DEBUG_HWREG + bool "Debug hardware registers from userspace" + depends on (DEBUG_FS && UX500_SOC_DB8500) + help + Adds various debug files to access registers. + This should never ever be used for anything else than debugging. + +config UX500_DEBUG_NO_LAUTERBACH + bool "Disable clocks needed for Lauterbach debugging" + help + Disable clocks needed for Lauterbach debugging at boot. + If yes, you will reduce the power consumption. + +config UX500_L2X0_PREFETCH_CTRL + bool "PL310 prefetch control" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && \ + (TEE_UX500 && CACHE_L2X0) default y help - Add support for U5500 mailbox communication with modem side + Adds interface to control instruction and data prefetch. + Communication with Trustzone is done through TEE driver. + +config UX500_DB_DUMP + bool "DBx500 register dump on crash" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) + default y + help + Reads specific DBx500 register in case of kernel crash + and saves it. + +source "arch/arm/mach-ux500/pm/Kconfig" +source "arch/arm/mach-ux500/test/Kconfig" + +source "arch/arm/mach-ux500/Kconfig-arch" + +config DB8500_MLOADER + bool "Modem firmware upload/download support" + depends on UX500_SOC_DB8500 + select DBX500_MLOADER + help + Adds Modem firmware upload/download support to DB8500. + +config U5500_MLOADER + bool "mLoader, mem config from kernel boot args exported to sysfs" + depends on UX500_SOC_DB5500 + help + Link between boot args and user space program that loads the modem ELF. + This is used to expose the modem parameters using sysfs interface. endif diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch new file mode 100644 index 00000000000..45fc2716814 --- /dev/null +++ b/arch/arm/mach-ux500/Kconfig-arch @@ -0,0 +1,56 @@ +config U8500_SECURE + bool "Support for running in Secure mode" + default n + help + Build the kernel to run in Secure mode. + +#Configuration for MCDE setup + +if FB_MCDE + +menu "Display setup" + +choice + prompt "TV output type" + default U8500_TV_OUTPUT_AV8100 + help + Select the source of TV output to use + +config U8500_TV_OUTPUT_AV8100 + bool "AV8100 (HDMI/CVBS)" + depends on MCDE_DISPLAY_AV8100 + +config U8500_TV_OUTPUT_AB8500 + bool "AB8500 (CVBS)" + depends on MCDE_DISPLAY_AB8500_DENC + +endchoice + +choice + prompt "Color depth" + depends on DISPLAY_GENERIC_PRIMARY + default MCDE_DISPLAY_PRIMARY_16BPP + help + Select color depth for primary display + +config MCDE_DISPLAY_PRIMARY_16BPP + bool "16 bpp" + help + 16 bpp color depth + +config MCDE_DISPLAY_PRIMARY_32BPP + bool "32 bpp" + help + 32 bpp color depth + +endchoice + +config DISPLAY_AV8100_TRIPPLE_BUFFER + bool "Enable tripple buffer for HDMI display" + depends on MCDE_DISPLAY_AV8100 + help + Say yes to enable tripple buffer. You'll get double buffer otherwise + +endmenu + +endif diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 465b9ec9510..165435edeed 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -1,20 +1,70 @@ # -# Makefile for the linux kernel, U8500 machine. +# Makefile for the linux kernel, UX500 machine. # -obj-y := clock.o cpu.o devices.o devices-common.o \ - id.o usb.o timer.o +obj-y := clock.o cpu.o devices.o \ + devices-common.o id.o pins.o \ + usb.o reboot_reasons.o timer.o \ + uart-db8500.o clock-debug.o +obj-y += pm/ test/ obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o -obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o -obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o + + +ifeq ($(CONFIG_UX500_SOC_DB5500), y) +obj-$(CONFIG_UX500_SOC_DBX500) += cpu-db5500.o dma-db5500.o \ + devices-db5500.o clock-db5500.o +board-mcde-objs += board-u5500-mcde.o +endif +ifeq ($(CONFIG_UX500_SOC_DB8500), y) +obj-$(CONFIG_UX500_SOC_DBX500) += cpu-db8500.o devices-db8500.o \ + clock-db8500.o dma-db8500.o cpu-db9500.o +board-mcde-objs += board-mop500-mcde.o +endif obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ board-mop500-regulators.o \ board-mop500-uib.o board-mop500-stuib.o \ - board-mop500-u8500uib.o \ - board-mop500-pins.o -obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o + board-mop500-u8500uib.o board-mop500-pins.o \ + board-mop500-bm.o \ + board-pins-sleep-force.o +obj-$(CONFIG_ANDROID_STE_TIMED_VIBRA) += board-mop500-vibra.o +obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o \ + board-u5500-regulators.o \ + board-u5500-pins.o +obj-$(CONFIG_U5500_MMIO) += board-u5500-mmio.o +obj-$(CONFIG_U8500_MMIO) += board-mop500-mmio.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o -obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o +obj-$(CONFIG_TEE_UX500) += tee_ux500.o product.o +obj-$(CONFIG_TEE_SVP) += tee_service_svp.o +obj-$(CONFIG_TEE_SVP) += tee_ta_start_modem_svp.o +obj-$(CONFIG_DB8500_MLOADER) += mloader-db8500.o +obj-$(CONFIG_U5500_MLOADER) += mloader-db5500.o +obj-$(CONFIG_UX500_DEBUG_HWREG) += hwreg.o +obj-$(CONFIG_HWMEM) += hwmem-int.o +obj-$(CONFIG_UX500_L2X0_PREFETCH_CTRL) += l2x0-prefetch.o +obj-$(CONFIG_AB5500_BM) += board-u5500-bm.o +obj-$(CONFIG_DBX500_PRCMU_DEBUG) += prcmu-debug.o +obj-$(CONFIG_UX500_DB_DUMP) += dbx500_dump.o + +obj-$(CONFIG_HWMEM) += dcache.o +ifdef CONFIG_STM_TRACE +obj-$(CONFIG_MACH_MOP500) += board-mop500-stm.o +endif +ifdef CONFIG_SENSORS_LSM303DLH +obj-$(CONFIG_MACH_MOP500) += board-mop500-sensors.o +endif +obj-$(CONFIG_FB_MCDE) += board-mcde.o +ifdef CONFIG_STM_MSP_SPI +obj-$(CONFIG_MACH_MOP500) += board-mop500-msp.o +endif +ifdef CONFIG_CW1200 +obj-$(CONFIG_MACH_MOP500) += board-mop500-wlan.o +obj-$(CONFIG_MACH_U5500) += board-u5500-wlan.o +endif +ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI +obj-$(CONFIG_MACH_MOP500) += board-mop500-cyttsp.o +obj-$(CONFIG_MACH_U5500) += board-u5500-cyttsp.o +endif diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c new file mode 100644 index 00000000000..afdc6ee59a3 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-bm.c @@ -0,0 +1,517 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific charger and battery initialization parameters. + * + * Author: Johan Palsson <johan.palsson@stericsson.com> for ST-Ericsson. + * Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson. + * + */ + +#include <linux/power_supply.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500-bm.h> +#include <linux/mfd/ab8500/pwmleds.h> +#include "board-mop500-bm.h" + +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL +/* + * These are the defined batteries that uses a NTC and ID resistor placed + * inside of the battery pack. + * Note that the res_to_temp table must be strictly sorted by falling resistance + * values to work. + */ +static struct abx500_res_to_temp temp_tbl_A[] = { + {-5, 53407}, + { 0, 48594}, + { 5, 43804}, + {10, 39188}, + {15, 34870}, + {20, 30933}, + {25, 27422}, + {30, 24347}, + {35, 21694}, + {40, 19431}, + {45, 17517}, + {50, 15908}, + {55, 14561}, + {60, 13437}, + {65, 12500}, +}; +static struct abx500_res_to_temp temp_tbl_B[] = { + {-5, 165418}, + { 0, 159024}, + { 5, 151921}, + {10, 144300}, + {15, 136424}, + {20, 128565}, + {25, 120978}, + {30, 113875}, + {35, 107397}, + {40, 101629}, + {45, 96592}, + {50, 92253}, + {55, 88569}, + {60, 85461}, + {65, 82869}, +}; +static struct abx500_v_to_cap cap_tbl_A[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; +static struct abx500_v_to_cap cap_tbl_B[] = { + {4161, 100}, + {4124, 98}, + {4044, 90}, + {4003, 85}, + {3966, 80}, + {3933, 75}, + {3888, 67}, + {3849, 60}, + {3813, 55}, + {3787, 47}, + {3772, 30}, + {3751, 25}, + {3718, 20}, + {3681, 16}, + {3660, 14}, + {3589, 10}, + {3546, 7}, + {3495, 4}, + {3404, 2}, + {3250, 0}, +}; +#endif +static struct abx500_v_to_cap cap_tbl[] = { + {4186, 100}, + {4163, 99}, + {4114, 95}, + {4068, 90}, + {3990, 80}, + {3926, 70}, + {3898, 65}, + {3866, 60}, + {3833, 55}, + {3812, 50}, + {3787, 40}, + {3768, 30}, + {3747, 25}, + {3730, 20}, + {3705, 15}, + {3699, 14}, + {3684, 12}, + {3672, 9}, + {3657, 7}, + {3638, 6}, + {3556, 4}, + {3424, 2}, + {3317, 1}, + {3094, 0}, +}; + +/* + * Note that the res_to_temp table must be strictly sorted by falling + * resistance values to work. + */ +static struct abx500_res_to_temp temp_tbl[] = { + {-5, 214834}, + { 0, 162943}, + { 5, 124820}, + {10, 96520}, + {15, 75306}, + {20, 59254}, + {25, 47000}, + {30, 37566}, + {35, 30245}, + {40, 24520}, + {45, 20010}, + {50, 16432}, + {55, 13576}, + {60, 11280}, + {65, 9425}, +}; + +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL +/* + * Note that the batres_vs_temp table must be strictly sorted by falling + * temperature values to work. + */ +static struct batres_vs_temp temp_to_batres_tbl[] = { + { 40, 120}, + { 30, 135}, + { 20, 165}, + { 10, 230}, + { 00, 325}, + {-10, 445}, + {-20, 595}, +}; +#else +/* + * Note that the batres_vs_temp table must be strictly sorted by falling + * temperature values to work. + */ +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY +#define BATRES 180 +#else +#define BATRES 300 +#endif +static struct batres_vs_temp temp_to_batres_tbl[] = { + { 60, BATRES}, + { 30, BATRES}, + { 20, BATRES}, + { 10, BATRES}, + { 00, BATRES}, + {-10, BATRES}, + {-20, BATRES}, +}; +#endif +static const struct abx500_battery_type bat_type[] = { + [BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .charge_full_design = 2600, +#else + .charge_full_design = 612, +#endif + .nominal_voltage = 3700, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .termination_vol = 4150, +#else + .termination_vol = 4050, +#endif + .termination_curr = 200, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .recharge_vol = 4130, + .normal_cur_lvl = 520, + .normal_vol_lvl = 4200, +#else + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, +#endif + .maint_a_cur_lvl = 400, + .maint_a_vol_lvl = 4050, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 400, + .maint_b_vol_lvl = 4000, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, + }, + +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 53407, + .resis_low = 12500, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A), + .r_to_t_tbl = temp_tbl_A, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A), + .v_to_cap_tbl = cap_tbl_A, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, + + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 165418, + .resis_low = 82869, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B), + .r_to_t_tbl = temp_tbl_B, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B), + .v_to_cap_tbl = cap_tbl_B, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, + }, +#else +/* + * These are the batteries that doesn't have an internal NTC resistor to measure + * its temperature. The temperature in this case is measure with a NTC placed + * near the battery but on the PCB. + */ + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 76000, + .resis_low = 53000, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 30000, + .resis_low = 10000, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 95000, + .resis_low = 76001, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl), + .batres_tbl = temp_to_batres_tbl, + }, +#endif +}; + +static char *ab8500_charger_supplied_to[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static char *ab8500_btemp_supplied_to[] = { + "ab8500_chargalg", + "ab8500_fg", +}; + +static char *ab8500_fg_supplied_to[] = { + "ab8500_chargalg", + "ab8500_usb", +}; + +static char *ab8500_chargalg_supplied_to[] = { + "ab8500_fg", +}; + +struct abx500_charger_platform_data ab8500_charger_plat_data = { + .supplied_to = ab8500_charger_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_charger_supplied_to), + .autopower_cfg = false, +}; + +struct abx500_btemp_platform_data ab8500_btemp_plat_data = { + .supplied_to = ab8500_btemp_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_btemp_supplied_to), +}; + +struct abx500_fg_platform_data ab8500_fg_plat_data = { + .supplied_to = ab8500_fg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_fg_supplied_to), +}; + +struct abx500_chargalg_platform_data ab8500_chargalg_plat_data = { + .supplied_to = ab8500_chargalg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab8500_chargalg_supplied_to), +}; + +static struct ab8500_led_pwm leds_pwm_data[] = { + [0] = { + .pwm_id = 1, + .blink_en = 1, + }, + [1] = { + .pwm_id = 2, + .blink_en = 0, + }, + [2] = { + .pwm_id = 3, + .blink_en = 0, + }, +}; + +struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data = { + .num_pwm = 3, + .leds = leds_pwm_data, +}; + +static const struct abx500_bm_capacity_levels cap_levels = { + .critical = 2, + .low = 10, + .normal = 70, + .high = 95, + .full = 100, +}; + +static const struct abx500_fg_parameters fg = { + .recovery_sleep_timer = 10, + .recovery_total_time = 100, + .init_timer = 1, + .init_discard_time = 5, + .init_total_time = 40, + .high_curr_time = 60, + .accu_charging = 30, + .accu_high_curr = 30, + .high_curr_threshold = 50, + .lowbat_threshold = 3100, + .battok_falling_th_sel0 = 2860, + .battok_raising_th_sel1 = 2860, + .user_cap_limit = 15, + .maint_thres = 97, +}; + +static const struct abx500_maxim_parameters maxi_params = { + .ena_maxi = true, + .chg_curr = 910, + .wait_cycles = 10, + .charger_curr_step = 100, +}; + +static const struct abx500_bm_charger_parameters chg = { + .usb_volt_max = 5500, + .usb_curr_max = 1500, + .ac_volt_max = 7500, + .ac_curr_max = 1500, +}; + +struct abx500_bm_data ab8500_bm_data = { + .temp_under = 3, + .temp_low = 8, + .temp_high = 43, + .temp_over = 48, + .main_safety_tmr_h = 4, + .temp_interval_chg = 20, + .temp_interval_nochg = 120, + .usb_safety_tmr_h = 4, + .bkup_bat_v = BUP_VCH_SEL_2P6V, + .bkup_bat_i = BUP_ICH_SEL_150UA, +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .no_maintenance = true, +#else + .no_maintenance = false, +#endif +#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL + .adc_therm = ABx500_ADC_THERM_BATCTRL, +#else + .adc_therm = ABx500_ADC_THERM_BATTEMP, +#endif +#ifdef CONFIG_AB8500_9100_LI_ION_BATTERY + .chg_unknown_bat = true, +#else + .chg_unknown_bat = false, +#endif + .enable_overshoot = false, + .fg_res = 100, + .cap_levels = &cap_levels, + .bat_type = bat_type, + .n_btypes = ARRAY_SIZE(bat_type), + .batt_id = 0, + .interval_charging = 5, + .interval_not_charging = 120, + .temp_hysteresis = 3, + .gnd_lift_resistance = 34, + .maxi = &maxi_params, + .chg_params = &chg, + .fg_params = &fg, +}; diff --git a/arch/arm/mach-ux500/board-mop500-bm.h b/arch/arm/mach-ux500/board-mop500-bm.h new file mode 100644 index 00000000000..61d6bc71cc3 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-bm.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific charger and battery initialization parameters. + * + * Author: Johan Palsson <johan.palsson@stericsson.com> for ST-Ericsson. + * Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson. + * + */ + +#ifndef __BOARD_MOP500_BM_H +#define __BOARD_MOP500_BM_H + +#include <linux/mfd/abx500/ab8500-bm.h> + +extern struct abx500_charger_platform_data ab8500_charger_plat_data; +extern struct abx500_btemp_platform_data ab8500_btemp_plat_data; +extern struct abx500_fg_platform_data ab8500_fg_plat_data; +extern struct abx500_chargalg_platform_data ab8500_chargalg_plat_data; +extern struct abx500_bm_data ab8500_bm_data; +extern struct ab8500_pwmled_platform_data ab8500_pwmled_plat_data; + +#endif diff --git a/arch/arm/mach-ux500/board-mop500-cyttsp.c b/arch/arm/mach-ux500/board-mop500-cyttsp.c new file mode 100644 index 00000000000..1551355f50d --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-cyttsp.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * Author: Avinash A <avinash.a@stericsson.com> for ST-Ericsson + * License terms:GNU General Public License (GPL) version 2 + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <linux/input/cyttsp.h> +#include <linux/delay.h> +#include <linux/gpio/nomadik.h> +#include <linux/i2c.h> +#ifdef CONFIG_U8500_FLASH +#include <../drivers/staging/camera_flash/adp1653_plat.h> +#endif +#include <linux/input/matrix_keypad.h> +#include <linux/mfd/tc3589x.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/amba/pl022.h> +#include <plat/pincfg.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/irqs-db8500.h> +#include <asm/mach-types.h> +#include "pins-db8500.h" +#include "board-mop500.h" +#include "devices-db8500.h" + +#define NUM_SSP_CLIENTS 10 + +#ifdef CONFIG_U8500_FLASH +static struct adp1653_platform_data __initdata adp1653_pdata_u8500_uib = { + .irq_no = CAMERA_FLASH_INT_PIN +}; +#endif + +static struct i2c_board_info __initdata mop500_i2c2_devices_u8500_r3[] = { +#ifdef CONFIG_U8500_FLASH + { + I2C_BOARD_INFO("adp1653", 0x30), + .platform_data = &adp1653_pdata_u8500_uib + } +#endif +}; + +/* cyttsp_gpio_board_init : configures the touch panel. */ +static int cyttsp_plat_init(void) +{ + int ret; + + ret = gpio_direction_output(CYPRESS_SLAVE_SELECT_GPIO, 1); + if (ret < 0) { + pr_err("slave select gpio direction failed\n"); + gpio_free(CYPRESS_SLAVE_SELECT_GPIO); + return ret; + } + return 0; +} + +/* cyttsp_gpio_board_exit : deconfigures the touch panel. */ +static void cyttsp_plat_exit(void) +{ + gpio_direction_output(CYPRESS_SLAVE_SELECT_GPIO, 0); +} + +static struct pl022_ssp_controller mop500_spi2_data = { + .bus_id = SPI023_2_CONTROLLER, + .num_chipselect = NUM_SSP_CLIENTS, +}; + +static int cyttsp_wakeup(void) +{ + int ret; + + ret = gpio_request(CYPRESS_TOUCH_INT_PIN, "Wakeup_pin"); + if (ret < 0) { + pr_err("touch gpio failed\n"); + return ret; + } + ret = gpio_direction_output(CYPRESS_TOUCH_INT_PIN, 1); + if (ret < 0) { + pr_err("touch gpio direction failed\n"); + goto out; + } + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + /* + * To wake up the controller from sleep + * state the interrupt pin needs to be + * pulsed twice with a delay greater + * than 2 micro seconds. + */ + udelay(3); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + ret = gpio_direction_input(CYPRESS_TOUCH_INT_PIN); + if (ret < 0) { + pr_err("touch gpio direction IN config failed\n"); + goto out; + } +out: + gpio_free(CYPRESS_TOUCH_INT_PIN); + return 0; +} +struct cyttsp_platform_data cyttsp_platdata = { + .maxx = 480, + .maxy = 854, + .use_hndshk = 0, + /* set active distance */ + .act_dist = CY_ACT_DIST_DFLT, + .act_intrvl = CY_ACT_INTRVL_DFLT, /* Active refresh interval; ms */ + .tch_tmout = CY_TCH_TMOUT_DFLT, /* Active touch timeout; ms */ + .lp_intrvl = CY_LP_INTRVL_DFLT, /* Low power refresh interval; ms */ + .init = cyttsp_plat_init, + .exit = cyttsp_plat_exit, + .name = CY_SPI_NAME, + .irq_gpio = CYPRESS_TOUCH_INT_PIN, +/* .rst_gpio = CYPRESS_TOUCH_RST_GPIO, Notavailable in mainline */ +}; + +static void cyttsp_spi_cs_control(u32 command) +{ + if (command == SSP_CHIP_SELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 0); + else if (command == SSP_CHIP_DESELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 1); +} + +static struct pl022_config_chip cyttsp_ssp_config_chip = { + .com_mode = INTERRUPT_TRANSFER, + .iface = SSP_INTERFACE_MOTOROLA_SPI, + /* we can act as master only */ + .hierarchy = SSP_MASTER, + .slave_tx_disable = 0, + .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, + .tx_lev_trig = SSP_TX_16_OR_MORE_EMPTY_LOC, + .ctrl_len = SSP_BITS_16, + .wait_state = SSP_MWIRE_WAIT_ZERO, + .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, + .cs_control = cyttsp_spi_cs_control, +}; + +static struct spi_board_info cypress_spi_devices[] = { + { + .modalias = CY_SPI_NAME, + .controller_data = &cyttsp_ssp_config_chip, + .platform_data = &cyttsp_platdata, + .max_speed_hz = 1000000, + .bus_num = SPI023_2_CONTROLLER, + .chip_select = 0, + .mode = SPI_MODE_0, + } +}; + +/* + * TC35893 + */ +static const unsigned int sony_keymap[] = { + KEY(3, 1, KEY_END), + KEY(4, 1, KEY_HOME), + KEY(6, 4, KEY_VOLUMEDOWN), + KEY(4, 2, KEY_EMAIL), + KEY(3, 3, KEY_RIGHT), + KEY(2, 5, KEY_BACKSPACE), + + KEY(6, 7, KEY_MENU), + KEY(5, 0, KEY_ENTER), + KEY(4, 3, KEY_0), + KEY(3, 4, KEY_DOT), + KEY(5, 2, KEY_UP), + KEY(3, 5, KEY_DOWN), + + KEY(4, 5, KEY_SEND), + KEY(0, 5, KEY_BACK), + KEY(6, 2, KEY_VOLUMEUP), + KEY(1, 3, KEY_SPACE), + KEY(7, 6, KEY_LEFT), + KEY(5, 5, KEY_SEARCH), +}; + +static struct matrix_keymap_data sony_keymap_data = { + .keymap = sony_keymap, + .keymap_size = ARRAY_SIZE(sony_keymap), +}; + +static struct tc3589x_keypad_platform_data tc35893_data = { + .krow = TC_KPD_ROWS, + .kcol = TC_KPD_COLUMNS, + .debounce_period = TC_KPD_DEBOUNCE_PERIOD, + .settle_time = TC_KPD_SETTLE_TIME, + .irqtype = IRQF_TRIGGER_FALLING, + .enable_wakeup = true, + .keymap_data = &sony_keymap_data, + .no_autorepeat = true, +}; + +static struct tc3589x_platform_data tc3589x_keypad_data = { + .block = TC3589x_BLOCK_KEYPAD, + .keypad = &tc35893_data, + .irq_base = MOP500_EGPIO_IRQ_BASE, +}; + +static struct i2c_board_info __initdata mop500_i2c0_devices_u8500[] = { + { + I2C_BOARD_INFO("tc3589x", 0x44), + .platform_data = &tc3589x_keypad_data, + .irq = NOMADIK_GPIO_TO_IRQ(64), + .flags = I2C_CLIENT_WAKE, + }, +}; + +static void mop500_cyttsp_init(void) +{ + int ret = 0; + + /* + * Enable the alternative C function + * in the PRCMU register + */ + prcmu_enable_spi2(); + ret = gpio_request(CYPRESS_SLAVE_SELECT_GPIO, "slave_select_gpio"); + if (ret < 0) + pr_err("slave select gpio failed\n"); + spi_register_board_info(cypress_spi_devices, + ARRAY_SIZE(cypress_spi_devices)); +} + +void __init mop500_u8500uib_r3_init() +{ + mop500_cyttsp_init(); + db8500_add_spi2(NULL, &mop500_spi2_data); + nmk_config_pin((GPIO64_GPIO | PIN_INPUT_PULLUP), false); + +#ifdef CONFIG_U8500_FLASH + if (machine_is_hrefv60() || machine_is_u8520()) { + adp1653_pdata_u8500_uib.enable_gpio = + HREFV60_CAMERA_FLASH_ENABLE; + } else { + adp1653_pdata_u8500_uib.enable_gpio = + GPIO_CAMERA_FLASH_ENABLE; + } +#endif + mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, + ARRAY_SIZE(mop500_i2c0_devices_u8500)); + mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, + ARRAY_SIZE(mop500_i2c0_devices_u8500)); + mop500_uib_i2c_add(2, mop500_i2c2_devices_u8500_r3, + ARRAY_SIZE(mop500_i2c2_devices_u8500_r3)); +} diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c new file mode 100644 index 00000000000..3d8c8fc4852 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-mcde.c @@ -0,0 +1,559 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * + * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/mfd/ab8500/denc.h> +#include <linux/workqueue.h> +#include <linux/dispdev.h> +#include <linux/compdev.h> +#include <asm/mach-types.h> +#include <linux/clk.h> +#include <mach/devices.h> +#include <video/av8100.h> +#include <video/mcde_display.h> +#include <video/mcde_display-vuib500-dpi.h> +#include <video/mcde_display-sony_acx424akp_dsi.h> +#include <video/mcde_display-av8100.h> +#include <video/mcde_display-ab8500.h> +#include <video/mcde_fb.h> +#include <video/mcde_dss.h> +#include <plat/pincfg.h> +#include "pins-db8500.h" +#include "pins.h" +#include "board-mop500.h" + +#define DSI_UNIT_INTERVAL_0 0x9 +#define DSI_UNIT_INTERVAL_1 0x9 +#define DSI_UNIT_INTERVAL_2 0x5 + +#define DSI_PLL_FREQ_HZ 840320000 +/* Based on PLL DDR Freq at 798,72 MHz */ +#define HDMI_FREQ_HZ 33280000 +#define TV_FREQ_HZ 38400000 + +#ifdef CONFIG_U8500_TV_OUTPUT_AV8100 +/* The initialization of hdmi disp driver must be delayed in order to + * ensure that inputclk will be available (needed by hdmi hw) */ +static struct delayed_work work_dispreg_hdmi; +#define DISPREG_HDMI_DELAY 6000 +#endif + +enum { + PRIMARY_DISPLAY_ID, + SECONDARY_DISPLAY_ID, + FICTIVE_DISPLAY_ID, + AV8100_DISPLAY_ID, + AB8500_DISPLAY_ID, + MCDE_NR_OF_DISPLAYS +}; + +static int display_initialized_during_boot; + +static int __init startup_graphics_setup(char *str) +{ + + if (get_option(&str, &display_initialized_during_boot) != 1) + display_initialized_during_boot = 0; + + switch (display_initialized_during_boot) { + case 1: + pr_info("Startup graphics support\n"); + break; + case 0: + default: + pr_info("No startup graphics supported\n"); + break; + }; + + return 1; +} +__setup("startup_graphics=", startup_graphics_setup); + +#if defined(CONFIG_U8500_TV_OUTPUT_AV8100) || \ + defined(CONFIG_U8500_TV_OUTPUT_AB8500) +static struct mcde_col_transform rgb_2_yCbCr_transform = { + .matrix = { + {0x0042, 0x0081, 0x0019}, + {0xffda, 0xffb6, 0x0070}, + {0x0070, 0xffa2, 0xffee}, + }, + .offset = {0x10, 0x80, 0x80}, +}; +#endif + +static struct mcde_port samsung_s6d16d0_port0 = { + .sync_src = MCDE_SYNCSRC_BTA, + .frame_trig = MCDE_TRIG_SW, +}; + +static struct mcde_display_dsi_platform_data samsung_s6d16d0_pdata0 = { + .link = 0, +}; + +static struct mcde_display_device samsung_s6d16d0_display0 = { + .name = "samsung_s6d16d0", + .id = PRIMARY_DISPLAY_ID, + .port = &samsung_s6d16d0_port0, + .chnl_id = MCDE_CHNL_A, + .fifo = MCDE_FIFO_A, + .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888, + .dev = { + .platform_data = &samsung_s6d16d0_pdata0, + }, +}; + +static struct mcde_port sony_port0 = { + .link = 0, + .sync_src = MCDE_SYNCSRC_BTA, + .frame_trig = MCDE_TRIG_HW, +}; + +static struct mcde_display_sony_acx424akp_platform_data + sony_acx424akp_display0_pdata = { + .reset_gpio = HREFV60_DISP1_RST_GPIO, +}; + +static struct mcde_display_device sony_acx424akp_display0 = { + .name = "mcde_disp_sony_acx424akp", + .id = PRIMARY_DISPLAY_ID, + .port = &sony_port0, + .chnl_id = MCDE_CHNL_A, + .fifo = MCDE_FIFO_A, + .orientation = MCDE_DISPLAY_ROT_0, + .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888, + .dev = { + .platform_data = &sony_acx424akp_display0_pdata, + }, +}; + +static struct mcde_port samsung_s6d16d0_port1 = { + .sync_src = MCDE_SYNCSRC_BTA, + .frame_trig = MCDE_TRIG_SW, +}; + +static struct mcde_display_dsi_platform_data samsung_s6d16d0_pdata1 = { + .link = 1, +}; + +static struct mcde_display_device samsung_s6d16d0_display1 = { + .name = "samsung_s6d16d0", + .id = SECONDARY_DISPLAY_ID, + .port = &samsung_s6d16d0_port1, + .chnl_id = MCDE_CHNL_C1, + .fifo = MCDE_FIFO_C1, + .orientation = MCDE_DISPLAY_ROT_90_CCW, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .dev = { + .platform_data = &samsung_s6d16d0_pdata1, + }, +}; + +#ifdef CONFIG_U8500_TV_OUTPUT_AB8500 +static struct mcde_port port_tvout1 = { + .type = MCDE_PORTTYPE_DPI, + .pixel_format = MCDE_PORTPIXFMT_DPI_24BPP, + .link = 1, /* channel B */ + .sync_src = MCDE_SYNCSRC_OFF, + .update_auto_trig = true, + .phy = { + .dpi = { + .bus_width = 4, /* DDR mode */ + .tv_mode = true, + .clock_div = MCDE_PORT_DPI_NO_CLOCK_DIV, + }, + }, +}; + +static struct ab8500_display_platform_data ab8500_display_pdata = { + .nr_regulators = 2, + .regulator_id = {"vtvout", "vcc-N2158"}, + .rgb_2_yCbCr_transform = &rgb_2_yCbCr_transform, +}; + +static struct ux500_pins *tvout_pins; + +static int ab8500_platform_enable(struct mcde_display_device *ddev) +{ + int res = 0; + + if (!tvout_pins) { + tvout_pins = ux500_pins_get("mcde-tvout"); + if (!tvout_pins) + return -EINVAL; + } + + dev_dbg(&ddev->dev, "%s\n", __func__); + res = ux500_pins_enable(tvout_pins); + if (res != 0) + goto failed; + + return res; + +failed: + dev_warn(&ddev->dev, "Failure during %s\n", __func__); + return res; +} + +static int ab8500_platform_disable(struct mcde_display_device *ddev) +{ + int res; + + dev_dbg(&ddev->dev, "%s\n", __func__); + + res = ux500_pins_disable(tvout_pins); + if (res != 0) + goto failed; + return res; + +failed: + dev_warn(&ddev->dev, "Failure during %s\n", __func__); + return res; +} + +static struct mcde_display_device tvout_ab8500_display = { + .name = "mcde_tv_ab8500", + .id = AB8500_DISPLAY_ID, + .port = &port_tvout1, + .chnl_id = MCDE_CHNL_B, + .fifo = MCDE_FIFO_B, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .native_x_res = 720, + .native_y_res = 576, + .dev = { + .platform_data = &ab8500_display_pdata, + }, + + /* + * We might need to describe the std here: + * - there are different PAL / NTSC formats (do they require MCDE + * settings?) + */ + .platform_enable = ab8500_platform_enable, + .platform_disable = ab8500_platform_disable, +}; +#endif + +#ifdef CONFIG_U8500_TV_OUTPUT_AV8100 + +#if defined(CONFIG_AV8100_HWTRIG_INT) + #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE0 +#elif defined(CONFIG_AV8100_HWTRIG_I2SDAT3) + #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE1 +#elif defined(CONFIG_AV8100_HWTRIG_DSI_TE) + #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE_POLLING +#else + #define AV8100_SYNC_SRC MCDE_SYNCSRC_OFF +#endif +static struct mcde_port av8100_port2 = { + .type = MCDE_PORTTYPE_DSI, + .mode = MCDE_PORTMODE_CMD, + .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, + .ifc = 1, + .link = 2, + .sync_src = AV8100_SYNC_SRC, + .update_auto_trig = true, + .phy = { + .dsi = { + .num_data_lanes = 2, + .ui = DSI_UNIT_INTERVAL_2, + }, + }, + .hdmi_sdtv_switch = HDMI_SWITCH, +}; + +static struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = { + .cvbs_regulator_id = "vcc-N2158", + .rgb_2_yCbCr_transform = &rgb_2_yCbCr_transform, +}; + +static struct ux500_pins *av8100_pins; +static int av8100_platform_enable(struct mcde_display_device *ddev) +{ + int res; + + dev_dbg(&ddev->dev, "%s\n", __func__); + if (!av8100_pins) { + av8100_pins = ux500_pins_get("av8100-hdmi"); + if (!av8100_pins) { + res = -EINVAL; + goto failed; + } + } + + res = ux500_pins_enable(av8100_pins); + if (res != 0) + goto failed; + + return res; + +failed: + dev_warn(&ddev->dev, "Failure during %s\n", __func__); + return res; +} + +static int av8100_platform_disable(struct mcde_display_device *ddev) +{ + int res; + + dev_dbg(&ddev->dev, "%s\n", __func__); + + res = ux500_pins_disable(av8100_pins); + if (res != 0) + goto failed; + return res; + +failed: + dev_warn(&ddev->dev, "Failure during %s\n", __func__); + return res; +} + +static struct mcde_display_device av8100_hdmi = { + .name = "av8100_hdmi", + .id = AV8100_DISPLAY_ID, + .port = &av8100_port2, + .chnl_id = MCDE_CHNL_B, + .fifo = MCDE_FIFO_B, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .native_x_res = 1280, + .native_y_res = 720, + .dev = { + .platform_data = &av8100_hdmi_pdata, + }, + .platform_enable = av8100_platform_enable, + .platform_disable = av8100_platform_disable, +}; + +static void delayed_work_dispreg_hdmi(struct work_struct *ptr) +{ + if (mcde_display_device_register(&av8100_hdmi)) + pr_warning("Failed to register av8100_hdmi\n"); +} +#endif /* CONFIG_U8500_TV_OUTPUT_AV8100 */ + +/* +* This function will create the framebuffer for the display that is registered. +*/ +static int display_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *dev) +{ + struct mcde_display_device *ddev = dev; + u16 width, height; + u16 virtual_height; + struct fb_info *fbi; +#if defined(CONFIG_DISPDEV) || defined(CONFIG_COMPDEV) + struct mcde_fb *mfb; +#endif + + if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) + return 0; + + if (ddev->id < 0 || ddev->id >= MCDE_NR_OF_DISPLAYS) + return 0; + + mcde_dss_get_native_resolution(ddev, &width, &height); + virtual_height = height * 2; + +#ifndef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE + if (ddev->id == AV8100_DISPLAY_ID) + goto out; +#endif + + /* Create frame buffer */ + fbi = mcde_fb_create(ddev, width, height, width, virtual_height, + ddev->default_pixel_format, FB_ROTATE_UR); + if (IS_ERR(fbi)) { + dev_warn(&ddev->dev, + "Failed to create fb for display %s\n", ddev->name); + goto display_postregistered_callback_err; + } else { + dev_info(&ddev->dev, "Framebuffer created (%s)\n", ddev->name); + } + +#ifdef CONFIG_DISPDEV + mfb = to_mcde_fb(fbi); + + /* Create a dispdev overlay for this display */ + if (dispdev_create(ddev, true, mfb->ovlys[0]) < 0) { + dev_warn(&ddev->dev, + "Failed to create disp for display %s\n", ddev->name); + goto display_postregistered_callback_err; + } else { + dev_info(&ddev->dev, "Disp dev created for (%s)\n", ddev->name); + } +#endif + +#ifdef CONFIG_COMPDEV + mfb = to_mcde_fb(fbi); + /* Create a compdev overlay for this display */ + if (compdev_create(ddev, mfb->ovlys[0], true) < 0) { + dev_warn(&ddev->dev, + "Failed to create compdev for display %s\n", + ddev->name); + goto display_postregistered_callback_err; + } else { + dev_info(&ddev->dev, "compdev created for (%s)\n", + ddev->name); + } +#endif + +out: + return 0; + +display_postregistered_callback_err: + return -1; +} + +static struct notifier_block display_nb = { + .notifier_call = display_postregistered_callback, +}; + +/* +* This function is used to refresh the display (lcd, hdmi, tvout) with black +* when the framebuffer is registered. +* The main display will not be updated if startup graphics is displayed +* from u-boot. +*/ +static int framebuffer_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int ret = 0; + struct fb_event *event_data = data; + struct fb_info *info; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + struct mcde_fb *mfb; + + if (event != FB_EVENT_FB_REGISTERED) + return 0; + + if (!event_data) + return 0; + + info = event_data->info; + mfb = to_mcde_fb(info); + if (mfb->id == 0 && display_initialized_during_boot) + goto out; + + var = info->var; + fix = info->fix; + var.yoffset = var.yoffset ? 0 : var.yres; + if (info->fbops->fb_pan_display) + ret = info->fbops->fb_pan_display(&var, info); +out: + return ret; +} + +static struct notifier_block framebuffer_nb = { + .notifier_call = framebuffer_postregistered_callback, +}; + +static int __init init_display_devices(void) +{ + int ret; + + if (!cpu_is_u8500()) + return 0; + + ret = fb_register_client(&framebuffer_nb); + if (ret) + pr_warning("Failed to register framebuffer notifier\n"); + + (void)mcde_dss_register_notifier(&display_nb); + + /* Set powermode to STANDBY if startup graphics is executed */ + if (display_initialized_during_boot) { + samsung_s6d16d0_display0.power_mode = MCDE_DISPLAY_PM_STANDBY; + sony_acx424akp_display0.power_mode = MCDE_DISPLAY_PM_STANDBY; + } + + /* Display reset GPIO is different depending on reference boards */ + if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) { + samsung_s6d16d0_pdata0.reset_gpio = HREFV60_DISP1_RST_GPIO; + samsung_s6d16d0_pdata1.reset_gpio = HREFV60_DISP2_RST_GPIO; + } else { + samsung_s6d16d0_pdata0.reset_gpio = MOP500_DISP1_RST_GPIO; + samsung_s6d16d0_pdata1.reset_gpio = MOP500_DISP2_RST_GPIO; + } + + /* Initialize all needed clocks*/ + if (!display_initialized_during_boot) { + struct clk *clk_dsi_pll; + struct clk *clk_hdmi; + struct clk *clk_tv; + + /* + * The TV CLK is used as parent for the + * DSI LP clock. + */ + clk_tv = clk_get(&u8500_mcde_device.dev, "tv"); + if (TV_FREQ_HZ != clk_round_rate(clk_tv, TV_FREQ_HZ)) + pr_warning("%s: TV_CLK freq differs %ld\n", __func__, + clk_round_rate(clk_tv, TV_FREQ_HZ)); + clk_set_rate(clk_tv, TV_FREQ_HZ); + clk_put(clk_tv); + + /* + * The HDMI CLK is used as parent for the + * DSI HS clock. + */ + clk_hdmi = clk_get(&u8500_mcde_device.dev, "hdmi"); + if (HDMI_FREQ_HZ != clk_round_rate(clk_hdmi, HDMI_FREQ_HZ)) + pr_warning("%s: HDMI freq differs %ld\n", __func__, + clk_round_rate(clk_hdmi, HDMI_FREQ_HZ)); + clk_set_rate(clk_hdmi, HDMI_FREQ_HZ); + clk_put(clk_hdmi); + + /* + * The DSI PLL CLK is used as DSI PLL for direct freq for + * link 2. Link 0/1 is then divided with 1/2/4 from this freq. + */ + clk_dsi_pll = clk_get(&u8500_mcde_device.dev, "dsihs2"); + if (DSI_PLL_FREQ_HZ != clk_round_rate(clk_dsi_pll, + DSI_PLL_FREQ_HZ)) + pr_warning("%s: DSI_PLL freq differs %ld\n", __func__, + clk_round_rate(clk_dsi_pll, DSI_PLL_FREQ_HZ)); + clk_set_rate(clk_dsi_pll, DSI_PLL_FREQ_HZ); + clk_put(clk_dsi_pll); + } + + /* Not all STUIBs supports VSYNC, disable vsync for STUIB */ + if (uib_is_stuib()) { + /* Samsung display on STUIB */ + samsung_s6d16d0_display0.port->sync_src = MCDE_SYNCSRC_OFF; + samsung_s6d16d0_display0.orientation = MCDE_DISPLAY_ROT_90_CCW; + (void)mcde_display_device_register(&samsung_s6d16d0_display0); + } else if (uib_is_u8500uib()) { + /* Samsung display on U8500UIB */ + samsung_s6d16d0_display0.orientation = MCDE_DISPLAY_ROT_90_CW; + (void)mcde_display_device_register(&samsung_s6d16d0_display0); + } else if (uib_is_u8500uibr3()) { + /* Sony display on U8500UIBV3 */ + (void)mcde_display_device_register(&sony_acx424akp_display0); + } + else + pr_warning("Unknown UI board\n"); + + /* Display reset GPIO is different depending on reference boards */ + if (uib_is_stuib()) + (void)mcde_display_device_register(&samsung_s6d16d0_display1); + +#if defined(CONFIG_U8500_TV_OUTPUT_AV8100) + INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi, + delayed_work_dispreg_hdmi); + schedule_delayed_work(&work_dispreg_hdmi, + msecs_to_jiffies(DISPREG_HDMI_DELAY)); +#elif defined(CONFIG_U8500_TV_OUTPUT_AB8500) + (void)mcde_display_device_register(&tvout_ab8500_display); +#endif + + return 0; +} +module_init(init_display_devices); diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c new file mode 100644 index 00000000000..45952d1823f --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -0,0 +1,514 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * Author: Joakim Axelsson <joakim.axelsson@stericsson.com> for ST-Ericsson + * Author: Rajat Verma <rajat.verma@stericsson.com> for ST-Ericsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/regulator/consumer.h> +#include <linux/vmalloc.h> +#include <asm/mach-types.h> +#include <plat/pincfg.h> +#include <mach/gpio.h> +#include <mach/devices.h> +#include <mach/hardware.h> + +#include "pins-db8500.h" +#include "pins.h" +#include "board-mop500.h" +#include "../drivers/staging/mmio/mmio.h" + +static pin_cfg_t i2c2_pins[] = { + GPIO8_I2C2_SDA, + GPIO9_I2C2_SCL +}; +static pin_cfg_t ipi2c_pins[] = { + GPIO8_IPI2C_SDA, + GPIO9_IPI2C_SCL +}; +static pin_cfg_t i2c_disable_pins[] = { + GPIO8_GPIO, + GPIO9_GPIO +}; +static pin_cfg_t xshutdown_host[] = { + GPIO141_GPIO, + GPIO142_GPIO +}; +static pin_cfg_t xshutdown_fw[] = { + GPIO141_IP_GPIO2, + GPIO142_IP_GPIO3 +}; +static pin_cfg_t xshutdown_disable[] = { + GPIO141_GPIO | PIN_OUTPUT_LOW, + GPIO142_GPIO | PIN_OUTPUT_LOW +}; + +struct mmio_board_data { + int number_of_regulators; + struct regulator **mmio_regulators; + /* Pin configs */ + int xenon_charge; + struct mmio_gpio xshutdown_pins[CAMERA_SLOT_END]; + /* Internal clocks */ + struct clk *clk_ptr_bml; + struct clk *clk_ptr_ipi2c; + /* External clocks */ + struct clk *clk_ptr_ext[CAMERA_SLOT_END]; +}; + +/* Fill names of regulators required for powering up the + * camera sensor in below array */ +static char *regulator_names[] = {"vaux12v5" , "vddcsi1v2"}; + +/* This function is used to translate the physical GPIO used for reset GPIO + * to logical IPGPIO that needs to be communicated to Firmware. so that + * firmware can control reset GPIO of a RAW Bayer sensor */ +static int mmio_get_ipgpio(struct mmio_platform_data *pdata, int gpio, + int *ip_gpio) +{ + int err = 0; + dev_dbg(pdata->dev, "%s() : IPGPIO requested for %d", __func__, gpio); + switch (gpio) { + case 67: + case 140: + *ip_gpio = 7; + break; + case 5: + case 66: + *ip_gpio = 6; + break; + case 81: + case 65: + *ip_gpio = 5; + break; + case 80: + case 64: + *ip_gpio = 4; + break; + case 10: + case 79: + case 142: + *ip_gpio = 3; + break; + case 11: + case 78: + case 141: + *ip_gpio = 2; + break; + case 7: + case 150: + *ip_gpio = 1; + break; + case 6: + case 149: + *ip_gpio = 0; + break; + default: + *ip_gpio = -1; + err = -1; + break; + } + return err; +} + +static int mmio_clock_init(struct mmio_platform_data *pdata) +{ + int err; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + + extra->clk_ptr_bml = clk_get_sys("bml", NULL); + if (IS_ERR(extra->clk_ptr_bml)) { + err = PTR_ERR(extra->clk_ptr_bml); + dev_err(pdata->dev, "Error %d getting clock 'bml'\n", err); + goto err_bml_clk; + } + extra->clk_ptr_ipi2c = clk_get_sys("ipi2", NULL); + if (IS_ERR(extra->clk_ptr_ipi2c)) { + err = PTR_ERR(extra->clk_ptr_ipi2c); + dev_err(pdata->dev, "Error %d getting clock 'ipi2'\n", err); + goto err_ipi2c_clk; + } + extra->clk_ptr_ext[PRIMARY_CAMERA] = clk_get_sys("pri-cam", NULL); + if (IS_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA]); + dev_err(pdata->dev, "Error %d getting clock 'pri-cam'\n", err); + goto err_pri_ext_clk; + } + extra->clk_ptr_ext[SECONDARY_CAMERA] = clk_get_sys("sec-cam", NULL); + if (IS_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA]); + dev_err(pdata->dev, "Error %d getting clock 'sec-cam'\n", err); + goto err_sec_ext_clk; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_sec_ext_clk: + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); +err_pri_ext_clk: + clk_put(extra->clk_ptr_ipi2c); +err_ipi2c_clk: + clk_put(extra->clk_ptr_bml); +err_bml_clk: + return err; +} +static void mmio_clock_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + clk_put(extra->clk_ptr_bml); + clk_put(extra->clk_ptr_ipi2c); + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); + clk_put(extra->clk_ptr_ext[SECONDARY_CAMERA]); +} + + +static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) +{ + int err; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + + extra->xshutdown_pins[PRIMARY_CAMERA].gpio = XSHUTDOWN_PRIMARY_SENSOR; + extra->xshutdown_pins[PRIMARY_CAMERA].active_high = 0; + extra->xshutdown_pins[PRIMARY_CAMERA].udelay = 500; + + extra->xshutdown_pins[SECONDARY_CAMERA].active_high = 0; + extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 500; + + /* Update GPIO mappings according to board */ + if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) { + extra->xenon_charge = HREFV60_MMIO_XENON_CHARGE; + xshutdown_host[SECONDARY_CAMERA] = GPIO140_GPIO; + xshutdown_fw[SECONDARY_CAMERA] = GPIO140_IP_GPIO7; + xshutdown_disable[SECONDARY_CAMERA] = + GPIO140_GPIO | PIN_OUTPUT_LOW; + extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 140; + } else { + extra->xenon_charge = GPIO_MMIO_XENON_CHARGE; + xshutdown_host[SECONDARY_CAMERA] = GPIO142_GPIO; + xshutdown_fw[SECONDARY_CAMERA] = GPIO142_IP_GPIO3; + xshutdown_disable[SECONDARY_CAMERA] = + GPIO142_GPIO | PIN_OUTPUT_LOW; + extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 142; + } + /* Setup Xenon Charge */ + err = gpio_request(extra->xenon_charge, "xenon charge"); + if (err) { + dev_err(pdata->dev, "Error %d while requesting xenon charge\n", + err); + goto err_xenon_gpio_req; + } + err = gpio_direction_output(extra->xenon_charge, 0); + if (err) { + dev_err(pdata->dev, "Error %d while setting xenon charge in" + "output mode\n", err); + goto err_xenon_gpio_set_dir; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_xenon_gpio_set_dir: + gpio_free(extra->xenon_charge); +err_xenon_gpio_req: + return err; +} + +static void mmio_pin_cfg_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + gpio_free(extra->xenon_charge); +} + +/* For now, both sensors on HREF have some power up sequence. If different + * sequences are needed for primary and secondary sensors, it can be + * implemented easily. Just use camera_slot field of mmio_platform_data + * to determine which camera needs to be powered up */ +static int mmio_power_init(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + extra->number_of_regulators = sizeof(regulator_names)/ + sizeof(regulator_names[0]); + extra->mmio_regulators = + kzalloc(sizeof(struct regulator *) * extra->number_of_regulators, + GFP_KERNEL); + if (!extra->mmio_regulators) { + dev_err(pdata->dev , "Error while allocating memory for mmio" + "regulators\n"); + err = -ENOMEM; + goto err_no_mem_reg; + } + for (i = 0; i < + extra->number_of_regulators; i++) { + extra->mmio_regulators[i] = + regulator_get(pdata->dev, regulator_names[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev , "Error %d getting regulator '%s'" + "\n", err, regulator_names[i]); + goto err_regulator; + } + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* Return regulators we have already requested */ + while (i--) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +err_no_mem_reg: + return err; +} + +static void mmio_power_exit(struct mmio_platform_data *pdata) +{ + int i = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + for (i = 0; i < extra->number_of_regulators; i++) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +} + +static int mmio_platform_init(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = NULL; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Alloc memory for our own extra data */ + extra = kzalloc(sizeof(struct mmio_board_data), GFP_KERNEL); + if (!extra) { + dev_err(pdata->dev, "%s: memory alloc failed for " + "mmio_board_data\n", __func__); + err = -ENOMEM; + goto err_no_mem_extra; + } + /* Hook the data for other callbacks to use */ + pdata->extra = extra; + + pdata->camera_slot = -1; + + err = mmio_power_init(pdata); + if (err) + goto err_regulator; + err = mmio_clock_init(pdata); + if (err) + goto err_clock; + err = mmio_pin_cfg_init(pdata); + if (err) + goto err_pin_cfg; + /* Store logical IPGPIO for physical reset GPIOs used */ + err = mmio_get_ipgpio(pdata, + extra->xshutdown_pins[PRIMARY_CAMERA].gpio, + &(pdata->reset_ipgpio[PRIMARY_CAMERA])); + if (err) { + dev_err(pdata->dev, "Error getting ipgpio for pri cam\n"); + goto err_ipgpio; + } + err = mmio_get_ipgpio(pdata, + extra->xshutdown_pins[SECONDARY_CAMERA].gpio, + &(pdata->reset_ipgpio[SECONDARY_CAMERA])); + if (err) { + dev_err(pdata->dev, "Error getting ipgpio for sec cam\n"); + goto err_ipgpio; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_ipgpio: + mmio_pin_cfg_exit(pdata); +err_pin_cfg: + mmio_clock_exit(pdata); +err_clock: + mmio_power_exit(pdata); +err_regulator: + kfree(extra); +err_no_mem_extra: + return err; +} +static void mmio_platform_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + mmio_power_exit(pdata); + mmio_clock_exit(pdata); + mmio_pin_cfg_exit(pdata); + kfree(extra); + pdata->extra = NULL; +} + +static int mmio_power_enable(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Enable the regulators */ + for (i = 0; i < extra->number_of_regulators; i++) { + err = regulator_enable(extra->mmio_regulators[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev , "Error %d enabling regulator '%s'" + "\n", err, regulator_names[i]); + goto err_regulator; + } + } + /* Set Xenon Charge */ + gpio_set_value_cansleep(extra->xenon_charge, 1); + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* Disable regulators we already enabled */ + while (i--) + regulator_disable(extra->mmio_regulators[i]); + return err; +} + +static void mmio_power_disable(struct mmio_platform_data *pdata) +{ + int i; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Disable the regulators */ + for (i = 0; i < extra->number_of_regulators; i++) + regulator_disable(extra->mmio_regulators[i]); + /* Disable Xenon Charge */ + gpio_set_value_cansleep(extra->xenon_charge, 0); +} +static int mmio_clock_enable(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Enable internal clocks */ + err = clk_enable(extra->clk_ptr_bml); + if (err) { + dev_err(pdata->dev, "Error activating bml clock %d\n", err); + goto err_bml_clk; + } + err = clk_enable(extra->clk_ptr_ipi2c); + if (err) { + dev_err(pdata->dev, "Error activating i2c2 clock %d\n", err); + goto err_ipi2c_clk; + } + /* Enable appropriate external clock */ + err = clk_enable(extra->clk_ptr_ext[pdata->camera_slot]); + if (err) { + dev_err(pdata->dev, "Error activating clock for sensor %d, err" + "%d\n", pdata->camera_slot, err); + goto err_ext_clk; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_ext_clk: + clk_disable(extra->clk_ptr_ipi2c); +err_ipi2c_clk: + clk_disable(extra->clk_ptr_bml); +err_bml_clk: + return err; +} + +static void mmio_clock_disable(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + clk_disable(extra->clk_ptr_bml); + clk_disable(extra->clk_ptr_ipi2c); + clk_disable(extra->clk_ptr_ext[pdata->camera_slot]); +} + + +static int mmio_config_xshutdown_pins(struct mmio_platform_data *pdata, + enum mmio_select_xshutdown_t select, + int is_active_high) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + switch (select) { + case MMIO_ENABLE_XSHUTDOWN_HOST: + extra->xshutdown_pins[pdata->camera_slot].active_high = + is_active_high; + err = nmk_config_pin(xshutdown_host[pdata->camera_slot] | + (is_active_high ? PIN_OUTPUT_LOW : PIN_OUTPUT_HIGH), + 0); + break; + case MMIO_ENABLE_XSHUTDOWN_FW: + err = nmk_config_pin(xshutdown_fw[pdata->camera_slot], 0); + break; + case MMIO_DISABLE_XSHUTDOWN: + err = nmk_config_pin(xshutdown_disable[pdata->camera_slot], + 0); + break; + default: + break; + } + if (err) + dev_dbg(pdata->dev , "Error configuring xshutdown, err = %d\n", + err); + return err; +} +static void mmio_set_xshutdown(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + gpio_set_value(extra->xshutdown_pins[pdata->camera_slot].gpio , + (extra->xshutdown_pins[pdata->camera_slot].active_high ? 1 : + 0)); + udelay(extra->xshutdown_pins[pdata->camera_slot].udelay); +} +static int mmio_config_i2c_pins(struct mmio_platform_data *pdata, + enum mmio_select_i2c_t select) +{ + int err = 0; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + switch (select) { + case MMIO_ACTIVATE_I2C_HOST: + err = nmk_config_pins(i2c2_pins, ARRAY_SIZE(i2c2_pins)); + break; + case MMIO_ACTIVATE_IPI2C2: + err = nmk_config_pins(ipi2c_pins, ARRAY_SIZE(ipi2c_pins)); + break; + case MMIO_DEACTIVATE_I2C: + err = nmk_config_pins(i2c_disable_pins, + ARRAY_SIZE(i2c_disable_pins)); + break; + default: + break; + } + + return err; +} +static struct mmio_platform_data mmio_config = { + .platform_init = mmio_platform_init, + .platform_exit = mmio_platform_exit, + .power_enable = mmio_power_enable, + .power_disable = mmio_power_disable, + .clock_enable = mmio_clock_enable, + .clock_disable = mmio_clock_disable, + .config_i2c_pins = mmio_config_i2c_pins, + .config_xshutdown_pins = mmio_config_xshutdown_pins, + .set_xshutdown = mmio_set_xshutdown, + .sia_base = U8500_SIA_BASE, + .cr_base = U8500_CR_BASE +}; + +struct platform_device ux500_mmio_device = { + .name = MMIO_NAME, + .id = -1, + .dev = { + .platform_data = &mmio_config, + } +}; diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c new file mode 100644 index 00000000000..c5fade6d0c7 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-msp.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> + +#include <plat/ste_dma40.h> +#include <plat/pincfg.h> + +#include <mach/devices.h> +#include <mach/ste-dma40-db8500.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/msp.h> + +#include "board-mop500.h" +#include "devices-db8500.h" +#include "pins-db8500.h" + +/* MSP1/3 Tx/Rx usage protection */ +static DEFINE_SPINLOCK(msp_rxtx_lock); + +/* Reference Count */ +static int msp_rxtx_ref; + +static pin_cfg_t mop500_msp1_pins_init[] = { + GPIO33_MSP1_TXD | PIN_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE, + GPIO34_MSP1_TFS | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE, + GPIO35_MSP1_TCK | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE, + GPIO36_MSP1_RXD | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE, +}; + +static pin_cfg_t mop500_msp1_pins_exit[] = { + GPIO33_MSP1_TXD | PIN_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE, + GPIO34_MSP1_TFS | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE, + GPIO35_MSP1_TCK | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE, + GPIO36_MSP1_RXD | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE, +}; + +int msp13_i2s_init(void) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&msp_rxtx_lock, flags); + if (msp_rxtx_ref == 0) + retval = nmk_config_pins( + ARRAY_AND_SIZE(mop500_msp1_pins_init)); + if (!retval) + msp_rxtx_ref++; + spin_unlock_irqrestore(&msp_rxtx_lock, flags); + + return retval; +} + +int msp13_i2s_exit(void) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&msp_rxtx_lock, flags); + WARN_ON(!msp_rxtx_ref); + msp_rxtx_ref--; + if (msp_rxtx_ref == 0) + retval = nmk_config_pins_sleep( + ARRAY_AND_SIZE(mop500_msp1_pins_exit)); + spin_unlock_irqrestore(&msp_rxtx_lock, flags); + + return retval; +} + +static struct stedma40_chan_cfg msp0_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp0_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp0_platform_data = { + .id = MSP_0_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp0_dma_rx, + .msp_i2s_dma_tx = &msp0_dma_tx, +}; + +static struct stedma40_chan_cfg msp1_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV30_MSP3_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp1_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp1_platform_data = { + .id = MSP_1_I2S_CONTROLLER, + .msp_i2s_dma_rx = NULL, + .msp_i2s_dma_tx = &msp1_dma_tx, + .msp_i2s_init = msp13_i2s_init, + .msp_i2s_exit = msp13_i2s_exit, +}; + +static struct stedma40_chan_cfg msp2_dma_rx = { + .high_priority = true, + .dir = STEDMA40_PERIPH_TO_MEM, + + .src_dev_type = DB8500_DMA_DEV14_MSP2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + + /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */ + .src_info.psize = STEDMA40_PSIZE_LOG_1, + .dst_info.psize = STEDMA40_PSIZE_LOG_1, + + /* data_width is set during configuration */ +}; + +static struct stedma40_chan_cfg msp2_dma_tx = { + .high_priority = true, + .dir = STEDMA40_MEM_TO_PERIPH, + + .src_dev_type = STEDMA40_DEV_DST_MEMORY, + .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX, + + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + + .use_fixed_channel = true, + .phy_channel = 1, + + /* data_width is set during configuration */ +}; + +static struct msp_i2s_platform_data msp2_platform_data = { + .id = MSP_2_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp2_dma_rx, + .msp_i2s_dma_tx = &msp2_dma_tx, +}; + +static struct msp_i2s_platform_data msp3_platform_data = { + .id = MSP_3_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp1_dma_rx, + .msp_i2s_dma_tx = NULL, + .msp_i2s_init = msp13_i2s_init, + .msp_i2s_exit = msp13_i2s_exit, +}; + +void __init mop500_msp_init(struct device *parent) +{ + db8500_add_msp0_i2s(parent, &msp0_platform_data); + db8500_add_msp1_i2s(parent, &msp1_platform_data); + db8500_add_msp2_i2s(parent, &msp2_platform_data); + db8500_add_msp3_i2s(parent, &msp3_platform_data); +} diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index f5413dca532..342954fdecf 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -7,109 +7,50 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/bug.h> +#include <linux/string.h> #include <asm/mach-types.h> #include <plat/pincfg.h> -#include <plat/gpio-nomadik.h> +#include <linux/gpio/nomadik.h> +#include <linux/mfd/abx500/ab8500-gpio.h> + #include <mach/hardware.h> +#include <mach/suspend.h> #include "pins-db8500.h" +#include "pins.h" +#include "board-mop500.h" +#include "board-pins-sleep-force.h" + +enum custom_pin_cfg_t { + PINS_FOR_DEFAULT, + PINS_FOR_U9500, +}; + +static enum custom_pin_cfg_t pinsfor; static pin_cfg_t mop500_pins_common[] = { - /* I2C */ - GPIO147_I2C0_SCL, - GPIO148_I2C0_SDA, - GPIO16_I2C1_SCL, - GPIO17_I2C1_SDA, - GPIO10_I2C2_SDA, - GPIO11_I2C2_SCL, - GPIO229_I2C3_SDA, - GPIO230_I2C3_SCL, - - /* MSP0 */ + /* uMSP0 */ GPIO12_MSP0_TXD, GPIO13_MSP0_TFS, GPIO14_MSP0_TCK, GPIO15_MSP0_RXD, /* MSP2: HDMI */ - GPIO193_MSP2_TXD, - GPIO194_MSP2_TCK, - GPIO195_MSP2_TFS, + GPIO193_MSP2_TXD | PIN_INPUT_PULLDOWN, + GPIO194_MSP2_TCK | PIN_INPUT_PULLDOWN, + GPIO195_MSP2_TFS | PIN_INPUT_PULLDOWN, GPIO196_MSP2_RXD | PIN_OUTPUT_LOW, + /* LCD TE0 */ + GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, + /* Touch screen INTERFACE */ GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */ /* STMPE1601/tc35893 keypad IRQ */ GPIO218_GPIO | PIN_INPUT_PULLUP, - /* MMC0 (MicroSD card) */ - GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, - GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, - GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, - - GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, - GPIO23_MC0_CLK | PIN_OUTPUT_LOW, - GPIO24_MC0_CMD | PIN_INPUT_PULLUP, - GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, - GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, - GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, - GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, - - /* SDI1 (SDIO) */ - GPIO208_MC1_CLK | PIN_OUTPUT_LOW, - GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL, - GPIO210_MC1_CMD | PIN_INPUT_PULLUP, - GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP, - GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP, - GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP, - GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP, - - /* MMC2 (On-board DATA INTERFACE eMMC) */ - GPIO128_MC2_CLK | PIN_OUTPUT_LOW, - GPIO129_MC2_CMD | PIN_INPUT_PULLUP, - GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL, - GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP, - GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP, - GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP, - GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP, - GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP, - GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP, - GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP, - GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP, - - /* MMC4 (On-board STORAGE INTERFACE eMMC) */ - GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP, - GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP, - GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP, - GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP, - GPIO201_MC4_CMD | PIN_INPUT_PULLUP, - GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL, - GPIO203_MC4_CLK | PIN_OUTPUT_LOW, - GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP, - GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP, - GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP, - GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP, - - /* SKE keypad */ - GPIO153_KP_I7, - GPIO154_KP_I6, - GPIO155_KP_I5, - GPIO156_KP_I4, - GPIO157_KP_O7, - GPIO158_KP_O6, - GPIO159_KP_O5, - GPIO160_KP_O4, - GPIO161_KP_I3, - GPIO162_KP_I2, - GPIO163_KP_I1, - GPIO164_KP_I0, - GPIO165_KP_O3, - GPIO166_KP_O2, - GPIO167_KP_O1, - GPIO168_KP_O0, - /* UART */ /* uart-0 pins gpio configuration should be * kept intact to prevent glitch in tx line @@ -128,10 +69,6 @@ static pin_cfg_t mop500_pins_common[] = { GPIO30_U2_TXD | PIN_OUTPUT_HIGH, GPIO31_U2_CTSn | PIN_INPUT_PULLUP, GPIO32_U2_RTSn | PIN_OUTPUT_HIGH, - - /* Display & HDMI HW sync */ - GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, - GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, }; static pin_cfg_t mop500_pins_default[] = { @@ -141,10 +78,13 @@ static pin_cfg_t mop500_pins_default[] = { GPIO145_SSP0_RXD | PIN_PULL_DOWN, GPIO146_SSP0_TXD, + /* XENON Flashgun INTERFACE */ + GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ + GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */ - /* SDI0 (MicroSD card) */ + /* sdi0 (removable MMC/SD/SDIO cards) not handled by pm_runtime */ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH, /* UART */ @@ -156,13 +96,11 @@ static pin_cfg_t mop500_pins_default[] = { static pin_cfg_t hrefv60_pins[] = { /* WLAN */ - GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ /* XENON Flashgun INTERFACE */ GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ - GPIO170_GPIO | PIN_OUTPUT_LOW, /* XENON_CHARGE */ /* Assistant LED INTERFACE */ GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */ @@ -173,7 +111,7 @@ static pin_cfg_t hrefv60_pins[] = { GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */ /* Display Interface */ - GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */ + GPIO65_GPIO | PIN_OUTPUT_HIGH, /* DISP1 NO RST */ GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */ /* Touch screen INTERFACE */ @@ -215,11 +153,8 @@ static pin_cfg_t hrefv60_pins[] = { /* DiPro Sensor Interface */ GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */ - /* HAL SWITCH INTERFACE */ - GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */ - /* Audio Amplifier Interface */ - GPIO149_GPIO | PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */ + GPIO149_GPIO | PIN_OUTPUT_HIGH, /* VAUDIO_HF_EN, enable MAX8968 */ /* GBF INTERFACE */ GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */ @@ -231,10 +166,29 @@ static pin_cfg_t hrefv60_pins[] = { GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */ GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */ - /* Proximity Sensor */ - GPIO217_GPIO | PIN_INPUT_PULLUP, + /* SD card detect */ + GPIO95_GPIO | PIN_INPUT_PULLUP, +}; +static pin_cfg_t u9500_pins[] = { + GPIO4_U1_RXD | PIN_INPUT_PULLUP, + GPIO5_U1_TXD | PIN_OUTPUT_HIGH, + GPIO144_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ + /* HSI */ + GPIO219_HSIR_FLA0 | PIN_INPUT_PULLDOWN, + GPIO220_HSIR_DAT0 | PIN_INPUT_PULLDOWN, + GPIO221_HSIR_RDY0 | PIN_OUTPUT_LOW, + GPIO222_HSIT_FLA0 | PIN_OUTPUT_LOW, + GPIO223_HSIT_DAT0 | PIN_OUTPUT_LOW, + GPIO224_HSIT_RDY0 | PIN_INPUT_PULLDOWN, + GPIO225_HSIT_CAWAKE0 | PIN_INPUT_PULLDOWN, /* CA_WAKE0 */ + GPIO226_GPIO | PIN_OUTPUT_HIGH, /* AC_WAKE0 */ +}; + +static pin_cfg_t u8500_pins[] = { + GPIO226_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN */ + GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ }; static pin_cfg_t snowball_pins[] = { @@ -247,6 +201,9 @@ static pin_cfg_t snowball_pins[] = { /* MMC0: MicroSD card */ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH, + /* USER PB pin */ + GPIO32_GPIO | PIN_INPUT_PULLUP, + /* MMC2: LAN */ GPIO86_SM_ADQ0, GPIO87_SM_ADQ1, @@ -275,15 +232,929 @@ static pin_cfg_t snowball_pins[] = { /* RSTn_LAN */ GPIO141_GPIO | PIN_OUTPUT_HIGH, + + /* Accelerometer/Magnetometer */ + GPIO163_GPIO | PIN_INPUT_PULLUP, /* ACCEL_IRQ1 */ + GPIO164_GPIO | PIN_INPUT_PULLUP, /* ACCEL_IRQ2 */ + GPIO165_GPIO | PIN_INPUT_PULLUP, /* MAG_DRDY */ + + /* WLAN/GBF */ + GPIO161_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN */ + GPIO171_GPIO | PIN_OUTPUT_HIGH,/* GBF_ENA */ + GPIO215_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ + GPIO216_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ +}; + +/* + * I2C + */ + +static UX500_PINS(mop500_pins_i2c0, + GPIO147_I2C0_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO148_I2C0_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c1, + GPIO16_I2C1_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO17_I2C1_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c2, + GPIO10_I2C2_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO11_I2C2_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c3, + GPIO229_I2C3_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO230_I2C3_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_mcde_tvout, + GPIO78_LCD_D8, + GPIO79_LCD_D9, + GPIO80_LCD_D10, + GPIO81_LCD_D11, + GPIO150_LCDA_CLK, +); + +static UX500_PINS(mop500_pins_mcde_hdmi, + GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, +); + +static UX500_PINS(mop500_pins_ske, + GPIO153_KP_I7 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO154_KP_I6 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO155_KP_I5 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO156_KP_I4 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO161_KP_I3 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO162_KP_I2 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO163_KP_I1 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO164_KP_I0 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO157_KP_O7 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO158_KP_O6 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO159_KP_O5 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO160_KP_O4 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO165_KP_O3 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO166_KP_O2 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO167_KP_O1 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO168_KP_O0 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, +); + +/* sdi0 (removable MMC/SD/SDIO cards) */ +static UX500_PINS(mop500_pins_sdi0, + GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, + GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, + GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, + + GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, + GPIO23_MC0_CLK | PIN_OUTPUT_LOW, + GPIO24_MC0_CMD | PIN_INPUT_PULLUP, + GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, + GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, + GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, + GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, +); + +/* sdi1 (WLAN CW1200) */ +static UX500_PINS(mop500_pins_sdi1, + GPIO208_MC1_CLK | PIN_OUTPUT_LOW, + GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL, + GPIO210_MC1_CMD | PIN_INPUT_PULLUP, + GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP, + GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP, + GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP, + GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP, +); + +/* sdi2 (POP eMMC) */ +static UX500_PINS(mop500_pins_sdi2, + GPIO128_MC2_CLK | PIN_OUTPUT_LOW, + GPIO129_MC2_CMD | PIN_INPUT_PULLUP, + GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL, + GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP, + GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP, + GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP, + GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP, + GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP, + GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP, + GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP, + GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP, +); + +/* sdi4 (PCB eMMC) */ +static UX500_PINS(mop500_pins_sdi4, + GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP, + GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP, + GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP, + GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP, + GPIO201_MC4_CMD | PIN_INPUT_PULLUP, + GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL, + GPIO203_MC4_CLK | PIN_OUTPUT_LOW, + GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP, + GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP, + GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP, + GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP, +); + +/* USB */ +static UX500_PINS(mop500_pins_usb, + GPIO256_USB_NXT, + GPIO257_USB_STP | PIN_OUTPUT_HIGH, + GPIO258_USB_XCLK, + GPIO259_USB_DIR, + GPIO260_USB_DAT7, + GPIO261_USB_DAT6, + GPIO262_USB_DAT5, + GPIO263_USB_DAT4, + GPIO264_USB_DAT3, + GPIO265_USB_DAT2, + GPIO266_USB_DAT1, + GPIO267_USB_DAT0, +); + +/* SPI2 */ +static UX500_PINS(mop500_pins_spi2, + GPIO216_GPIO | PIN_OUTPUT_HIGH, + GPIO218_SPI2_RXD | PIN_INPUT_PULLDOWN, + GPIO215_SPI2_TXD | PIN_OUTPUT_LOW, + GPIO217_SPI2_CLK | PIN_OUTPUT_LOW, +); + +static UX500_PINS(mop500_pins_sensors1p_v60, + GPIO217_GPIO| PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO145_GPIO | PIN_INPUT_PULLDOWN | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO139_GPIO | PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_sensors1p, + PIN_CFG_INPUT(GPIO_PROX_SENSOR, GPIO, NOPULL), + PIN_CFG_INPUT(GPIO_HAL_SENSOR, GPIO, NOPULL), +); + +static struct ux500_pin_lookup mop500_runtime_pins[] = { + PIN_LOOKUP("mcde-tvout", &mop500_pins_mcde_tvout), + PIN_LOOKUP("av8100-hdmi", &mop500_pins_mcde_hdmi), + PIN_LOOKUP("nmk-i2c.0", &mop500_pins_i2c0), + PIN_LOOKUP("nmk-i2c.1", &mop500_pins_i2c1), + PIN_LOOKUP("nmk-i2c.2", &mop500_pins_i2c2), + PIN_LOOKUP("nmk-i2c.3", &mop500_pins_i2c3), + PIN_LOOKUP("sdi0", &mop500_pins_sdi0), + PIN_LOOKUP("sdi1", &mop500_pins_sdi1), + PIN_LOOKUP("sdi2", &mop500_pins_sdi2), + PIN_LOOKUP("sdi4", &mop500_pins_sdi4), + PIN_LOOKUP("musb-ux500.0", &mop500_pins_usb), + PIN_LOOKUP("spi2", &mop500_pins_spi2), +}; + +static struct ux500_pin_lookup mop500_runtime_pins_v60[] = { + PIN_LOOKUP("ske", &mop500_pins_ske), + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p_v60), +}; + +static struct ux500_pin_lookup mop500_runtime_pins_pre_v60[] = { + PIN_LOOKUP("ske", &mop500_pins_ske), + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p), +}; + +/* + * Sleep pin configuration for u8500 platform. + * If another HW is used the GPIO's must be configured + * correctly when entering sleep for optimal power + * consumption. + */ +static pin_cfg_t mop500_pins_common_power_save_bank0[] = { + GPIO0_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO1_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO2_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO3_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO4_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO5_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO6_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO7_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO8_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO9_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 10-11 - I2C2 */ + GPIO10_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO11_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO12_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO13_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO14_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO15_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 16-17 - I2C1 */ + GPIO16_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO17_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO18_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO19_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO20_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO21_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO22_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO23_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO24_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO25_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO26_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO27_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO28_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO29_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO30_U2_TXD | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO31_U2_CTSn | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank0_href60[] = { + GPIO0_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO1_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO2_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO3_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO4_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO5_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO6_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO7_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO8_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO9_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 10-11 - I2C2 */ + GPIO10_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO11_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO12_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO13_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO14_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO15_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 16-17 - I2C1 */ + GPIO16_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO17_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO18_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO19_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO20_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO21_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO22_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO23_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO24_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO25_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO26_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO27_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO28_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO29_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO30_U2_TXD | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO31_U2_CTSn | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank1[] = { + GPIO32_U2_RTSn | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO33_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO34_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO35_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO36_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank1_snowball[] = { + /*GPIO32 is used as USER_PB input in snowball*/ + GPIO32_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_PDIS_ENABLED, + GPIO33_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO34_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO35_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO36_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, }; +static pin_cfg_t mop500_pins_common_power_save_bank2[] = { + GPIO64_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO65_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO66_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO67_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO68_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO69_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO70_STMAPE_CLK | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO71_STMAPE_DAT3 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO72_STMAPE_DAT2 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO73_STMAPE_DAT1 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO74_STMAPE_DAT0 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO75_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO76_U2_TXD | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO77_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO78_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO79_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO80_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO81_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO82_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO83_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO84_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO85_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO86_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO87_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO88_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO89_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO90_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO91_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO92_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO93_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO94_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO95_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank2_href60[] = { + GPIO64_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO65_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO66_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO67_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO68_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO69_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO70_STMAPE_CLK | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO71_STMAPE_DAT3 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO72_STMAPE_DAT2 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO73_STMAPE_DAT1 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO74_STMAPE_DAT0 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO75_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO76_U2_TXD | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO77_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO78_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO79_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO80_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO81_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO82_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO83_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO84_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO85_GPIO, + GPIO86_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO87_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO88_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO89_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO90_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO91_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO92_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO93_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO94_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO95_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank3[] = { + GPIO96_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO97_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank4[] = { + GPIO128_MC2_CLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO129_MC2_CMD | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO130_MC2_FBCLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO131_MC2_DAT0 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO132_MC2_DAT1 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO133_MC2_DAT2 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO134_MC2_DAT3 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO135_MC2_DAT4 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO136_MC2_DAT5 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO137_MC2_DAT6 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO138_MC2_DAT7 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO139_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO140_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO141_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO142_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 145 - HAL sensor (on v60 and later) */ + GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO146_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 147-148 - I2C0 */ + GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO148_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO149_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO150_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO151_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO152_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO153_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO154_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO155_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO156_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO157_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO158_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO159_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank4_snowball[] = { + GPIO128_MC2_CLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO129_MC2_CMD | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO130_MC2_FBCLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO131_MC2_DAT0 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO132_MC2_DAT1 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO133_MC2_DAT2 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO134_MC2_DAT3 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO135_MC2_DAT4 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO136_MC2_DAT5 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO137_MC2_DAT6 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO138_MC2_DAT7 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO139_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO140_GPIO | PIN_SLPM_DIR_INPUT, + /* 141 - (RSTn_LAN) Keep this high to avoid smsc reset at suspend */ + GPIO141_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO142_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 145 - HAL sensor (on v60 and later) */ + GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO146_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 147-148 - I2C0 */ + GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO148_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO149_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO150_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO151_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO152_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO153_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO154_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO155_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO156_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO157_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO158_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO159_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank4_u9500_uibr3[] = { + GPIO128_MC2_CLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO129_MC2_CMD | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO130_MC2_FBCLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO131_MC2_DAT0 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO132_MC2_DAT1 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO133_MC2_DAT2 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO134_MC2_DAT3 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO135_MC2_DAT4 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO136_MC2_DAT5 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO137_MC2_DAT6 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO138_MC2_DAT7 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO139_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO140_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO141_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO142_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 145 - HAL sensor (on v60 and later) */ + GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 147-148 - I2C0 */ + GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO148_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO149_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO150_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO151_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO152_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO153_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO154_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO155_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO156_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO157_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO158_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO159_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank5[] = { + GPIO160_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO161_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO162_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO163_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO164_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO165_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO166_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO167_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO168_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO169_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO170_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO171_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank5_href60[] = { + GPIO160_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO161_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO162_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO163_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO164_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO165_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO166_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO167_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO168_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO169_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO170_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO171_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank6[] = { + GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO212_GPIO, + GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO215_GPIO, + + GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO220_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO221_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO222_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO223_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank6_href60[] = { + GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO212_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO215_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 217 - Proximity */ + GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO220_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO221_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO222_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO223_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank6_u9500[] = { + GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO212_GPIO, + GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO215_GPIO, + + GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO219_GPIO | PIN_SLPM_INPUT_PULLDOWN, + + GPIO220_GPIO | PIN_SLPM_INPUT_PULLDOWN, + GPIO221_GPIO | PIN_SLPM_OUTPUT_LOW, + GPIO222_GPIO | PIN_SLPM_OUTPUT_LOW, + GPIO223_GPIO | PIN_SLPM_OUTPUT_LOW, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank7[] = { + GPIO224_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO225_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO226_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 229-230 - I2C3 */ + GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank7_href60[] = { + GPIO224_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO225_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO226_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 229-230 - I2C3 */ + GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank7_u9500[] = { + GPIO224_GPIO | PIN_SLPM_INPUT_PULLDOWN, + GPIO225_GPIO | PIN_SLPM_INPUT_PULLDOWN | PIN_SLPM_WAKEUP_ENABLE, + GPIO226_GPIO | PIN_SLPM_OUTPUT_LOW, + GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank8[] = { + GPIO256_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO257_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO258_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO259_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + + GPIO260_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO261_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO262_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO263_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + + GPIO264_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO265_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO266_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO267_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, +}; + +static void mop500_pins_suspend_force(void) +{ + if (machine_is_hrefv60() || machine_is_u8520() || + machine_is_u9540()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank0_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank0_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank0, + ARRAY_SIZE(mop500_pins_common_power_save_bank0)); + + if (machine_is_snowball()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank1_snowball, + ARRAY_SIZE(mop500_pins_common_power_save_bank1_snowball)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank1, + ARRAY_SIZE(mop500_pins_common_power_save_bank1)); + + if (machine_is_hrefv60() || machine_is_u8520() || + machine_is_u9540()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank2_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank2_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank2, + ARRAY_SIZE(mop500_pins_common_power_save_bank2)); + + sleep_pins_config_pm(mop500_pins_common_power_save_bank3, + ARRAY_SIZE(mop500_pins_common_power_save_bank3)); + + + if (pins_for_u9500() && uib_is_u8500uibr3()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank4_u9500_uibr3, + ARRAY_SIZE(mop500_pins_common_power_save_bank4_u9500_uibr3)); + else if (machine_is_snowball()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank4_snowball, + ARRAY_SIZE(mop500_pins_common_power_save_bank4_snowball)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank4, + ARRAY_SIZE(mop500_pins_common_power_save_bank4)); + + if (machine_is_hrefv60() || machine_is_u8520() || + machine_is_u9540()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank5_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank5_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank5, + ARRAY_SIZE(mop500_pins_common_power_save_bank5)); + + if (pins_for_u9500()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank6_u9500, + ARRAY_SIZE(mop500_pins_common_power_save_bank6_u9500)); + else if (machine_is_hrefv60() || machine_is_u8520() || + machine_is_u9540()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank6_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank6_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank6, + ARRAY_SIZE(mop500_pins_common_power_save_bank6)); + + if (pins_for_u9500()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank7_u9500, + ARRAY_SIZE(mop500_pins_common_power_save_bank7_u9500)); + else if (machine_is_hrefv60() || machine_is_u8520() || + machine_is_u9540()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank7_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank7_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank7, + ARRAY_SIZE(mop500_pins_common_power_save_bank7)); + + sleep_pins_config_pm(mop500_pins_common_power_save_bank8, + ARRAY_SIZE(mop500_pins_common_power_save_bank8)); +} + +/* + * This function is called to force gpio power save + * mux settings during suspend. + * This is a temporary solution until all drivers are + * controlling their pin settings when in inactive mode. + */ +static void mop500_pins_suspend_force_mux(void) +{ + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank0, + ARRAY_SIZE(mop500_pins_common_power_save_bank0)); + + if (machine_is_snowball()) + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank1_snowball, + ARRAY_SIZE(mop500_pins_common_power_save_bank1_snowball)); + else + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank1, + ARRAY_SIZE(mop500_pins_common_power_save_bank1)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank2, + ARRAY_SIZE(mop500_pins_common_power_save_bank2)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank3, + ARRAY_SIZE(mop500_pins_common_power_save_bank3)); + + if (machine_is_snowball()) + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank4_snowball, + ARRAY_SIZE(mop500_pins_common_power_save_bank4_snowball)); + else + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank4, + ARRAY_SIZE(mop500_pins_common_power_save_bank4)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank5, + ARRAY_SIZE(mop500_pins_common_power_save_bank5)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank6, + ARRAY_SIZE(mop500_pins_common_power_save_bank6)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank7, + ARRAY_SIZE(mop500_pins_common_power_save_bank7)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank8, + ARRAY_SIZE(mop500_pins_common_power_save_bank8)); +} + +/* + * passing "pinsfor=" in kernel cmdline allows for custom + * configuration of GPIOs on u8500 derived boards. + */ +static int __init early_pinsfor(char *p) +{ + pinsfor = PINS_FOR_DEFAULT; + + if (strcmp(p, "u9500-21") == 0) + pinsfor = PINS_FOR_U9500; + + return 0; +} +early_param("pinsfor", early_pinsfor); + +int pins_for_u9500(void) +{ + if (pinsfor == PINS_FOR_U9500) + return 1; + + return 0; +} + +static UX500_PINS(mop500_offchip_gpio_cfg, + /* + * Workaround for auto shutdown of 3.2MHz oscillator during + * deep sleep. APESPICSn/GPIO37 must be floating on the board + * to use this fix. + */ + AB8500_PIN_GPIO37 | PIN_OUTPUT_HIGH, +); + void __init mop500_pins_init(void) { nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + ux500_pins_add(mop500_runtime_pins_pre_v60, + ARRAY_SIZE(mop500_runtime_pins_pre_v60)); + + switch (pinsfor) { + case PINS_FOR_U9500: + nmk_config_pins(u9500_pins, ARRAY_SIZE(u9500_pins)); + break; + + case PINS_FOR_DEFAULT: + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + default: + break; + } + nmk_config_pins(mop500_pins_default, ARRAY_SIZE(mop500_pins_default)); + + suspend_set_pins_force_fn(mop500_pins_suspend_force, + mop500_pins_suspend_force_mux); } void __init snowball_pins_init(void) @@ -291,8 +1162,14 @@ void __init snowball_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); - nmk_config_pins(snowball_pins, - ARRAY_SIZE(snowball_pins)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + + nmk_config_pins(snowball_pins, ARRAY_SIZE(snowball_pins)); + + suspend_set_pins_force_fn(mop500_pins_suspend_force, + mop500_pins_suspend_force_mux); } void __init hrefv60_pins_init(void) @@ -300,6 +1177,35 @@ void __init hrefv60_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + ux500_pins_add(mop500_runtime_pins_v60, + ARRAY_SIZE(mop500_runtime_pins_v60)); + nmk_config_pins(hrefv60_pins, ARRAY_SIZE(hrefv60_pins)); + + switch (pinsfor) { + case PINS_FOR_U9500: + nmk_config_pins(u9500_pins, ARRAY_SIZE(u9500_pins)); + break; + + case PINS_FOR_DEFAULT: + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + default: + break; + } + + suspend_set_pins_force_fn(mop500_pins_suspend_force, + mop500_pins_suspend_force_mux); +} + +static int __init mop500_offchip_gpio_init(void) +{ + if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) + ux500_offchip_gpio_init(&mop500_offchip_gpio_cfg); + + return 0; } +/* Let gpio chip drivers initialize. */ +late_initcall(mop500_offchip_gpio_init); diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index 52426a42578..44fbb68b15a 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -11,8 +11,52 @@ #include <linux/kernel.h> #include <linux/regulator/machine.h> #include <linux/regulator/ab8500.h> +#include <mach/id.h> /* to identify older boards for fixes */ +#include <asm/mach-types.h> #include "board-mop500-regulators.h" +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE +/* + * GPIO regulator controlled by the ab8500 GPIO16 + */ +static struct regulator_consumer_supply gpio_wlan_vbat_consumers[] = { + /* for cg2900 chip */ + REGULATOR_SUPPLY("vdd", "cg2900-uart.0"), + /* for cw1200 chip */ + REGULATOR_SUPPLY("vdd", "cw1200_wlan"), +}; + +struct regulator_init_data gpio_wlan_vbat_regulator = { + .constraints = { + .name = "WLAN-VBAT", + .min_uV = 3600000, + .max_uV = 3600000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(gpio_wlan_vbat_consumers), + .consumer_supplies = gpio_wlan_vbat_consumers, +}; + +/* + * GPIO regulator controlled by the ab8500 GPIO26 + */ +static struct regulator_consumer_supply gpio_en_3v3_consumers[] = { + /* for LAN chip */ + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + +struct regulator_init_data gpio_en_3v3_regulator = { + .constraints = { + .name = "EN-3V3", + .min_uV = 3300000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(gpio_en_3v3_consumers), + .consumer_supplies = gpio_en_3v3_consumers, +}; +#endif + /* * TPS61052 regulator */ @@ -38,21 +82,37 @@ struct regulator_init_data tps61052_regulator = { }; static struct regulator_consumer_supply ab8500_vaux1_consumers[] = { - /* External displays, connector on board 2v5 power supply */ - REGULATOR_SUPPLY("vaux12v5", "mcde.0"), + /* Main display, u8500 R3 uib */ + REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"), + /* Main display, u8500 uib and ST uib */ + REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"), + /* Secondary display, ST uib */ + REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"), /* SFH7741 proximity sensor */ REGULATOR_SUPPLY("vcc", "gpio-keys.0"), /* BH1780GLS ambient light sensor */ REGULATOR_SUPPLY("vcc", "2-0029"), /* lsm303dlh accelerometer */ - REGULATOR_SUPPLY("vdd", "3-0018"), + REGULATOR_SUPPLY("vdd", "lsm303dlh.0"), /* lsm303dlh magnetometer */ - REGULATOR_SUPPLY("vdd", "3-001e"), + REGULATOR_SUPPLY("vdd", "lsm303dlh.1"), /* Rohm BU21013 Touchscreen devices */ REGULATOR_SUPPLY("avdd", "3-005c"), REGULATOR_SUPPLY("avdd", "3-005d"), /* Synaptics RMI4 Touchscreen device */ REGULATOR_SUPPLY("vdd", "3-004b"), + /* L3G4200D Gyroscope device */ + REGULATOR_SUPPLY("vdd", "l3g4200d"), + /* Proximity and Hal sensor device */ + REGULATOR_SUPPLY("vdd", "sensor1p.0"), + /* Ambient light sensor device */ + REGULATOR_SUPPLY("vdd", "3-0029"), + /* Pressure sensor device */ + REGULATOR_SUPPLY("vdd", "2-005c"), + /* Cypress TrueTouch Touchscreen device */ + REGULATOR_SUPPLY("vcpin", "spi8.0"), + /* Camera device */ + REGULATOR_SUPPLY("vaux12v5", "mmio_camera"), }; static struct regulator_consumer_supply ab8500_vaux2_consumers[] = { @@ -60,9 +120,16 @@ static struct regulator_consumer_supply ab8500_vaux2_consumers[] = { REGULATOR_SUPPLY("vmmc", "sdi4"), /* AB8500 audio codec */ REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"), + /* AB8500 accessory detect 1 */ + REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"), + /* AB8500 Tv-out device */ + REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"), + /* AV8100 HDMI device */ + REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"), }; static struct regulator_consumer_supply ab8500_vaux3_consumers[] = { + REGULATOR_SUPPLY("v-SD-STM", "stm"), /* External MMC slot power */ REGULATOR_SUPPLY("vmmc", "sdi0"), }; @@ -72,26 +139,30 @@ static struct regulator_consumer_supply ab8500_vtvout_consumers[] = { REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"), /* Internal general-purpose ADC */ REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"), + /* ADC for charger */ + REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"), + /* AB8500 Tv-out device */ + REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"), }; static struct regulator_consumer_supply ab8500_vaud_consumers[] = { /* AB8500 audio-codec main supply */ - REGULATOR_SUPPLY("vaud", "ab8500-codec.0"), + REGULATOR_SUPPLY("v-audio", NULL), }; static struct regulator_consumer_supply ab8500_vamic1_consumers[] = { /* AB8500 audio-codec Mic1 supply */ - REGULATOR_SUPPLY("vamic1", "ab8500-codec.0"), + REGULATOR_SUPPLY("v-amic1", NULL), }; static struct regulator_consumer_supply ab8500_vamic2_consumers[] = { /* AB8500 audio-codec Mic2 supply */ - REGULATOR_SUPPLY("vamic2", "ab8500-codec.0"), + REGULATOR_SUPPLY("v-amic2", NULL), }; static struct regulator_consumer_supply ab8500_vdmic_consumers[] = { /* AB8500 audio-codec DMic supply */ - REGULATOR_SUPPLY("vdmic", "ab8500-codec.0"), + REGULATOR_SUPPLY("v-dmic", NULL), }; static struct regulator_consumer_supply ab8500_vintcore_consumers[] = { @@ -102,74 +173,85 @@ static struct regulator_consumer_supply ab8500_vintcore_consumers[] = { }; static struct regulator_consumer_supply ab8500_vana_consumers[] = { - /* External displays, connector on board, 1v8 power supply */ - REGULATOR_SUPPLY("vsmps2", "mcde.0"), + /* DB8500 DSI */ + REGULATOR_SUPPLY("vdddsi1v2", "mcde"), + /* DB8500 CSI */ + REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"), +}; + +static struct regulator_consumer_supply ab8500_sysclkreq_2_consumers[] = { + /* CG2900 device */ + REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), +}; + +static struct regulator_consumer_supply ab8500_sysclkreq_4_consumers[] = { + /* CW1200 device */ + REGULATOR_SUPPLY("wlan_1v8", "cw1200_wlan.0"), }; /* ab8500 regulator register initialization */ -struct ab8500_regulator_reg_init -ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { +static struct ab8500_regulator_reg_init ab8500_reg_init[] = { /* * VanaRequestCtrl = HP/LP depending on VxRequest * VextSupply1RequestCtrl = HP/LP depending on VxRequest */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xf0, 0x00), /* * VextSupply2RequestCtrl = HP/LP depending on VxRequest * VextSupply3RequestCtrl = HP/LP depending on VxRequest * Vaux1RequestCtrl = HP/LP depending on VxRequest * Vaux2RequestCtrl = HP/LP depending on VxRequest */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0xff, 0x00), /* * Vaux3RequestCtrl = HP/LP depending on VxRequest * SwHPReq = Control through SWValid disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x07, 0x00), /* * VanaSysClkReq1HPValid = disabled * Vaux1SysClkReq1HPValid = disabled * Vaux2SysClkReq1HPValid = disabled * Vaux3SysClkReq1HPValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00), /* * VextSupply1SysClkReq1HPValid = disabled * VextSupply2SysClkReq1HPValid = disabled * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x40), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40), /* * VanaHwHPReq1Valid = disabled * Vaux1HwHPreq1Valid = disabled * Vaux2HwHPReq1Valid = disabled * Vaux3HwHPReqValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0xe8, 0x00), /* * VextSupply1HwHPReq1Valid = disabled * VextSupply2HwHPReq1Valid = disabled * VextSupply3HwHPReq1Valid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x07, 0x00), /* * VanaHwHPReq2Valid = disabled * Vaux1HwHPReq2Valid = disabled * Vaux2HwHPReq2Valid = disabled * Vaux3HwHPReq2Valid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0xe8, 0x00), /* * VextSupply1HwHPReq2Valid = disabled * VextSupply2HwHPReq2Valid = disabled * VextSupply3HwHPReq2Valid = HWReq2 controlled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x04), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x07, 0x04), /* * VanaSwHPReqValid = disabled * Vaux1SwHPReqValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0xa0, 0x00), /* * Vaux2SwHPReqValid = disabled * Vaux3SwHPReqValid = disabled @@ -177,7 +259,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * VextSupply2SwHPReqValid = disabled * VextSupply3SwHPReqValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x1f, 0x00), /* * SysClkReq2Valid1 = SysClkReq2 controlled * SysClkReq3Valid1 = disabled @@ -187,7 +269,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * SysClkReq7Valid1 = disabled * SysClkReq8Valid1 = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0x2a), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0xfe, 0x2a), /* * SysClkReq2Valid2 = disabled * SysClkReq3Valid2 = disabled @@ -197,7 +279,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * SysClkReq7Valid2 = disabled * SysClkReq8Valid2 = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0x20), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0xfe, 0x20), /* * VTVoutEna = disabled * Vintcore12Ena = disabled @@ -205,66 +287,62 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * Vintcore12LP = inactive (HP) * VTVoutLP = inactive (HP) */ - INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0x10), + INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0xfe, 0x10), /* * VaudioEna = disabled * VdmicEna = disabled * Vamic1Ena = disabled * Vamic2Ena = disabled */ - INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x1e, 0x00), /* * Vamic1_dzout = high-Z when Vamic1 is disabled * Vamic2_dzout = high-Z when Vamic2 is disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00), /* - * VPll = Hw controlled + * VPll = Hw controlled (NOTE! PRCMU bits) * VanaRegu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x02), + INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x0f, 0x02), /* * VrefDDREna = disabled * VrefDDRSleepMode = inactive (no pulldown) */ - INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x03, 0x00), /* - * VextSupply1Regu = HW control - * VextSupply2Regu = HW control - * VextSupply3Regu = HW control + * VextSupply1Regu = force LP + * VextSupply2Regu = force OFF + * VextSupply3Regu = force HP (-> STBB2=LP and TPS=LP) * ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0 * ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0 */ - INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0x2a), + INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0xff, 0x13), /* * Vaux1Regu = force HP * Vaux2Regu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x01), - /* - * Vaux3regu = force off - */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x0f, 0x01), /* - * Vsmps1 = 1.15V + * Vaux3Regu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x24), + INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x03, 0x00), /* - * Vaux1Sel = 2.5 V + * Vaux1Sel = 2.8 V */ - INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x08), + INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x0f, 0x0C), /* * Vaux2Sel = 2.9 V */ - INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0d), + INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0f, 0x0d), /* * Vaux3Sel = 2.91 V */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07), + INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07, 0x07), /* * VextSupply12LP = disabled (no LP) */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x01, 0x00), /* * Vaux1Disch = short discharge time * Vaux2Disch = short discharge time @@ -273,23 +351,24 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * VTVoutDisch = short discharge time * VaudioDisch = short discharge time */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0xfc, 0x00), /* * VanaDisch = short discharge time * VdmicPullDownEna = pulldown disabled when Vdmic is disabled * VdmicDisch = short discharge time */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x16, 0x00), }; /* AB8500 regulators */ -struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { +static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { /* supplies to the display/camera */ [AB8500_LDO_AUX1] = { + .supply_regulator = "ab8500-ext-supply3", .constraints = { .name = "V-DISPLAY", - .min_uV = 2500000, - .max_uV = 2900000, + .min_uV = 2800000, + .max_uV = 3300000, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, .boot_on = 1, /* display is on at boot */ @@ -306,24 +385,32 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { }, /* supplies to the on-board eMMC */ [AB8500_LDO_AUX2] = { + .supply_regulator = "ab8500-ext-supply3", .constraints = { .name = "V-eMMC1", .min_uV = 1100000, .max_uV = 3300000, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS, + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers), .consumer_supplies = ab8500_vaux2_consumers, }, /* supply for VAUX3, supplies to SDcard slots */ [AB8500_LDO_AUX3] = { + .supply_regulator = "ab8500-ext-supply3", .constraints = { .name = "V-MMC-SD", .min_uV = 1100000, .max_uV = 3300000, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS, + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers), .consumer_supplies = ab8500_vaux3_consumers, @@ -377,18 +464,167 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { [AB8500_LDO_INTCORE] = { .constraints = { .name = "V-INTCORE", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .min_uV = 1250000, + .max_uV = 1350000, + .input_uV = 1800000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE | + REGULATOR_CHANGE_DRMS, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers), .consumer_supplies = ab8500_vintcore_consumers, }, - /* supply for U8500 CSI/DSI, VANA LDO */ + /* supply for U8500 CSI-DSI, VANA LDO */ [AB8500_LDO_ANA] = { .constraints = { - .name = "V-CSI/DSI", + .name = "V-CSI-DSI", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers), .consumer_supplies = ab8500_vana_consumers, }, + /* sysclkreq 2 pin */ + [AB8500_SYSCLKREQ_2] = { + .constraints = { + .name = "V-SYSCLKREQ-2", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = + ARRAY_SIZE(ab8500_sysclkreq_2_consumers), + .consumer_supplies = ab8500_sysclkreq_2_consumers, + }, + /* sysclkreq 4 pin */ + [AB8500_SYSCLKREQ_4] = { + .constraints = { + .name = "V-SYSCLKREQ-4", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = + ARRAY_SIZE(ab8500_sysclkreq_4_consumers), + .consumer_supplies = ab8500_sysclkreq_4_consumers, + }, }; + +/* supply for VextSupply3 */ +static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = { + /* SIM supply for 3 V SIM cards */ + REGULATOR_SUPPLY("vinvsim", "sim-detect.0"), +}; + +/* extended configuration for VextSupply2, only used for HREFP_V20 boards */ +static struct ab8500_ext_regulator_cfg ab8500_ext_supply2 = { + .hwreq = true, +}; + +/* + * AB8500 external regulators + */ +static struct regulator_init_data ab8500_ext_regulators[] = { + /* fixed Vbat supplies VSMPS1_EXT_1V8 */ + [AB8500_EXT_SUPPLY1] = { + .constraints = { + .name = "ab8500-ext-supply1", + .min_uV = 1800000, + .max_uV = 1800000, + .initial_mode = REGULATOR_MODE_IDLE, + .boot_on = 1, + .always_on = 1, + }, + }, + /* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */ + [AB8500_EXT_SUPPLY2] = { + .constraints = { + .name = "ab8500-ext-supply2", + .min_uV = 1360000, + .max_uV = 1360000, + }, + }, + /* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */ + [AB8500_EXT_SUPPLY3] = { + .constraints = { + .name = "ab8500-ext-supply3", + .min_uV = 3400000, + .max_uV = 3400000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = + ARRAY_SIZE(ab8500_ext_supply3_consumers), + .consumer_supplies = ab8500_ext_supply3_consumers, + }, +}; + +struct ab8500_regulator_platform_data ab8500_regulator_plat_data = { + .reg_init = ab8500_reg_init, + .num_reg_init = ARRAY_SIZE(ab8500_reg_init), + .regulator = ab8500_regulators, + .num_regulator = ARRAY_SIZE(ab8500_regulators), + .ext_regulator = ab8500_ext_regulators, + .num_ext_regulator = ARRAY_SIZE(ab8500_ext_regulators), +}; + +static void ab8500_modify_reg_init(int id, u8 mask, u8 value) +{ + int i; + + for (i = ARRAY_SIZE(ab8500_reg_init) - 1; i >= 0; i--) { + if (ab8500_reg_init[i].id == id) { + u8 initval = ab8500_reg_init[i].value; + initval = (initval & ~mask) | (value & mask); + ab8500_reg_init[i].value = initval; + + BUG_ON(mask & ~ab8500_reg_init[i].mask); + return; + } + } + + BUG_ON(1); +} + +void mop500_regulator_init(void) +{ + struct regulator_init_data *regulator; + + /* + * Temporarily turn on Vaux2 on 8520 machine + */ + if (machine_is_u8520()) { + /* Vaux2 initialized to be on */ + ab8500_modify_reg_init(AB8500_VAUX12REGU, 0x0f, 0x05); + + /* Vaux2 always on */ + regulator = &ab8500_ext_regulators[AB8500_LDO_AUX2]; + regulator->constraints.always_on = 1; + } + + /* + * Handle AB8500_EXT_SUPPLY2 on HREFP_V20_V50 boards (do it for + * all HREFP_V20 boards) + */ + if (cpu_is_u8500v20()) { + /* VextSupply2RequestCtrl = HP/OFF depending on VxRequest */ + ab8500_modify_reg_init(AB8500_REGUREQUESTCTRL3, 0x01, 0x01); + + /* VextSupply2SysClkReq1HPValid = SysClkReq1 controlled */ + ab8500_modify_reg_init(AB8500_REGUSYSCLKREQ1HPVALID2, + 0x20, 0x20); + + /* VextSupply2 = force HP at initialization */ + ab8500_modify_reg_init(AB8500_EXTSUPPLYREGU, 0x0c, 0x04); + + /* enable VextSupply2 during platform active */ + regulator = &ab8500_ext_regulators[AB8500_EXT_SUPPLY2]; + regulator->constraints.always_on = 1; + + /* disable VextSupply2 in suspend */ + regulator = &ab8500_ext_regulators[AB8500_EXT_SUPPLY2]; + regulator->constraints.state_mem.disabled = 1; + regulator->constraints.state_standby.disabled = 1; + + /* enable VextSupply2 HW control (used in suspend) */ + regulator->driver_data = (void *)&ab8500_ext_supply2; + } +} diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h index 94992158d96..b5fc81a3649 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.h +++ b/arch/arm/mach-ux500/board-mop500-regulators.h @@ -14,9 +14,11 @@ #include <linux/regulator/machine.h> #include <linux/regulator/ab8500.h> -extern struct ab8500_regulator_reg_init -ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS]; -extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS]; +extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data; extern struct regulator_init_data tps61052_regulator; +extern struct regulator_init_data gpio_wlan_vbat_regulator; +extern struct regulator_init_data gpio_en_3v3_regulator; + +void mop500_regulator_init(void); #endif diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 920251cf834..828b230dd27 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -11,15 +11,16 @@ #include <linux/amba/mmci.h> #include <linux/mmc/host.h> #include <linux/platform_device.h> +#include <linux/delay.h> #include <asm/mach-types.h> #include <plat/ste_dma40.h> #include <mach/devices.h> #include <mach/hardware.h> +#include <mach/ste-dma40-db8500.h> #include "devices-db8500.h" #include "board-mop500.h" -#include "ste-dma40-db8500.h" /* * v2 has a new version of this block that need to be forced, the number found @@ -37,26 +38,55 @@ static int sdi0_vsel = -1; static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios) { + static unsigned char power_mode = MMC_POWER_ON; + static unsigned char signal_voltage = MMC_SIGNAL_VOLTAGE_330; + + if (signal_voltage == ios->signal_voltage) + goto do_power; + + /* + * We need to re-init the levelshifter when switching I/O voltage level. + * Max discharge time according to ST6G3244ME spec is 1 ms. + */ + if (power_mode == MMC_POWER_ON) { + power_mode = MMC_POWER_OFF; + gpio_direction_output(sdi0_en, 0); + msleep(1); + } + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + gpio_direction_output(sdi0_vsel, 0); + break; + case MMC_SIGNAL_VOLTAGE_180: + gpio_direction_output(sdi0_vsel, 1); + break; + default: + pr_warning("Non supported signal voltage for levelshifter.\n"); + break; + } + + signal_voltage = ios->signal_voltage; + +do_power: + if (power_mode == ios->power_mode) + return 0; + switch (ios->power_mode) { case MMC_POWER_UP: + break; case MMC_POWER_ON: - /* - * Level shifter voltage should depend on vdd to when deciding - * on either 1.8V or 2.9V. Once the decision has been made the - * level shifter must be disabled and re-enabled with a changed - * select signal in order to switch the voltage. Since there is - * no framework support yet for indicating 1.8V in vdd, use the - * default 2.9V. - */ - gpio_direction_output(sdi0_vsel, 0); gpio_direction_output(sdi0_en, 1); + /* Max settling time according to ST6G3244ME spec is 100 us. */ + udelay(100); break; case MMC_POWER_OFF: - gpio_direction_output(sdi0_vsel, 0); gpio_direction_output(sdi0_en, 0); break; } + power_mode = ios->power_mode; + return 0; } @@ -64,29 +94,34 @@ static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios) struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX, + .src_dev_type = DB8500_DMA_DEV1_SD_MMC0_RX, .dst_dev_type = STEDMA40_DEV_DST_MEMORY, .src_info.data_width = STEDMA40_WORD_WIDTH, .dst_info.data_width = STEDMA40_WORD_WIDTH, + .use_fixed_channel = true, + .phy_channel = 0, }; static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_MEM_TO_PERIPH, .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX, + .dst_dev_type = DB8500_DMA_DEV1_SD_MMC0_TX, .src_info.data_width = STEDMA40_WORD_WIDTH, .dst_info.data_width = STEDMA40_WORD_WIDTH, + .use_fixed_channel = true, + .phy_channel = 0, }; #endif static struct mmci_platform_data mop500_sdi0_data = { .ios_handler = mop500_sdi0_ios_handler, - .ocr_mask = MMC_VDD_29_30, .f_max = 50000000, .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | - MMC_CAP_MMC_HIGHSPEED, + MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_UHS_SDR12 | + MMC_CAP_UHS_SDR25, .gpio_wp = -1, .sigdir = MCI_ST_FBCLKEN | MCI_ST_CMDDIREN | @@ -121,14 +156,6 @@ static void sdi0_configure(struct device *parent) db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID); } -void mop500_sdi_tc35892_init(struct device *parent) -{ - mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; - sdi0_en = GPIO_SDMMC_EN; - sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; - sdi0_configure(parent); -} - /* * SDI1 (SDIO WLAN) */ @@ -193,7 +220,9 @@ static struct mmci_platform_data mop500_sdi2_data = { .ocr_mask = MMC_VDD_165_195, .f_max = 50000000, .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | - MMC_CAP_MMC_HIGHSPEED, + MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_ERASE, + .capabilities2 = MMC_CAP2_NO_SLEEP_CMD, .gpio_cd = -1, .gpio_wp = -1, #ifdef CONFIG_STE_DMA40 @@ -228,7 +257,6 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = { #endif static struct mmci_platform_data mop500_sdi4_data = { - .ocr_mask = MMC_VDD_29_30, .f_max = 50000000, .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED, @@ -241,6 +269,16 @@ static struct mmci_platform_data mop500_sdi4_data = { #endif }; +void mop500_sdi_tc35892_init(struct device *parent) +{ + mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; + sdi0_en = GPIO_SDMMC_EN; + sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; + sdi0_configure(parent); + /* WLAN SDIO channel */ + db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); +} + void __init mop500_sdi_init(struct device *parent) { /* PoP:ed eMMC */ @@ -267,6 +305,8 @@ void __init snowball_sdi_init(struct device *parent) sdi0_en = SNOWBALL_SDMMC_EN_GPIO; sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO; sdi0_configure(parent); + /* WLAN SDIO channel */ + db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); } void __init hrefv60_sdi_init(struct device *parent) @@ -283,3 +323,18 @@ void __init hrefv60_sdi_init(struct device *parent) /* WLAN SDIO channel */ db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); } + +void __init mach_u8520_sdi_init(struct device *parent) +{ + /* PoP:ed eMMC */ + db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); + /* On-board eMMC */ + db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); + /* External Micro SD slot */ + mop500_sdi0_data.gpio_cd = U8520_SDMMC_CD_GPIO; + sdi0_en = U8520_SDMMC_EN_GPIO; + sdi0_vsel = U8520_SDMMC_1V8_3V_GPIO; + sdi0_configure(parent); + /* WLAN SDIO channel */ + db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); +} diff --git a/arch/arm/mach-ux500/board-mop500-sensors.c b/arch/arm/mach-ux500/board-mop500-sensors.c new file mode 100644 index 00000000000..8569cf9248a --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-sensors.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/gpio.h> +#include <linux/lsm303dlh.h> +#include <linux/l3g4200d.h> +#include <linux/i2c.h> +#include <linux/input/lps001wp.h> +#include <asm/mach-types.h> +#include <mach/id.h> + +#include "board-mop500.h" + +/* + * LSM303DLH accelerometer + magnetometer & L3G4200D Gyroscope sensors + */ +static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata = { + .name_a = "lsm303dlh.0", + .name_m = "lsm303dlh.1", + .axis_map_x = 0, + .axis_map_y = 1, + .axis_map_z = 2, + .negative_x = 1, + .negative_y = 1, + .negative_z = 0, +}; + +static struct l3g4200d_gyr_platform_data __initdata l3g4200d_pdata = { + .name_gyr = "l3g4200d", + .axis_map_x = 1, + .axis_map_y = 0, + .axis_map_z = 2, + .negative_x = 0, + .negative_y = 0, + .negative_z = 1, +}; + +/* + * Platform data for pressure sensor, + * poll interval and min interval in millseconds. + */ +static struct lps001wp_prs_platform_data __initdata lps001wp_pdata = { + .poll_interval = 1000, + .min_interval = 10, +}; + +static struct i2c_board_info __initdata mop500_i2c2_devices[] = { + { + /* LSM303DLH Magnetometer */ + I2C_BOARD_INFO("lsm303dlh_m", 0x1E), + .platform_data = &lsm303dlh_pdata, + }, + { + /* L3G4200D Gyroscope */ + I2C_BOARD_INFO("l3g4200d", 0x68), + .platform_data = &l3g4200d_pdata, + }, + { + /* LSP001WM Barometer */ + I2C_BOARD_INFO("lps001wp_prs", 0x5C), + .platform_data = &lps001wp_pdata, + }, +}; + +/* + * Break this out due to the fact that this have changed address on snowball + */ +static struct i2c_board_info __initdata mop500_2_i2c2_devices[] = { + { + /* LSM303DLH Accelerometer */ + I2C_BOARD_INFO("lsm303dlh_a", 0x18), + .platform_data = &lsm303dlh_pdata, + }, +}; + +/* + * This is needed due to the fact that the i2c address changed in V7 =< + * and there is no way of knowing if the HW is V7 or higher so we just + * have to try and fail. + */ +static struct i2c_board_info __initdata snowball_i2c2_devices[] = { + { + /* LSM303DLH Accelerometer */ + I2C_BOARD_INFO("lsm303dlhc_a", 0x19), + .platform_data = &lsm303dlh_pdata, + }, +}; + + +/* + * Register/Add i2c sensors + */ +void mop500_sensors_i2c_add(int busnum, struct i2c_board_info const *info, + unsigned n) +{ + struct i2c_adapter *adap; + struct i2c_client *client; + int i; + + adap = i2c_get_adapter(busnum); + if (!adap) { + /* We have no i2c adapter yet lets create it. */ + pr_info(__FILE__ ": Creating i2c adapter %d\n", busnum); + i2c_register_board_info(busnum, info, n); + return; + } + + for (i = 0; i < n; i++) { + client = i2c_new_device(adap, &info[i]); + if (!client) + pr_err(__FILE__ ": failed to register %s to i2c%d\n", + info[i].type, + busnum); + } + + i2c_put_adapter(adap); +} + +/* + * Register/Add i2c sensors + */ +void mop500_sensors_probe_add_lsm303dlh_a(void) +{ + static const int busnum = 2; + struct i2c_adapter *adap; + struct i2c_client *client; + static const unsigned short i2c_addr_list[] = { + 0x18, 0x19, I2C_CLIENT_END }; + struct i2c_board_info i2c_info = { + /* LSM303DLH Accelerometer */ + I2C_BOARD_INFO("lsm303dlh_a", 0), + .platform_data = &lsm303dlh_pdata, + }; + + adap = i2c_get_adapter(busnum); + if (!adap) { + /* We have no i2c adapter yet lets create it. */ + pr_err(__FILE__ ": Could not get adapter %d\n", busnum); + return; + } + client = i2c_new_probed_device(adap, &i2c_info, + i2c_addr_list, NULL); + if (!client) + pr_err(__FILE__ ": failed to register %s to i2c%d\n", + i2c_info.type, + busnum); + i2c_put_adapter(adap); +} + +/* + * Check which accelerometer chip is mounted on UIB and + * read the chip ID to detect whether chip is LSM303DHL/LSM303DHLC. + */ +static int mop500_get_acc_id(void) +{ + int status; + union i2c_smbus_data data; + struct i2c_adapter *i2c2; + + i2c2 = i2c_get_adapter(2); + if (!i2c2) { + pr_err("failed to get i2c adapter\n"); + return -1; + } + status = i2c_smbus_xfer(i2c2, 0x18 , 0 , + I2C_SMBUS_READ, 0x0F , + I2C_SMBUS_BYTE_DATA, &data); + if (status < 0) { + status = i2c_smbus_xfer(i2c2, 0x19 , 0 , + I2C_SMBUS_READ, 0x0F , + I2C_SMBUS_BYTE_DATA, &data); + } + i2c_put_adapter(i2c2); + return (status < 0) ? status : data.byte; +} + +static int __init mop500_sensors_init(void) +{ + int ret; + + if (!machine_is_snowball() && !uib_is_stuib() && + !uib_is_u8500uib() && !uib_is_u8500uibr3()) + return 0; + + if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) { + lsm303dlh_pdata.irq_a1 = HREFV60_ACCEL_INT1_GPIO; + lsm303dlh_pdata.irq_a2 = HREFV60_ACCEL_INT2_GPIO; + lsm303dlh_pdata.irq_m = HREFV60_MAGNET_DRDY_GPIO; + } else if (machine_is_snowball()) { + lsm303dlh_pdata.irq_a1 = SNOWBALL_ACCEL_INT1_GPIO; + lsm303dlh_pdata.irq_a2 = SNOWBALL_ACCEL_INT2_GPIO; + lsm303dlh_pdata.irq_m = SNOWBALL_MAGNET_DRDY_GPIO; + } else { + lsm303dlh_pdata.irq_a1 = GPIO_ACCEL_INT1; + lsm303dlh_pdata.irq_a2 = GPIO_ACCEL_INT2; + lsm303dlh_pdata.irq_m = GPIO_MAGNET_DRDY; + } + + /* Special sensors data for 8500 UIBs */ + if (uib_is_u8500uib() || uib_is_u8500uibr3()) { + lsm303dlh_pdata.axis_map_x = 1; + lsm303dlh_pdata.axis_map_y = 0; + lsm303dlh_pdata.negative_x = 0; + lsm303dlh_pdata.negative_y = 0; + lsm303dlh_pdata.negative_z = 1; + + l3g4200d_pdata.axis_map_x = 0; + l3g4200d_pdata.axis_map_y = 1; + l3g4200d_pdata.negative_x = 1; + l3g4200d_pdata.negative_y = 0; + l3g4200d_pdata.negative_z = 1; + } + + ret = mop500_get_acc_id(); + if (ret < 0) + printk(KERN_ERR " Failed to get Accelerometer chip ID\n"); + else + lsm303dlh_pdata.chip_id = ret; + + if (machine_is_snowball()) { + if (cpu_is_u8500v21()) + /* This is ugly but we cant know what address to use */ + mop500_sensors_probe_add_lsm303dlh_a(); + else /* Add the accelerometer with new addr */ + mop500_sensors_i2c_add(2, snowball_i2c2_devices, + ARRAY_SIZE(snowball_i2c2_devices)); + } else /* none snowball have the old addr */ + mop500_sensors_i2c_add(2, mop500_2_i2c2_devices, + ARRAY_SIZE(mop500_2_i2c2_devices)); + + mop500_sensors_i2c_add(2, mop500_i2c2_devices, + ARRAY_SIZE(mop500_i2c2_devices)); + return 0; +} + +module_init(mop500_sensors_init); diff --git a/arch/arm/mach-ux500/board-mop500-stm.c b/arch/arm/mach-ux500/board-mop500-stm.c new file mode 100644 index 00000000000..1bef2a01873 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-stm.c @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * + * Author: Pierre Peiffer <pierre.peiffer@stericsson.com> for ST-Ericsson. + * Author: Olivier Germain <olivier.germain@stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ + +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/regulator/consumer.h> + +#include <asm/mach-types.h> +#include <plat/pincfg.h> +#include <mach/devices.h> +#include <asm/io.h> +#include <trace/stm.h> +#include "pins-db8500.h" + +#define HREFV60_SDMMC_EN_GPIO 169 +#define HREFV60_SDMMC_1V8_3V_GPIO 5 + +#define U8520_SDMMC_EN_GPIO 78 +#define U8520_SDMMC_1V8_3V_GPIO 5 + +#define STM_DEVICE (&u8500_stm_device.dev) +#define STM_ERR(msg) dev_err(STM_DEVICE, msg) +#define STM_WARN(msg) dev_warn(STM_DEVICE, msg) + +static struct regulator *regulator_aux3; +static enum stm_connection_type + stm_current_connection = STM_STE_INVALID_CONNECTION; + +static pin_cfg_t mop500_stm_mipi34_pins[] = { + GPIO70_STMAPE_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO71_STMAPE_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO72_STMAPE_DAT2 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO73_STMAPE_DAT1 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO74_STMAPE_DAT0 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO75_U2_RXD | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO76_U2_TXD | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, +}; + +static pin_cfg_t mop500_stm_mipi60_pins[] = { + GPIO153_U2_RXD, + GPIO154_U2_TXD, + GPIO155_STMAPE_CLK, + GPIO156_STMAPE_DAT3, + GPIO157_STMAPE_DAT2, + GPIO158_STMAPE_DAT1, + GPIO159_STMAPE_DAT0, +}; + +static pin_cfg_t mop500_stm_ape_microsd_pins[] = { + GPIO23_MS_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO24_MS_BS | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO25_MS_DAT0 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO26_MS_DAT1 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO27_MS_DAT2 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO28_MS_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, +}; + +static pin_cfg_t mop500_ske_pins[] = { + GPIO153_KP_I7 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO154_KP_I6 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO155_KP_I5 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO156_KP_I4 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO161_KP_I3 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO162_KP_I2 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO163_KP_I1 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO164_KP_I0 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP, + GPIO157_KP_O7 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO158_KP_O6 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO159_KP_O5 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO160_KP_O4 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO165_KP_O3 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO166_KP_O2 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO167_KP_O1 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO168_KP_O0 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, +}; + +static pin_cfg_t mop500_stm_modem_microsd_pins[] = { + GPIO18_GPIO | PIN_OUTPUT_LOW, + GPIO19_GPIO | PIN_OUTPUT_HIGH, + GPIO20_GPIO | PIN_OUTPUT_HIGH, + GPIO22_GPIO | PIN_INPUT_PULLUP, + GPIO23_STMMOD_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO24_UARTMOD_RXD | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO25_STMMOD_DAT0 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO26_STMMOD_DAT1 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO27_STMMOD_DAT2 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, + GPIO28_STMMOD_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP, +}; + +/* sdi0 (removable MMC/SD/SDIO cards) */ +static pin_cfg_t mop500_sdi0_pins[] = { + GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, + GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, + GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, + + GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, + GPIO23_MC0_CLK | PIN_OUTPUT_LOW, + GPIO24_MC0_CMD | PIN_INPUT_PULLUP, + GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, + GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, + GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, + GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, +}; + +static int stm_ste_disable_ape_on_mipi60(void) +{ + int retval; + + retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_stm_mipi60_pins)); + if (retval) + STM_ERR("Failed to disable MIPI60\n"); + else { + retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_ske_pins)); + if (retval) + STM_ERR("Failed to enable SKE gpio\n"); + } + return retval; +} + +static int stm_enable_ape_microsd(void) +{ + int retval; + + /* + * Configure STM APE on GPIO23,GPIO28,GPIO27,GPIO26,GPIO25 + * On HREF board an external SD buffer exist (ST6G3244ME) + * to perform level conversion from 1.8v to 3.3V on SD card signals + * When STM is redirected on micro SD connector GPIO18,GP19,GPIO20 + * are configured in standard GPIO mode and are used to configure + * direction on external SD buffer ST6G3244ME. + */ + + retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_stm_ape_microsd_pins)); + if (retval) + STM_ERR("Failed to enable STM APE on MICRO SD\n"); + + /* Enable altC1 on GPIO23-28 (STMAPE) */ + prcmu_enable_stm_ape(); + + return retval; +} + +static int stm_disable_ape_microsd(void) +{ + int retval; + + /* Disable altC1 on GPIO23-28 (STMAPE) */ + prcmu_disable_stm_ape(); + + /* Reconfigure GPIO for SD */ + retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_sdi0_pins)); + if (retval) + STM_ERR("Failed to disable STM APE on MICRO SD " + "and to reconfigure GPIO for SD\n"); + + return retval; +} + +static int stm_enable_modem_microsd(void) +{ + int retval; + + /* + * Configure STM APE on GPIO23,GPIO28,GPIO27,GPIO26,GPIO25 + * On HREF board an external SD buffer exist (ST6G3244ME) + * to perform level conversion from 1.8v to 3.3V on SD card + * signals. When STM is redirected on micro SD connector + * GPIO18,GP19,GPIO20 are configured in standard GPIO mode + * and are used to configure direction on external SD buffer + * ST6G3244ME. + */ + + retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_stm_modem_microsd_pins)); + if (retval) + STM_ERR("Failed to enable STM MODEM on MICRO SD\n"); + + return retval; +} + +static int stm_disable_modem_microsd(void) +{ + int retval; + + /* Reconfigure GPIO for SD */ + retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_sdi0_pins)); + if (retval) + STM_ERR("Failed to disable STM MODEM on MICRO SD " + "and to reconfigure GPIO for SD\n"); + + return retval; +} + +/* Enable or disable micro sd card buffers on HREF */ +static void control_level_shifter_for_microsd(int gpio_dir) +{ + int gpio[2]; + + if (machine_is_hrefv60() || machine_is_u9540()) { + gpio[0] = HREFV60_SDMMC_EN_GPIO; + gpio[1] = HREFV60_SDMMC_1V8_3V_GPIO; + } else if (machine_is_u8520()) { + gpio[0] = U8520_SDMMC_EN_GPIO; + gpio[1] = U8520_SDMMC_1V8_3V_GPIO; + } else { + gpio[0] = MOP500_EGPIO(17); + gpio[1] = MOP500_EGPIO(18); + } + + /* Select the default 2.9V and enable / disable level shifter */ + gpio_direction_output(gpio[1], 0); + gpio_direction_output(gpio[0], gpio_dir); +} + +/* Enable micro sd card buffers on HREF */ +static int enable_level_shifter_for_microsd(void) +{ + control_level_shifter_for_microsd(1); + STM_WARN("Level Shifter for SD card connector on.\n"); + return 0; +} + +/* Disable micro sd card buffers on HREF */ +static int disable_level_shifter_for_microsd(void) +{ + control_level_shifter_for_microsd(0); + STM_WARN("Level Shifter for SD card connector off.\n"); + return 0; +} + +/* Enable VAUX3 to power on buffer on STM MICRO SD cable */ +static int enable_vaux3_for_microsd_cable(void) +{ + int error; + + regulator_aux3 = regulator_get(&u8500_stm_device.dev, "v-SD-STM"); + + if (IS_ERR(regulator_aux3)) { + error = PTR_ERR(regulator_aux3); + STM_ERR("Failed to get regulator, supply: v-SD-STM\n"); + return error; + } + + error = regulator_enable(regulator_aux3); + + if (error) { + STM_ERR("Unable to enable regulator on SD card connector\n"); + return error; + } + + STM_WARN("Regulator on SD card connector power on.\n"); + return error; +} + +/* Disable VAUX3 to power off buffer on STM MICRO SD cable */ +static int disable_vaux3_for_microsd_cable(void) +{ + int error = 0; + + error = regulator_disable(regulator_aux3); + + if (regulator_aux3) + regulator_put(regulator_aux3); + + STM_WARN("Regulator for stm on SD card connector power off.\n"); + + return error; + +} + +static int stm_ste_connection(enum stm_connection_type con_type) +{ + int retval = -EINVAL; + + /* Check if connection type has been changed */ + if (con_type == stm_current_connection) + return 0; + + if (con_type != STM_DISCONNECT) { + /* Always enable MIPI34 GPIO pins */ + retval = nmk_config_pins( + ARRAY_AND_SIZE(mop500_stm_mipi34_pins)); + if (retval) { + STM_ERR("Failed to enable MIPI34\n"); + goto stm_ste_connection_error; + } + } + + switch (con_type) { + case STM_DEFAULT_CONNECTION: + case STM_STE_MODEM_ON_MIPI34_NONE_ON_MIPI60: + /* Enable altC3 on GPIO70-74 (STMMOD) & GPIO75-76 (UARTMOD) */ + prcmu_enable_stm_mod_uart(); + retval = stm_ste_disable_ape_on_mipi60(); + break; + + case STM_STE_APE_ON_MIPI34_NONE_ON_MIPI60: + /* Disable altC3 on GPIO70-74 (STMMOD) & GPIO75-76 (UARTMOD) */ + prcmu_disable_stm_mod_uart(); + retval = stm_ste_disable_ape_on_mipi60(); + break; + + case STM_STE_MODEM_ON_MIPI34_APE_ON_MIPI60: + /* Enable altC3 on GPIO70-74 (STMMOD) and GPIO75-76 (UARTMOD) */ + prcmu_enable_stm_mod_uart(); + /* Enable APE on MIPI60 */ + retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_ske_pins)); + if (retval) + STM_ERR("Failed to disable SKE GPIO\n"); + else { + retval = nmk_config_pins( + ARRAY_AND_SIZE(mop500_stm_mipi60_pins)); + if (retval) + STM_ERR("Failed to enable MIPI60\n"); + } + break; + + case STM_STE_MODEM_ON_MICROSD: + /* Disable APE on micro SD */ + retval = stm_disable_ape_microsd(); + /* Enable modem on micro SD */ + if (!retval) + retval = stm_enable_modem_microsd(); + /* Enable SD card buffer and regulator on href */ + if (!retval && (stm_current_connection + != STM_STE_APE_ON_MICROSD)) { + enable_level_shifter_for_microsd(); + enable_vaux3_for_microsd_cable(); + } + break; + + case STM_STE_APE_ON_MICROSD: + /* Disable modem on micro SD */ + retval = stm_disable_modem_microsd(); + /* Enable ape on micro SD */ + if (!retval) + retval = stm_enable_ape_microsd(); + /* Enable SD card buffer and regulator on href */ + if (!retval && (stm_current_connection + != STM_STE_MODEM_ON_MICROSD)) { + enable_level_shifter_for_microsd(); + enable_vaux3_for_microsd_cable(); + } + break; + + case STM_DISCONNECT: + retval = nmk_config_pins_sleep( + ARRAY_AND_SIZE(mop500_stm_mipi34_pins)); + if (retval) + STM_ERR("Failed to disable MIPI34\n"); + + retval = stm_ste_disable_ape_on_mipi60(); + if (retval) + STM_ERR("Failed to disable MIPI60\n"); + + retval = stm_disable_modem_microsd(); + if (retval) + STM_ERR("Failed to disable modem on microsd\n"); + + retval = stm_disable_ape_microsd(); + if (retval) + STM_ERR("Failed to disable ape on microsd\n"); + break; + + default: + STM_ERR("Bad connection type\n"); + goto stm_ste_connection_error; + } + + /* Disable power for microsd */ + if ((stm_current_connection == STM_STE_MODEM_ON_MICROSD) + || (stm_current_connection == STM_STE_APE_ON_MICROSD)) { + if ((con_type != STM_STE_MODEM_ON_MICROSD) + && (con_type != STM_STE_APE_ON_MICROSD)) { + disable_vaux3_for_microsd_cable(); + disable_level_shifter_for_microsd(); + } + } + + stm_current_connection = con_type; + +stm_ste_connection_error: + return retval; +} + +/* Possible STM sources (masters) on ux500 */ +enum stm_master { + STM_ARM0 = 0, + STM_ARM1 = 1, + STM_SVA = 2, + STM_SIA = 3, + STM_SIA_XP70 = 4, + STM_PRCMU = 5, + STM_MCSBAG = 9 +}; + +#define STM_ENABLE_ARM0 BIT(STM_ARM0) +#define STM_ENABLE_ARM1 BIT(STM_ARM1) +#define STM_ENABLE_SVA BIT(STM_SVA) +#define STM_ENABLE_SIA BIT(STM_SIA) +#define STM_ENABLE_SIA_XP70 BIT(STM_SIA_XP70) +#define STM_ENABLE_PRCMU BIT(STM_PRCMU) +#define STM_ENABLE_MCSBAG BIT(STM_MCSBAG) + +/* + * These are the channels used by NMF and some external softwares + * expect the NMF traces to be output on these channels + * For legacy reason, we need to reserve them. + */ +static const s16 stm_channels_reserved[] = { + 100, /* NMF MPCEE channel */ + 101, /* NMF CM channel */ + 151, /* NMF HOSTEE channel */ +}; + +/* On Ux500 we 2 consecutive STMs therefore 512 channels available */ +static struct stm_platform_data stm_pdata = { + .regs_phys_base = U8500_STM_REG_BASE, + .channels_phys_base = U8500_STM_BASE, + .id_mask = 0x000fffff, /* Ignore revisions differences */ + .channels_reserved = stm_channels_reserved, + .channels_reserved_sz = ARRAY_SIZE(stm_channels_reserved), + /* Enable all except MCSBAG */ + .masters_enabled = STM_ENABLE_ARM0 | STM_ENABLE_ARM1 | + STM_ENABLE_SVA | STM_ENABLE_PRCMU | + STM_ENABLE_SIA | STM_ENABLE_SIA_XP70, + /* Provide function for MIPI34/MIPI60 STM connection */ + .stm_connection = stm_ste_connection, +}; + +struct platform_device u8500_stm_device = { + .name = "stm", + .id = -1, + .dev = { + .platform_data = &stm_pdata, + }, +}; diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c index 8c979770d87..6256f3375c4 100644 --- a/arch/arm/mach-ux500/board-mop500-stuib.c +++ b/arch/arm/mach-ux500/board-mop500-stuib.c @@ -11,33 +11,70 @@ #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/i2c.h> +#ifdef CONFIG_U8500_FLASH +#include <../drivers/staging/camera_flash/adp1653_plat.h> +#endif #include <linux/input/matrix_keypad.h> #include <asm/mach-types.h> #include "board-mop500.h" -/* STMPE/SKE keypad use this key layout */ +/* + * ux500 keymaps + * + * Organized row-wise as on the UIB, starting at the top-left + * + * we support two key layouts, specific to requirements. The first + * keylayout includes controls for power/volume a few generic keys; + * the second key layout contains the full numeric layout, enter/back/left + * buttons along with a "."(dot), specifically for connectivity testing + */ static const unsigned int mop500_keymap[] = { +#if defined(CONFIG_KEYLAYOUT_LAYOUT1) KEY(2, 5, KEY_END), - KEY(4, 1, KEY_POWER), + KEY(4, 1, KEY_HOME), KEY(3, 5, KEY_VOLUMEDOWN), - KEY(1, 3, KEY_3), + KEY(1, 3, KEY_EMAIL), KEY(5, 2, KEY_RIGHT), - KEY(5, 0, KEY_9), + KEY(5, 0, KEY_BACKSPACE), KEY(0, 5, KEY_MENU), KEY(7, 6, KEY_ENTER), KEY(4, 5, KEY_0), - KEY(6, 7, KEY_2), + KEY(6, 7, KEY_DOT), KEY(3, 4, KEY_UP), KEY(3, 3, KEY_DOWN), KEY(6, 4, KEY_SEND), KEY(6, 2, KEY_BACK), KEY(4, 2, KEY_VOLUMEUP), - KEY(5, 5, KEY_1), + KEY(5, 5, KEY_SPACE), KEY(4, 3, KEY_LEFT), + KEY(3, 2, KEY_SEARCH), +#elif defined(CONFIG_KEYLAYOUT_LAYOUT2) + KEY(2, 5, KEY_RIGHT), + KEY(4, 1, KEY_ENTER), + KEY(3, 5, KEY_MENU), + KEY(1, 3, KEY_3), + KEY(5, 2, KEY_6), + KEY(5, 0, KEY_9), + + KEY(0, 5, KEY_UP), + KEY(7, 6, KEY_DOWN), + KEY(4, 5, KEY_0), + KEY(6, 7, KEY_2), + KEY(3, 4, KEY_5), + KEY(3, 3, KEY_8), + + KEY(6, 4, KEY_LEFT), + KEY(6, 2, KEY_BACK), + KEY(4, 2, KEY_KPDOT), + KEY(5, 5, KEY_1), + KEY(4, 3, KEY_4), KEY(3, 2, KEY_7), +#else +#warning "No keypad layout defined." +#endif }; static const struct matrix_keymap_data mop500_keymap_data = { @@ -73,6 +110,24 @@ static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = { }, }; +#ifdef CONFIG_U8500_FLASH +/* + * Config data for the flash + */ +static struct adp1653_platform_data __initdata adp1653_pdata_u8500_uib = { + .irq_no = CAMERA_FLASH_INT_PIN +}; +#endif + +static struct i2c_board_info __initdata mop500_i2c2_devices_stuib[] = { +#ifdef CONFIG_U8500_FLASH + { + I2C_BOARD_INFO("adp1653", 0x30), + .platform_data = &adp1653_pdata_u8500_uib + } +#endif +}; + /* * BU21013 ROHM touchscreen interface on the STUIBs */ @@ -111,6 +166,7 @@ static int bu21013_gpio_board_init(int reset_pin) __func__); return retval; } + gpio_set_value_cansleep(reset_pin, 1); } return retval; @@ -133,7 +189,8 @@ static int bu21013_gpio_board_exit(int reset_pin) __func__); return retval; } - gpio_set_value(reset_pin, 0); + gpio_set_value_cansleep(reset_pin, 0); + gpio_free(reset_pin); } bu21013_devices--; @@ -157,9 +214,19 @@ static struct bu21013_platform_device tsc_plat_device = { .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN), .touch_x_max = TOUCH_XMAX, .touch_y_max = TOUCH_YMAX, - .ext_clk = false, - .x_flip = false, - .y_flip = true, + .x_max_res = 480, + .y_max_res = 864, + .portrait = true, + .has_ext_clk = true, + .enable_ext_clk = false, +#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE) && \ + CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE == 270 + .x_flip = true, + .y_flip = false, +#else + .x_flip = false, + .y_flip = true, +#endif }; static struct bu21013_platform_device tsc_plat2_device = { @@ -169,18 +236,28 @@ static struct bu21013_platform_device tsc_plat2_device = { .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN), .touch_x_max = TOUCH_XMAX, .touch_y_max = TOUCH_YMAX, - .ext_clk = false, - .x_flip = false, - .y_flip = true, + .x_max_res = 480, + .y_max_res = 864, + .portrait = true, + .has_ext_clk = true, + .enable_ext_clk = false, +#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE) && \ + CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE == 270 + .x_flip = true, + .y_flip = false, +#else + .x_flip = false, + .y_flip = true, +#endif }; static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = { { - I2C_BOARD_INFO("bu21013_tp", 0x5C), + I2C_BOARD_INFO("bu21013_ts", 0x5C), .platform_data = &tsc_plat_device, }, { - I2C_BOARD_INFO("bu21013_tp", 0x5D), + I2C_BOARD_INFO("bu21013_ts", 0x5D), .platform_data = &tsc_plat2_device, }, @@ -188,18 +265,28 @@ static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = { void __init mop500_stuib_init(void) { - if (machine_is_hrefv60()) { + if (machine_is_hrefv60() || machine_is_u8520()) { tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO; tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO; +#ifdef CONFIG_U8500_FLASH + adp1653_pdata_u8500_uib.enable_gpio = + HREFV60_CAMERA_FLASH_ENABLE; +#endif } else { tsc_plat_device.cs_pin = GPIO_BU21013_CS; tsc_plat2_device.cs_pin = GPIO_BU21013_CS; - +#ifdef CONFIG_U8500_FLASH + adp1653_pdata_u8500_uib.enable_gpio = + GPIO_CAMERA_FLASH_ENABLE; +#endif } mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib, ARRAY_SIZE(mop500_i2c0_devices_stuib)); + mop500_uib_i2c_add(2, mop500_i2c2_devices_stuib, + ARRAY_SIZE(mop500_i2c2_devices_stuib)); + mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib, ARRAY_SIZE(u8500_i2c3_devices_stuib)); } diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c index ead91c968ff..0b77ee29982 100644 --- a/arch/arm/mach-ux500/board-mop500-u8500uib.c +++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c @@ -8,10 +8,21 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/i2c.h> +#ifdef CONFIG_U8500_FLASH +#include <../drivers/staging/camera_flash/adp1653_plat.h> +#endif #include <linux/interrupt.h> +#ifdef CONFIG_SENSORS_LSM303DLH +#include <linux/lsm303dlh.h> +#endif +#ifdef CONFIG_SENSORS_L3G4200D +#include <linux/l3g4200d.h> +#endif #include <linux/mfd/tc3589x.h> #include <linux/input/matrix_keypad.h> +#include <asm/mach-types.h> +#include <linux/gpio.h> #include <mach/irqs.h> #include "board-mop500.h" @@ -20,12 +31,28 @@ struct i2c_board_info __initdata __weak mop500_i2c3_devices_u8500[] = { }; +#ifdef CONFIG_U8500_FLASH +static struct adp1653_platform_data __initdata adp1653_pdata_u8500_uib = { + .irq_no = CAMERA_FLASH_INT_PIN +}; +#endif + +static struct i2c_board_info __initdata mop500_i2c2_devices_u8500[] = { +#ifdef CONFIG_U8500_FLASH + { + I2C_BOARD_INFO("adp1653", 0x30), + .platform_data = &adp1653_pdata_u8500_uib + } +#endif +}; + + /* * TC35893 */ static const unsigned int u8500_keymap[] = { KEY(3, 1, KEY_END), - KEY(4, 1, KEY_POWER), + KEY(4, 1, KEY_HOME), KEY(6, 4, KEY_VOLUMEDOWN), KEY(4, 2, KEY_EMAIL), KEY(3, 3, KEY_RIGHT), @@ -86,4 +113,15 @@ void __init mop500_u8500uib_init(void) mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, ARRAY_SIZE(mop500_i2c0_devices_u8500)); +#ifdef CONFIG_U8500_FLASH + if (machine_is_hrefv60() || machine_is_u8520()) + adp1653_pdata_u8500_uib.enable_gpio = + HREFV60_CAMERA_FLASH_ENABLE; + else + adp1653_pdata_u8500_uib.enable_gpio = + GPIO_CAMERA_FLASH_ENABLE; +#endif + + mop500_uib_i2c_add(2, mop500_i2c2_devices_u8500, + ARRAY_SIZE(mop500_i2c2_devices_u8500)); } diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c index 5af36aa56c0..908c5d973da 100644 --- a/arch/arm/mach-ux500/board-mop500-uib.c +++ b/arch/arm/mach-ux500/board-mop500-uib.c @@ -1,4 +1,5 @@ /* + * Copyright (C) ST-Ericsson SA 2010 * * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson @@ -10,13 +11,22 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/gpio_keys.h> +#include <linux/regulator/consumer.h> #include <mach/hardware.h> +#include <asm/mach-types.h> + +#include "pins.h" #include "board-mop500.h" enum mop500_uib { STUIB, U8500UIB, + U8500UIB_R3, + NO_UIB, }; struct uib { @@ -25,6 +35,8 @@ struct uib { void (*init)(void); }; +static u8 type_of_uib = NO_UIB; + static struct uib __initdata mop500_uibs[] = { [STUIB] = { .name = "ST-UIB", @@ -36,9 +48,16 @@ static struct uib __initdata mop500_uibs[] = { .option = "u8500uib", .init = mop500_u8500uib_init, }, +#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI + [U8500UIB_R3] = { + .name = "U8500-UIBR3", + .option = "u8500uibr3", + .init = mop500_u8500uib_r3_init, + }, +#endif }; -static struct uib *mop500_uib; +static struct uib __initdata *mop500_uib; static int __init mop500_uib_setup(char *str) { @@ -64,7 +83,7 @@ __setup("uib=", mop500_uib_setup); * The UIBs are detected after the I2C host controllers are registered, so * i2c_register_board_info() can't be used. */ -void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, +void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info, unsigned n) { struct i2c_adapter *adap; @@ -90,26 +109,137 @@ void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, static void __init __mop500_uib_init(struct uib *uib, const char *why) { pr_info("%s (%s)\n", uib->name, why); + + if (strcmp("stuib", uib->option) == 0) + type_of_uib = STUIB; + else if (strcmp("u8500uib", uib->option) == 0) + type_of_uib = U8500UIB; + else if (strcmp("u8500uibr3", uib->option) == 0) + type_of_uib = U8500UIB_R3; + uib->init(); } +int uib_is_stuib(void) +{ + return (type_of_uib == STUIB); +} + +int uib_is_u8500uib(void) +{ + return (type_of_uib == U8500UIB); +} + +int uib_is_u8500uibr3(void) +{ + return (type_of_uib == U8500UIB_R3); +} + + +#ifdef CONFIG_UX500_GPIO_KEYS +static struct gpio_keys_button mop500_gpio_keys[] = { + { + .desc = "SFH7741 Proximity Sensor", + .type = EV_SW, + .code = SW_FRONT_PROXIMITY, + .active_low = 0, + .can_disable = 1, + }, + { + .desc = "HED54XXU11 Hall Effect Sensor", + .type = EV_SW, + .code = SW_LID, /* FIXME arbitrary usage */ + .active_low = 0, + .can_disable = 1, + } +}; + +static struct regulator *gpio_keys_regulator; +static int mop500_gpio_keys_activate(struct device *dev); +static void mop500_gpio_keys_deactivate(struct device *dev); + +static struct gpio_keys_platform_data mop500_gpio_keys_data = { + .buttons = mop500_gpio_keys, + .nbuttons = ARRAY_SIZE(mop500_gpio_keys), + .enable = mop500_gpio_keys_activate, + .disable = mop500_gpio_keys_deactivate, +}; + +static struct platform_device mop500_gpio_keys_device = { + .name = "gpio-keys", + .id = 0, + .dev = { + .platform_data = &mop500_gpio_keys_data, + }, +}; + +static int mop500_gpio_keys_activate(struct device *dev) +{ + gpio_keys_regulator = regulator_get(&mop500_gpio_keys_device.dev, + "vcc"); + if (IS_ERR(gpio_keys_regulator)) { + dev_err(&mop500_gpio_keys_device.dev, "no regulator\n"); + return PTR_ERR(gpio_keys_regulator); + } + regulator_enable(gpio_keys_regulator); + + /* + * Please be aware that the start-up time of the SFH7741 is + * 120 ms and during that time the output is undefined. + */ + + return 0; +} + +static void mop500_gpio_keys_deactivate(struct device *dev) +{ + if (!IS_ERR(gpio_keys_regulator)) { + regulator_disable(gpio_keys_regulator); + regulator_put(gpio_keys_regulator); + } +} + +static __init void mop500_gpio_keys_init(void) +{ + struct ux500_pins *gpio_keys_pins = ux500_pins_get("gpio-keys.0"); + + if (gpio_keys_pins == NULL) { + pr_err("gpio_keys: Fail to get pins\n"); + return; + } + + ux500_pins_enable(gpio_keys_pins); + if (type_of_uib == U8500UIB_R3) + mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[2]); + else + mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[0]); + mop500_gpio_keys[1].gpio = PIN_NUM(gpio_keys_pins->cfg[1]); +} +#else +static inline void mop500_gpio_keys_init(void) { } +#endif + +/* add any platform devices here - TODO */ +static struct platform_device *mop500_uib_platform_devs[] __initdata = { +#ifdef CONFIG_UX500_GPIO_KEYS + &mop500_gpio_keys_device, +#endif +}; + /* * Detect the UIB attached based on the presence or absence of i2c devices. */ static int __init mop500_uib_init(void) { - struct uib *uib = mop500_uib; + struct uib *uib = mop500_uibs; struct i2c_adapter *i2c0; + struct i2c_adapter *i2c3; int ret; - if (!cpu_is_u8500()) + /* snowball and non u8500 cpus dont have uib */ + if (!cpu_is_u8500() || machine_is_snowball()) return -ENODEV; - if (uib) { - __mop500_uib_init(uib, "from uib= boot argument"); - return 0; - } - i2c0 = i2c_get_adapter(0); if (!i2c0) { __mop500_uib_init(&mop500_uibs[STUIB], @@ -121,14 +251,32 @@ static int __init mop500_uib_init(void) ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_QUICK, NULL); i2c_put_adapter(i2c0); + i2c3 = i2c_get_adapter(3); + if (!i2c3) { + __mop500_uib_init(&mop500_uibs[STUIB], + "fallback, could not get i2c3"); + return -ENODEV; + } - if (ret == 0) - uib = &mop500_uibs[U8500UIB]; - else - uib = &mop500_uibs[STUIB]; - + if (ret == 0) { + ret = i2c_smbus_xfer(i2c3, 0x4B, 0, I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL); + i2c_put_adapter(i2c3); + if (ret == 0) + uib = &mop500_uibs[U8500UIB]; + else + uib = &mop500_uibs[U8500UIB_R3]; + } else { + ret = i2c_smbus_xfer(i2c3, 0x5C, 0, I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL); + i2c_put_adapter(i2c3); + if (ret == 0) + uib = &mop500_uibs[STUIB]; + } __mop500_uib_init(uib, "detected"); - + mop500_gpio_keys_init(); + platform_add_devices(mop500_uib_platform_devs, + ARRAY_SIZE(mop500_uib_platform_devs)); return 0; } diff --git a/arch/arm/mach-ux500/board-mop500-vibra.c b/arch/arm/mach-ux500/board-mop500-vibra.c new file mode 100644 index 00000000000..911ecf26b5a --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-vibra.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 ST-Ericsson SA + * + * License terms:GNU General Public License (GPL) version 2 + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <asm/mach-types.h> + +#include <linux/ste_timed_vibra.h> +#include <sound/ux500_ab8500_ext.h> + +/* For details check ste_timed_vibra docbook */ +static struct ste_timed_vibra_platform_data rotary_vibra_plat_data = { + .is_linear_vibra = false, + .boost_level = 100, + .boost_time = 60, + .on_level = 50, + .off_level = 50, + .off_time = 60, + .timed_vibra_control = ux500_ab8500_audio_pwm_vibra, +}; + +static struct ste_timed_vibra_platform_data linear_vibra_plat_data = { + .is_linear_vibra = true, + .boost_level = 80, + .boost_time = 40, + .on_level = 80, + .off_level = 80, + .off_time = 0, + .timed_vibra_control = ux500_ab8500_audio_pwm_vibra, +}; + +/* Timed output vibrator device */ +static struct platform_device ux500_vibra_device = { + .name = "ste_timed_output_vibra", +}; + +void __init mop500_vibra_init(void) +{ + int ret; + + if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) + ux500_vibra_device.dev.platform_data = &linear_vibra_plat_data; + else + ux500_vibra_device.dev.platform_data = &rotary_vibra_plat_data; + + ret = platform_device_register(&ux500_vibra_device); + if (ret < 0) + pr_err("vibra dev register failed"); +} diff --git a/arch/arm/mach-ux500/board-mop500-wlan.c b/arch/arm/mach-ux500/board-mop500-wlan.c new file mode 100644 index 00000000000..821baae5273 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-wlan.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <asm/mach-types.h> +#include <mach/irqs.h> +#include <plat/pincfg.h> +#include <linux/clk.h> +#include <mach/cw1200_plat.h> + +#include "pins.h" + +static void cw1200_release(struct device *dev); +static int cw1200_power_ctrl(const struct cw1200_platform_data *pdata, + bool enable); +static int cw1200_clk_ctrl(const struct cw1200_platform_data *pdata, + bool enable); + +static struct resource cw1200_href_resources[] = { + { + .start = 215, + .end = 215, + .flags = IORESOURCE_IO, + .name = "cw1200_reset", + }, + { + .start = NOMADIK_GPIO_TO_IRQ(216), + .end = NOMADIK_GPIO_TO_IRQ(216), + .flags = IORESOURCE_IRQ, + .name = "cw1200_irq", + }, +}; + +static struct resource cw1200_href60_resources[] = { + { + .start = 85, + .end = 85, + .flags = IORESOURCE_IO, + .name = "cw1200_reset", + }, + { + .start = NOMADIK_GPIO_TO_IRQ(4), + .end = NOMADIK_GPIO_TO_IRQ(4), + .flags = IORESOURCE_IRQ, + .name = "cw1200_irq", + }, +}; + +static struct resource cw1200_u9500_resources[] = { + { + .start = 85, + .end = 85, + .flags = IORESOURCE_IO, + .name = "cw1200_reset", + }, + { + .start = NOMADIK_GPIO_TO_IRQ(144), + .end = NOMADIK_GPIO_TO_IRQ(144), + .flags = IORESOURCE_IRQ, + .name = "cw1200_irq", + }, +}; + +static struct cw1200_platform_data cw1200_platform_data = { + .clk_ctrl = cw1200_clk_ctrl, +}; + +static struct platform_device cw1200_device = { + .name = "cw1200_wlan", + .dev = { + .platform_data = &cw1200_platform_data, + .release = cw1200_release, + .init_name = "cw1200_wlan", + }, +}; + +const struct cw1200_platform_data *cw1200_get_platform_data(void) +{ + return &cw1200_platform_data; +} +EXPORT_SYMBOL_GPL(cw1200_get_platform_data); + +static int cw1200_pins_enable(bool enable) +{ + struct ux500_pins *pins = NULL; + int ret = 0; + + pins = ux500_pins_get("sdi1"); + + if (!pins) { + printk(KERN_ERR "cw1200: Pins are not found. " + "Check platform data.\n"); + return -ENOENT; + } + + if (enable) + ret = ux500_pins_enable(pins); + else + ret = ux500_pins_disable(pins); + + if (ret) + printk(KERN_ERR "cw1200: Pins can not be %s: %d.\n", + enable ? "enabled" : "disabled", + ret); + + ux500_pins_put(pins); + + return ret; +} + +static int cw1200_power_ctrl(const struct cw1200_platform_data *pdata, + bool enable) +{ + static const char *vdd_name = "vdd"; + struct regulator *vdd; + int ret = 0; + + vdd = regulator_get(&cw1200_device.dev, vdd_name); + if (IS_ERR(vdd)) { + ret = PTR_ERR(vdd); + dev_warn(&cw1200_device.dev, + "%s: Failed to get regulator '%s': %d\n", + __func__, vdd_name, ret); + } else { + if (enable) + ret = regulator_enable(vdd); + else + ret = regulator_disable(vdd); + + if (ret) { + dev_warn(&cw1200_device.dev, + "%s: Failed to %s regulator '%s': %d\n", + __func__, enable ? "enable" : "disable", + vdd_name, ret); + } + regulator_put(vdd); + } + return ret; +} + +static int cw1200_clk_ctrl(const struct cw1200_platform_data *pdata, + bool enable) +{ + static const char *clock_name = "sys_clk_out"; + struct clk *clk_dev; + int ret = 0; + + clk_dev = clk_get(&cw1200_device.dev, clock_name); + + if (IS_ERR(clk_dev)) { + ret = PTR_ERR(clk_dev); + dev_warn(&cw1200_device.dev, + "%s: Failed to get clk '%s': %d\n", + __func__, clock_name, ret); + + } else { + + if (enable) + ret = clk_enable(clk_dev); + else + clk_disable(clk_dev); + + if (ret) { + dev_warn(&cw1200_device.dev, + "%s: Failed to %s clk enable: %d\n", + __func__, clock_name, ret); + } + } + + return ret; +} + +int __init mop500_wlan_init(struct device *parent) +{ + int ret; + + if (pins_for_u9500()) { + cw1200_device.num_resources = ARRAY_SIZE(cw1200_u9500_resources); + cw1200_device.resource = cw1200_u9500_resources; + } else if (machine_is_u8500() || machine_is_nomadik() || machine_is_snowball()) { + cw1200_device.num_resources = ARRAY_SIZE(cw1200_href_resources); + cw1200_device.resource = cw1200_href_resources; + } else if (machine_is_hrefv60() || machine_is_u8520() + || machine_is_u9540()) { + cw1200_device.num_resources = + ARRAY_SIZE(cw1200_href60_resources); + cw1200_device.resource = cw1200_href60_resources; + } else { + dev_err(&cw1200_device.dev, + "Unsupported mach type %d " + "(check mach-types.h)\n", + __machine_arch_type); + return -ENOTSUPP; + } + + if (machine_is_snowball()) + cw1200_platform_data.mmc_id = "mmc2"; + else + cw1200_platform_data.mmc_id = "mmc3"; + + cw1200_platform_data.reset = &cw1200_device.resource[0]; + cw1200_platform_data.irq = &cw1200_device.resource[1]; + + cw1200_device.dev.release = cw1200_release; + + if (machine_is_snowball()) + cw1200_platform_data.power_ctrl = cw1200_power_ctrl; + + ret = cw1200_pins_enable(true); + if (WARN_ON(ret)) + return ret; + + cw1200_device.dev.parent = parent; + ret = platform_device_register(&cw1200_device); + if (ret) + cw1200_pins_enable(false); + + return ret; +} + +static void cw1200_release(struct device *dev) +{ + cw1200_pins_enable(false); +} diff --git a/arch/arm/mach-ux500/board-mop500-wlan.h b/arch/arm/mach-ux500/board-mop500-wlan.h new file mode 100644 index 00000000000..19a12d57ded --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-wlan.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U8500 board specific cw1200 (WLAN device) initialization. + * + * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> + * + */ + +#ifndef __BOARD_MOP500_WLAN_H +#define __BOARD_MOP500_WLAN_H + +int mop500_wlan_init(struct device *parent); + +#endif diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 77d03c1fbd0..ea703097be6 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -15,25 +15,41 @@ #include <linux/io.h> #include <linux/i2c.h> #include <linux/gpio.h> +#include <linux/gpio/nomadik.h> #include <linux/amba/bus.h> #include <linux/amba/pl022.h> #include <linux/amba/serial.h> #include <linux/spi/spi.h> +#ifdef CONFIG_HSI +#include <linux/hsi/hsi.h> +#endif #include <linux/mfd/abx500/ab8500.h> #include <linux/regulator/ab8500.h> #include <linux/mfd/tc3589x.h> -#include <linux/mfd/tps6105x.h> #include <linux/mfd/abx500/ab8500-gpio.h> +#include <linux/regulator/fixed.h> #include <linux/leds-lp5521.h> #include <linux/input.h> #include <linux/smsc911x.h> #include <linux/gpio_keys.h> #include <linux/delay.h> +#include <linux/mfd/ab8500/denc.h> +#ifdef CONFIG_STM_MSP_SPI +#include <linux/spi/stm_msp.h> +#endif +#include <linux/leds_pwm.h> +#include <linux/pwm_backlight.h> +#include <linux/gpio/nomadik.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/leds.h> +#include <linux/mfd/abx500/ab8500-sysctrl.h> +#ifdef CONFIG_INPUT_AB8500_ACCDET +#include <linux/input/abx500-accdet.h> +#endif + #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> @@ -41,23 +57,52 @@ #include <plat/i2c.h> #include <plat/ste_dma40.h> #include <plat/pincfg.h> -#include <plat/gpio-nomadik.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> #include <mach/irqs.h> +#include <mach/ste-dma40-db8500.h> +#ifdef CONFIG_U8500_SIM_DETECT +#include <mach/sim_detect.h> +#endif +#ifdef CONFIG_CRYPTO_DEV_UX500 +#include <mach/crypto-ux500.h> +#endif +#include <mach/pm.h> +#ifdef CONFIG_AV8100 +#include <video/av8100.h> +#endif +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE +#include <plat/ske.h> +#include "pins.h" +#endif + +#include "cpu-db8500.h" #include "pins-db8500.h" -#include "ste-dma40-db8500.h" #include "devices-db8500.h" #include "board-mop500.h" #include "board-mop500-regulators.h" +#include "board-mop500-bm.h" +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) +#include "board-mop500-wlan.h" +#endif + +#define PRCM_DEBUG_NOPWRDOWN_VAL 0x194 +#define ARM_DEBUG_NOPOWER_DOWN_REQ 1 + +#ifdef CONFIG_AB8500_DENC +static struct ab8500_denc_platform_data ab8500_denc_pdata = { + .ddr_enable = true, + .ddr_little_endian = false, +}; +#endif static struct gpio_led snowball_led_array[] = { { .name = "user_led", - .default_trigger = "none", + .default_trigger = "heartbeat", .gpio = 142, }, }; @@ -75,85 +120,156 @@ static struct platform_device snowball_led_dev = { }; static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { - .gpio_base = MOP500_AB8500_PIN_GPIO(1), + .gpio_base = AB8500_PIN_GPIO1, .irq_base = MOP500_AB8500_VIR_GPIO_IRQ_BASE, - /* config_reg is the initial configuration of ab8500 pins. + /* + * config_reg is the initial configuration of ab8500 pins. * The pins can be configured as GPIO or alt functions based * on value present in GpioSel1 to GpioSel6 and AlternatFunction * register. This is the array of 7 configuration settings. * One has to compile time decide these settings. Below is the * explanation of these setting - * GpioSel1 = 0x00 => Pins GPIO1 to GPIO8 are not used as GPIO - * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO - * GpioSel3 = 0x80 => Pin GPIO24 is configured as GPIO - * GpioSel4 = 0x01 => Pin GPIo25 is configured as GPIO - * GpioSel5 = 0x7A => Pins GPIO34, GPIO36 to GPIO39 are conf as GPIO - * GpioSel6 = 0x00 => Pins GPIO41 & GPIo42 are not configured as GPIO + * GpioSel1 = 0x0F => Pin GPIO1 (SysClkReq2) + * Pin GPIO2 (SysClkReq3) + * Pin GPIO3 (SysClkReq4) + * Pin GPIO4 (SysClkReq6) are configured as GPIO + * GpioSel2 = 0x9E => Pins GPIO10 to GPIO13 are configured as GPIO + * GpioSel3 = 0x80 => Pin GPIO24 (SysClkReq7) is configured as GPIO + * GpioSel4 = 0x01 => Pin GPIO25 (SysClkReq8) is configured as GPIO + * GpioSel5 = 0x78 => Pin GPIO36 (ApeSpiClk) + * Pin GPIO37 (ApeSpiCSn) + * Pin GPIO38 (ApeSpiDout) + * Pin GPIO39 (ApeSpiDin) are configured as GPIO + * GpioSel6 = 0x02 => Pin GPIO42 (SysClkReq5) is configured as GPIO * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured * as GPIO then this register selectes the alternate fucntions */ - .config_reg = {0x00, 0x1E, 0x80, 0x01, - 0x7A, 0x00, 0x00}, + .config_reg = {0x0F, 0x9E, 0x80, 0x01, 0x78, 0x02, 0x00}, + + /* + * config_direction allows for the initial GPIO direction to + * be set. For Snowball we set GPIO26 to output. + */ + .config_direction = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, + + /* + * config_pullups allows for the intial configuration of the + * GPIO pullup/pulldown configuration. + */ + .config_pullups = {0xE0, 0x01, 0x00, 0x00, 0x00, 0x00}, +}; + +static struct ab8500_gpio_platform_data ab8505_gpio_pdata = { + .gpio_base = AB8500_PIN_GPIO1, + .irq_base = MOP500_AB8500_VIR_GPIO_IRQ_BASE, + /* + * config_reg is the initial configuration of ab8500 pins. + * The pins can be configured as GPIO or alt functions based + * on value present in GpioSel1 to GpioSel6 and AlternatFunction + * register. This is the array of 7 configuration settings. + * One has to compile time decide these settings. Below is the + * explanation of these setting + * GpioSel1 = 0x0F => Pin GPIO1 (SysClkReq2) + * Pin GPIO2 (SysClkReq3) + * Pin GPIO3 (SysClkReq4) + * Pin GPIO4 (SysClkReq6) are configured as GPIO + * GpioSel2 = 0x9E => Pins GPIO10 to GPIO13 are configured as GPIO + * GpioSel3 = 0x80 => Pin GPIO24 (SysClkReq7) is configured as GPIO + * GpioSel4 = 0x01 => Pin GPIO25 (SysClkReq8) is configured as GPIO + * GpioSel5 = 0x78 => Pin GPIO36 (ApeSpiClk) + * Pin GPIO37 (ApeSpiCSn) + * Pin GPIO38 (ApeSpiDout) + * Pin GPIO39 (ApeSpiDin) are configured as GPIO + * GpioSel6 = 0x02 => Pin GPIO42 (SysClkReq5) is configured as GPIO + * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured + * as GPIO then this register selectes the alternate functions + * GpioSel7 = 0x22 => Pins GPIO50 to GPIO52 are configured as GPIO. + */ + .config_reg = {0x0F, 0x9E, 0x80, 0x01, 0x7A, 0x02, 0x22}, + + /* + * config_direction allows for the initial GPIO direction to + * be set. For Snowball we set GPIO26 to output. + */ + .config_direction = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, + + /* + * config_pullups allows for the intial configuration of the + * GPIO pullup/pulldown configuration. + * GPIO13(GpioPud2) = 1 and GPIO50(GpioPud7) = 1. + */ + .config_pullups = {0xE0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x02}, +}; + +static struct ab8500_sysctrl_platform_data ab8500_sysctrl_pdata = { + /* + * SysClkReq1RfClkBuf - SysClkReq8RfClkBuf + * The initial values should not be changed because of the way + * the system works today + */ + .initial_req_buf_config + = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }; +#ifdef CONFIG_INPUT_AB8500_ACCDET +static struct abx500_accdet_platform_data ab8500_accdet_pdata = { + .btn_keycode = KEY_MEDIA, + .accdet1_dbth = ACCDET1_TH_1200mV | ACCDET1_DB_70ms, + .accdet2122_th = ACCDET21_TH_1000mV | ACCDET22_TH_1000mV, + .video_ctrl_gpio = AB8500_PIN_GPIO35, +}; +#endif + static struct gpio_keys_button snowball_key_array[] = { { - .gpio = 32, - .type = EV_KEY, - .code = KEY_1, - .desc = "userpb", + .gpio = 32, + .type = EV_KEY, + .code = KEY_1, + .desc = "userpb", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 151, - .type = EV_KEY, - .code = KEY_2, - .desc = "extkb1", + .gpio = 151, + .type = EV_KEY, + .code = KEY_2, + .desc = "extkb1", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 152, - .type = EV_KEY, - .code = KEY_3, - .desc = "extkb2", + .gpio = 152, + .type = EV_KEY, + .code = KEY_3, + .desc = "extkb2", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 161, - .type = EV_KEY, - .code = KEY_4, - .desc = "extkb3", + .gpio = 162, + .type = EV_KEY, + .code = KEY_5, + .desc = "extkb4", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, - }, - { - .gpio = 162, - .type = EV_KEY, - .code = KEY_5, - .desc = "extkb4", - .active_low = 1, - .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, }; static struct gpio_keys_platform_data snowball_key_data = { - .buttons = snowball_key_array, + .buttons = snowball_key_array, .nbuttons = ARRAY_SIZE(snowball_key_array), }; static struct platform_device snowball_key_dev = { - .name = "gpio-keys", - .id = -1, - .dev = { + .name = "gpio-keys", + .id = -1, + .dev = { .platform_data = &snowball_key_data, + .pm_domain = &ux500_dev_power_domain, } }; @@ -179,21 +295,45 @@ static struct resource sbnet_res[] = { }; static struct platform_device snowball_sbnet_dev = { - .name = "smsc911x", + .name = "smsc911x", .num_resources = ARRAY_SIZE(sbnet_res), .resource = sbnet_res, - .dev = { + .dev = { .platform_data = &snowball_sbnet_cfg, }, }; +#ifdef CONFIG_MODEM_U8500 +static struct platform_device u8500_modem_dev = { + .name = "u8500-modem", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; +#endif + static struct ab8500_platform_data ab8500_platdata = { .irq_base = MOP500_AB8500_IRQ_BASE, - .regulator_reg_init = ab8500_regulator_reg_init, - .num_regulator_reg_init = ARRAY_SIZE(ab8500_regulator_reg_init), - .regulator = ab8500_regulators, - .num_regulator = ARRAY_SIZE(ab8500_regulators), + .regulator = &ab8500_regulator_plat_data, +#ifdef CONFIG_AB8500_DENC + .denc = &ab8500_denc_pdata, +#endif + .battery = &ab8500_bm_data, + .charger = &ab8500_charger_plat_data, + .btemp = &ab8500_btemp_plat_data, + .fg = &ab8500_fg_plat_data, + .chargalg = &ab8500_chargalg_plat_data, .gpio = &ab8500_gpio_pdata, + .sysctrl = &ab8500_sysctrl_pdata, + .pwmled = &ab8500_pwmled_plat_data, +#ifdef CONFIG_INPUT_AB8500_ACCDET + .accdet = &ab8500_accdet_pdata, +#endif +#ifdef CONFIG_PM + .pm_power_off = true, +#endif + .thermal_time_out = 20, /* seconds */ }; static struct resource ab8500_resources[] = { @@ -214,14 +354,203 @@ struct platform_device ab8500_device = { .resource = ab8500_resources, }; +struct platform_device ab8505_device = { + .name = "ab8505-i2c", + .id = 0, + .dev = { + .platform_data = &ab8500_platdata, + }, + .num_resources = 1, + .resource = ab8500_resources, +}; + +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE + +/* + * Nomadik SKE keypad + */ +#define ROW_PIN_I0 164 +#define ROW_PIN_I1 163 +#define ROW_PIN_I2 162 +#define ROW_PIN_I3 161 +#define ROW_PIN_I4 156 +#define ROW_PIN_I5 155 +#define ROW_PIN_I6 154 +#define ROW_PIN_I7 153 +#define COL_PIN_O0 168 +#define COL_PIN_O1 167 +#define COL_PIN_O2 166 +#define COL_PIN_O3 165 +#define COL_PIN_O4 160 +#define COL_PIN_O5 159 +#define COL_PIN_O6 158 +#define COL_PIN_O7 157 + +static int ske_kp_rows[] = { + ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, + ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7, +}; +static int ske_kp_cols[] = { + COL_PIN_O0, COL_PIN_O1, COL_PIN_O2, COL_PIN_O3, + COL_PIN_O4, COL_PIN_O5, COL_PIN_O6, COL_PIN_O7, +}; + /* - * TPS61052 + * ske_set_gpio_row: request and set gpio rows */ +static int ske_set_gpio_row(int gpio) +{ + int ret; + ret = gpio_request(gpio, "ske-kp"); + if (ret < 0) { + pr_err("ske_set_gpio_row: gpio request failed\n"); + return ret; + } + + ret = gpio_direction_output(gpio, 1); + if (ret < 0) { + pr_err("ske_set_gpio_row: gpio direction failed\n"); + gpio_free(gpio); + } -static struct tps6105x_platform_data mop500_tps61052_data = { - .mode = TPS6105X_MODE_VOLTAGE, - .regulator_data = &tps61052_regulator, + return ret; +} + +/* + * ske_kp_init - enable the gpio configuration + */ +static int ske_kp_init(void) +{ + struct ux500_pins *pins; + int ret, i; + + pins = ux500_pins_get("ske"); + if (pins) + ux500_pins_enable(pins); + + for (i = 0; i < SKE_KPD_MAX_ROWS; i++) { + ret = ske_set_gpio_row(ske_kp_rows[i]); + if (ret < 0) { + pr_err("ske_kp_init: failed init\n"); + return ret; + } + } + + return 0; +} + +static int ske_kp_exit(void) +{ + struct ux500_pins *pins; + int i; + + pins = ux500_pins_get("ske"); + if (pins) + ux500_pins_disable(pins); + + for (i = 0; i < SKE_KPD_MAX_ROWS; i++) + gpio_free(ske_kp_rows[i]); + + return 0; +} + +static const unsigned int mop500_ske_keymap[] = { +#if defined(CONFIG_KEYLAYOUT_LAYOUT1) + KEY(2, 5, KEY_END), + KEY(4, 1, KEY_HOME), + KEY(3, 5, KEY_VOLUMEDOWN), + KEY(1, 3, KEY_EMAIL), + KEY(5, 2, KEY_RIGHT), + KEY(5, 0, KEY_BACKSPACE), + + KEY(0, 5, KEY_MENU), + KEY(7, 6, KEY_ENTER), + KEY(4, 5, KEY_0), + KEY(6, 7, KEY_DOT), + KEY(3, 4, KEY_UP), + KEY(3, 3, KEY_DOWN), + + KEY(6, 4, KEY_SEND), + KEY(6, 2, KEY_BACK), + KEY(4, 2, KEY_VOLUMEUP), + KEY(5, 5, KEY_SPACE), + KEY(4, 3, KEY_LEFT), + KEY(3, 2, KEY_SEARCH), +#elif defined(CONFIG_KEYLAYOUT_LAYOUT2) + KEY(2, 5, KEY_RIGHT), + KEY(4, 1, KEY_ENTER), + KEY(3, 5, KEY_MENU), + KEY(1, 3, KEY_3), + KEY(5, 2, KEY_6), + KEY(5, 0, KEY_9), + + KEY(0, 5, KEY_UP), + KEY(7, 6, KEY_DOWN), + KEY(4, 5, KEY_0), + KEY(6, 7, KEY_2), + KEY(3, 4, KEY_5), + KEY(3, 3, KEY_8), + + KEY(6, 4, KEY_LEFT), + KEY(6, 2, KEY_BACK), + KEY(4, 2, KEY_KPDOT), + KEY(5, 5, KEY_1), + KEY(4, 3, KEY_4), + KEY(3, 2, KEY_7), +#else +#warning "No keypad layout defined." +#endif +}; + +static struct matrix_keymap_data mop500_ske_keymap_data = { + .keymap = mop500_ske_keymap, + .keymap_size = ARRAY_SIZE(mop500_ske_keymap), +}; + + + +static struct ske_keypad_platform_data mop500_ske_keypad_data = { + .init = ske_kp_init, + .exit = ske_kp_exit, + .gpio_input_pins = ske_kp_rows, + .gpio_output_pins = ske_kp_cols, + .keymap_data = &mop500_ske_keymap_data, + .no_autorepeat = true, + .krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */ + .kcol = SKE_KPD_MAX_COLS, + .debounce_ms = 20, /* in timeout period */ + .switch_delay = 200, /* in jiffies */ +}; + +#endif + + +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE +/* + * GPIO-regulator wlan vbat data + */ +static struct fixed_voltage_config snowball_gpio_wlan_vbat_data = { + .supply_name = "WLAN-VBAT", + .gpio = SNOWBALL_EN_3V6_GPIO, + .microvolts = 3600000, + .enable_high = 1, + .init_data = &gpio_wlan_vbat_regulator, + .startup_delay = 3500, /* Startup time */ +}; + +/* + * GPIO-regulator en 3v3 vbat data + */ + +static struct fixed_voltage_config snowball_gpio_en_3v3_data = { + .supply_name = "EN-3V3", + .gpio = SNOWBALL_EN_3V3_ETH_GPIO, + .microvolts = 3300000, + .enable_high = 1, + .init_data = &gpio_en_3v3_regulator, + .startup_delay = 5000, /* 1200us according to data sheet */ }; +#endif /* * TC35892 @@ -249,53 +578,64 @@ static struct tc3589x_platform_data mop500_tc35892_data = { }; static struct lp5521_led_config lp5521_pri_led[] = { - [0] = { - .chan_nr = 0, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [1] = { - .chan_nr = 1, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [2] = { - .chan_nr = 2, - .led_current = 0x2f, - .max_current = 0x5f, - }, + [0] = { + .chan_nr = 0, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [1] = { + .chan_nr = 1, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [2] = { + .chan_nr = 2, + .led_current = 0x2f, + .max_current = 0x5f, + }, }; +#ifdef CONFIG_AV8100 +static struct av8100_platform_data av8100_plat_data = { + .irq = NOMADIK_GPIO_TO_IRQ(192), + .reset = MOP500_HDMI_RST_GPIO, + .inputclk_id = "sysclk2", + .regulator_pwr_id = "hdmi_1v8", + .alt_powerupseq = true, + .mclk_freq = 3, /* MCLK_RNG_31_38 */ +}; +#endif + static struct lp5521_platform_data __initdata lp5521_pri_data = { - .label = "lp5521_pri", - .led_config = &lp5521_pri_led[0], - .num_channels = 3, - .clock_mode = LP5521_CLOCK_EXT, + .label = "lp5521_pri", + .led_config = &lp5521_pri_led[0], + .num_channels = 3, + .clock_mode = LP5521_CLOCK_EXT, }; static struct lp5521_led_config lp5521_sec_led[] = { - [0] = { - .chan_nr = 0, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [1] = { - .chan_nr = 1, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [2] = { - .chan_nr = 2, - .led_current = 0x2f, - .max_current = 0x5f, - }, + [0] = { + .chan_nr = 0, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [1] = { + .chan_nr = 1, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [2] = { + .chan_nr = 2, + .led_current = 0x2f, + .max_current = 0x5f, + }, }; static struct lp5521_platform_data __initdata lp5521_sec_data = { - .label = "lp5521_sec", - .led_config = &lp5521_sec_led[0], - .num_channels = 3, - .clock_mode = LP5521_CLOCK_EXT, + .label = "lp5521_sec", + .led_config = &lp5521_sec_led[0], + .num_channels = 3, + .clock_mode = LP5521_CLOCK_EXT, }; static struct i2c_board_info __initdata mop500_i2c0_devices[] = { @@ -304,15 +644,26 @@ static struct i2c_board_info __initdata mop500_i2c0_devices[] = { .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, - /* I2C0 devices only available prior to HREFv60 */ +#ifdef CONFIG_AV8100 { - I2C_BOARD_INFO("tps61052", 0x33), - .platform_data = &mop500_tps61052_data, + I2C_BOARD_INFO("av8100", 0x70), + .platform_data = &av8100_plat_data, }, +#endif + /* I2C0 devices only available prior to HREFv60 */ }; #define NUM_PRE_V60_I2C0_DEVICES 1 +static struct i2c_board_info __initdata snowball_i2c0_devices[] = { +#ifdef CONFIG_AV8100 + { + I2C_BOARD_INFO("av8100", 0x70), + .platform_data = &av8100_plat_data, + }, +#endif +}; + static struct i2c_board_info __initdata mop500_i2c2_devices[] = { { /* lp5521 LED driver, 1st device */ @@ -353,13 +704,13 @@ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* * The board uses 4 i2c controllers, initialize all of * them with slave data setup time of 250 ns, - * Tx & Rx FIFO threshold values as 8 and standard + * Tx & Rx FIFO threshold values as 1 and standard * mode of operation */ -U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST); static void __init mop500_i2c_init(struct device *parent) { @@ -369,60 +720,267 @@ static void __init mop500_i2c_init(struct device *parent) db8500_add_i2c3(parent, &u8500_i2c3_data); } -static struct gpio_keys_button mop500_gpio_keys[] = { - { - .desc = "SFH7741 Proximity Sensor", - .type = EV_SW, - .code = SW_FRONT_PROXIMITY, - .active_low = 0, - .can_disable = 1, - } +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE +static struct platform_device snowball_gpio_wlan_vbat_regulator_device = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &snowball_gpio_wlan_vbat_data, + }, }; -static struct regulator *prox_regulator; -static int mop500_prox_activate(struct device *dev); -static void mop500_prox_deactivate(struct device *dev); +static struct platform_device snowball_gpio_en_3v3_regulator_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &snowball_gpio_en_3v3_data, + }, +}; +#endif + +#ifdef CONFIG_LEDS_PWM +static struct led_pwm pwm_leds_data[] = { + [0] = { + .name = "lcd-backlight", + .pwm_id = 1, + .max_brightness = 255, + .lth_brightness = 90, + .pwm_period_ns = 1023, + .dutycycle_steps = 16, + .period_steps = 4, + }, + [1] = { + .name = "sec-lcd-backlight", + .pwm_id = 2, + .max_brightness = 255, + .lth_brightness = 90, + .pwm_period_ns = 1023, + }, +}; -static struct gpio_keys_platform_data mop500_gpio_keys_data = { - .buttons = mop500_gpio_keys, - .nbuttons = ARRAY_SIZE(mop500_gpio_keys), - .enable = mop500_prox_activate, - .disable = mop500_prox_deactivate, +static struct led_pwm_platform_data u8500_leds_data = { + .num_leds = 1, + .leds = pwm_leds_data, }; -static struct platform_device mop500_gpio_keys_device = { - .name = "gpio-keys", +static struct platform_device ux500_leds_device = { + .name = "leds_pwm", + .dev = { + .platform_data = &u8500_leds_data, + }, +}; +#endif + +#ifdef CONFIG_BACKLIGHT_PWM +static struct platform_pwm_backlight_data u8500_backlight_data[] = { + [0] = { + .pwm_id = 1, + .max_brightness = 255, + .dft_brightness = 200, + .lth_brightness = 90, + .pwm_period_ns = 1023, + }, + [1] = { + .pwm_id = 2, + .max_brightness = 255, + .dft_brightness = 200, + .lth_brightness = 90, + .pwm_period_ns = 1023, + }, +}; + +static struct platform_device ux500_backlight_device[] = { + [0] = { + .name = "pwm-backlight", + .id = 0, + .dev = { + .platform_data = &u8500_backlight_data[0], + }, + }, + [1] = { + .name = "pwm-backlight", + .id = 1, + .dev = { + .platform_data = &u8500_backlight_data[1], + }, + }, +}; +#endif + +/* Force feedback vibrator device */ +static struct platform_device ste_ff_vibra_device = { + .name = "ste_ff_vibra" +}; + +#ifdef CONFIG_HSI +static struct hsi_board_info __initdata u8500_hsi_devices[] = { + { + .name = "hsi_char", + .hsi_id = 0, + .port = 0, + .tx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 1, + .speed = 200000, + .ch_prio = {}, + {.arb_mode = HSI_ARB_RR}, + }, + .rx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 1, + .speed = 200000, + .ch_prio = {}, + {.flow = HSI_FLOW_SYNC}, + }, + }, + { + .name = "hsi_test", + .hsi_id = 0, + .port = 0, + .tx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 2, + .speed = 100000, + .ch_prio = {}, + {.arb_mode = HSI_ARB_RR}, + }, + .rx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 2, + .speed = 200000, + .ch_prio = {}, + {.flow = HSI_FLOW_SYNC}, + }, + }, + { + .name = "cfhsi_v3_driver", + .hsi_id = 0, + .port = 0, + .tx_cfg = { + .mode = HSI_MODE_STREAM, + .channels = 2, + .speed = 20000, + .ch_prio = {}, + {.arb_mode = HSI_ARB_RR}, + }, + .rx_cfg = { + .mode = HSI_MODE_STREAM, + .channels = 2, + .speed = 200000, + .ch_prio = {}, + {.flow = HSI_FLOW_SYNC}, + }, + }, +}; +#endif + +#ifdef CONFIG_U8500_SIM_DETECT +static struct sim_detect_platform_data sim_detect_pdata = { + .irq_num = MOP500_AB8500_VIR_GPIO_IRQ(6), +}; +struct platform_device u8500_sim_detect_device = { + .name = "sim-detect", .id = 0, .dev = { - .platform_data = &mop500_gpio_keys_data, + .platform_data = &sim_detect_pdata, }, }; +#endif -static int mop500_prox_activate(struct device *dev) -{ - prox_regulator = regulator_get(&mop500_gpio_keys_device.dev, - "vcc"); - if (IS_ERR(prox_regulator)) { - dev_err(&mop500_gpio_keys_device.dev, - "no regulator\n"); - return PTR_ERR(prox_regulator); +#ifdef CONFIG_CRYPTO_DEV_UX500 +static struct cryp_platform_data u8500_cryp1_platform_data = { + .mem_to_engine = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV48_CAC1_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, + .mode = STEDMA40_MODE_LOGICAL, + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + }, + .engine_to_mem = { + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV48_CAC1_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, + .mode = STEDMA40_MODE_LOGICAL, + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, } - regulator_enable(prox_regulator); - return 0; -} +}; -static void mop500_prox_deactivate(struct device *dev) -{ - regulator_disable(prox_regulator); - regulator_put(prox_regulator); -} +static struct stedma40_chan_cfg u8500_hash_dma_cfg_tx = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV50_HAC1_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, + .mode = STEDMA40_MODE_LOGICAL, + .src_info.psize = STEDMA40_PSIZE_LOG_16, + .dst_info.psize = STEDMA40_PSIZE_LOG_16, +}; + +static struct hash_platform_data u8500_hash1_platform_data = { + .mem_to_engine = &u8500_hash_dma_cfg_tx, + .dma_filter = stedma40_filter, +}; +#endif /* add any platform devices here - TODO */ static struct platform_device *mop500_platform_devs[] __initdata = { - &mop500_gpio_keys_device, - &ab8500_device, +#ifdef CONFIG_U8500_SIM_DETECT + &u8500_sim_detect_device, +#endif + &ste_ff_vibra_device, +#ifdef CONFIG_U8500_MMIO + &ux500_mmio_device, +#endif + &ux500_hwmem_device, +#ifdef CONFIG_FB_MCDE + &u8500_mcde_device, +#endif +#ifdef CONFIG_FB_B2R2 + &u8500_b2r2_device, + &u8500_b2r2_blt_device, +#endif + &u8500_thsens_device, +#ifdef CONFIG_LEDS_PWM + &ux500_leds_device, +#endif +#ifdef CONFIG_BACKLIGHT_PWM + &ux500_backlight_device[0], + &ux500_backlight_device[1], +#endif +#ifdef CONFIG_DB8500_MLOADER + &mloader_fw_device, +#endif +#ifdef CONFIG_HSI + &u8500_hsi_device, +#endif }; +#ifdef CONFIG_STM_MSP_SPI +/* + * MSP-SPI + */ + +#define NUM_MSP_CLIENTS 10 + +static struct stm_msp_controller mop500_msp2_spi_data = { + .id = 2, + .num_chipselect = NUM_MSP_CLIENTS, + .base_addr = U8500_MSP2_BASE, + .device_name = "msp2", +}; + +/* + * SSP + */ + +#define NUM_SSP_CLIENTS 10 + #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg ssp0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, @@ -444,27 +1002,32 @@ static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { #endif static struct pl022_ssp_controller ssp0_plat = { - .bus_id = 0, + .bus_id = 4, #ifdef CONFIG_STE_DMA40 .enable_dma = 1, .dma_filter = stedma40_filter, .dma_rx_param = &ssp0_dma_cfg_rx, .dma_tx_param = &ssp0_dma_cfg_tx, -#else - .enable_dma = 0, #endif /* on this platform, gpio 31,142,144,214 & * 224 are connected as chip selects */ - .num_chipselect = 5, + .num_chipselect = NUM_SSP_CLIENTS, }; static void __init mop500_spi_init(struct device *parent) { db8500_add_ssp0(parent, &ssp0_plat); + if (!machine_is_snowball()) + db8500_add_msp2_spi(parent, &mop500_msp2_spi_data); +} +#else +static void __init mop500_spi_init(struct device *parent) +{ } +#endif /* CONFIG_STM_MSP_SPI */ -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE static struct stedma40_chan_cfg uart0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, @@ -528,26 +1091,6 @@ static pin_cfg_t mop500_pins_uart0[] = { GPIO3_U0_TXD | PIN_OUTPUT_HIGH, }; -#define PRCC_K_SOFTRST_SET 0x18 -#define PRCC_K_SOFTRST_CLEAR 0x1C -static void ux500_uart0_reset(void) -{ - void __iomem *prcc_rst_set, *prcc_rst_clr; - - prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE + - PRCC_K_SOFTRST_SET); - prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE + - PRCC_K_SOFTRST_CLEAR); - - /* Activate soft reset PRCC_K_SOFTRST_CLEAR */ - writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr); - udelay(1); - - /* Release soft reset PRCC_K_SOFTRST_SET */ - writel((readl(prcc_rst_set) | 0x1), prcc_rst_set); - udelay(1); -} - static void ux500_uart0_init(void) { int ret; @@ -568,31 +1111,51 @@ static void ux500_uart0_exit(void) pr_err("pl011: uart pins_disable failed\n"); } +static void u8500_uart0_reset(void) +{ + /* UART0 lies in PER1 */ + return u8500_reset_ip(1, PRCC_K_SOFTRST_UART0_MASK); +} + +static void u8500_uart1_reset(void) +{ + /* UART1 lies in PER1 */ + return u8500_reset_ip(1, PRCC_K_SOFTRST_UART1_MASK); +} + +static void u8500_uart2_reset(void) +{ + /* UART2 lies in PER3 */ + return u8500_reset_ip(3, PRCC_K_SOFTRST_UART2_MASK); +} + static struct amba_pl011_data uart0_plat = { -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE .dma_filter = stedma40_filter, .dma_rx_param = &uart0_dma_cfg_rx, .dma_tx_param = &uart0_dma_cfg_tx, #endif .init = ux500_uart0_init, .exit = ux500_uart0_exit, - .reset = ux500_uart0_reset, + .reset = u8500_uart0_reset, }; static struct amba_pl011_data uart1_plat = { -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE .dma_filter = stedma40_filter, .dma_rx_param = &uart1_dma_cfg_rx, .dma_tx_param = &uart1_dma_cfg_tx, #endif + .reset = u8500_uart1_reset, }; static struct amba_pl011_data uart2_plat = { -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE .dma_filter = stedma40_filter, .dma_rx_param = &uart2_dma_cfg_rx, .dma_tx_param = &uart2_dma_cfg_tx, #endif + .reset = u8500_uart2_reset, }; static void __init mop500_uart_init(struct device *parent) @@ -602,25 +1165,55 @@ static void __init mop500_uart_init(struct device *parent) db8500_add_uart2(parent, &uart2_plat); } +static void __init u8500_cryp1_hash1_init(void) +{ +#ifdef CONFIG_CRYPTO_DEV_UX500 + db8500_add_cryp1(&u8500_cryp1_platform_data); + db8500_add_hash1(&u8500_hash1_platform_data); +#endif +} + static struct platform_device *snowball_platform_devs[] __initdata = { + &ux500_hwmem_device, &snowball_led_dev, &snowball_key_dev, +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE + &snowball_gpio_en_3v3_regulator_device, + &snowball_gpio_wlan_vbat_regulator_device, +#endif &snowball_sbnet_dev, - &ab8500_device, +#ifdef CONFIG_FB_MCDE + &u8500_mcde_device, +#endif +#ifdef CONFIG_FB_B2R2 + &u8500_b2r2_device, + &u8500_b2r2_blt_device, +#endif }; +static void fixup_ab8505_gpio(void) +{ + ab8500_gpio_pdata = ab8505_gpio_pdata; +} + static void __init mop500_init_machine(void) { struct device *parent = NULL; - int i2c0_devs; int i; - mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; - parent = u8500_init_devices(); mop500_pins_init(); + mop500_regulator_init(); + + u8500_cryp1_hash1_init(); + +#ifdef CONFIG_HSI + hsi_register_board_info(u8500_hsi_devices, + ARRAY_SIZE(u8500_hsi_devices)); +#endif + /* FIXME: parent of ab8500 should be prcmu */ for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; @@ -628,16 +1221,38 @@ static void __init mop500_init_machine(void) platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); + platform_device_register(&u8500_shrm_device); +#ifdef CONFIG_STE_TRACE_MODEM + platform_device_register(&u8500_trace_modem); +#endif +#ifdef CONFIG_MODEM_U8500 + platform_device_register(&u8500_modem_dev); +#endif mop500_i2c_init(parent); mop500_sdi_init(parent); mop500_spi_init(parent); mop500_uart_init(parent); +#ifdef CONFIG_STM_MSP_SPI + mop500_msp_init(parent); +#endif +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) + mop500_wlan_init(parent); +#endif - i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE + db8500_add_ske_keypad(parent, &mop500_ske_keypad_data, + sizeof(mop500_ske_keypad_data)); +#endif - i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); +#ifdef CONFIG_ANDROID_STE_TIMED_VIBRA + mop500_vibra_init(); +#endif + platform_device_register(&ab8500_device); + + i2c_register_board_info(0, mop500_i2c0_devices, + ARRAY_SIZE(mop500_i2c0_devices)); i2c_register_board_info(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); + ARRAY_SIZE(mop500_i2c2_devices)); /* This board has full regulator constraints */ regulator_has_full_constraints(); @@ -646,13 +1261,21 @@ static void __init mop500_init_machine(void) static void __init snowball_init_machine(void) { struct device *parent = NULL; - int i2c0_devs; int i; parent = u8500_init_devices(); snowball_pins_init(); + mop500_regulator_init(); + + u8500_cryp1_hash1_init(); + +#ifdef CONFIG_HSI + hsi_register_board_info(u8500_hsi_devices, + ARRAY_SIZE(u8500_hsi_devices)); +#endif + for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++) snowball_platform_devs[i]->dev.parent = parent; @@ -663,11 +1286,17 @@ static void __init snowball_init_machine(void) snowball_sdi_init(parent); mop500_spi_init(parent); mop500_uart_init(parent); +#ifdef CONFIG_STM_MSP_SPI + mop500_msp_init(parent); +#endif +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) + mop500_wlan_init(parent); +#endif - i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); - i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); - i2c_register_board_info(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); + platform_device_register(&ab8500_device); + + i2c_register_board_info(0, snowball_i2c0_devices, + ARRAY_SIZE(snowball_i2c0_devices)); /* This board has full regulator constraints */ regulator_has_full_constraints(); @@ -676,7 +1305,6 @@ static void __init snowball_init_machine(void) static void __init hrefv60_init_machine(void) { struct device *parent = NULL; - int i2c0_devs; int i; /* @@ -684,30 +1312,92 @@ static void __init hrefv60_init_machine(void) * all these GPIO pins to the internal GPIO controller * instead. */ - mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; + +#ifdef CONFIG_INPUT_AB8500_ACCDET + /* + * On boards hrefpv60 and later, the accessory insertion/removal, + * button press/release are inverted. + */ + ab8500_accdet_pdata.is_detection_inverted = true; + + if (machine_is_u8520()) { + ab8500_accdet_pdata.video_ctrl_gpio = AB8500_PIN_GPIO10; + ab8500_accdet_pdata.mic_ctrl = AB8500_PIN_GPIO34; + } +#endif parent = u8500_init_devices(); hrefv60_pins_init(); + mop500_regulator_init(); + + u8500_cryp1_hash1_init(); + +#ifdef CONFIG_HSI + hsi_register_board_info(u8500_hsi_devices, + ARRAY_SIZE(u8500_hsi_devices)); +#endif +#ifdef CONFIG_LEDS_PWM + if (uib_is_stuib()) + u8500_leds_data.num_leds = 2; +#endif + for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); + if (!cpu_is_u9500()) { + platform_device_register(&u8500_shrm_device); +#ifdef CONFIG_STE_TRACE_MODEM + platform_device_register(&u8500_trace_modem); +#endif +#ifdef CONFIG_MODEM_U8500 + platform_device_register(&u8500_modem_dev); +#endif + } + mop500_i2c_init(parent); - hrefv60_sdi_init(parent); + if (machine_is_u8520()) + mach_u8520_sdi_init(parent); + else + hrefv60_sdi_init(parent); mop500_spi_init(parent); mop500_uart_init(parent); +#ifdef CONFIG_STM_MSP_SPI + mop500_msp_init(parent); +#endif +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) + mop500_wlan_init(parent); +#endif - i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE + /* + * If a hw debugger is detected, do not load the ske driver + * since the gpio usage collides. + */ + if (!(prcmu_read(PRCM_DEBUG_NOPWRDOWN_VAL) & + ARM_DEBUG_NOPOWER_DOWN_REQ)) + db8500_add_ske_keypad(parent, &mop500_ske_keypad_data, + sizeof(mop500_ske_keypad_data)); +#endif - i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; +#ifdef CONFIG_ANDROID_STE_TIMED_VIBRA + mop500_vibra_init(); +#endif + if (machine_is_u8520()) { + fixup_ab8505_gpio(); + platform_device_register(&ab8505_device); + } + else + platform_device_register(&ab8500_device); - i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); + i2c_register_board_info(0, mop500_i2c0_devices, + ARRAY_SIZE(mop500_i2c0_devices)); i2c_register_board_info(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); + ARRAY_SIZE(mop500_i2c2_devices)); /* This board has full regulator constraints */ regulator_has_full_constraints(); @@ -722,6 +1412,21 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = mop500_init_machine, + .restart = ux500_restart, +MACHINE_END + +/* + * NOTE! 8520 machine reports as a HREFV60 until user space updates has been + * done for 8520. + */ +MACHINE_START(U8520, "ST-Ericsson U8500 Platform HREFv60+") + .atag_offset = 0x100, + .map_io = u8500_map_io, + .init_irq = ux500_init_irq, + .timer = &ux500_timer, + .handle_irq = gic_handle_irq, + .init_machine = hrefv60_init_machine, + .restart = ux500_restart, MACHINE_END MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") @@ -731,9 +1436,10 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = hrefv60_init_machine, + .restart = ux500_restart, MACHINE_END -MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") +MACHINE_START(SNOWBALL, "ST-Ericsson Snowball platform") .atag_offset = 0x100, .map_io = u8500_map_io, .init_irq = ux500_init_irq, @@ -741,6 +1447,18 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = snowball_init_machine, + .restart = ux500_restart, +MACHINE_END + +/* Temporary reuse hrefv60 machine */ +MACHINE_START(U9540, "ST-Ericsson 9540 platform") + .atag_offset = 0x100, + .map_io = u8500_map_io, + .init_irq = ux500_init_irq, + .timer = &ux500_timer, + .handle_irq = gic_handle_irq, + .init_machine = hrefv60_init_machine, + .restart = ux500_restart, MACHINE_END #ifdef CONFIG_MACH_UX500_DT @@ -749,7 +1467,9 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat), OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat), OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat), +#ifdef CONFIG_STM_MSP_SPI OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat), +#endif {}, }; @@ -777,7 +1497,6 @@ static void __init u8500_init_machine(void) of_platform_populate(NULL, u8500_soc_node, u8500_auxdata_lookup, parent); if (of_machine_is_compatible("st-ericsson,mop500")) { - mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; mop500_pins_init(); platform_add_devices(mop500_platform_devs, @@ -796,7 +1515,6 @@ static void __init u8500_init_machine(void) * all these GPIO pins to the internal GPIO controller * instead. */ - mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; hrefv60_pins_init(); platform_add_devices(mop500_platform_devs, diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index fdcfa8721bb..fd6d4aad95c 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -7,6 +7,10 @@ #ifndef __BOARD_MOP500_H #define __BOARD_MOP500_H +/* This defines the NOMADIK_NR_GPIO */ +#include <linux/mfd/abx500/ab8500-gpio.h> +#include <mach/gpio.h> + /* Snowball specific GPIO assignments, this board has no GPIO expander */ #define SNOWBALL_ACCEL_INT1_GPIO 163 #define SNOWBALL_ACCEL_INT2_GPIO 164 @@ -40,8 +44,12 @@ #define MOP500_HDMI_RST_GPIO 196 #define CYPRESS_SLAVE_SELECT_GPIO 216 +/* U8520-specific GPIO assignments */ +#define U8520_SDMMC_EN_GPIO 78 +#define U8520_SDMMC_1V8_3V_GPIO 5 +#define U8520_SDMMC_CD_GPIO 95 + /* GPIOs on the TC35892 expander */ -#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) #define GPIO_MAGNET_DRDY MOP500_EGPIO(1) #define GPIO_SDMMC_CD MOP500_EGPIO(3) #define GPIO_CAMERA_FLASH_ENABLE MOP500_EGPIO(4) @@ -55,7 +63,6 @@ #define MOP500_DISP1_RST_GPIO MOP500_EGPIO(15) #define GPIO_SDMMC_EN MOP500_EGPIO(17) #define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) -#define MOP500_EGPIO_END MOP500_EGPIO(24) /* * GPIOs on the AB8500 mixed-signals circuit @@ -78,14 +85,25 @@ struct i2c_board_info; extern void mop500_sdi_init(struct device *parent); extern void snowball_sdi_init(struct device *parent); extern void hrefv60_sdi_init(struct device *parent); +extern void mach_u8520_sdi_init(struct device *parent); extern void mop500_sdi_tc35892_init(struct device *parent); void __init mop500_u8500uib_init(void); void __init mop500_stuib_init(void); +void __init mop500_msp_init(struct device *parent); void __init mop500_pins_init(void); +void __init mop500_vibra_init(void); void __init hrefv60_pins_init(void); void __init snowball_pins_init(void); +void __init mop500_u8500uib_r3_init(void); -void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, +void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info, unsigned n); +int msp13_i2s_init(void); +int msp13_i2s_exit(void); + +int uib_is_stuib(void); +int uib_is_u8500uib(void); +int uib_is_u8500uibr3(void); + #endif diff --git a/arch/arm/mach-ux500/board-pins-sleep-force.c b/arch/arm/mach-ux500/board-pins-sleep-force.c new file mode 100644 index 00000000000..91eb1cefc22 --- /dev/null +++ b/arch/arm/mach-ux500/board-pins-sleep-force.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/io.h> +#include <linux/string.h> + +#include <linux/gpio/nomadik.h> +#include <mach/hardware.h> + +#include "board-pins-sleep-force.h" +#include "pins-db8500.h" +#include "pins.h" + +static u32 u8500_gpio_banks[] = {U8500_GPIOBANK0_BASE, + U8500_GPIOBANK1_BASE, + U8500_GPIOBANK2_BASE, + U8500_GPIOBANK3_BASE, + U8500_GPIOBANK4_BASE, + U8500_GPIOBANK5_BASE, + U8500_GPIOBANK6_BASE, + U8500_GPIOBANK7_BASE, + U8500_GPIOBANK8_BASE}; + +/* + * This function is called to force gpio power save + * settings during suspend. + */ +void sleep_pins_config_pm(pin_cfg_t *cfgs, int num) +{ + int i = 0; + int gpio = 0; + u32 w_imsc = 0; + u32 imsc = 0; + u32 offset; + u32 bitmask = 1; + u32 dirs_register = 0; + u32 dirc_register = 0; + u32 dats_register = 0; + u32 datc_register = 0; + u32 pdis_register_disable = 0; + u32 pdis_register_enabled = 0; + u32 slpm_register_disabled = 0; + u32 slpm_register_enabled = 0; + u32 bankaddr = 0; + + gpio = PIN_NUM(cfgs[i]); + + /* Get the bank number the pin is mapped to */ + bankaddr = IO_ADDRESS(u8500_gpio_banks[(gpio >> GPIO_BLOCK_SHIFT)]); + + w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) | + readl(bankaddr + NMK_GPIO_FWIMSC); + + imsc = readl(bankaddr + NMK_GPIO_RIMSC) | + readl(bankaddr + NMK_GPIO_FIMSC); + + for (i = 0; i < num; i++) { + /* Get the pin number */ + gpio = PIN_NUM(cfgs[i]); + + /* get the offest into the register */ + offset = gpio % NMK_GPIO_PER_CHIP; + /* Set the bit to toggle */ + bitmask = 1 << offset ; + + /* Next we check for direction (INPUT/OUTPUT) */ + switch (PIN_SLPM_DIR(cfgs[i])) { + case GPIO_IS_INPUT: + /* GPIO is set to input */ + dirc_register |= bitmask; + + /* + * Next check for pull (PULLUP/PULLDOWN) + * and configure accordingly. + */ + switch (PIN_SLPM_PULL(cfgs[i])) { + case GPIO_PULL_UPDOWN_DISABLED: + pdis_register_disable |= bitmask; + break; + + case GPIO_IS_PULLUP: + dats_register |= bitmask; + pdis_register_enabled |= bitmask; + break; + + case GPIO_IS_PULLDOWN: + datc_register |= bitmask; + pdis_register_enabled |= bitmask; + break; + + case GPIO_PULL_NO_CHANGE: + break; + + default: + BUG(); + break; + + } + break; + + case GPIO_IS_OUTPUT: + /* GPIO is set to output */ + dirs_register |= bitmask; + + /* + * Since its output there should not + * be a need to disable PULL UP/DOWN + * but better safe than sorry. + */ + pdis_register_disable |= bitmask; + /* Next we check for setting GPIO HIGH/LOW */ + switch (PIN_SLPM_VAL(cfgs[i])) { + case GPIO_IS_OUTPUT_LOW: + /* GPIO is set to LOW */ + datc_register |= bitmask; + break; + + case GPIO_IS_OUTPUT_HIGH: + /* GPIO is set to high */ + dats_register |= bitmask; + break; + + case GPIO_IS_NO_CHANGE: + break; + + default: + BUG(); + break; + } + + break; + case GPIO_IS_NOT_CHANGED: + break; + + default: + BUG(); + break; + } + + /* Next check for Sleep Power Managment (SLPM) */ + switch (PIN_SLPM(cfgs[i])) { + case GPIO_WAKEUP_IS_ENABLED: + slpm_register_enabled |= bitmask; + break; + + case GPIO_WAKEUP_IS_DISBLED: + slpm_register_disabled |= bitmask; + break; + + default: + BUG(); + break; + } + + /* Next check for Sleep Power Managment (SLPM) */ + switch (PIN_SLPM_PDIS(cfgs[i])) { + case GPIO_PDIS_NO_CHANGE: + break; + + case GPIO_PDIS_DISABLED: + pdis_register_disable |= bitmask; + break; + + case GPIO_PDIS_ENABLED: + pdis_register_enabled |= bitmask; + break; + + default: + BUG(); + break; + } + + } + + /* Write the register settings GPIO direction */ + writel(dirs_register & ~w_imsc, bankaddr + NMK_GPIO_DIRS); + writel(dirc_register, bankaddr + NMK_GPIO_DIRC); + + writel(datc_register & ~w_imsc, bankaddr + NMK_GPIO_DATC); + writel(dats_register & ~w_imsc, bankaddr + NMK_GPIO_DATS); + + /* Write the PDIS enable/disable */ + writel(readl(bankaddr + NMK_GPIO_PDIS) + | (pdis_register_disable & ~w_imsc & ~imsc), + bankaddr + NMK_GPIO_PDIS); + writel(readl(bankaddr + NMK_GPIO_PDIS) + & (~pdis_register_enabled & ~w_imsc & ~imsc), + bankaddr + NMK_GPIO_PDIS); + + /* Write the SLPM enable/disable */ + writel(readl(bankaddr + NMK_GPIO_SLPC) | slpm_register_disabled, + bankaddr + NMK_GPIO_SLPC); + writel(readl(bankaddr + NMK_GPIO_SLPC) & ~slpm_register_enabled, + bankaddr + NMK_GPIO_SLPC); +} + +void sleep_pins_config_pm_mux(pin_cfg_t *cfgs, int num) +{ + int i = 0; + int gpio = 0; + u32 offset; + u32 bitmask = 1; + u32 gpio_afsla_register_set = 0; + u32 gpio_afslb_register_set = 0; + u32 gpio_afsla_register_clear = 0; + u32 gpio_afslb_register_clear = 0; + u32 bankaddr = 0; + + gpio = PIN_NUM(cfgs[i]); + + /* Get the bank number the pin is mapped to */ + bankaddr = IO_ADDRESS(u8500_gpio_banks[(gpio >> GPIO_BLOCK_SHIFT)]); + + for (i = 0; i < num; i++) { + /* Get the pin number */ + gpio = PIN_NUM(cfgs[i]); + + /* get the offset into the register */ + offset = gpio % NMK_GPIO_PER_CHIP; + /* Set the bit to toggle */ + bitmask = 1 << offset ; + + /* First check for ALT pin configuration */ + switch (PIN_ALT(cfgs[i])) { + case NMK_GPIO_ALT_GPIO: + /* Set bit to configured as GPIO */ + gpio_afsla_register_clear |= bitmask; + gpio_afslb_register_clear |= bitmask; + break; + + case NMK_GPIO_ALT_A: + /* ALT A setting so set corresponding bit */ + gpio_afsla_register_set |= bitmask; + break; + + case NMK_GPIO_ALT_B: + /* ALT B setting so set corresponding bit */ + gpio_afslb_register_set |= bitmask; + break; + + case NMK_GPIO_ALT_C: + /* ALT C setting so set corresponding bits */ + gpio_afsla_register_set |= bitmask; + gpio_afslb_register_set |= bitmask; + break; + + default: + BUG(); + break; + } + } + /* Set bits that configures GPIO */ + writel(readl(bankaddr + NMK_GPIO_AFSLA) + & ~gpio_afsla_register_clear, bankaddr + NMK_GPIO_AFSLA); + writel(readl(bankaddr + NMK_GPIO_AFSLB) + & ~gpio_afslb_register_clear, bankaddr + NMK_GPIO_AFSLB); + + /* Set bits that configures ALT_X */ + writel(readl(bankaddr + NMK_GPIO_AFSLA) + | gpio_afsla_register_set, bankaddr + NMK_GPIO_AFSLA); + writel(readl(bankaddr + NMK_GPIO_AFSLB) + | gpio_afslb_register_set, bankaddr + NMK_GPIO_AFSLB); +} diff --git a/arch/arm/mach-ux500/board-pins-sleep-force.h b/arch/arm/mach-ux500/board-pins-sleep-force.h new file mode 100644 index 00000000000..0949c9bfcda --- /dev/null +++ b/arch/arm/mach-ux500/board-pins-sleep-force.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __BOARD_PINS_SLEEP_FORCE_H +#define __BOARD_PINS_SLEEP_FORCE_H + +#include <plat/pincfg.h> + +#define NMK_GPIO_PER_CHIP 32 +#define GPIO_BLOCK_SHIFT 5 + +#define GPIO_IS_NOT_CHANGED 0 +#define GPIO_IS_INPUT 1 +#define GPIO_IS_OUTPUT 2 + +#define GPIO_WAKEUP_IS_ENABLED 0 +#define GPIO_WAKEUP_IS_DISBLED 1 + +#define GPIO_IS_NO_CHANGE 0 +#define GPIO_IS_OUTPUT_LOW 1 +#define GPIO_IS_OUTPUT_HIGH 2 + +#define GPIO_PULL_NO_CHANGE 0 +#define GPIO_PULL_UPDOWN_DISABLED 1 +#define GPIO_IS_PULLUP 2 +#define GPIO_IS_PULLDOWN 3 + +#define GPIO_PDIS_NO_CHANGE 0 +#define GPIO_PDIS_DISABLED 1 +#define GPIO_PDIS_ENABLED 2 + +void sleep_pins_config_pm_mux(pin_cfg_t *cfgs, int num); +void sleep_pins_config_pm(pin_cfg_t *cfgs, int num); + +#endif diff --git a/arch/arm/mach-ux500/board-u5500-bm.c b/arch/arm/mach-ux500/board-u5500-bm.c new file mode 100644 index 00000000000..333f2cb8563 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-bm.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U5500 board specific charger and battery initialization parameters. + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson <johan.palsson@stericsson.com> + * Karl Komierowski <karl.komierowski@stericsson.com> + */ + +#include <linux/power_supply.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab5500-bm.h> +#include "board-u5500-bm.h" + +#ifdef CONFIG_AB5500_BATTERY_THERM_ON_BATCTRL +/* + * These are the defined batteries that uses a NTC and ID resistor placed + * inside of the battery pack. + * Note that the abx500_res_to_temp table must be strictly sorted by falling + * resistance values to work. + */ +static struct abx500_res_to_temp temp_tbl_type1[] = { + {-20, 67400}, + { 0, 49200}, + { 5, 44200}, + { 10, 39400}, + { 15, 35000}, + { 20, 31000}, + { 25, 27400}, + { 30, 24300}, + { 35, 21700}, + { 40, 19400}, + { 45, 17500}, + { 50, 15900}, + { 55, 14600}, + { 60, 13500}, + { 65, 12500}, + { 70, 11800}, + {100, 9200}, +}; + +static struct abx500_res_to_temp temp_tbl_type2[] = { + {-20, 180700}, + { 0, 160000}, + { 5, 152700}, + { 10, 144900}, + { 15, 136800}, + { 20, 128700}, + { 25, 121000}, + { 30, 113800}, + { 35, 107300}, + { 40, 101500}, + { 45, 96500}, + { 50, 92200}, + { 55, 88600}, + { 60, 85600}, + { 65, 83000}, + { 70, 80900}, + {100, 73900}, +}; + +static struct abx500_res_to_temp temp_tbl_A[] = { + {-5, 53407}, + { 0, 48594}, + { 5, 43804}, + {10, 39188}, + {15, 34870}, + {20, 30933}, + {25, 27422}, + {30, 24347}, + {35, 21694}, + {40, 19431}, + {45, 17517}, + {50, 15908}, + {55, 14561}, + {60, 13437}, + {65, 12500}, +}; + +static struct abx500_res_to_temp temp_tbl_B[] = { + {-5, 165418}, + { 0, 159024}, + { 5, 151921}, + {10, 144300}, + {15, 136424}, + {20, 128565}, + {25, 120978}, + {30, 113875}, + {35, 107397}, + {40, 101629}, + {45, 96592}, + {50, 92253}, + {55, 88569}, + {60, 85461}, + {65, 82869}, +}; + +static struct abx500_v_to_cap cap_tbl_type1[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; + +static struct abx500_v_to_cap cap_tbl_A[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; +static struct abx500_v_to_cap cap_tbl_B[] = { + {4161, 100}, + {4124, 98}, + {4044, 90}, + {4003, 85}, + {3966, 80}, + {3933, 75}, + {3888, 67}, + {3849, 60}, + {3813, 55}, + {3787, 47}, + {3772, 30}, + {3751, 25}, + {3718, 20}, + {3681, 16}, + {3660, 14}, + {3589, 10}, + {3546, 7}, + {3495, 4}, + {3404, 2}, + {3250, 0}, +}; +#endif +static struct abx500_v_to_cap cap_tbl[] = { + {4186, 100}, + {4163, 99}, + {4114, 95}, + {4068, 90}, + {3990, 80}, + {3926, 70}, + {3898, 65}, + {3866, 60}, + {3833, 55}, + {3812, 50}, + {3787, 40}, + {3768, 30}, + {3747, 25}, + {3730, 20}, + {3705, 15}, + {3699, 14}, + {3684, 12}, + {3672, 9}, + {3657, 7}, + {3638, 6}, + {3556, 4}, + {3424, 2}, + {3317, 1}, + {3094, 0}, +}; + +/* + * Note that the abx500_res_to_temp table must be strictly sorted by falling + * resistance values to work. + */ +static struct abx500_res_to_temp temp_tbl[] = { + {-5, 214834}, + { 0, 162943}, + { 5, 124820}, + {10, 96520}, + {15, 75306}, + {20, 59254}, + {25, 47000}, + {30, 37566}, + {35, 30245}, + {40, 24520}, + {45, 20010}, + {50, 16432}, + {55, 13576}, + {60, 11280}, + {65, 9425}, +}; + +static const struct abx500_battery_type bat_type[] = { + [BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, + .charge_full_design = 612, + .nominal_voltage = 3700, + .termination_vol = 4050, + .termination_curr = 200, + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, + .maint_a_cur_lvl = 400, + .maint_a_vol_lvl = 4050, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 400, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + +#ifdef CONFIG_AB5500_BATTERY_THERM_ON_BATCTRL + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 70000, + .resis_low = 8200, + .battery_resistance = 300, + .charge_full_design = 1500, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_type1), + .r_to_t_tbl = temp_tbl_type1, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_type1), + .v_to_cap_tbl = cap_tbl_type1, + + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 165418, + .resis_low = 82869, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B), + .r_to_t_tbl = temp_tbl_B, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B), + .v_to_cap_tbl = cap_tbl_B, + }, +#else +/* + * These are the batteries that doesn't have an internal NTC resistor to measure + * its temperature. The temperature in this case is measure with a NTC placed + * near the battery but on the PCB. + */ + { + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 76000, + .resis_low = 53000, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 30000, + .resis_low = 10000, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, + { + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 95000, + .resis_low = 76001, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4025, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4025, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + }, +#endif +}; + +static char *ab5500_charger_supplied_to[] = { + "abx500_chargalg", + "ab5500_fg", + "ab5500_btemp", +}; + +static char *ab5500_btemp_supplied_to[] = { + "abx500_chargalg", + "ab5500_fg", +}; + +static char *ab5500_fg_supplied_to[] = { + "abx500_chargalg", +}; + +static char *abx500_chargalg_supplied_to[] = { + "ab5500_fg", +}; + +struct abx500_charger_platform_data ab5500_charger_plat_data = { + .supplied_to = ab5500_charger_supplied_to, + .num_supplicants = ARRAY_SIZE(ab5500_charger_supplied_to), +}; + +struct abx500_btemp_platform_data ab5500_btemp_plat_data = { + .supplied_to = ab5500_btemp_supplied_to, + .num_supplicants = ARRAY_SIZE(ab5500_btemp_supplied_to), +}; + +struct abx500_fg_platform_data ab5500_fg_plat_data = { + .supplied_to = ab5500_fg_supplied_to, + .num_supplicants = ARRAY_SIZE(ab5500_fg_supplied_to), +}; + +struct abx500_chargalg_platform_data abx500_chargalg_plat_data = { + .supplied_to = abx500_chargalg_supplied_to, + .num_supplicants = ARRAY_SIZE(abx500_chargalg_supplied_to), +}; + +static const struct abx500_bm_capacity_levels cap_levels = { + .critical = 2, + .low = 10, + .normal = 70, + .high = 95, + .full = 100, +}; + +static const struct abx500_fg_parameters fg = { + .recovery_sleep_timer = 10, + .recovery_total_time = 100, + .init_timer = 1, + .init_discard_time = 5, + .init_total_time = 40, + .high_curr_time = 60, + .accu_charging = 30, + .accu_high_curr = 30, + .high_curr_threshold = 50, + .lowbat_threshold = 3560, + .overbat_threshold = 4400, +}; + +static const struct abx500_maxim_parameters maxi_params = { + .ena_maxi = true, + .chg_curr = 910, + .wait_cycles = 10, + .charger_curr_step = 100, +}; + +static const struct abx500_bm_charger_parameters chg = { + .usb_volt_max = 5500, + .usb_curr_max = 1500, + .ac_volt_max = 7500, + .ac_curr_max = 1500, +}; + +struct abx500_bm_data ab5500_bm_data = { + .temp_under = 3, + .temp_low = 8, + /* TODO: Need to verify the temp values */ + .temp_high = 155, + .temp_over = 160, + .main_safety_tmr_h = 4, + .usb_safety_tmr_h = 4, + .bkup_bat_v = 0x00, + .bkup_bat_i = 0x00, + .no_maintenance = true, +#ifdef CONFIG_AB5500_BATTERY_THERM_ON_BATCTRL + .adc_therm = ABx500_ADC_THERM_BATCTRL, +#else + .adc_therm = ABx500_ADC_THERM_BATTEMP, +#endif + .chg_unknown_bat = false, + .enable_overshoot = false, + .auto_trig = true, + .fg_res = 200, + .cap_levels = &cap_levels, + .bat_type = bat_type, + .n_btypes = ARRAY_SIZE(bat_type), + .batt_id = 0, + .interval_charging = 5, + .interval_not_charging = 120, + .temp_hysteresis = 3, + .maxi = &maxi_params, + .chg_params = &chg, + .fg_params = &fg, +}; + +/* ab5500 energy management platform data */ +struct abx500_bm_plat_data abx500_bm_pt_data = { + .battery = &ab5500_bm_data, + .charger = &ab5500_charger_plat_data, + .btemp = &ab5500_btemp_plat_data, + .fg = &ab5500_fg_plat_data, + .chargalg = &abx500_chargalg_plat_data, +}; diff --git a/arch/arm/mach-ux500/board-u5500-bm.h b/arch/arm/mach-ux500/board-u5500-bm.h new file mode 100644 index 00000000000..a6346905911 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-bm.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U5500 board specific charger and battery initialization parameters. + * + * License Terms: GNU General Public License v2 + * Authors: + * Johan Palsson <johan.palsson@stericsson.com> + * Karl Komierowski <karl.komierowski@stericsson.com> + */ + +#ifndef __BOARD_U5500_BM_H +#define __BOARD_U5500_BM_H + +#include <linux/mfd/abx500/ab5500-bm.h> + +extern struct abx500_charger_platform_data ab5500_charger_plat_data; +extern struct abx500_btemp_platform_data ab5500_btemp_plat_data; +extern struct abx500_fg_platform_data ab5500_fg_plat_data; +extern struct abx500_chargalg_platform_data abx500_chargalg_plat_data; +extern struct abx500_bm_data ab5500_bm_data; +extern struct abx500_bm_plat_data abx500_bm_pt_data; + +#endif diff --git a/arch/arm/mach-ux500/board-u5500-cyttsp.c b/arch/arm/mach-ux500/board-u5500-cyttsp.c new file mode 100644 index 00000000000..47eaa36c030 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-cyttsp.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * Author: Avinash A <avinash.a@stericsson.com> for ST-Ericsson + * License terms:GNU General Public License (GPL) version 2 + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <linux/cyttsp.h> +#include <linux/delay.h> +#include <linux/amba/pl022.h> +#include <plat/pincfg.h> +#include <mach/hardware.h> + +#include "pins-db5500.h" +#include "board-u5500.h" + +/* cyttsp_gpio_board_init : configures the touch panel. */ +static int cyttsp_plat_init(int on) +{ + int ret; + + ret = gpio_direction_output(CYPRESS_SLAVE_SELECT_GPIO, 1); + if (ret < 0) { + pr_err("slave select gpio direction failed\n"); + gpio_free(CYPRESS_SLAVE_SELECT_GPIO); + return ret; + } + + return 0; +} + +static int cyttsp_wakeup(void) +{ + int ret; + + ret = gpio_request(CYPRESS_TOUCH_INT_PIN, "Wakeup_pin"); + if (ret < 0) { + pr_err("touch gpio failed\n"); + return ret; + } + ret = gpio_direction_output(CYPRESS_TOUCH_INT_PIN, 1); + if (ret < 0) { + pr_err("touch gpio direction failed\n"); + goto out; + } + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + /* + * To wake up the controller from sleep + * state the interrupt pin needs to be + * pulsed twice with a delay greater + * than 2 micro seconds. + */ + udelay(3); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + ret = gpio_direction_input(CYPRESS_TOUCH_INT_PIN); + if (ret < 0) { + pr_err("touch gpio direction IN config failed\n"); + goto out; + } +out: + gpio_free(CYPRESS_TOUCH_INT_PIN); + return 0; +} +static struct cyttsp_platform_data cyttsp_spi_platdata = { + .maxx = 480, + .maxy = 854, + .flags = 0, + .gen = CY_GEN3, + .use_st = 0, + .use_mt = 1, + .use_trk_id = 0, + .use_hndshk = 0, + .use_sleep = 1, + .use_gestures = 0, + .use_load_file = 0, + .use_force_fw_update = 0, + .use_virtual_keys = 0, + /* activate up to 4 groups and set active distance */ + .gest_set = CY_GEST_GRP_NONE | CY_ACT_DIST, + /* change scn_type to enable finger and/or stylus detection */ + .scn_typ = 0xA5, /* autodetect finger+stylus; balanced mutual scan */ + .act_intrvl = CY_ACT_INTRVL_DFLT, /* Active refresh interval; ms */ + .tch_tmout = CY_TCH_TMOUT_DFLT, /* Active touch timeout; ms */ + .lp_intrvl = CY_LP_INTRVL_DFLT, /* Low power refresh interval; ms */ + .init = cyttsp_plat_init, + .mt_sync = input_mt_sync, + .wakeup = cyttsp_wakeup, + .name = CY_SPI_NAME, + .irq_gpio = CYPRESS_TOUCH_INT_PIN, + .rst_gpio = CYPRESS_TOUCH_RST_GPIO, +}; + +static void cyttsp_spi_cs_control(u32 command) +{ + if (command == SSP_CHIP_SELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 0); + else if (command == SSP_CHIP_DESELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 1); +} + +static struct pl022_config_chip cyttsp_ssp_config_chip = { + .com_mode = INTERRUPT_TRANSFER, + .iface = SSP_INTERFACE_MOTOROLA_SPI, + /* we can act as master only */ + .hierarchy = SSP_MASTER, + .slave_tx_disable = 0, + .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, + .tx_lev_trig = SSP_TX_16_OR_MORE_EMPTY_LOC, + .ctrl_len = SSP_BITS_16, + .wait_state = SSP_MWIRE_WAIT_ZERO, + .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, + .cs_control = cyttsp_spi_cs_control, +}; + +static struct spi_board_info cypress_spi_devices[] = { + { + .modalias = CY_SPI_NAME, + .controller_data = &cyttsp_ssp_config_chip, + .platform_data = &cyttsp_spi_platdata, + .max_speed_hz = 1000000, + .bus_num = 1, + .chip_select = 0, + .mode = SPI_MODE_0, + } +}; + +void u5500_cyttsp_init(void) +{ + int ret = 0; + + ret = gpio_request(CYPRESS_SLAVE_SELECT_GPIO, "slave_select_gpio"); + if (ret < 0) { + pr_err("slave select gpio failed\n"); + return; + } + if (cpu_is_u5500v2()) + cyttsp_spi_platdata.invert = true; + spi_register_board_info(cypress_spi_devices, + ARRAY_SIZE(cypress_spi_devices)); +} diff --git a/arch/arm/mach-ux500/board-u5500-mcde.c b/arch/arm/mach-ux500/board-u5500-mcde.c new file mode 100644 index 00000000000..906b5572229 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-mcde.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/dispdev.h> +#include <video/av8100.h> +#include <asm/mach-types.h> +#include <video/mcde_display.h> +#include <video/mcde_display-generic_dsi.h> +#include <video/mcde_display-sony_acx424akp_dsi.h> +#include <video/mcde_display-av8100.h> +#include <video/mcde_fb.h> +#include <video/mcde_dss.h> + +#define DSI_UNIT_INTERVAL_0 0xA +#define DSI_UNIT_INTERVAL_2 0x5 + +/* The initialization of hdmi disp driver must be delayed in order to + * ensure that inputclk will be available (needed by hdmi hw) */ +static struct delayed_work work_dispreg_hdmi; +#define DISPREG_HDMI_DELAY 6000 + +enum { + PRIMARY_DISPLAY_ID, + AV8100_DISPLAY_ID, + MCDE_NR_OF_DISPLAYS +}; + +static int display_initialized_during_boot; + +static int __init startup_graphics_setup(char *str) +{ + + if (get_option(&str, &display_initialized_during_boot) != 1) + display_initialized_during_boot = 0; + + switch (display_initialized_during_boot) { + case 1: + pr_info("Startup graphics support\n"); + break; + case 0: + default: + pr_info("No startup graphics supported\n"); + break; + }; + + return 1; +} +__setup("startup_graphics=", startup_graphics_setup); + +static struct mcde_col_transform rgb_2_yCbCr_transform = { + .matrix = { + {0x0042, 0x0081, 0x0019}, + {0xffda, 0xffb6, 0x0070}, + {0x0070, 0xffa2, 0xffee}, + }, + .offset = {0x10, 0x80, 0x80}, +}; + +static struct mcde_port sony_port0 = { + .link = 0, + .sync_src = MCDE_SYNCSRC_BTA, + .frame_trig = MCDE_TRIG_SW, +}; + +static struct mcde_display_sony_acx424akp_platform_data \ + sony_acx424akp_display0_pdata = { + .reset_gpio = 226, +}; + +static struct mcde_display_device sony_acx424akp_display0 = { + .name = "mcde_disp_sony_acx424akp", + .id = PRIMARY_DISPLAY_ID, + .port = &sony_port0, + .chnl_id = MCDE_CHNL_A, + .fifo = MCDE_FIFO_A, + .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888, + .dev = { + .platform_data = &sony_acx424akp_display0_pdata, + }, +}; + +#if defined(CONFIG_AV8100_HWTRIG_INT) + #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE0 +#elif defined(CONFIG_AV8100_HWTRIG_I2SDAT3) + #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE1 +#elif defined(CONFIG_AV8100_HWTRIG_DSI_TE) + #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE_POLLING +#else + #define AV8100_SYNC_SRC MCDE_SYNCSRC_OFF +#endif +static struct mcde_port av8100_port2 = { + .type = MCDE_PORTTYPE_DSI, + .mode = MCDE_PORTMODE_CMD, + .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, + .link = 1, + .sync_src = AV8100_SYNC_SRC, + .update_auto_trig = true, + .phy = { + .dsi = { + .num_data_lanes = 2, + .ui = DSI_UNIT_INTERVAL_2, + }, + }, + .hdmi_sdtv_switch = HDMI_SWITCH, +}; + +static struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = { + .rgb_2_yCbCr_transform = &rgb_2_yCbCr_transform, +}; + +static struct mcde_display_device av8100_hdmi = { + .name = "av8100_hdmi", + .id = AV8100_DISPLAY_ID, + .port = &av8100_port2, + .chnl_id = MCDE_CHNL_B, + .fifo = MCDE_FIFO_B, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB888, + .native_x_res = 1280, + .native_y_res = 720, + .dev = { + .platform_data = &av8100_hdmi_pdata, + }, +}; + +static void delayed_work_dispreg_hdmi(struct work_struct *ptr) +{ + if (mcde_display_device_register(&av8100_hdmi)) + pr_warning("Failed to register av8100_hdmi\n"); +} + +/* +* This function will create the framebuffer for the display that is registered. +*/ +static int display_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *dev) +{ + struct mcde_display_device *ddev = dev; + u16 width, height; + u16 virtual_height; + u32 rotate = FB_ROTATE_UR; + struct fb_info *fbi; +#ifdef CONFIG_DISPDEV + struct mcde_fb *mfb; +#endif + + if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) + return 0; + + if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= MCDE_NR_OF_DISPLAYS) + return 0; + + mcde_dss_get_native_resolution(ddev, &width, &height); + + virtual_height = height * 2; + +#ifndef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE + if (ddev->id == AV8100_DISPLAY_ID) + goto out; +#endif + + /* Create frame buffer */ + fbi = mcde_fb_create(ddev, width, height, width, virtual_height, + ddev->default_pixel_format, rotate); + if (IS_ERR(fbi)) { + dev_warn(&ddev->dev, + "Failed to create fb for display %s\n", ddev->name); + goto display_postregistered_callback_err; + } else { + dev_info(&ddev->dev, "Framebuffer created (%s)\n", ddev->name); + } + +#ifdef CONFIG_DISPDEV + mfb = to_mcde_fb(fbi); + + /* Create a dispdev overlay for this display */ + if (dispdev_create(ddev, true, mfb->ovlys[0]) < 0) { + dev_warn(&ddev->dev, + "Failed to create disp for display %s\n", ddev->name); + goto display_postregistered_callback_err; + } else { + dev_info(&ddev->dev, "Disp dev created for (%s)\n", ddev->name); + } +#endif + +out: + return 0; + +display_postregistered_callback_err: + return -1; +} + +static struct notifier_block display_nb = { + .notifier_call = display_postregistered_callback, +}; + +/* +* This function is used to refresh the display (lcd, hdmi, tvout) with black +* when the framebuffer is registered. +* The main display will not be updated if startup graphics is displayed +* from u-boot. +*/ +static int framebuffer_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int ret = 0; + struct fb_event *event_data = data; + struct fb_info *info; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + struct mcde_fb *mfb; + + if (event != FB_EVENT_FB_REGISTERED) + return 0; + + if (!event_data) + return 0; + + info = event_data->info; + mfb = to_mcde_fb(info); + if (mfb->id == 0 && display_initialized_during_boot) + goto out; + + var = info->var; + fix = info->fix; + var.yoffset = var.yoffset ? 0 : var.yres; + if (info->fbops->fb_pan_display) + ret = info->fbops->fb_pan_display(&var, info); +out: + return ret; +} + +static struct notifier_block framebuffer_nb = { + .notifier_call = framebuffer_postregistered_callback, +}; + +int __init init_u5500_display_devices(void) +{ + int ret; + + if (!cpu_is_u5500()) + return 0; + + ret = fb_register_client(&framebuffer_nb); + if (ret) + pr_warning("Failed to register framebuffer notifier\n"); + + (void)mcde_dss_register_notifier(&display_nb); + + if (display_initialized_during_boot) + sony_acx424akp_display0.power_mode = MCDE_DISPLAY_PM_STANDBY; + + (void)mcde_display_device_register(&sony_acx424akp_display0); + + INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi, + delayed_work_dispreg_hdmi); + schedule_delayed_work(&work_dispreg_hdmi, + msecs_to_jiffies(DISPREG_HDMI_DELAY)); + + return 0; +} +module_init(init_u5500_display_devices); + diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c new file mode 100644 index 00000000000..ded7cb94c1f --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * Author: Joakim Axelsson <joakim.axelsson@stericsson.com> for ST-Ericsson + * Author: Rajat Verma <rajat.verma@stericsson.com> for ST-Ericsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/regulator/consumer.h> +#include <linux/vmalloc.h> +#include <plat/pincfg.h> +#include <mach/gpio.h> +#include <mach/devices.h> +#include "board-u5500.h" +#include <linux/mmio.h> + +struct mmio_board_data { + int number_of_regulators; + struct regulator **mmio_regulators; + /* * Pin configs */ + struct mmio_gpio xshutdown_pins[CAMERA_SLOT_END]; + /* * Internal clocks */ + struct clk *clk_ptr_bml; + struct clk *clk_ptr_ipi2c; + /* * External clocks */ + struct clk *clk_ptr_ext[CAMERA_SLOT_END]; +}; + +/* + * Fill names of regulators required for powering up the + * camera sensor in below array + */ +static char *regulator_names[] = {"v-mmio-camera", "v-ana"}; + +static int mmio_clock_init(struct mmio_platform_data *pdata) +{ + int err; + struct mmio_board_data *extra = pdata->extra; + + extra->clk_ptr_ext[PRIMARY_CAMERA] = + clk_get(pdata->dev, "primary-cam"); + if (IS_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA]); + dev_err(pdata->dev, + "Error %d clock 'primary-cam'\n", err); + goto err_pri_ext_clk; + } + extra->clk_ptr_ext[SECONDARY_CAMERA] = + clk_get(pdata->dev, "secondary-cam"); + if (IS_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA]); + dev_err(pdata->dev, + "Error %d clock 'secondary-cam'\n", err); + goto err_sec_ext_clk; + } + + return 0; +err_sec_ext_clk: + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); +err_pri_ext_clk: + return err; +} + +static void mmio_clock_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); + clk_put(extra->clk_ptr_ext[SECONDARY_CAMERA]); +} + +static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + extra->xshutdown_pins[PRIMARY_CAMERA].gpio = + GPIO_PRIMARY_CAM_XSHUTDOWN; + extra->xshutdown_pins[PRIMARY_CAMERA].active_high = 0; + extra->xshutdown_pins[PRIMARY_CAMERA].udelay = 250; + + extra->xshutdown_pins[SECONDARY_CAMERA].gpio = + GPIO_SECONDARY_CAM_XSHUTDOWN; + extra->xshutdown_pins[SECONDARY_CAMERA].active_high = 0; + extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 250; + + return 0; +} + +static void mmio_pin_cfg_exit(struct mmio_platform_data *pdata) +{ +} + +/* + * For now, both sensors on B5500/S5500 have some power up sequence. If + * different sequences are needed for primary and secondary sensors, it can + * be implemented easily. Just use camera_slot field of mmio_platform_data + * to determine which camera needs to be powered up + */ +static int mmio_power_init(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + extra->number_of_regulators = ARRAY_SIZE(regulator_names); + extra->mmio_regulators = + kzalloc(sizeof(struct regulator *) * extra->number_of_regulators, + GFP_KERNEL); + if (!extra->mmio_regulators) { + dev_err(pdata->dev + , "Error allocating memory for mmio regulators\n"); + err = -ENOMEM; + goto err_no_mem_reg; + } + for (i = 0; i < + extra->number_of_regulators; i++) { + extra->mmio_regulators[i] = + regulator_get(pdata->dev, regulator_names[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev + , "Error %d getting regulator '%s'\n" + , err, regulator_names[i]); + goto err_regulator; + } + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* + * Return regulators we have already requested + */ + while (i--) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +err_no_mem_reg: + return err; +} + +static void mmio_power_exit(struct mmio_platform_data *pdata) +{ + int i = 0; + struct mmio_board_data *extra = pdata->extra; + + for (i = 0; i < extra->number_of_regulators; i++) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +} + +static int mmio_platform_init(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = NULL; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* + * Alloc memory for our own extra data + */ + extra = kzalloc(sizeof(struct mmio_board_data), GFP_KERNEL); + if (!extra) { + dev_err(pdata->dev, "%s: memory alloc failed for " + "mmio_board_data\n", __func__); + err = -ENOMEM; + goto err_no_mem_extra; + } + /* + * Hook the data for other callbacks to use + */ + pdata->extra = extra; + + pdata->camera_slot = -1; + + err = mmio_power_init(pdata); + if (err) + goto err_regulator; + err = mmio_clock_init(pdata); + if (err) + goto err_clock; + err = mmio_pin_cfg_init(pdata); + if (err) + goto err_pin_cfg; + + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; + +err_pin_cfg: + mmio_clock_exit(pdata); +err_clock: + mmio_power_exit(pdata); +err_regulator: + kfree(extra); +err_no_mem_extra: + return err; +} + +static void mmio_platform_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + mmio_power_exit(pdata); + mmio_clock_exit(pdata); + mmio_pin_cfg_exit(pdata); + kfree(extra); + pdata->extra = NULL; +} + +static int mmio_power_enable(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* + * Enable the regulators + */ + for (i = 0; i < extra->number_of_regulators; i++) { + err = regulator_enable(extra->mmio_regulators[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev , "Error %d enabling regulator '%s'" + "\n", err, regulator_names[i]); + goto err_regulator; + } + } + + err = gpio_request(GPIO_CAMERA_PMIC_EN, "Camera PMIC GPIO"); + if (err) { + dev_err(pdata->dev, "Error %d while requesting" + "Camera PMIC GPIO\n", + err); + return err; + } + + err = gpio_direction_output(GPIO_CAMERA_PMIC_EN, 0); + if (err) { + dev_err(pdata->dev, "Error %d while setting" + "Camera PMIC GPIO" + "output mode\n", err); + return err; + } + + if (!(u5500_board_is_s5500())) + gpio_set_value(GPIO_CAMERA_PMIC_EN, 1); + else + gpio_set_value(GPIO_CAMERA_PMIC_EN, 0); + + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* + * Disable regulators we already enabled + */ + while (i--) + regulator_disable(extra->mmio_regulators[i]); + return err; +} + +static void mmio_power_disable(struct mmio_platform_data *pdata) +{ + int i; + struct mmio_board_data *extra = pdata->extra; + /* + * Disable the regulators + */ + for (i = 0; i < extra->number_of_regulators; i++) + regulator_disable(extra->mmio_regulators[i]); + + if (!(u5500_board_is_s5500())) + gpio_set_value(GPIO_CAMERA_PMIC_EN, 0); + else + gpio_set_value(GPIO_CAMERA_PMIC_EN, 1); + + gpio_free(GPIO_CAMERA_PMIC_EN); +} + +static int mmio_clock_enable(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + + /* + * Enable appropriate external clock + */ + err = clk_enable(extra->clk_ptr_ext[pdata->camera_slot]); + if (err) { + dev_err(pdata->dev, "Error activating clock for sensor %d, err" + "%d\n", pdata->camera_slot, err); + goto err_ext_clk; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_ext_clk: + return err; +} + +static void mmio_clock_disable(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + clk_disable(extra->clk_ptr_ext[pdata->camera_slot]); +} + +static int mmio_config_xshutdown_pins(struct mmio_platform_data *pdata, + enum mmio_select_xshutdown_t select, + int is_active_high) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + switch (select) { + case MMIO_ENABLE_XSHUTDOWN_HOST: + extra->xshutdown_pins[pdata->camera_slot].active_high = + is_active_high; + dev_dbg(pdata->dev , "Enabling Xshutdown GPIO PIN = %d", + extra->xshutdown_pins[pdata->camera_slot].gpio); + + err = gpio_request + (extra->xshutdown_pins[pdata->camera_slot].gpio, + "MMIO GPIO"); + if (err) { + dev_err(pdata->dev, "Error %d while requesting" + "Xshutdown MMIO GPIO\n", + err); + return err; + } + + err = gpio_direction_output + (extra->xshutdown_pins[pdata->camera_slot].gpio, + 0); + if (err) { + dev_err(pdata->dev, "Error %d while setting" + "Xshutdown MMIO GPIO" + "output mode\n", err); + return err; + } + break; + case MMIO_DISABLE_XSHUTDOWN: + dev_dbg(pdata->dev , "Disabling Xshutdown GPIO PIN = %d", + extra->xshutdown_pins[pdata->camera_slot].gpio); + gpio_free(extra->xshutdown_pins[pdata->camera_slot].gpio); + break; + default: + break; + } + if (err) + dev_err(pdata->dev , "Error configuring xshutdown, err = %d\n", + err); + return err; +} + +static void mmio_set_xshutdown(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + gpio_set_value(extra->xshutdown_pins[pdata->camera_slot].gpio , + (extra->xshutdown_pins[pdata->camera_slot].active_high + ? 1 : 0)); + udelay(extra->xshutdown_pins[pdata->camera_slot].udelay); +} + +/* + * TODO: This function would be removed in futute. + * Since this function is called frequently + * from HSM Camera code , it is kept for Legacy. + */ +static int mmio_config_i2c_pins(struct mmio_platform_data *pdata, + enum mmio_select_i2c_t select) +{ + int err = 0; + + switch (select) { + case MMIO_ACTIVATE_I2C_HOST: + dev_dbg(pdata->dev , "Activate I2C from Host called\n"); + break; + case MMIO_DEACTIVATE_I2C: + dev_dbg(pdata->dev , "DeActivate I2C from Host called\n"); + break; + default: + break; + } + + return err; +} + +static struct mmio_platform_data mmio_config = { + .platform_init = mmio_platform_init, + .platform_exit = mmio_platform_exit, + .power_enable = mmio_power_enable, + .power_disable = mmio_power_disable, + .clock_enable = mmio_clock_enable, + .clock_disable = mmio_clock_disable, + .config_i2c_pins = mmio_config_i2c_pins, + .config_xshutdown_pins = mmio_config_xshutdown_pins, + .set_xshutdown = mmio_set_xshutdown +}; + +struct platform_device u5500_mmio_device = { + .name = MMIO_NAME, + .id = -1, + .dev = { + .platform_data = &mmio_config, + } +}; diff --git a/arch/arm/mach-ux500/board-u5500-pins.c b/arch/arm/mach-ux500/board-u5500-pins.c new file mode 100644 index 00000000000..a6b63ca3ead --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-pins.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> +#include <plat/pincfg.h> + +#include "pins-db5500.h" +#include "pins.h" + +static pin_cfg_t u5500_pins_default[] = { + GPIO77_ACCTX_ON | PIN_SLPM_ALTFUNC, + GPIO79_ACCSIM_Clk | PIN_SLPM_ALTFUNC, + GPIO80_ACCSIM_Da | PIN_SLPM_ALTFUNC, + GPIO81_ACCSIM_Reset | PIN_SLPM_ALTFUNC, + GPIO82_ACCSIM_DDir | PIN_SLPM_ALTFUNC, + + /* MSP */ + GPIO32_MSP0_TCK | PIN_INPUT_PULLDOWN, + GPIO33_MSP0_TFS | PIN_INPUT_PULLDOWN, + GPIO34_MSP0_TXD | PIN_INPUT_PULLDOWN, + GPIO35_MSP0_RXD | PIN_INPUT_PULLDOWN, + GPIO96_MSP1_TCK | PIN_INPUT_PULLDOWN, + GPIO97_MSP1_TFS | PIN_INPUT_PULLDOWN, + GPIO98_MSP1_TXD | PIN_INPUT_PULLDOWN, + GPIO99_MSP1_RXD | PIN_INPUT_PULLDOWN, + GPIO220_MSP2_TCK | PIN_OUTPUT_LOW, + GPIO221_MSP2_TFS | PIN_OUTPUT_LOW, + GPIO222_MSP2_TXD | PIN_OUTPUT_LOW, + + /* DISPLAY_ENABLE */ + GPIO226_GPIO | PIN_OUTPUT_HIGH, + + /* Backlight Enable */ + GPIO224_GPIO | PIN_OUTPUT_HIGH, + + /* UART0 */ + GPIO28_U0_TXD | PIN_OUTPUT_HIGH, + GPIO29_U0_RXD | PIN_INPUT_PULLUP, + + /* UART3 */ + GPIO165_U3_RXD | PIN_INPUT_PULLUP, + GPIO166_U3_TXD | PIN_OUTPUT_HIGH | PIN_LOWEMI_ENABLED, + GPIO167_U3_RTSn | PIN_OUTPUT_HIGH | PIN_LOWEMI_ENABLED, + GPIO168_U3_CTSn | PIN_INPUT_PULLUP, + + /* AB5500 */ + GPIO78_IRQn | PIN_SLPM_NOCHANGE, + GPIO100_I2C0_SCL | PIN_INPUT_PULLUP | PIN_SLPM_NOCHANGE, + GPIO101_I2C0_SDA | PIN_SLPM_NOCHANGE, + + /* TOUCH_IRQ */ + GPIO179_GPIO | PIN_INPUT_PULLUP, + + /* SD-CARD detect/levelshifter pins */ + GPIO180_GPIO | PIN_INPUT_NOPULL, /* SD_CARD_DETn */ + GPIO227_GPIO | PIN_OUTPUT_LOW, /* SD_CARD_CTRL */ + GPIO185_GPIO | PIN_OUTPUT_LOW, /* SD_CARD_VSEL */ + + /* Display & HDMI HW sync */ + GPIO204_LCD_VSI1 | PIN_INPUT_PULLUP, + + /* TVOUT (connected, but unused) */ + GPIO205_GPIO | PIN_OUTPUT_LOW, + GPIO206_GPIO | PIN_OUTPUT_LOW, + GPIO207_GPIO | PIN_OUTPUT_LOW, + GPIO208_GPIO | PIN_OUTPUT_LOW, + GPIO209_GPIO | PIN_INPUT_PULLDOWN, + + /* Display (connected to NT35560 / TE, but unused) */ + GPIO211_GPIO | PIN_INPUT_PULLDOWN, + + /* Camera & MMIO XshutDown*/ + GPIO1_GPIO | PIN_OUTPUT_LOW, + GPIO2_GPIO | PIN_OUTPUT_LOW, + + /* USB chip select */ + GPIO76_GPIO | PIN_OUTPUT_LOW, + + GPIO202_ACCU0_RXD | PIN_INPUT_PULLUP | PIN_SLPM_NOCHANGE, + GPIO203_ACCU0_TXD | PIN_OUTPUT_HIGH | PIN_SLPM_NOCHANGE, + + /* Board Id Identification B5500 or S5500 */ + GPIO0_GPIO | PIN_INPUT_PULLUP, + GPIO214_GPIO | PIN_OUTPUT_LOW, /* SW_CRASH_INDICATOR */ + + /* Touchscreen chip select */ + GPIO186_GPIO | PIN_OUTPUT_HIGH | PIN_LOWEMI_ENABLED, + + GPIO133_GPIO | PIN_OUTPUT_LOW, /* DUALSIMRESETn */ + GPIO187_GPIO | PIN_OUTPUT_HIGH, /* Dual SIM CS */ + + GPIO163_GPIO | PIN_INPUT_PULLUP, /* SERVICEn */ + + GPIO223_GPIO | PIN_INPUT_PULLDOWN, /* HDMI_INT */ + GPIO225_GPIO | PIN_OUTPUT_LOW, /* HDMI_ENABLE */ +}; + +static UX500_PINS(db5500_kp_pins, + /* Keypad */ + GPIO128_KP_I0 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO130_KP_I1 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO132_KP_I2 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO134_KP_I3 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO137_KP_O4 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO139_KP_O5 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, +); + +static UX500_PINS(db5500_pins_sdi0, + /* SDI0 (eMMC) */ + GPIO5_MC0_DAT0 | PIN_INPUT_PULLUP, + GPIO6_MC0_DAT1 | PIN_INPUT_PULLUP, + GPIO7_MC0_DAT2 | PIN_INPUT_PULLUP, + GPIO8_MC0_DAT3 | PIN_INPUT_PULLUP, + GPIO9_MC0_DAT4 | PIN_INPUT_PULLUP, + GPIO10_MC0_DAT5 | PIN_INPUT_PULLUP, + GPIO11_MC0_DAT6 | PIN_INPUT_PULLUP, + GPIO12_MC0_DAT7 | PIN_INPUT_PULLUP, + GPIO13_MC0_CMD | PIN_INPUT_PULLUP, + GPIO14_MC0_CLK | PIN_OUTPUT_LOW, +); + +static UX500_PINS(db5500_pins_sdi1, + /* SDI1 (SD-CARD) */ + GPIO191_MC1_DAT0 | PIN_INPUT_PULLUP, + GPIO192_MC1_DAT1 | PIN_INPUT_PULLUP, + GPIO193_MC1_DAT2 | PIN_INPUT_PULLUP, + GPIO194_MC1_DAT3 | PIN_INPUT_PULLUP, + GPIO195_MC1_CLK | PIN_OUTPUT_LOW, + GPIO196_MC1_CMD | PIN_INPUT_PULLUP, + GPIO197_MC1_CMDDIR | PIN_OUTPUT_HIGH, + GPIO198_MC1_FBCLK | PIN_INPUT_PULLDOWN, + GPIO199_MC1_DAT0DIR | PIN_OUTPUT_HIGH, +); + +static UX500_PINS(db5500_pins_sdi2, + /* SDI2 (eMMC) */ + GPIO16_MC2_CMD | PIN_INPUT_PULLUP, + GPIO17_MC2_CLK | PIN_OUTPUT_LOW, + GPIO23_MC2_DAT0 | PIN_INPUT_PULLUP, + GPIO19_MC2_DAT1 | PIN_INPUT_PULLUP, + GPIO24_MC2_DAT2 | PIN_INPUT_PULLUP, + GPIO20_MC2_DAT3 | PIN_INPUT_PULLUP, + GPIO25_MC2_DAT4 | PIN_INPUT_PULLUP, + GPIO21_MC2_DAT5 | PIN_INPUT_PULLUP, + GPIO26_MC2_DAT6 | PIN_INPUT_PULLUP, + GPIO22_MC2_DAT7 | PIN_INPUT_PULLUP +); + +static UX500_PINS(db5500_pins_sdi3, + /* SDI3 (SDIO) */ + GPIO171_MC3_DAT0 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO172_MC3_DAT1 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO173_MC3_DAT2 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO174_MC3_DAT3 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO175_MC3_CMD | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO176_MC3_CLK | PIN_OUTPUT_LOW, +); + +static UX500_PINS(u5500_pins_i2c1, + GPIO3_I2C1_SCL | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, + GPIO4_I2C1_SDA | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, +); + +static UX500_PINS(u5500_pins_i2c2, + GPIO218_I2C2_SCL | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, + GPIO219_I2C2_SDA | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, +); + +static UX500_PINS(u5500_pins_i2c3, + GPIO177_I2C3_SCL | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, + GPIO178_I2C3_SDA | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, +); + +static UX500_PINS(u5500_pins_spi3, + GPIO188_SPI3_RXD | PIN_INPUT_PULLUP, + GPIO189_SPI3_TXD | PIN_OUTPUT_LOW | PIN_LOWEMI_ENABLED, + GPIO190_SPI3_CLK | PIN_OUTPUT_LOW | PIN_LOWEMI_ENABLED, +); + +/* USB */ +static UX500_PINS(u5500_pins_usb, + GPIO74_USB_NXT | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO72_USB_STP | PIN_OUTPUT_HIGH | PIN_SLPM_OUTPUT_HIGH, + GPIO75_USB_XCLK | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO73_USB_DIR | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO71_USB_DAT7 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO70_USB_DAT6 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO69_USB_DAT5 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO68_USB_DAT4 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO67_USB_DAT3 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO66_USB_DAT2 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO65_USB_DAT1 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO64_USB_DAT0 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, +); + +static struct ux500_pin_lookup u5500_pins[] = { + PIN_LOOKUP("nmk-i2c.1", &u5500_pins_i2c1), + PIN_LOOKUP("nmk-i2c.2", &u5500_pins_i2c2), + PIN_LOOKUP("nmk-i2c.3", &u5500_pins_i2c3), + PIN_LOOKUP("spi3", &u5500_pins_spi3), + PIN_LOOKUP("db5500_kp", &db5500_kp_pins), + PIN_LOOKUP("ab5500-usb.0", &u5500_pins_usb), + PIN_LOOKUP("sdi0", &db5500_pins_sdi0), + PIN_LOOKUP("sdi1", &db5500_pins_sdi1), + PIN_LOOKUP("sdi2", &db5500_pins_sdi2), + PIN_LOOKUP("sdi3", &db5500_pins_sdi3), +}; + +void __init u5500_pins_init(void) +{ + nmk_config_pins(u5500_pins_default, ARRAY_SIZE(u5500_pins_default)); + ux500_pins_add(u5500_pins, ARRAY_SIZE(u5500_pins)); +} + +/* Stub function to make board-ux500-cg2900.c compile within a U5500 configuration */ +int pins_for_u9500(void) +{ + return 0; +} diff --git a/arch/arm/mach-ux500/board-u5500-regulators.c b/arch/arm/mach-ux500/board-u5500-regulators.c new file mode 100644 index 00000000000..9e343259e53 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-regulators.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/ab5500.h> + +#include "regulator-u5500.h" +#include "board-u5500.h" + +/* + * AB5500 + */ + +static struct regulator_consumer_supply ab5500_ldo_g_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sdi1"), +}; + +static struct regulator_consumer_supply ab5500_ldo_h_consumers[] = { + REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"), + REGULATOR_SUPPLY("vdd", "1-004b"), /* Synaptics */ + REGULATOR_SUPPLY("vin", "2-0036"), /* LM3530 */ + REGULATOR_SUPPLY("vcpin", "spi1.0"), + REGULATOR_SUPPLY("v-ana", "mmio_camera"), + REGULATOR_SUPPLY("vdd", "lsm303dlh.0"), + REGULATOR_SUPPLY("vdd", "lsm303dlh.1"), +}; + +static struct regulator_consumer_supply ab5500_ldo_k_consumers[] = { + REGULATOR_SUPPLY("v-mmio-camera", "mmio_camera"), +}; + +static struct regulator_consumer_supply ab5500_ldo_h_consumers_pre_r3a[] = { + REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"), + REGULATOR_SUPPLY("vdd", "1-004b"), /* Synaptics */ + REGULATOR_SUPPLY("vin", "2-0036"), /* LM3530 */ + REGULATOR_SUPPLY("vcpin", "spi1.0"), + REGULATOR_SUPPLY("v-ana", "mmio_camera"), +}; + +static struct regulator_consumer_supply ab5500_ldo_k_consumers_pre_r3a[] = { + REGULATOR_SUPPLY("vdd", "lsm303dlh.0"), + REGULATOR_SUPPLY("vdd", "lsm303dlh.1"), + REGULATOR_SUPPLY("v-mmio-camera", "mmio_camera"), +}; + +static struct regulator_consumer_supply ab5500_ldo_l_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sdi0"), + REGULATOR_SUPPLY("vmmc", "sdi2"), +}; + +static struct regulator_consumer_supply ab5500_ldo_vdigmic_consumers[] = { + REGULATOR_SUPPLY("vdigmic", "ab5500-codec.0"), +}; + +static struct regulator_consumer_supply ab5500_ldo_sim_consumers[] = { + REGULATOR_SUPPLY("debug", "reg-virt-consumer.5"), +}; + +static struct regulator_consumer_supply ab5500_bias2_consumers[] = { + REGULATOR_SUPPLY("v-amic", NULL), +}; + +static struct regulator_init_data +ab5500_regulator_init_data[AB5500_NUM_REGULATORS] = { + /* SD Card */ + [AB5500_LDO_G] = { + .constraints = { + .min_uV = 1200000, + .max_uV = 2910000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .consumer_supplies = ab5500_ldo_g_consumers, + .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_g_consumers), + }, + /* Display */ + [AB5500_LDO_H] = { + .constraints = { + .min_uV = 2790000, + .max_uV = 2790000, + .apply_uV = 1, + .boot_on = 1, /* display on during boot */ + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = ab5500_ldo_h_consumers, + .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_h_consumers), + }, + /* Camera */ + [AB5500_LDO_K] = { + .constraints = { + .min_uV = 2790000, + .max_uV = 2790000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = ab5500_ldo_k_consumers, + .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_k_consumers), + }, + /* External eMMC */ + [AB5500_LDO_L] = { + .constraints = { + .min_uV = 1200000, + .max_uV = 2910000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .consumer_supplies = ab5500_ldo_l_consumers, + .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_l_consumers), + }, + [AB5500_LDO_VDIGMIC] = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = ab5500_ldo_vdigmic_consumers, + .num_consumer_supplies = + ARRAY_SIZE(ab5500_ldo_vdigmic_consumers), + }, + [AB5500_LDO_SIM] = { + .constraints = { + .min_uV = 1875000, + .max_uV = 2900000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = ab5500_ldo_sim_consumers, + .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_sim_consumers), + }, + [AB5500_BIAS2] = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = ab5500_bias2_consumers, + .num_consumer_supplies = ARRAY_SIZE(ab5500_bias2_consumers), + }, +}; + +static struct ab5500_regulator_data +ab5500_regulator_data[AB5500_NUM_REGULATORS] = { + [AB5500_LDO_H] = { + /* + * The sub camera on the dev boards needs both supplies to be + * on to avoid high leakage. + */ + .off_is_lowpower = true, + }, +}; + +struct ab5500_regulator_platform_data u5500_ab5500_regulator_data = { + .regulator = ab5500_regulator_init_data, + .data = ab5500_regulator_data, + .num_regulator = ARRAY_SIZE(ab5500_regulator_init_data), +}; + + +static void __init u5500_regulators_init_debug(void) +{ + const char data[] = "debug"; + int i; + + for (i = 0; i < 6; i++) + platform_device_register_data(NULL, "reg-virt-consumer", i, + data, sizeof(data)); +} + +static struct regulator_consumer_supply u5500_vio_consumers[] = { + REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), +}; + +static struct regulator_init_data u5500_vio_init_data = { + .constraints.always_on = 1, + .consumer_supplies = u5500_vio_consumers, + .num_consumer_supplies = ARRAY_SIZE(u5500_vio_consumers), +}; + +static struct fixed_voltage_config u5500_vio_pdata __initdata = { + .supply_name = "vio_1v8", + .microvolts = 1800000, + .init_data = &u5500_vio_init_data, + .gpio = -EINVAL, +}; + +void __init u5500_regulators_init(void) +{ + if (u5500_board_is_pre_r3a()) { + struct regulator_init_data *rid = ab5500_regulator_init_data; + + rid[AB5500_LDO_K].consumer_supplies + = ab5500_ldo_k_consumers_pre_r3a; + rid[AB5500_LDO_K].num_consumer_supplies + = ARRAY_SIZE(ab5500_ldo_k_consumers_pre_r3a); + + rid[AB5500_LDO_H].consumer_supplies + = ab5500_ldo_h_consumers_pre_r3a; + rid[AB5500_LDO_H].num_consumer_supplies + = ARRAY_SIZE(ab5500_ldo_h_consumers_pre_r3a); + } + + u5500_regulators_init_debug(); + + platform_device_register_data(NULL, "reg-fixed-voltage", -1, + &u5500_vio_pdata, + sizeof(u5500_vio_pdata)); + + regulator_has_full_constraints(); +} diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c index 836112eedde..25b519b5476 100644 --- a/arch/arm/mach-ux500/board-u5500-sdi.c +++ b/arch/arm/mach-ux500/board-u5500-sdi.c @@ -5,34 +5,28 @@ * License terms: GNU General Public License (GPL) version 2 */ +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/amba/bus.h> #include <linux/amba/mmci.h> #include <linux/mmc/host.h> +#include <linux/platform_device.h> +#include <linux/delay.h> -#include <plat/pincfg.h> -#include <plat/gpio-nomadik.h> -#include <mach/db5500-regs.h> +#include <asm/mach-types.h> #include <plat/ste_dma40.h> +#include <mach/devices.h> +#include <mach/hardware.h> +#include <mach/ste-dma40-db5500.h> -#include "pins-db5500.h" #include "devices-db5500.h" -#include "ste-dma40-db5500.h" - -static pin_cfg_t u5500_sdi_pins[] = { - /* SDI0 (POP eMMC) */ - GPIO5_MC0_DAT0 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO6_MC0_DAT1 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO7_MC0_DAT2 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO8_MC0_DAT3 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO9_MC0_DAT4 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO10_MC0_DAT5 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO11_MC0_DAT6 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO12_MC0_DAT7 | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO13_MC0_CMD | PIN_DIR_INPUT | PIN_PULL_UP, - GPIO14_MC0_CLK | PIN_DIR_OUTPUT | PIN_VAL_LOW, -}; +#include "board-u5500.h" +/* + * SDI 0 (eMMC) + */ #ifdef CONFIG_STE_DMA40 -struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = { +static struct stedma40_chan_cfg sdi0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, .src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX, @@ -41,7 +35,7 @@ struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = { .dst_info.data_width = STEDMA40_WORD_WIDTH, }; -static struct stedma40_chan_cfg u5500_sdi0_dma_cfg_tx = { +static struct stedma40_chan_cfg sdi0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_MEM_TO_PERIPH, .src_dev_type = STEDMA40_DEV_SRC_MEMORY, @@ -57,18 +51,206 @@ static struct mmci_platform_data u5500_sdi0_data = { .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED, + .capabilities2 = MMC_CAP2_NO_SLEEP_CMD, .gpio_cd = -1, .gpio_wp = -1, #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, - .dma_rx_param = &u5500_sdi0_dma_cfg_rx, - .dma_tx_param = &u5500_sdi0_dma_cfg_tx, + .dma_rx_param = &sdi0_dma_cfg_rx, + .dma_tx_param = &sdi0_dma_cfg_tx, +#endif +}; + +/* + * SDI 1 (MicroSD slot) + */ + +static int u5500_sdi1_ios_handler(struct device *dev, struct mmc_ios *ios) +{ + static int power_mode = -1; + + if (power_mode == ios->power_mode) + return 0; + + switch (ios->power_mode) { + case MMC_POWER_UP: + break; + case MMC_POWER_ON: + /* + * Level shifter voltage should depend on vdd to when deciding + * on either 1.8V or 2.9V. Once the decision has been made the + * level shifter must be disabled and re-enabled with a changed + * select signal in order to switch the voltage. Since there is + * no framework support yet for indicating 1.8V in vdd, use the + * default 2.9V. + */ + gpio_set_value_cansleep(GPIO_MMC_CARD_CTRL, 1); + udelay(100); + break; + case MMC_POWER_OFF: + gpio_set_value_cansleep(GPIO_MMC_CARD_CTRL, 0); + break; + } + + power_mode = ios->power_mode; + return 0; +} + +#ifdef CONFIG_STE_DMA40 +static struct stedma40_chan_cfg sdi1_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB5500_DMA_DEV34_SDMMC1_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg sdi1_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV34_SDMMC1_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; +#endif + +static struct mmci_platform_data u5500_sdi1_data = { + .ios_handler = u5500_sdi1_ios_handler, + .ocr_mask = MMC_VDD_29_30, + .f_max = 50000000, + .capabilities = MMC_CAP_4_BIT_DATA | + MMC_CAP_SD_HIGHSPEED | + MMC_CAP_MMC_HIGHSPEED, + .gpio_cd = GPIO_SDMMC_CD, + .gpio_wp = -1, + .cd_invert = true, +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &sdi1_dma_cfg_rx, + .dma_tx_param = &sdi1_dma_cfg_tx, #endif }; +/* + * SDI2 (EMMC2) + */ + +static struct stedma40_chan_cfg sdi2_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB5500_DMA_DEV26_SDMMC2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg sdi2_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV26_SDMMC2_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct mmci_platform_data u5500_sdi2_data = { + .ocr_mask = MMC_VDD_165_195, + .f_max = 50000000, + .capabilities = MMC_CAP_4_BIT_DATA | + MMC_CAP_8_BIT_DATA | + MMC_CAP_MMC_HIGHSPEED, + .capabilities2 = MMC_CAP2_NO_SLEEP_CMD, + .gpio_cd = -1, + .gpio_wp = -1, +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &sdi2_dma_cfg_rx, + .dma_tx_param = &sdi2_dma_cfg_tx, +#endif +}; + +/* + * SDI 3 (SDIO WLAN) + */ +#ifdef SDIO_DMA_ON +#ifdef CONFIG_STE_DMA40 +static struct stedma40_chan_cfg sdi3_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB5500_DMA_DEV27_SDMMC3_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg sdi3_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV27_SDMMC3_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; +#endif +#endif + +static struct mmci_platform_data u5500_sdi3_data = { + .ocr_mask = MMC_VDD_29_30, + .f_max = 50000000, + .capabilities = MMC_CAP_4_BIT_DATA, + .gpio_cd = -1, + .gpio_wp = -1, +#ifdef SDIO_DMA_ON +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &sdi3_dma_cfg_rx, + .dma_tx_param = &sdi3_dma_cfg_tx, +#endif +#endif +}; + +static void sdi1_configure(void) +{ + int pin[2]; + int ret; + + /* Level-shifter GPIOs */ + pin[0] = GPIO_MMC_CARD_CTRL; + pin[1] = GPIO_MMC_CARD_VSEL; + + ret = gpio_request(pin[0], "MMC_CARD_CTRL"); + if (!ret) + ret = gpio_request(pin[1], "MMC_CARD_VSEL"); + + if (ret) { + pr_warning("unable to config sdi0 gpios for level shifter.\n"); + return; + } + /* Select the default 2.9V and eanble level shifter */ + gpio_direction_output(pin[0], 1); + gpio_direction_output(pin[1], 0); +} + void __init u5500_sdi_init(struct device *parent) { - nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins)); + u32 periphid = 0x10480180; + + /* + * Fix me in 5500 v2.1 + * Dynamic detection of booting device by reading + * ROM debug register from BACKUP RAM and register the + * corresponding EMMC. + * This is done due to wrong configuration of MMC0 clock + * in ROM code for u5500 v2. + */ + if (u5500_get_boot_mmc() == 2) + db5500_add_sdi2(parent, &u5500_sdi2_data, periphid); + else + db5500_add_sdi0(parent, &u5500_sdi0_data, periphid); - db5500_add_sdi0(parent, &u5500_sdi0_data); + sdi1_configure(); + db5500_add_sdi1(parent, &u5500_sdi1_data, periphid); + db5500_add_sdi3(parent, &u5500_sdi3_data, periphid); } diff --git a/arch/arm/mach-ux500/board-u5500-wlan.c b/arch/arm/mach-ux500/board-u5500-wlan.c new file mode 100644 index 00000000000..fd64089108a --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-wlan.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> + *Author: Bartosz Markowski <bartosz.markowski@tieto.com> for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <asm/mach-types.h> +#include <mach/irqs.h> +#include "pins.h" +#include <mach/cw1200_plat.h> + + +static void cw1200_release(struct device *dev); +static int cw1200_prcmu_ctrl(const struct cw1200_platform_data *pdata, + bool enable); + +static struct resource cw1200_u5500_resources[] = { + { + .start = NOMADIK_GPIO_TO_IRQ(129), + .end = NOMADIK_GPIO_TO_IRQ(129), + .flags = IORESOURCE_IRQ, + .name = "cw1200_irq", + }, +}; + +static struct cw1200_platform_data cw1200_u5500_platform_data = { + .prcmu_ctrl = cw1200_prcmu_ctrl, +}; + +static struct platform_device cw1200_device = { + .name = "cw1200_wlan", + .dev = { + .platform_data = &cw1200_u5500_platform_data, + .release = cw1200_release, + .init_name = "cw1200_wlan", + }, +}; + +const struct cw1200_platform_data *cw1200_u5500_get_platform_data(void) +{ + return &cw1200_u5500_platform_data; +} +EXPORT_SYMBOL_GPL(cw1200_u5500_get_platform_data); + +static int cw1200_prcmu_ctrl(const struct cw1200_platform_data *pdata, + bool enable) +{ + int ret; + + if (enable) + ret = prcmu_resetout(2, 1); + else + ret = prcmu_resetout(2, 0); + + return ret; +} + +int __init u5500_wlan_init(void) +{ + if (machine_is_u5500()) { + cw1200_device.num_resources = ARRAY_SIZE(cw1200_u5500_resources); + cw1200_device.resource = cw1200_u5500_resources; + } else { + dev_err(&cw1200_device.dev, + "Unsupported mach type %d " + "(check mach-types.h)\n", + __machine_arch_type); + return -ENOTSUPP; + } + + cw1200_u5500_platform_data.mmc_id = "mmc2"; + cw1200_u5500_platform_data.irq = &cw1200_device.resource[0]; + + cw1200_device.dev.release = cw1200_release; + + return platform_device_register(&cw1200_device); +} + +static void cw1200_release(struct device *dev) +{ + +} diff --git a/arch/arm/mach-ux500/board-u5500-wlan.h b/arch/arm/mach-ux500/board-u5500-wlan.h new file mode 100644 index 00000000000..89fd41166fd --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-wlan.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * U5500 board specific cw1200 (WLAN device) initialization. + * + * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> + * Author: Bartosz Markowski <bartosz.markowski@tieto.com> for ST-Ericsson + * + */ + +#ifndef __BOARD_U5500_WLAN_H +#define __BOARD_U5500_WLAN_H + +int u5500_wlan_init(void); + +#endif diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 0ff4be72a80..86222034890 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -1,7 +1,6 @@ /* * Copyright (C) ST-Ericsson SA 2010 * - * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson * License terms: GNU General Public License (GPL) version 2 */ @@ -9,8 +8,27 @@ #include <linux/platform_device.h> #include <linux/amba/bus.h> #include <linux/irq.h> +#include <linux/gpio/nomadik.h> #include <linux/i2c.h> #include <linux/mfd/abx500/ab5500.h> +#include <linux/ab5500-vibra.h> +#include <linux/amba/pl022.h> +#include <linux/delay.h> +#include <linux/led-lm3530.h> +#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h> +#include <linux/input/matrix_keypad.h> +#ifdef CONFIG_SENSORS_LSM303DLH +#include <linux/lsm303dlh.h> +#endif +#include <linux/leds-ab5500.h> +#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI +#include <linux/cyttsp.h> +#endif +#include <linux/input/abx500-accdet.h> + +#ifdef CONFIG_AV8100 +#include <video/av8100.h> +#endif #include <asm/hardware/gic.h> #include <asm/mach/arch.h> @@ -18,36 +36,141 @@ #include <plat/pincfg.h> #include <plat/i2c.h> -#include <plat/gpio-nomadik.h> #include <mach/hardware.h> +#include <mach/ste-dma40-db5500.h> +#ifdef CONFIG_UX500_SOC_DBX500 +#include <mach/msp.h> +#endif #include <mach/devices.h> #include <mach/setup.h> +#include <mach/db5500-keypad.h> +#include <mach/crypto-ux500.h> +#include <mach/usb.h> #include "pins-db5500.h" +#include "pins.h" #include "devices-db5500.h" -#include <linux/led-lm3530.h> +#include "board-u5500.h" +#include "board-u5500-bm.h" +#include "board-u5500-wlan.h" +#include "board-ux500-usb.h" +#ifdef CONFIG_SENSORS_LSM303DLH /* - * GPIO + * LSM303DLH */ -static pin_cfg_t u5500_pins[] = { - /* I2C */ - GPIO218_I2C2_SCL | PIN_INPUT_PULLUP, - GPIO219_I2C2_SDA | PIN_INPUT_PULLUP, +static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata = { + .name_a = "lsm303dlh.0", + .name_m = "lsm303dlh.1", + .axis_map_x = 1, + .axis_map_y = 0, + .axis_map_z = 2, +/* display is mounted reverse in the hardware */ + .negative_x = 1, + .negative_y = 1, + .negative_z = 1, +}; +#endif - /* DISPLAY_ENABLE */ - GPIO226_GPIO | PIN_OUTPUT_LOW, +/* + * Touchscreen + */ +static struct synaptics_rmi4_platform_data rmi4_i2c_platformdata = { + .irq_number = NOMADIK_GPIO_TO_IRQ(179), + .irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED), + .x_flip = false, + .y_flip = true, + .regulator_en = true, +}; - /* Backlight Enbale */ - GPIO224_GPIO | PIN_OUTPUT_HIGH, +static struct av8100_platform_data av8100_plat_data = { + .irq = NOMADIK_GPIO_TO_IRQ(223), + .reset = 225, + .alt_powerupseq = true, + .mclk_freq = 1, /* MCLK_RNG_22_27 */ }; + +/* + * leds LM3530 + */ +static struct lm3530_platform_data u5500_als_platform_data = { + .mode = LM3530_BL_MODE_MANUAL, + .als_input_mode = LM3530_INPUT_ALS1, + .max_current = LM3530_FS_CURR_26mA, + .pwm_pol_hi = true, + .als_avrg_time = LM3530_ALS_AVRG_TIME_4096ms, + .brt_ramp_law = 1, /* Linear */ + .brt_ramp_fall = LM3530_RAMP_TIME_260ms, + .brt_ramp_rise = LM3530_RAMP_TIME_260ms, + .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm, + .als2_resistor_sel = LM3530_ALS_IMPD_Z, + .als_vmin = 730, /* mV */ + .als_vmax = 1020, /* mV */ + .brt_val = 0x7F, /* Max brightness */ + .hw_en_gpio = LM3530_BL_ENABLE_GPIO, +}; + + +/* leds-ab5500 */ +static struct ab5500_hvleds_platform_data ab5500_hvleds_data = { + .hw_fade = false, + .leds = { + [0] = { + .name = "red", + .led_on = true, + .led_id = 0, + .fade_hi = 255, + .fade_lo = 0, + .max_current = 10, /* wrong value may damage h/w */ + }, + [1] = { + .name = "green", + .led_on = true, + .led_id = 1, + .fade_hi = 255, + .fade_lo = 0, + .max_current = 10, /* wrong value may damage h/w */ + }, + [2] { + .name = "blue", + .led_on = true, + .led_id = 2, + .fade_hi = 255, + .fade_lo = 0, + .max_current = 10, /* wrong value may damage h/w */ + }, + }, +}; + +static struct ab5500_ponkey_platform_data ab5500_ponkey_data = { + /* + * Shutdown time in secs. Can be set + * to 10sec, 5sec and 0sec(disabled) + */ + .shutdown_secs = 10, +}; + +/* ab5500-vibra */ +static struct ab5500_vibra_platform_data ab5500_vibra_data = { + .type = AB5500_VIB_ROTARY, + .voltage = AB5500_VIB_VOLT_MIN, + /* + * EOL voltage in millivolts. By default, it is + * disabled. Set threshold volatge to enable. + */ + .eol_voltage = 0, + .res_freq = AB5500_VIB_RFREQ_150HZ, + .magnitude = 0x7F, + .pulse = AB5500_VIB_PULSE_130ms, +}; + /* * I2C */ -#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ +#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm) \ static struct nmk_i2c_controller u5500_i2c##id##_data = { \ /* \ * slave data setup time, which is \ @@ -62,31 +185,35 @@ static struct nmk_i2c_controller u5500_i2c##id##_data = { \ .rft = _rft, \ /* std. mode operation */ \ .clk_freq = clk, \ + /* Slave response timeout(ms) */\ + .timeout = t_out, \ .sm = _sm, \ } + /* - * The board uses TODO <3> i2c controllers, initialize all of + * The board uses 3 i2c controllers, initialize all of * them with slave data setup time of 250 ns, * Tx & Rx FIFO threshold values as 1 and standard * mode of operation */ -U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST); +U5500_I2C_CONTROLLER(1, 0xe, 1, 10, 400000, 200, I2C_FREQ_MODE_FAST); +U5500_I2C_CONTROLLER(2, 0xe, 1, 10, 400000, 200, I2C_FREQ_MODE_FAST); +U5500_I2C_CONTROLLER(3, 0xe, 1, 10, 400000, 200, I2C_FREQ_MODE_FAST); -static struct lm3530_platform_data u5500_als_platform_data = { - .mode = LM3530_BL_MODE_MANUAL, - .als_input_mode = LM3530_INPUT_ALS1, - .max_current = LM3530_FS_CURR_26mA, - .pwm_pol_hi = true, - .als_avrg_time = LM3530_ALS_AVRG_TIME_512ms, - .brt_ramp_law = 1, /* Linear */ - .brt_ramp_fall = LM3530_RAMP_TIME_8s, - .brt_ramp_rise = LM3530_RAMP_TIME_8s, - .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm, - .als2_resistor_sel = LM3530_ALS_IMPD_Z, - .als_vmin = 730, /* mV */ - .als_vmax = 1020, /* mV */ - .brt_val = 0x7F, /* Max brightness */ +static struct i2c_board_info __initdata u5500_i2c2_sensor_devices[] = { +#ifdef CONFIG_SENSORS_LSM303DLH + { + /* LSM303DLHC Accelerometer */ + I2C_BOARD_INFO("lsm303dlhc_a", 0x19), + .platform_data = &lsm303dlh_pdata, + }, + { + /* LSM303DLH Magnetometer */ + I2C_BOARD_INFO("lsm303dlh_m", 0x1E), + .platform_data = &lsm303dlh_pdata, + }, +#endif }; static struct i2c_board_info __initdata u5500_i2c2_devices[] = { @@ -95,43 +222,561 @@ static struct i2c_board_info __initdata u5500_i2c2_devices[] = { I2C_BOARD_INFO("lm3530-led", 0x36), .platform_data = &u5500_als_platform_data, }, + { + I2C_BOARD_INFO("av8100", 0x70), + .platform_data = &av8100_plat_data, + }, }; -static void __init u5500_i2c_init(struct device *parent) +/* + * Keypad + */ + +#define ROW_PIN_I0 128 +#define ROW_PIN_I1 130 +#define ROW_PIN_I2 132 +#define ROW_PIN_I3 134 +#define COL_PIN_O4 137 +#define COL_PIN_O5 139 + +static int db5500_kp_rows[] = { + ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, +}; + +static int db5500_kp_cols[] = { + COL_PIN_O4, COL_PIN_O5, +}; + +static bool db5500_config; +static int db5500_set_gpio_row(int gpio) { - db5500_add_i2c2(parent, &u5500_i2c2_data); - i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); + int ret = -1; + + + if (!db5500_config) { + ret = gpio_request(gpio, "db5500_kpd"); + if (ret < 0) { + pr_err("db5500_set_gpio_row: gpio request failed\n"); + return ret; + } + } + + ret = gpio_direction_output(gpio, 1); + if (ret < 0) { + pr_err("db5500_set_gpio_row: gpio direction failed\n"); + gpio_free(gpio); + } + + return ret; } +static int db5500_kp_init(void) +{ + struct ux500_pins *pins; + int ret, i; + + pins = ux500_pins_get("db5500_kp"); + if (pins) + ux500_pins_enable(pins); + + for (i = 0; i < ARRAY_SIZE(db5500_kp_rows); i++) { + ret = db5500_set_gpio_row(db5500_kp_rows[i]); + if (ret < 0) { + pr_err("db5500_kp_init: failed init\n"); + return ret; + } + } + + if (!db5500_config) + db5500_config = true; + + return 0; +} + +static int db5500_kp_exit(void) +{ + struct ux500_pins *pins; + + pins = ux500_pins_get("db5500_kp"); + if (pins) + ux500_pins_disable(pins); + + return 0; +} + +static const unsigned int u5500_keymap[] = { + KEY(4, 0, KEY_CAMERA), /* Camera2 */ + KEY(4, 1, KEY_CAMERA_FOCUS), /* Camera1 */ + KEY(4, 2, KEY_MENU), + KEY(4, 3, KEY_BACK), + KEY(5, 2, KEY_SEND), + KEY(5, 3, KEY_HOME), +#ifndef CONFIG_INPUT_AB8500_PONKEY + /* AB5500 ONSWa is also hooked up to this key */ + KEY(8, 0, KEY_END), +#endif + KEY(8, 1, KEY_VOLUMEUP), + KEY(8, 2, KEY_VOLUMEDOWN), +}; + +static struct matrix_keymap_data u5500_keymap_data = { + .keymap = u5500_keymap, + .keymap_size = ARRAY_SIZE(u5500_keymap), +}; + +static struct db5500_keypad_platform_data u5500_keypad_board = { + .init = db5500_kp_init, + .exit = db5500_kp_exit, + .gpio_input_pins = db5500_kp_rows, + .gpio_output_pins = db5500_kp_cols, + .keymap_data = &u5500_keymap_data, + .no_autorepeat = true, + .krow = ARRAY_SIZE(db5500_kp_rows), + .kcol = ARRAY_SIZE(db5500_kp_cols), + .debounce_ms = 40, /* milliseconds */ + .switch_delay = 200, /* in jiffies */ +}; + +#ifdef CONFIG_UX500_SOC_DBX500 +/* + * MSP + */ + +#define MSP_DMA(num, eventline) \ +static struct stedma40_chan_cfg msp##num##_dma_rx = { \ + .high_priority = true, \ + .dir = STEDMA40_PERIPH_TO_MEM, \ + .src_dev_type = eventline##_RX, \ + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \ + .src_info.psize = STEDMA40_PSIZE_LOG_4, \ + .dst_info.psize = STEDMA40_PSIZE_LOG_4, \ +}; \ + \ +static struct stedma40_chan_cfg msp##num##_dma_tx = { \ + .high_priority = true, \ + .dir = STEDMA40_MEM_TO_PERIPH, \ + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \ + .dst_dev_type = eventline##_TX, \ + .src_info.psize = STEDMA40_PSIZE_LOG_4, \ + .dst_info.psize = STEDMA40_PSIZE_LOG_4, \ +} + +MSP_DMA(0, DB5500_DMA_DEV9_MSP0); +MSP_DMA(1, DB5500_DMA_DEV10_MSP1); +MSP_DMA(2, DB5500_DMA_DEV11_MSP2); + +static struct msp_i2s_platform_data u5500_msp0_data = { + .id = MSP_0_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp0_dma_rx, + .msp_i2s_dma_tx = &msp0_dma_tx, +}; + +static struct msp_i2s_platform_data u5500_msp1_data = { + .id = MSP_1_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp1_dma_rx, + .msp_i2s_dma_tx = &msp1_dma_tx, +}; + +static struct msp_i2s_platform_data u5500_msp2_data = { + .id = MSP_2_I2S_CONTROLLER, + .msp_i2s_dma_rx = &msp2_dma_rx, + .msp_i2s_dma_tx = &msp2_dma_tx, +}; + +static void __init u5500_msp_init(void) +{ + db5500_add_msp0_i2s(&u5500_msp0_data); + db5500_add_msp1_i2s(&u5500_msp1_data); + db5500_add_msp2_i2s(&u5500_msp2_data); +} +#else +static void __init u5500_msp_init(void) +{ +} +#endif + +/* + * SPI + */ + +static struct pl022_ssp_controller u5500_spi3_data = { + .bus_id = 1, + .num_chipselect = 4, /* 3 possible CS lines + 1 for tests */ +}; + +static void __init u5500_spi_init(void) +{ + db5500_add_spi3(&u5500_spi3_data); +} + +static struct resource ab5500_resources[] = { + [0] = { + .start = IRQ_DB5500_PRCMU_ABB, + .end = IRQ_DB5500_PRCMU_ABB, + .flags = IORESOURCE_IRQ + } +}; + + +#ifdef CONFIG_INPUT_AB5500_ACCDET +static struct abx500_accdet_platform_data ab5500_accdet_pdata = { + .btn_keycode = KEY_MEDIA, + .accdet1_dbth = ACCDET1_TH_300mV | ACCDET1_DB_10ms, + .accdet2122_th = ACCDET21_TH_300mV | ACCDET22_TH_300mV, + .is_detection_inverted = false, + }; +#endif + +static struct abx500_init_settings ab5500_init_settings[] = { + { + .bank = AB5500_BANK_SIM_USBSIM, + .reg = 0x17, + .setting = 0x0F, + }, + /* SIMOFF_N is not connected and is set to GPIO. + Set SIMOFF_N in invert mode */ + { + .bank = AB5500_BANK_SIM_USBSIM, + .reg = 0x13, + .setting = 0x4, + }, + { + .bank = AB5500_BANK_SIM_USBSIM, + .reg = 0x18, + .setting = 0x10, + }, + /* Set unused PWRCTRL0 & PWRCTRL1 as GPIOs */ + { + .bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, + .reg = 0x30, + .setting = 0x30, + }, + /* Set unused EXTBST1/CLK/SLP,RTCCLK2 as GPIOs */ + { + .bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, + .reg = 0x31, + .setting = 0x74, + }, + /* Set unused AVCTRL,EXTBST2/CLK/SLP,RTCCLK2 as GPIO */ + { + .bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, + .reg = 0x33, + .setting = 0x3C, + }, + /* Set unused EXT32CLK as GPIO */ + { + .bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, + .reg = 0x35, + .setting = 0x1, + }, + /* Set unused SIMOFF_N as GPIO */ + { + .bank = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST, + .reg = 0x31, + .setting = 0x80, + }, + /* Set unused YcBcR2 & YcBcR1 as GPIO */ + { + .bank = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST, + .reg = 0x33, + .setting = 0xC0, + }, + /* Set unused USBUICCPD/SE0/DATA, + YcBcR0,YcBcR3 as GPIO */ + { + .bank = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST, + .reg = 0x34, + .setting = 0x1F, + }, +}; + static struct ab5500_platform_data ab5500_plf_data = { .irq = { - .base = 0, - .count = 0, + .base = IRQ_AB5500_BASE, + .count = AB5500_NR_IRQS, }, - .init_settings = NULL, - .init_settings_sz = 0, - .pm_power_off = false, + .pm_power_off = true, + .regulator = &u5500_ab5500_regulator_data, +#ifdef CONFIG_INPUT_AB5500_ACCDET + .dev_data[AB5500_DEVID_ACCDET] = &ab5500_accdet_pdata, + .dev_data_sz[AB5500_DEVID_ACCDET] = sizeof(ab5500_accdet_pdata), +#endif + .dev_data[AB5500_DEVID_LEDS] = &ab5500_hvleds_data, + .dev_data_sz[AB5500_DEVID_LEDS] = sizeof(ab5500_hvleds_data), + .dev_data[AB5500_DEVID_VIBRATOR] = &ab5500_vibra_data, + .dev_data_sz[AB5500_DEVID_VIBRATOR] = sizeof(ab5500_vibra_data), + .init_settings = &ab5500_init_settings, + .init_settings_sz = ARRAY_SIZE(ab5500_init_settings), +#if defined(CONFIG_AB5500_BM) + .dev_data[AB5500_DEVID_CHARGALG] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_CHARGALG] = sizeof(abx500_bm_pt_data), + .dev_data[AB5500_DEVID_CHARGER] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_CHARGER] = sizeof(abx500_bm_pt_data), + .dev_data[AB5500_DEVID_FG] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_FG] = sizeof(abx500_bm_pt_data), + .dev_data[AB5500_DEVID_BTEMP] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_BTEMP] = sizeof(abx500_bm_pt_data), +#endif + .dev_data[AB5500_DEVID_ONSWA] = &ab5500_ponkey_data, + .dev_data_sz[AB5500_DEVID_ONSWA] = sizeof(ab5500_ponkey_data), + .dev_data[AB5500_DEVID_USB] = &abx500_usbgpio_plat_data, + .dev_data_sz[AB5500_DEVID_USB] = sizeof(abx500_usbgpio_plat_data), }; -static struct platform_device ab5500_device = { +static struct platform_device u5500_ab5500_device = { .name = "ab5500-core", .id = 0, .dev = { .platform_data = &ab5500_plf_data, }, + .num_resources = 1, + .resource = ab5500_resources, +}; + +static struct platform_device u5500_mloader_device = { + .name = "db5500_mloader", + .id = -1, .num_resources = 0, }; +static struct cryp_platform_data u5500_cryp1_platform_data = { + .mem_to_engine = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV48_CRYPTO1_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, + .mode = STEDMA40_MODE_LOGICAL, + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + }, + .engine_to_mem = { + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB5500_DMA_DEV48_CRYPTO1_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, + .mode = STEDMA40_MODE_LOGICAL, + .src_info.psize = STEDMA40_PSIZE_LOG_4, + .dst_info.psize = STEDMA40_PSIZE_LOG_4, + } +}; + +static struct stedma40_chan_cfg u5500_hash_dma_cfg_tx = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV50_HASH1_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, + .mode = STEDMA40_MODE_LOGICAL, + .src_info.psize = STEDMA40_PSIZE_LOG_16, + .dst_info.psize = STEDMA40_PSIZE_LOG_16, +}; + +static struct hash_platform_data u5500_hash1_platform_data = { + .mem_to_engine = &u5500_hash_dma_cfg_tx, + .dma_filter = stedma40_filter, +}; + +/* modem crash dump detection driver data */ +static struct resource mcdd_resources[] = { + { + .name = "mcdd_intreset_addr", + .start = U5500_INTCON_MBOX1_INT_RESET_ADDR, + .end = U5500_INTCON_MBOX1_INT_RESET_ADDR, + .flags = IORESOURCE_MEM, + }, + { + .name = "mcdd_mbox_irq", + .start = MBOX_PAIR1_VIRT_IRQ, + .end = MBOX_PAIR1_VIRT_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device u5500_mcdd_device = { + .name = "u5500-mcdd-modem", + .id = 0, + .resource = mcdd_resources, + .num_resources = ARRAY_SIZE(mcdd_resources), +}; + static struct platform_device *u5500_platform_devices[] __initdata = { - &ab5500_device, + &u5500_ab5500_device, +#ifdef CONFIG_FB_MCDE + &u5500_mcde_device, +#endif + &ux500_hwmem_device, + &u5500_b2r2_device, + &u5500_b2r2_blt_device, + &u5500_mloader_device, +#ifdef CONFIG_U5500_MMIO + &u5500_mmio_device, +#endif + &u5500_thsens_device, + &u5500_mcdd_device, +}; + +#define BACKUPRAM_ROM_DEBUG_ADDR 0xFFC +#define MMC_BLOCK_ID 0x20 + +int u5500_get_boot_mmc(void) +{ + unsigned int mmcblk; + + mmcblk = readl(__io_address(U5500_BACKUPRAM1_BASE) + + BACKUPRAM_ROM_DEBUG_ADDR); + + if (mmcblk & MMC_BLOCK_ID) + return 2; + + return 0; +} + +/* + * R3A (and presumably, future) S5500 boards have different regulator + * assignments from the earlier boards. Since there's no clean way to identify + * the board revision from hardware, we use the fact that R2A boots from MMC0 + * (via peripheral boot) and R3A boots from MMC2 to distinguish them. + */ +bool u5500_board_is_pre_r3a(void) +{ + if (!cpu_is_u5500v20()) + return false; + + if (!u5500_board_is_s5500()) + return true; + + if (u5500_get_boot_mmc() == 2) + return false; + + return true; +} + + +/* + * This function check whether it is Small S5500 board + * GPIO0 is HIGH for S5500 + */ +bool u5500_board_is_s5500(void) +{ + static bool s5500; + static bool once; + int err, val; + + if (once) + return s5500; + + err = gpio_request(GPIO_BOARD_VERSION, "Board Version"); + if (err) { + pr_err("Error %d while requesting GPIO for Board Version\n", + err); + return err; + } + + err = gpio_direction_input(GPIO_BOARD_VERSION); + if (err) { + pr_err("Error %d while setting GPIO for Board Version" + "output mode\n", err); + return err; + } + + val = gpio_get_value(GPIO_BOARD_VERSION); + + gpio_free(GPIO_BOARD_VERSION); + + s5500 = val; + once = true; + + return val; +} + +static long u5500_panic_blink(int state) +{ + gpio_direction_output(GPIO_SW_CRASH_INDICATOR, state); + return 0; +} + +#define PRCC_K_SOFTRST_SET 0x18 +#define PRCC_K_SOFTRST_CLEAR 0x1C +/* pl011 reset */ +static void ux500_uart3_reset(void) +{ + void __iomem *prcc_rst_set, *prcc_rst_clr; + + prcc_rst_set = __io_address(U5500_CLKRST5_BASE + + PRCC_K_SOFTRST_SET); + prcc_rst_clr = __io_address(U5500_CLKRST5_BASE + + PRCC_K_SOFTRST_CLEAR); + + /* + * Activate soft reset PRCC_K_SOFTRST_CLEAR + * + * As we are dealing with IP register lockup + * so to make double sure that IP gets reset + * and reset pulse remains for more than one + * clock cycle a delay is added. + */ + writel((readl(prcc_rst_clr) | 0x08), prcc_rst_clr); + udelay(1); + + /* Release soft reset PRCC_K_SOFTRST_SET */ + writel((readl(prcc_rst_set) | 0x08), prcc_rst_set); + udelay(1); +} + +static struct amba_pl011_data uart3_plat = { + .reset = ux500_uart3_reset, }; +static void __init u5500_i2c_init(struct device *parent) +{ + db5500_add_i2c1(pareent, &u5500_i2c1_data); + db5500_add_i2c2(pareent, &u5500_i2c2_data); + db5500_add_i2c3(pareent, &u5500_i2c3_data); + + i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); + i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_sensor_devices)); +} + static void __init u5500_uart_init(struct device *parent) { db5500_add_uart0(parent, NULL); db5500_add_uart1(parent, NULL); db5500_add_uart2(parent, NULL); + db5500_add_uart3(parent, &uart3_plat); +} + +static void __init u5500_cryp1_hash1_init(void) +{ + db5500_add_cryp1(&u5500_cryp1_platform_data); + db5500_add_hash1(&u5500_hash1_platform_data); +} + +static int __init u5500_accel_sensor_init(void) +{ + int status; + union i2c_smbus_data data; + struct i2c_adapter *i2c2; + + i2c2 = i2c_get_adapter(2); + if (!i2c2) { + pr_err("failed to get i2c adapter\n"); + return -ENODEV; + } + status = i2c_smbus_xfer(i2c2, 0x19 , 0, + I2C_SMBUS_READ, 0x0F , + I2C_SMBUS_BYTE_DATA, &data); + if (status < 0) + lsm303dlh_pdata.chip_id = 0; + else + lsm303dlh_pdata.chip_id = data.byte; + + i2c_put_adapter(i2c2); + + return status; } +module_init(u5500_accel_sensor_init); static void __init u5500_init_machine(void) { @@ -139,17 +784,34 @@ static void __init u5500_init_machine(void) int i; parent = u5500_init_devices(); - nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); + u5500_regulators_init(); + u5500_pins_init(); u5500_i2c_init(parent); + u5500_msp_init(); + u5500_spi_init(); + u5500_sdi_init(parent); u5500_uart_init(parent); for (i = 0; i < ARRAY_SIZE(u5500_platform_devices); i++) u5500_platform_devices[i]->dev.parent = parent; + u5500_wlan_init(); + + db5500_add_keypad(&u5500_keypad_board); + u5500_cryp1_hash1_init(); + +#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI + u5500_cyttsp_init(); +#endif + platform_add_devices(u5500_platform_devices, ARRAY_SIZE(u5500_platform_devices)); + + if (!gpio_request_one(GPIO_SW_CRASH_INDICATOR, GPIOF_OUT_INIT_LOW, + "SW_CRASH_INDICATOR")) + panic_blink = u5500_panic_blink; } MACHINE_START(U5500, "ST-Ericsson U5500 Platform") @@ -159,4 +821,14 @@ MACHINE_START(U5500, "ST-Ericsson U5500 Platform") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = u5500_init_machine, + .restart = ux500_restart, +MACHINE_END + +MACHINE_START(B5500, "ST-Ericsson U5500 Big Board") + .atag_offset = 0x00000100, + .map_io = u5500_map_io, + .init_irq = ux500_init_irq, + .timer = &ux500_timer, + .init_machine = u5500_init_machine, + .restart = ux500_restart, MACHINE_END diff --git a/arch/arm/mach-ux500/board-u5500.h b/arch/arm/mach-ux500/board-u5500.h new file mode 100644 index 00000000000..a7e4bbbc714 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __BOARD_U5500_H +#define __BOARD_U5500_H + +#define GPIO_SDMMC_CD 180 +#define GPIO_MMC_CARD_CTRL 227 +#define GPIO_MMC_CARD_VSEL 185 +#define GPIO_BOARD_VERSION 0 +#define GPIO_PRIMARY_CAM_XSHUTDOWN 1 +#define GPIO_SECONDARY_CAM_XSHUTDOWN 2 +#define GPIO_CAMERA_PMIC_EN 212 +#define GPIO_SW_CRASH_INDICATOR 214 + +#define CYPRESS_TOUCH_INT_PIN 179 +#define CYPRESS_TOUCH_RST_GPIO 135 +#define CYPRESS_SLAVE_SELECT_GPIO 186 + +#define LM3530_BL_ENABLE_GPIO 224 + +struct ab5500_regulator_platform_data; +extern struct ab5500_regulator_platform_data u5500_ab5500_regulator_data; + +extern void u5500_pins_init(void); +extern void __init u5500_regulators_init(void); +void u5500_cyttsp_init(void); +bool u5500_board_is_s5500(void); +int u5500_get_boot_mmc(void); +bool u5500_board_is_pre_r3a(void); + +#endif diff --git a/arch/arm/mach-ux500/board-ux500-usb.h b/arch/arm/mach-ux500/board-ux500-usb.h new file mode 100644 index 00000000000..6b35a181c0a --- /dev/null +++ b/arch/arm/mach-ux500/board-ux500-usb.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Saketh Ram Bommisetti <sakethram.bommisetti@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __BOARD_UX500_USB_H +#define __BOARD_UX500_USB_H + +extern struct abx500_usbgpio_platform_data abx500_usbgpio_plat_data; + +#endif diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 77a75ed0df6..7048fc71aff 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -36,9 +36,11 @@ static int __init ux500_l2x0_unlock(void) static int __init ux500_l2x0_init(void) { + uint32_t aux_val = 0x3e000000; /* 8 way associativity, force WA */ + if (cpu_is_u5500()) l2x0_base = __io_address(U5500_L2CC_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500() || cpu_is_u9540()) l2x0_base = __io_address(U8500_L2CC_BASE); else ux500_unknown_soc(); @@ -46,11 +48,18 @@ static int __init ux500_l2x0_init(void) /* Unlock before init */ ux500_l2x0_unlock(); - /* 64KB way size, 8 way associativity, force WA */ + /* u9540's L2 has 128KB way size */ + if (cpu_is_u9540()) + aux_val |= + (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); /* 128KB way size */ + else + aux_val |= + (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); /* 64KB way size */ + if (of_have_populated_dt()) - l2x0_of_init(0x3e060000, 0xc0000fff); + l2x0_of_init(aux_val, 0xc0000fff); else - l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); + l2x0_init(l2x0_base, aux_val, 0xc0000fff); /* * We can't disable l2 as we are in non secure mode, currently diff --git a/arch/arm/mach-ux500/clock-db5500.c b/arch/arm/mach-ux500/clock-db5500.c new file mode 100644 index 00000000000..aa61b1129e6 --- /dev/null +++ b/arch/arm/mach-ux500/clock-db5500.c @@ -0,0 +1,745 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * Copyright (C) 2009 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/list.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/debugfs.h> +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/gpio/nomadik.h> +#include <linux/regulator/consumer.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/dbx500-prcmu.h> + +#include <plat/pincfg.h> + +#include <mach/hardware.h> + +#include "clock.h" +#include "pins-db5500.h" + +static DEFINE_MUTEX(sysclk_mutex); +static DEFINE_MUTEX(pll_mutex); + +/* SysClk operations. */ +static int sysclk_enable(struct clk *clk) +{ + return prcmu_request_clock(PRCMU_SYSCLK, true); +} + +static void sysclk_disable(struct clk *clk) +{ + + prcmu_request_clock(PRCMU_SYSCLK, false); + return; +} + +static struct clkops sysclk_ops = { + .enable = sysclk_enable, + .disable = sysclk_disable, +}; + +static int rtc_clk_enable(struct clk *clk) +{ + return ab5500_clock_rtc_enable(clk->cg_sel, true); +} + +static void rtc_clk_disable(struct clk *clk) +{ + int ret = ab5500_clock_rtc_enable(clk->cg_sel, false); + + if (ret) + pr_err("clock: %s failed to disable: %d\n", clk->name, ret); +} + +static struct clkops rtc_clk_ops = { + .enable = rtc_clk_enable, + .disable = rtc_clk_disable, +}; + +static pin_cfg_t clkout0_pins[] = { + GPIO161_CLKOUT_0 | PIN_OUTPUT_LOW, +}; + +static pin_cfg_t clkout1_pins[] = { + GPIO162_CLKOUT_1 | PIN_OUTPUT_LOW, +}; + +static int clkout0_enable(struct clk *clk) +{ + return nmk_config_pins(clkout0_pins, ARRAY_SIZE(clkout0_pins)); +} + +static void clkout0_disable(struct clk *clk) +{ + int r; + + r = nmk_config_pins_sleep(clkout0_pins, ARRAY_SIZE(clkout0_pins)); + if (!r) + return; + + pr_err("clock: failed to disable %s.\n", clk->name); +} + +static int clkout1_enable(struct clk *clk) +{ + return nmk_config_pins(clkout1_pins, ARRAY_SIZE(clkout0_pins)); +} + +static void clkout1_disable(struct clk *clk) +{ + int r; + + r = nmk_config_pins_sleep(clkout1_pins, ARRAY_SIZE(clkout1_pins)); + if (!r) + return; + + pr_err("clock: failed to disable %s.\n", clk->name); +} + +static struct clkops clkout0_ops = { + .enable = clkout0_enable, + .disable = clkout0_disable, +}; + +static struct clkops clkout1_ops = { + .enable = clkout1_enable, + .disable = clkout1_disable, +}; + +#define PRCM_CLKOCR2 0x58C +#define PRCM_CLKOCR2_REFCLK (1 << 0) +#define PRCM_CLKOCR2_STATIC0 (1 << 2) + +static int clkout2_enable(struct clk *clk) +{ + prcmu_write(PRCM_CLKOCR2, PRCM_CLKOCR2_REFCLK); + return 0; +} + +static void clkout2_disable(struct clk *clk) +{ + prcmu_write(PRCM_CLKOCR2, PRCM_CLKOCR2_STATIC0); +} + +static struct clkops clkout2_ops = { + .enable = clkout2_enable, + .disable = clkout2_disable, +}; + +#define DEF_PER1_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U5500_CLKRST1_BASE, _cg_bit, &per1clk) +#define DEF_PER2_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U5500_CLKRST2_BASE, _cg_bit, &per2clk) +#define DEF_PER3_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U5500_CLKRST3_BASE, _cg_bit, &per3clk) +#define DEF_PER5_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U5500_CLKRST5_BASE, _cg_bit, &per5clk) +#define DEF_PER6_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U5500_CLKRST6_BASE, _cg_bit, &per6clk) + +#define DEF_PER1_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U5500_CLKRST1_BASE, _cg_bit, _parent, &per1clk) +#define DEF_PER2_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U5500_CLKRST2_BASE, _cg_bit, _parent, &per2clk) +#define DEF_PER3_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U5500_CLKRST3_BASE, _cg_bit, _parent, &per3clk) +#define DEF_PER5_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U5500_CLKRST5_BASE, _cg_bit, _parent, &per5clk) +#define DEF_PER6_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U5500_CLKRST6_BASE, _cg_bit, _parent, &per6clk) + +/* Clock sources. */ + +static struct clk soc0_pll = { + .name = "soc0_pll", + .ops = &prcmu_clk_ops, + .mutex = &pll_mutex, + .cg_sel = PRCMU_PLLSOC0, +}; + +static struct clk soc1_pll = { + .name = "soc1_pll", + .ops = &prcmu_clk_ops, + .mutex = &pll_mutex, + .cg_sel = PRCMU_PLLSOC1, +}; + +static struct clk ddr_pll = { + .name = "ddr_pll", + .ops = &prcmu_clk_ops, + .mutex = &pll_mutex, + .cg_sel = PRCMU_PLLDDR, +}; + +static struct clk sysclk = { + .name = "sysclk", + .ops = &sysclk_ops, + .rate = 26000000, + .mutex = &sysclk_mutex, +}; + +static struct clk rtc32k = { + .name = "rtc32k", + .rate = 32768, +}; + +static struct clk kbd32k = { + .name = "kbd32k", + .rate = 32768, +}; + +static struct clk clk_dummy = { + .name = "dummy", +}; + +static struct clk rtc_clk1 = { + .name = "rtc_clk1", + .ops = &rtc_clk_ops, + .cg_sel = 1, + .mutex = &sysclk_mutex, +}; + +static struct clk clkout0 = { + .name = "clkout0", + .ops = &clkout0_ops, + .parent = &sysclk, + .mutex = &sysclk_mutex, +}; + +static struct clk clkout1 = { + .name = "clkout1", + .ops = &clkout1_ops, + .parent = &sysclk, + .mutex = &sysclk_mutex, +}; + +static struct clk clkout2 = { + .name = "clkout2", + .ops = &clkout2_ops, + .parent = &sysclk, + .mutex = &sysclk_mutex, +}; + +static DEFINE_MUTEX(parented_prcmu_mutex); + +#define DEF_PRCMU_CLK_PARENT(_name, _cg_sel, _rate, _parent) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcmu_clk_ops, \ + .cg_sel = _cg_sel, \ + .rate = _rate, \ + .parent = _parent, \ + .mutex = &parented_prcmu_mutex, \ + } + +static DEFINE_MUTEX(prcmu_client_mutex); + +#define DEF_PRCMU_CLIENT_CLK(_name, _cg_sel, _rate) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcmu_clk_ops, \ + .cg_sel = _cg_sel, \ + .rate = _rate, \ + .mutex = &prcmu_client_mutex, \ + } + +static DEF_PRCMU_CLK(dmaclk, PRCMU_DMACLK, 200000000); +static DEF_PRCMU_CLK(b2r2clk, PRCMU_B2R2CLK, 200000000); +static DEF_PRCMU_CLK(sgaclk, PRCMU_SGACLK, 199900000); +static DEF_PRCMU_CLK(uartclk, PRCMU_UARTCLK, 36360000); +static DEF_PRCMU_CLK(msp02clk, PRCMU_MSP02CLK, 13000000); +static DEF_PRCMU_CLIENT_CLK(msp1clk, PRCMU_MSP1CLK, 26000000); +static DEF_PRCMU_CLIENT_CLK(cdclk, PRCMU_CDCLK, 26000000); +static DEF_PRCMU_CLK(i2cclk, PRCMU_I2CCLK, 24000000); +static DEF_PRCMU_CLK_PARENT(irdaclk, PRCMU_IRDACLK, 48000000, &soc1_pll); +static DEF_PRCMU_CLK_PARENT(irrcclk, PRCMU_IRRCCLK, 48000000, &soc1_pll); +static DEF_PRCMU_CLK(rngclk, PRCMU_RNGCLK, 26000000); +static DEF_PRCMU_CLK(pwmclk, PRCMU_PWMCLK, 26000000); +static DEF_PRCMU_CLK(sdmmcclk, PRCMU_SDMMCCLK, 50000000); +static DEF_PRCMU_CLK(spare1clk, PRCMU_SPARE1CLK, 50000000); +static DEF_PRCMU_CLK(per1clk, PRCMU_PER1CLK, 133330000); +static DEF_PRCMU_CLK(per2clk, PRCMU_PER2CLK, 133330000); +static DEF_PRCMU_CLK(per3clk, PRCMU_PER3CLK, 133330000); +static DEF_PRCMU_CLK(per5clk, PRCMU_PER5CLK, 133330000); +static DEF_PRCMU_CLK(per6clk, PRCMU_PER6CLK, 133330000); +static DEF_PRCMU_CLK(hdmiclk, PRCMU_HDMICLK, 26000000); +static DEF_PRCMU_CLK(apeatclk, PRCMU_APEATCLK, 200000000); +static DEF_PRCMU_CLK(apetraceclk, PRCMU_APETRACECLK, 266000000); +static DEF_PRCMU_CLK(mcdeclk, PRCMU_MCDECLK, 160000000); +static DEF_PRCMU_CLK(tvclk, PRCMU_TVCLK, 40000000); +static DEF_PRCMU_CLK(dsialtclk, PRCMU_DSIALTCLK, 400000000); +static DEF_PRCMU_CLK(timclk, PRCMU_TIMCLK, 3250000); +static DEF_PRCMU_CLK_PARENT(svaclk, PRCMU_SVACLK, 156000000, &soc1_pll); +static DEF_PRCMU_CLK(siaclk, PRCMU_SIACLK, 133330000); + +/* PRCC PClocks */ + +static DEF_PER1_PCLK(0, p1_pclk0); +static DEF_PER1_PCLK(1, p1_pclk1); +static DEF_PER1_PCLK(2, p1_pclk2); +static DEF_PER1_PCLK(3, p1_pclk3); +static DEF_PER1_PCLK(4, p1_pclk4); +static DEF_PER1_PCLK(5, p1_pclk5); +static DEF_PER1_PCLK(6, p1_pclk6); + +static DEF_PER2_PCLK(0, p2_pclk0); +static DEF_PER2_PCLK(1, p2_pclk1); + +static DEF_PER3_PCLK(0, p3_pclk0); +static DEF_PER3_PCLK(1, p3_pclk1); +static DEF_PER3_PCLK(2, p3_pclk2); + +static DEF_PER5_PCLK(0, p5_pclk0); +static DEF_PER5_PCLK(1, p5_pclk1); +static DEF_PER5_PCLK(2, p5_pclk2); +static DEF_PER5_PCLK(3, p5_pclk3); +static DEF_PER5_PCLK(4, p5_pclk4); +static DEF_PER5_PCLK(5, p5_pclk5); +static DEF_PER5_PCLK(6, p5_pclk6); +static DEF_PER5_PCLK(7, p5_pclk7); +static DEF_PER5_PCLK(8, p5_pclk8); +static DEF_PER5_PCLK(9, p5_pclk9); +static DEF_PER5_PCLK(10, p5_pclk10); +static DEF_PER5_PCLK(11, p5_pclk11); +static DEF_PER5_PCLK(12, p5_pclk12); +static DEF_PER5_PCLK(13, p5_pclk13); +static DEF_PER5_PCLK(14, p5_pclk14); +static DEF_PER5_PCLK(15, p5_pclk15); + +static DEF_PER6_PCLK(0, p6_pclk0); +static DEF_PER6_PCLK(1, p6_pclk1); +static DEF_PER6_PCLK(2, p6_pclk2); +static DEF_PER6_PCLK(3, p6_pclk3); +static DEF_PER6_PCLK(4, p6_pclk4); +static DEF_PER6_PCLK(5, p6_pclk5); +static DEF_PER6_PCLK(6, p6_pclk6); +static DEF_PER6_PCLK(7, p6_pclk7); + +/* MSP0 */ +static DEF_PER1_KCLK(0, p1_msp0_kclk, &msp02clk); +static DEF_PER_CLK(p1_msp0_clk, &p1_pclk0, &p1_msp0_kclk); + +/* SDI0 */ +static DEF_PER1_KCLK(1, p1_sdi0_kclk, &spare1clk); /* &sdmmcclk on v1 */ +static DEF_PER_CLK(p1_sdi0_clk, &p1_pclk1, &p1_sdi0_kclk); + +/* SDI2 */ +static DEF_PER1_KCLK(2, p1_sdi2_kclk, &sdmmcclk); +static DEF_PER_CLK(p1_sdi2_clk, &p1_pclk2, &p1_sdi2_kclk); + +/* UART0 */ +static DEF_PER1_KCLK(3, p1_uart0_kclk, &uartclk); +static DEF_PER_CLK(p1_uart0_clk, &p1_pclk3, &p1_uart0_kclk); + +/* I2C1 */ +static DEF_PER1_KCLK(4, p1_i2c1_kclk, &i2cclk); +static DEF_PER_CLK(p1_i2c1_clk, &p1_pclk4, &p1_i2c1_kclk); + +/* PWM */ +static DEF_PER3_KCLK(0, p3_pwm_kclk, &pwmclk); +static DEF_PER_CLK(p3_pwm_clk, &p3_pclk1, &p3_pwm_kclk); + +/* KEYPAD */ +static DEF_PER3_KCLK(0, p3_keypad_kclk, &kbd32k); +static DEF_PER_CLK(p3_keypad_clk, &p3_pclk0, &p3_keypad_kclk); + +/* MSP2 */ +static DEF_PER5_KCLK(0, p5_msp2_kclk, &msp02clk); +static DEF_PER_CLK(p5_msp2_clk, &p5_pclk0, &p5_msp2_kclk); + +/* UART1 */ +static DEF_PER5_KCLK(1, p5_uart1_kclk, &uartclk); +static DEF_PER_CLK(p5_uart1_clk, &p5_pclk1, &p5_uart1_kclk); + +/* UART2 */ +static DEF_PER5_KCLK(2, p5_uart2_kclk, &uartclk); +static DEF_PER_CLK(p5_uart2_clk, &p5_pclk2, &p5_uart2_kclk); + +/* UART3 */ +static DEF_PER5_KCLK(3, p5_uart3_kclk, &uartclk); +static DEF_PER_CLK(p5_uart3_clk, &p5_pclk3, &p5_uart3_kclk); + +/* SDI1 */ +static DEF_PER5_KCLK(4, p5_sdi1_kclk, &sdmmcclk); +static DEF_PER_CLK(p5_sdi1_clk, &p5_pclk4, &p5_sdi1_kclk); + +/* SDI3 */ +static DEF_PER5_KCLK(5, p5_sdi3_kclk, &sdmmcclk); +static DEF_PER_CLK(p5_sdi3_clk, &p5_pclk5, &p5_sdi3_kclk); + +/* SDI4 */ +static DEF_PER5_KCLK(6, p5_sdi4_kclk, &sdmmcclk); +static DEF_PER_CLK(p5_sdi4_clk, &p5_pclk6, &p5_sdi4_kclk); + +/* I2C2 */ +static DEF_PER5_KCLK(7, p5_i2c2_kclk, &i2cclk); +static DEF_PER_CLK(p5_i2c2_clk, &p5_pclk7, &p5_i2c2_kclk); + +/* I2C3 */ +static DEF_PER5_KCLK(8, p5_i2c3_kclk, &i2cclk); +static DEF_PER_CLK(p5_i2c3_clk, &p5_pclk8, &p5_i2c3_kclk); + +/* IRRC */ +static DEF_PER5_KCLK(9, p5_irrc_kclk, &irrcclk); +static DEF_PER_CLK(p5_irrc_clk, &p5_pclk9, &p5_irrc_kclk); + +/* IRDA */ +static DEF_PER5_KCLK(10, p5_irda_kclk, &irdaclk); +static DEF_PER_CLK(p5_irda_clk, &p5_pclk10, &p5_irda_kclk); + +/* RNG */ +static DEF_PER6_KCLK(0, p6_rng_kclk, &rngclk); +static DEF_PER_CLK(p6_rng_clk, &p6_pclk0, &p6_rng_kclk); + +/* MTU:S */ + +/* MTU0 */ +static DEF_PER_CLK(p6_mtu0_clk, &p6_pclk6, &timclk); + +/* MTU1 */ +static DEF_PER_CLK(p6_mtu1_clk, &p6_pclk7, &timclk); + +static struct clk *db5500_dbg_clks[] __initdata = { + /* Clock sources */ + &soc0_pll, + &soc1_pll, + &ddr_pll, + &sysclk, + &rtc32k, + + /* PRCMU clocks */ + &sgaclk, + &siaclk, + &svaclk, + &uartclk, + &msp02clk, + &msp1clk, + &cdclk, + &i2cclk, + &irdaclk, + &irrcclk, + &sdmmcclk, + &spare1clk, + &per1clk, + &per2clk, + &per3clk, + &per5clk, + &per6clk, + &hdmiclk, + &apeatclk, + &apetraceclk, + &mcdeclk, + &dsialtclk, + &dmaclk, + &b2r2clk, + &tvclk, + &rngclk, + &pwmclk, + + /* PRCC clocks */ + &p1_pclk0, + &p1_pclk1, + &p1_pclk2, + &p1_pclk3, + &p1_pclk4, + &p1_pclk5, + &p1_pclk6, + + &p2_pclk0, + &p2_pclk1, + + &p3_pclk0, + &p3_pclk1, + &p3_pclk2, + + &p5_pclk0, + &p5_pclk1, + &p5_pclk2, + &p5_pclk3, + &p5_pclk4, + &p5_pclk5, + &p5_pclk6, + &p5_pclk7, + &p5_pclk8, + &p5_pclk9, + &p5_pclk10, + &p5_pclk11, + &p5_pclk12, + &p5_pclk13, + &p5_pclk14, + &p5_pclk15, + + &p6_pclk0, + &p6_pclk1, + &p6_pclk2, + &p6_pclk3, + &p6_pclk4, + &p6_pclk5, + &p6_pclk6, + &p6_pclk7, + + /* Clock sources */ + &clkout0, + &clkout1, + &clkout2, + &rtc_clk1, +}; + +static struct clk_lookup u8500_common_clock_sources[] = { + CLK_LOOKUP(soc0_pll, NULL, "soc0_pll"), + CLK_LOOKUP(soc1_pll, NULL, "soc1_pll"), + CLK_LOOKUP(ddr_pll, NULL, "ddr_pll"), + CLK_LOOKUP(sysclk, NULL, "sysclk"), + CLK_LOOKUP(rtc32k, NULL, "clk32k"), +}; + +static struct clk_lookup db5500_prcmu_clocks[] = { + CLK_LOOKUP(sgaclk, "mali", NULL), + CLK_LOOKUP(siaclk, "mmio_camera", "sia"), + CLK_LOOKUP(svaclk, "hva", NULL), + CLK_LOOKUP(uartclk, "UART", NULL), + CLK_LOOKUP(msp02clk, "MSP02", NULL), + CLK_LOOKUP(msp1clk, "ux500-msp-i2s.1", NULL), + CLK_LOOKUP(cdclk, "cable_detect.0", NULL), + CLK_LOOKUP(i2cclk, "I2C", NULL), + CLK_LOOKUP(sdmmcclk, "sdmmc", NULL), + CLK_LOOKUP(per1clk, "PERIPH1", NULL), + CLK_LOOKUP(per2clk, "PERIPH2", NULL), + CLK_LOOKUP(per3clk, "PERIPH3", NULL), + CLK_LOOKUP(per5clk, "PERIPH5", NULL), + CLK_LOOKUP(per6clk, "PERIPH6", NULL), + CLK_LOOKUP(hdmiclk, "mcde", "hdmi"), + CLK_LOOKUP(apeatclk, "apeat", NULL), + CLK_LOOKUP(apetraceclk, "apetrace", NULL), + CLK_LOOKUP(mcdeclk, "mcde", NULL), + CLK_LOOKUP(mcdeclk, "mcde", "mcde"), + CLK_LOOKUP(dmaclk, "dma40.0", NULL), + CLK_LOOKUP(b2r2clk, "b2r2", NULL), + CLK_LOOKUP(b2r2clk, "b2r2_bus", NULL), + CLK_LOOKUP(b2r2clk, "U8500-B2R2.0", NULL), + CLK_LOOKUP(tvclk, "tv", NULL), + CLK_LOOKUP(tvclk, "mcde", "tv"), +}; + +static struct clk_lookup db5500_prcc_clocks[] = { + CLK_LOOKUP(p1_msp0_clk, "ux500-msp-i2s.0", NULL), + CLK_LOOKUP(p1_sdi0_clk, "sdi0", NULL), + CLK_LOOKUP(p1_sdi2_clk, "sdi2", NULL), + CLK_LOOKUP(p1_uart0_clk, "uart0", NULL), + CLK_LOOKUP(p1_i2c1_clk, "nmk-i2c.1", NULL), + CLK_LOOKUP(p1_pclk5, "gpio.0", NULL), + CLK_LOOKUP(p1_pclk5, "gpio.1", NULL), + CLK_LOOKUP(p1_pclk6, "fsmc", NULL), + + CLK_LOOKUP(p2_pclk0, "musb-ux500.0", "usb"), + CLK_LOOKUP(p2_pclk1, "gpio.2", NULL), + + CLK_LOOKUP(p3_keypad_clk, "db5500-keypad", NULL), + CLK_LOOKUP(p3_pwm_clk, "pwm", NULL), + CLK_LOOKUP(p3_pclk2, "gpio.4", NULL), + + CLK_LOOKUP(p5_msp2_clk, "ux500-msp-i2s.2", NULL), + CLK_LOOKUP(p5_uart1_clk, "uart1", NULL), + CLK_LOOKUP(p5_uart2_clk, "uart2", NULL), + CLK_LOOKUP(p5_uart3_clk, "uart3", NULL), + CLK_LOOKUP(p5_sdi1_clk, "sdi1", NULL), + CLK_LOOKUP(p5_sdi3_clk, "sdi3", NULL), + CLK_LOOKUP(p5_sdi4_clk, "sdi4", NULL), + CLK_LOOKUP(p5_i2c2_clk, "nmk-i2c.2", NULL), + CLK_LOOKUP(p5_i2c3_clk, "nmk-i2c.3", NULL), + CLK_LOOKUP(p5_irrc_clk, "irrc", NULL), + CLK_LOOKUP(p5_irda_clk, "irda", NULL), + CLK_LOOKUP(p5_pclk11, "spi0", NULL), + CLK_LOOKUP(p5_pclk12, "spi1", NULL), + CLK_LOOKUP(p5_pclk13, "spi2", NULL), + CLK_LOOKUP(p5_pclk14, "spi3", NULL), + CLK_LOOKUP(p5_pclk15, "gpio.5", NULL), + CLK_LOOKUP(p5_pclk15, "gpio.6", NULL), + CLK_LOOKUP(p5_pclk15, "gpio.7", NULL), + + CLK_LOOKUP(p6_rng_clk, "rng", NULL), + CLK_LOOKUP(p6_pclk1, "cryp0", NULL), + CLK_LOOKUP(p6_pclk2, "hash0", NULL), + CLK_LOOKUP(p6_pclk3, "pka", NULL), + CLK_LOOKUP(p6_pclk4, "hash1", NULL), + CLK_LOOKUP(p6_pclk1, "cryp1", NULL), + CLK_LOOKUP(p6_pclk5, "cfgreg", NULL), + CLK_LOOKUP(p6_mtu0_clk, "mtu0", NULL), + CLK_LOOKUP(p6_mtu1_clk, "mtu1", NULL), + + /* + * Dummy clock sets up the GPIOs. + */ + CLK_LOOKUP(clk_dummy, "gpio.3", NULL), + CLK_LOOKUP(rtc32k, "rtc-pl031", NULL), +}; + +static struct clk_lookup db5500_clkouts[] = { + CLK_LOOKUP(clkout1, "mmio_camera", "primary-cam"), + CLK_LOOKUP(clkout1, "mmio_camera", "secondary-cam"), + CLK_LOOKUP(clkout2, "ab5500-usb.0", "sysclk"), + CLK_LOOKUP(clkout2, "ab5500-codec.0", "sysclk"), +}; + +static struct clk_lookup u5500_clocks[] = { + CLK_LOOKUP(rtc_clk1, "cg2900-uart.0", "lpoclk"), +}; + +static const char *db5500_boot_clk[] __initdata = { + "spi0", + "spi1", + "spi2", + "spi3", + "uart0", + "uart1", + "uart2", + "uart3", + "sdi0", + "sdi1", + "sdi2", + "sdi3", + "sdi4", +}; + +static struct clk *boot_clks[ARRAY_SIZE(db5500_boot_clk)] __initdata; + +static int __init db5500_boot_clk_disable(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(db5500_boot_clk); i++) { + clk_disable(boot_clks[i]); + clk_put(boot_clks[i]); + } + + return 0; +} +late_initcall_sync(db5500_boot_clk_disable); + +static void __init db5500_boot_clk_enable(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(db5500_boot_clk); i++) { + boot_clks[i] = clk_get_sys(db5500_boot_clk[i], NULL); + BUG_ON(IS_ERR(boot_clks[i])); + clk_enable(boot_clks[i]); + } +} + +static void configure_clkouts(void) +{ + /* div parameter does not matter for sel0 REF_CLK */ + WARN_ON(prcmu_config_clkout(DB5500_CLKOUT0, + DB5500_CLKOUT_REF_CLK_SEL0, 0)); + WARN_ON(prcmu_config_clkout(DB5500_CLKOUT1, + DB5500_CLKOUT_REF_CLK_SEL0, 0)); +} + +static struct clk *db5500_clks_tobe_disabled[] __initdata = { + &siaclk, + &sgaclk, + &sdmmcclk, + &p1_pclk0, + &p1_pclk6, + &p3_keypad_clk, + &p3_pclk1, + &p5_pclk0, + &p5_pclk11, + &p5_pclk12, + &p5_pclk13, + &p5_pclk14, + &p6_pclk4, + &p6_pclk5, + &p6_pclk7, + &p5_uart1_clk, + &p5_uart2_clk, + &p5_uart3_clk, + &p5_sdi1_clk, + &p5_sdi3_clk, + &p5_sdi4_clk, + &p5_i2c3_clk, + &pwmclk, + &svaclk, + &cdclk, + &clkout2, +}; + +static int __init init_clock_states(void) +{ + int i = 0; + /* + * The following clks are shared with secure world. + * Currently this leads to a limitation where we need to + * enable them at all times. + */ + clk_enable(&p6_pclk1); + clk_enable(&p6_pclk2); + clk_enable(&p6_pclk3); + clk_enable(&p6_rng_clk); + + /* + * Disable clocks that are on at boot, but should be off. + */ + for (i = 0; i < ARRAY_SIZE(db5500_clks_tobe_disabled); i++) { + if (!clk_enable(db5500_clks_tobe_disabled[i])) + clk_disable(db5500_clks_tobe_disabled[i]); + } + return 0; +} +late_initcall(init_clock_states); + +int __init db5500_clk_init(void) +{ + if (ux500_is_svp()) { + prcmu_clk_ops.enable = NULL; + prcmu_clk_ops.disable = NULL; + prcc_pclk_ops.enable = NULL; + prcc_pclk_ops.disable = NULL; + prcc_kclk_ops.enable = NULL; + prcc_kclk_ops.disable = NULL; + } + prcmu_clk_ops.get_rate = NULL; + + clkdev_add_table(u8500_common_clock_sources, + ARRAY_SIZE(u8500_common_clock_sources)); + + clkdev_add_table(db5500_prcmu_clocks, ARRAY_SIZE(db5500_prcmu_clocks)); + clkdev_add_table(db5500_prcc_clocks, ARRAY_SIZE(db5500_prcc_clocks)); + clkdev_add_table(db5500_clkouts, ARRAY_SIZE(db5500_clkouts)); + clkdev_add_table(u5500_clocks, ARRAY_SIZE(u5500_clocks)); + + db5500_boot_clk_enable(); + + /* + * The following clks are shared with secure world. + * Currently this leads to a limitation where we need to + * enable them at all times. + */ + clk_enable(&p6_pclk1); + clk_enable(&p6_pclk2); + clk_enable(&p6_pclk3); + clk_enable(&p6_rng_clk); + + configure_clkouts(); + + return 0; +} + +int __init db5500_clk_debug_init(void) +{ + return dbx500_clk_debug_init(db5500_dbg_clks, + ARRAY_SIZE(db5500_dbg_clks)); +} diff --git a/arch/arm/mach-ux500/clock-db8500.c b/arch/arm/mach-ux500/clock-db8500.c new file mode 100644 index 00000000000..d41a22dd041 --- /dev/null +++ b/arch/arm/mach-ux500/clock-db8500.c @@ -0,0 +1,1171 @@ +/* + * Copyright (C) 2009-2011 ST-Ericsson SA + * Copyright (C) 2009 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/list.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> +#include <linux/debugfs.h> +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> +#include <linux/mfd/abx500/ab8500-sysctrl.h> +#include <linux/workqueue.h> +#include <linux/regulator/consumer.h> + +#include <plat/pincfg.h> + +#include <mach/hardware.h> +#include <linux/mfd/dbx500-prcmu.h> + +#include "clock.h" +#include "pins-db8500.h" +#include "product.h" +#include "prcc.h" + +static DEFINE_MUTEX(soc0_pll_mutex); +static DEFINE_MUTEX(soc1_pll_mutex); +static DEFINE_MUTEX(sysclk_mutex); +static DEFINE_MUTEX(ab_ulpclk_mutex); +static DEFINE_MUTEX(ab_intclk_mutex); +static DEFINE_MUTEX(clkout0_mutex); +static DEFINE_MUTEX(dsi_pll_mutex); + +static struct delayed_work sysclk_disable_work; + +/* PLL operations. */ + +static unsigned long pll_get_rate(struct clk *clk) +{ + return prcmu_clock_rate(clk->cg_sel); +} + +static struct clkops pll_ops = { + .get_rate = pll_get_rate, +}; + +/* SysClk operations. */ + +static int request_sysclk(bool enable) +{ + static int requests; + + if ((enable && (requests++ == 0)) || (!enable && (--requests == 0))) + return prcmu_request_clock(PRCMU_SYSCLK, enable); + return 0; +} + +static int sysclk_enable(struct clk *clk) +{ + static bool swat_enable; + int r; + + if (!swat_enable) { + r = ab8500_sysctrl_set(AB8500_SWATCTRL, + AB8500_SWATCTRL_SWATENABLE); + if (r) + return r; + + swat_enable = true; + } + + r = request_sysclk(true); + if (r) + return r; + + if (clk->cg_sel) { + r = ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1, (u8)clk->cg_sel); + if (r) + (void)request_sysclk(false); + } + return r; +} + +static void sysclk_disable(struct clk *clk) +{ + int r; + + if (clk->cg_sel) { + r = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + (u8)clk->cg_sel); + if (r) + goto disable_failed; + } + r = request_sysclk(false); + if (r) + goto disable_failed; + return; + +disable_failed: + pr_err("clock: failed to disable %s.\n", clk->name); +} + +static struct clkops sysclk_ops = { + .enable = sysclk_enable, + .disable = sysclk_disable, +}; + +/* AB8500 UlpClk operations */ + +static int ab_ulpclk_enable(struct clk *clk) +{ + int err; + + if (clk->regulator == NULL) { + struct regulator *reg; + + reg = regulator_get(NULL, "v-intcore"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + clk->regulator = reg; + } + err = regulator_set_optimum_mode(clk->regulator, 1500); + if (unlikely(err < 0)) + goto regulator_enable_error; + err = regulator_enable(clk->regulator); + if (unlikely(err)) + goto regulator_enable_error; + err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCONF, + AB8500_SYSULPCLKCONF_ULPCLKCONF_MASK); + if (unlikely(err)) + goto enable_error; + err = ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_ULPCLKREQ); + if (unlikely(err)) + goto enable_error; + /* Unknown/undocumented PLL locking time => wait 1 ms. */ + mdelay(1); + return 0; + +enable_error: + (void)regulator_disable(clk->regulator); +regulator_enable_error: + return err; +} + +static void ab_ulpclk_disable(struct clk *clk) +{ + int err; + + err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_ULPCLKREQ); + if (unlikely(regulator_disable(clk->regulator) || err)) + goto out_err; + + regulator_set_optimum_mode(clk->regulator, 0); + + return; + +out_err: + pr_err("clock: %s failed to disable %s.\n", __func__, clk->name); +} + +static struct clkops ab_ulpclk_ops = { + .enable = ab_ulpclk_enable, + .disable = ab_ulpclk_disable, +}; + +/* AB8500 intclk operations */ + +enum ab_intclk_parent { + AB_INTCLK_PARENT_SYSCLK, + AB_INTCLK_PARENT_ULPCLK, + AB_INTCLK_PARENTS_END, + NUM_AB_INTCLK_PARENTS +}; + +static int ab_intclk_enable(struct clk *clk) +{ + if (clk->parent == clk->parents[AB_INTCLK_PARENT_ULPCLK]) { + return ab8500_sysctrl_write(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK, + (1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT)); + } + return 0; +} + +static void ab_intclk_disable(struct clk *clk) +{ + if (clk->parent == clk->parents[AB_INTCLK_PARENT_SYSCLK]) + return; + + if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK)) { + pr_err("clock: %s failed to disable %s.\n", __func__, + clk->name); + } +} + +static int ab_intclk_set_parent(struct clk *clk, struct clk *parent) +{ + int err; + + if (!clk->enabled) + return 0; + + err = __clk_enable(parent, clk->mutex); + + if (unlikely(err)) + goto parent_enable_error; + + if (parent == clk->parents[AB_INTCLK_PARENT_ULPCLK]) { + err = ab8500_sysctrl_write(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK, + (1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT)); + } else { + err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK); + } + if (unlikely(err)) + goto config_error; + + __clk_disable(clk->parent, clk->mutex); + + return 0; + +config_error: + __clk_disable(parent, clk->mutex); +parent_enable_error: + return err; +} + +static struct clkops ab_intclk_ops = { + .enable = ab_intclk_enable, + .disable = ab_intclk_disable, + .set_parent = ab_intclk_set_parent, +}; + +/* AB8500 audio clock operations */ + +static int audioclk_enable(struct clk *clk) +{ + return ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_AUDIOCLKENA); +} + +static void audioclk_disable(struct clk *clk) +{ + if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_AUDIOCLKENA)) { + pr_err("clock: %s failed to disable %s.\n", __func__, + clk->name); + } +} + +static struct clkops audioclk_ops = { + .enable = audioclk_enable, + .disable = audioclk_disable, +}; + +/* Primary camera clock operations */ +static int clkout0_enable(struct clk *clk) +{ + int r; + + if (clk->regulator == NULL) { + struct regulator *reg; + + reg = regulator_get(NULL, "v-ape"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + clk->regulator = reg; + } + r = regulator_enable(clk->regulator); + if (r) + goto regulator_failed; + r = prcmu_config_clkout(0, PRCMU_CLKSRC_CLK38M, 4); + if (r) + goto config_failed; + r = nmk_config_pin(GPIO227_CLKOUT1, false); + if (r) + goto gpio_failed; + return r; + +gpio_failed: + (void)prcmu_config_clkout(0, PRCMU_CLKSRC_CLK38M, 0); +config_failed: + (void)regulator_disable(clk->regulator); +regulator_failed: + return r; +} + +static void clkout0_disable(struct clk *clk) +{ + int r; + + r = nmk_config_pin((GPIO227_GPIO | PIN_OUTPUT_LOW), false); + if (r) + goto disable_failed; + (void)prcmu_config_clkout(0, PRCMU_CLKSRC_CLK38M, 0); + (void)regulator_disable(clk->regulator); + return; + +disable_failed: + pr_err("clock: failed to disable %s.\n", clk->name); +} + +/* Touch screen/secondary camera clock operations. */ +static int clkout1_enable(struct clk *clk) +{ + int r; + + if (clk->regulator == NULL) { + struct regulator *reg; + + reg = regulator_get(NULL, "v-ape"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + clk->regulator = reg; + } + r = regulator_enable(clk->regulator); + if (r) + goto regulator_failed; + r = prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 4); + if (r) + goto config_failed; + r = nmk_config_pin(GPIO228_CLKOUT2, false); + if (r) + goto gpio_failed; + return r; + +gpio_failed: + (void)prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 0); +config_failed: + (void)regulator_disable(clk->regulator); +regulator_failed: + return r; +} + +static void clkout1_disable(struct clk *clk) +{ + int r; + + r = nmk_config_pin((GPIO228_GPIO | PIN_OUTPUT_LOW), false); + if (r) + goto disable_failed; + (void)prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 0); + (void)regulator_disable(clk->regulator); + return; + +disable_failed: + pr_err("clock: failed to disable %s.\n", clk->name); +} + +static struct clkops clkout0_ops = { + .enable = clkout0_enable, + .disable = clkout0_disable, +}; + +static struct clkops clkout1_ops = { + .enable = clkout1_enable, + .disable = clkout1_disable, +}; + +#define DEF_PER1_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U8500_CLKRST1_BASE, _cg_bit, &per1clk) +#define DEF_PER2_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U8500_CLKRST2_BASE, _cg_bit, &per2clk) +#define DEF_PER3_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U8500_CLKRST3_BASE, _cg_bit, &per3clk) +#define DEF_PER5_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U8500_CLKRST5_BASE, _cg_bit, &per5clk) +#define DEF_PER6_PCLK(_cg_bit, _name) \ + DEF_PRCC_PCLK(_name, U8500_CLKRST6_BASE, _cg_bit, &per6clk) + +#define DEF_PER1_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U8500_CLKRST1_BASE, _cg_bit, _parent, &per1clk) +#define DEF_PER2_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U8500_CLKRST2_BASE, _cg_bit, _parent, &per2clk) +#define DEF_PER3_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U8500_CLKRST3_BASE, _cg_bit, _parent, &per3clk) +#define DEF_PER5_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U8500_CLKRST5_BASE, _cg_bit, _parent, &per5clk) +#define DEF_PER6_KCLK(_cg_bit, _name, _parent) \ + DEF_PRCC_KCLK(_name, U8500_CLKRST6_BASE, _cg_bit, _parent, &per6clk) + +/* Clock sources. */ + +static struct clk soc0_pll = { + .name = "soc0_pll", + .ops = &prcmu_clk_ops, + .cg_sel = PRCMU_PLLSOC0, + .mutex = &soc0_pll_mutex, +}; + +static struct clk soc1_pll = { + .name = "soc1_pll", + .ops = &prcmu_clk_ops, + .cg_sel = PRCMU_PLLSOC1, + .mutex = &soc1_pll_mutex, +}; + +static struct clk ddr_pll = { + .name = "ddr_pll", + .ops = &pll_ops, + .cg_sel = PRCMU_PLLDDR, +}; + +static struct clk ulp38m4 = { + .name = "ulp38m4", + .rate = 38400000, +}; + +static struct clk sysclk = { + .name = "sysclk", + .ops = &sysclk_ops, + .rate = 38400000, + .mutex = &sysclk_mutex, +}; + +static struct clk sysclk2 = { + .name = "sysclk2", + .ops = &sysclk_ops, + .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ, + .rate = 38400000, + .mutex = &sysclk_mutex, +}; + +static struct clk sysclk3 = { + .name = "sysclk3", + .ops = &sysclk_ops, + .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ, + .rate = 38400000, + .mutex = &sysclk_mutex, +}; + +static struct clk sysclk4 = { + .name = "sysclk4", + .ops = &sysclk_ops, + .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ, + .rate = 38400000, + .mutex = &sysclk_mutex, +}; + +static struct clk rtc32k = { + .name = "rtc32k", + .rate = 32768, +}; + +static struct clk clkout0 = { + .name = "clkout0", + .ops = &clkout0_ops, + .parent = &ulp38m4, + .rate = 9600000, + .mutex = &clkout0_mutex, +}; + +static struct clk clkout1 = { + .name = "clkout1", + .ops = &clkout1_ops, + .parent = &sysclk, + .rate = 9600000, + .mutex = &sysclk_mutex, +}; + +static struct clk ab_ulpclk = { + .name = "ab_ulpclk", + .ops = &ab_ulpclk_ops, + .rate = 38400000, + .mutex = &ab_ulpclk_mutex, +}; + +static struct clk *ab_intclk_parents[NUM_AB_INTCLK_PARENTS] = { + [AB_INTCLK_PARENT_SYSCLK] = &sysclk, + [AB_INTCLK_PARENT_ULPCLK] = &ab_ulpclk, + [AB_INTCLK_PARENTS_END] = NULL, +}; + +static struct clk ab_intclk = { + .name = "ab_intclk", + .ops = &ab_intclk_ops, + .mutex = &ab_intclk_mutex, + .parent = &sysclk, + .parents = ab_intclk_parents, +}; + +static struct clk audioclk = { + .name = "audioclk", + .ops = &audioclk_ops, + .mutex = &ab_intclk_mutex, + .parent = &ab_intclk, +}; + +static DEF_PRCMU_CLK(sgaclk, PRCMU_SGACLK, 320000000); +static DEF_PRCMU_CLK(uartclk, PRCMU_UARTCLK, 38400000); +static DEF_PRCMU_CLK(msp02clk, PRCMU_MSP02CLK, 19200000); +static DEF_PRCMU_CLK(msp1clk, PRCMU_MSP1CLK, 19200000); +static DEF_PRCMU_CLK(i2cclk, PRCMU_I2CCLK, 24000000); +static DEF_PRCMU_CLK(slimclk, PRCMU_SLIMCLK, 19200000); +static DEF_PRCMU_CLK(per1clk, PRCMU_PER1CLK, 133330000); +static DEF_PRCMU_CLK(per2clk, PRCMU_PER2CLK, 133330000); +static DEF_PRCMU_CLK(per3clk, PRCMU_PER3CLK, 133330000); +static DEF_PRCMU_CLK(per5clk, PRCMU_PER5CLK, 133330000); +static DEF_PRCMU_CLK(per6clk, PRCMU_PER6CLK, 133330000); +static DEF_PRCMU_CLK(per7clk, PRCMU_PER7CLK, 100000000); +static DEF_PRCMU_SCALABLE_CLK(lcdclk, PRCMU_LCDCLK); +static DEF_PRCMU_OPP100_CLK(bmlclk, PRCMU_BMLCLK, 200000000); +static DEF_PRCMU_SCALABLE_CLK(hsitxclk, PRCMU_HSITXCLK); +static DEF_PRCMU_SCALABLE_CLK(hsirxclk, PRCMU_HSIRXCLK); +static DEF_PRCMU_SCALABLE_CLK(hdmiclk, PRCMU_HDMICLK); +static DEF_PRCMU_CLK(apeatclk, PRCMU_APEATCLK, 160000000); +static DEF_PRCMU_CLK(apetraceclk, PRCMU_APETRACECLK, 160000000); +static DEF_PRCMU_CLK(mcdeclk, PRCMU_MCDECLK, 160000000); +static DEF_PRCMU_OPP100_CLK(ipi2cclk, PRCMU_IPI2CCLK, 24000000); +static DEF_PRCMU_CLK(dsialtclk, PRCMU_DSIALTCLK, 384000000); +static DEF_PRCMU_CLK(dmaclk, PRCMU_DMACLK, 200000000); +static DEF_PRCMU_CLK(b2r2clk, PRCMU_B2R2CLK, 200000000); +static DEF_PRCMU_SCALABLE_CLK(tvclk, PRCMU_TVCLK); +/* TODO: For SSPCLK, the spec says 24MHz, while the old driver says 48MHz. */ +static DEF_PRCMU_CLK(sspclk, PRCMU_SSPCLK, 24000000); +static DEF_PRCMU_CLK(rngclk, PRCMU_RNGCLK, 19200000); +static DEF_PRCMU_CLK(uiccclk, PRCMU_UICCCLK, 48000000); +static DEF_PRCMU_CLK(timclk, PRCMU_TIMCLK, 2400000); +static DEF_PRCMU_CLK(sdmmcclk, PRCMU_SDMMCCLK, 50000000); + +static struct clk dsi_pll = { + .name = "dsi_pll", + .ops = &prcmu_scalable_clk_ops, + .cg_sel = PRCMU_PLLDSI, + .parent = &hdmiclk, + .mutex = &dsi_pll_mutex, +}; + +static struct clk dsi0clk = { + .name = "dsi0clk", + .ops = &prcmu_scalable_clk_ops, + .cg_sel = PRCMU_DSI0CLK, + .parent = &dsi_pll, + .mutex = &dsi_pll_mutex, +}; + +static struct clk dsi1clk = { + .name = "dsi1clk", + .ops = &prcmu_scalable_clk_ops, + .cg_sel = PRCMU_DSI1CLK, + .parent = &dsi_pll, + .mutex = &dsi_pll_mutex, +}; + +static struct clk dsi0escclk = { + .name = "dsi0escclk", + .ops = &prcmu_scalable_clk_ops, + .cg_sel = PRCMU_DSI0ESCCLK, + .parent = &tvclk, +}; + +static struct clk dsi1escclk = { + .name = "dsi1escclk", + .ops = &prcmu_scalable_clk_ops, + .cg_sel = PRCMU_DSI1ESCCLK, + .parent = &tvclk, +}; + +static struct clk dsi2escclk = { + .name = "dsi2escclk", + .ops = &prcmu_scalable_clk_ops, + .cg_sel = PRCMU_DSI2ESCCLK, + .parent = &tvclk, +}; + +/* PRCC PClocks */ + +static DEF_PER1_PCLK(0, p1_pclk0); +static DEF_PER1_PCLK(1, p1_pclk1); +static DEF_PER1_PCLK(2, p1_pclk2); +static DEF_PER1_PCLK(3, p1_pclk3); +static DEF_PER1_PCLK(4, p1_pclk4); +static DEF_PER1_PCLK(5, p1_pclk5); +static DEF_PER1_PCLK(6, p1_pclk6); +static DEF_PER1_PCLK(7, p1_pclk7); +static DEF_PER1_PCLK(8, p1_pclk8); +static DEF_PER1_PCLK(9, p1_pclk9); +static DEF_PER1_PCLK(10, p1_pclk10); +static DEF_PER1_PCLK(11, p1_pclk11); + +static DEF_PER2_PCLK(0, p2_pclk0); +static DEF_PER2_PCLK(1, p2_pclk1); +static DEF_PER2_PCLK(2, p2_pclk2); +static DEF_PER2_PCLK(3, p2_pclk3); +static DEF_PER2_PCLK(4, p2_pclk4); +static DEF_PER2_PCLK(5, p2_pclk5); +static DEF_PER2_PCLK(6, p2_pclk6); +static DEF_PER2_PCLK(7, p2_pclk7); +static DEF_PER2_PCLK(8, p2_pclk8); +static DEF_PER2_PCLK(9, p2_pclk9); +static DEF_PER2_PCLK(10, p2_pclk10); +static DEF_PER2_PCLK(11, p2_pclk11); + +static DEF_PER3_PCLK(0, p3_pclk0); +static DEF_PER3_PCLK(1, p3_pclk1); +static DEF_PER3_PCLK(2, p3_pclk2); +static DEF_PER3_PCLK(3, p3_pclk3); +static DEF_PER3_PCLK(4, p3_pclk4); +static DEF_PER3_PCLK(5, p3_pclk5); +static DEF_PER3_PCLK(6, p3_pclk6); +static DEF_PER3_PCLK(7, p3_pclk7); +static DEF_PER3_PCLK(8, p3_pclk8); + +static DEF_PER5_PCLK(0, p5_pclk0); +static DEF_PER5_PCLK(1, p5_pclk1); + +static DEF_PER6_PCLK(0, p6_pclk0); +static DEF_PER6_PCLK(1, p6_pclk1); +static DEF_PER6_PCLK(2, p6_pclk2); +static DEF_PER6_PCLK(3, p6_pclk3); +static DEF_PER6_PCLK(4, p6_pclk4); +static DEF_PER6_PCLK(5, p6_pclk5); +static DEF_PER6_PCLK(6, p6_pclk6); +static DEF_PER6_PCLK(7, p6_pclk7); + +/* UART0 */ +static DEF_PER1_KCLK(0, p1_uart0_kclk, &uartclk); +static DEF_PER_CLK(p1_uart0_clk, &p1_pclk0, &p1_uart0_kclk); + +/* UART1 */ +static DEF_PER1_KCLK(1, p1_uart1_kclk, &uartclk); +static DEF_PER_CLK(p1_uart1_clk, &p1_pclk1, &p1_uart1_kclk); + +/* I2C1 */ +static DEF_PER1_KCLK(2, p1_i2c1_kclk, &i2cclk); +static DEF_PER_CLK(p1_i2c1_clk, &p1_pclk2, &p1_i2c1_kclk); + +/* MSP0 */ +static DEF_PER1_KCLK(3, p1_msp0_kclk, &msp02clk); +static DEF_PER_CLK(p1_msp0_clk, &p1_pclk3, &p1_msp0_kclk); + +/* MSP1 */ +static DEF_PER1_KCLK(4, p1_msp1_kclk, &msp1clk); +static DEF_PER_CLK(p1_msp1_clk, &p1_pclk4, &p1_msp1_kclk); + +/* SDI0 */ +static DEF_PER1_KCLK(5, p1_sdi0_kclk, &sdmmcclk); +static DEF_PER_CLK(p1_sdi0_clk, &p1_pclk5, &p1_sdi0_kclk); + +/* I2C2 */ +static DEF_PER1_KCLK(6, p1_i2c2_kclk, &i2cclk); +static DEF_PER_CLK(p1_i2c2_clk, &p1_pclk6, &p1_i2c2_kclk); + +/* SLIMBUS0 */ +static DEF_PER1_KCLK(3, p1_slimbus0_kclk, &slimclk); +static DEF_PER_CLK(p1_slimbus0_clk, &p1_pclk8, &p1_slimbus0_kclk); + +/* I2C4 */ +static DEF_PER1_KCLK(9, p1_i2c4_kclk, &i2cclk); +static DEF_PER_CLK(p1_i2c4_clk, &p1_pclk10, &p1_i2c4_kclk); + +/* MSP3 */ +static DEF_PER1_KCLK(10, p1_msp3_kclk, &msp1clk); +static DEF_PER_CLK(p1_msp3_clk, &p1_pclk11, &p1_msp3_kclk); + +/* I2C3 */ +static DEF_PER2_KCLK(0, p2_i2c3_kclk, &i2cclk); +static DEF_PER_CLK(p2_i2c3_clk, &p2_pclk0, &p2_i2c3_kclk); + +/* SDI4 */ +static DEF_PER2_KCLK(2, p2_sdi4_kclk, &sdmmcclk); +static DEF_PER_CLK(p2_sdi4_clk, &p2_pclk4, &p2_sdi4_kclk); + +/* MSP2 */ +static DEF_PER2_KCLK(3, p2_msp2_kclk, &msp02clk); +static DEF_PER_CLK(p2_msp2_clk, &p2_pclk5, &p2_msp2_kclk); + +/* SDI1 */ +static DEF_PER2_KCLK(4, p2_sdi1_kclk, &sdmmcclk); +static DEF_PER_CLK(p2_sdi1_clk, &p2_pclk6, &p2_sdi1_kclk); + +/* SDI3 */ +static DEF_PER2_KCLK(5, p2_sdi3_kclk, &sdmmcclk); +static DEF_PER_CLK(p2_sdi3_clk, &p2_pclk7, &p2_sdi3_kclk); + +/* HSIR */ +static struct clk p2_ssirx_kclk = { + .name = "p2_ssirx_kclk", + .ops = &prcc_kclk_rec_ops, + .io_base = U8500_CLKRST2_BASE, + .cg_sel = BIT(6), + .parent = &hsirxclk, + .clock = &per2clk, +}; + +/* HSIT */ +static struct clk p2_ssitx_kclk = { + .name = "p2_ssitx_kclk", + .ops = &prcc_kclk_rec_ops, + .io_base = U8500_CLKRST2_BASE, + .cg_sel = BIT(7), + .parent = &hsitxclk, + .clock = &per2clk, +}; + +/* SSP0 */ +static DEF_PER3_KCLK(1, p3_ssp0_kclk, &sspclk); +static DEF_PER_CLK(p3_ssp0_clk, &p3_pclk1, &p3_ssp0_kclk); + +/* SSP1 */ +static DEF_PER3_KCLK(2, p3_ssp1_kclk, &sspclk); +static DEF_PER_CLK(p3_ssp1_clk, &p3_pclk2, &p3_ssp1_kclk); + +/* I2C0 */ +static DEF_PER3_KCLK(3, p3_i2c0_kclk, &i2cclk); +static DEF_PER_CLK(p3_i2c0_clk, &p3_pclk3, &p3_i2c0_kclk); + +/* SDI2 */ +static DEF_PER3_KCLK(4, p3_sdi2_kclk, &sdmmcclk); +static DEF_PER_CLK(p3_sdi2_clk, &p3_pclk4, &p3_sdi2_kclk); + +/* SKE */ +static DEF_PER3_KCLK(5, p3_ske_kclk, &rtc32k); +static DEF_PER_CLK(p3_ske_clk, &p3_pclk5, &p3_ske_kclk); + +/* UART2 */ +static DEF_PER3_KCLK(6, p3_uart2_kclk, &uartclk); +static DEF_PER_CLK(p3_uart2_clk, &p3_pclk6, &p3_uart2_kclk); + +/* SDI5 */ +static DEF_PER3_KCLK(7, p3_sdi5_kclk, &sdmmcclk); +static DEF_PER_CLK(p3_sdi5_clk, &p3_pclk7, &p3_sdi5_kclk); + +/* RNG */ +static DEF_PER6_KCLK(0, p6_rng_kclk, &rngclk); +static DEF_PER_CLK(p6_rng_clk, &p6_pclk0, &p6_rng_kclk); + +/* MTU:S */ + +/* MTU0 */ +static DEF_PER_CLK(p6_mtu0_clk, &p6_pclk6, &timclk); + +/* MTU1 */ +static DEF_PER_CLK(p6_mtu1_clk, &p6_pclk7, &timclk); + +/* + * TODO: Ensure names match with devices and then remove unnecessary entries + * when all drivers use the clk API. + */ + +static struct clk_lookup u8500_clocks[] = { + CLK_LOOKUP(soc0_pll, NULL, "soc0_pll"), + CLK_LOOKUP(soc1_pll, NULL, "soc1_pll"), + CLK_LOOKUP(ddr_pll, NULL, "ddr_pll"), + CLK_LOOKUP(ulp38m4, NULL, "ulp38m4"), + CLK_LOOKUP(sysclk, NULL, "sysclk"), + CLK_LOOKUP(rtc32k, NULL, "clk32k"), + CLK_LOOKUP(sysclk, "ab8500-usb.0", "sysclk"), + CLK_LOOKUP(sysclk, "ab8500-codec.0", "sysclk"), + CLK_LOOKUP(ab_ulpclk, "ab8500-codec.0", "ulpclk"), + CLK_LOOKUP(ab_intclk, "ab8500-codec.0", "intclk"), + CLK_LOOKUP(audioclk, "ab8500-codec.0", "audioclk"), + CLK_LOOKUP(ab_intclk, "ab8500-pwm.1", NULL), + + CLK_LOOKUP(clkout0, "pri-cam", NULL), + CLK_LOOKUP(clkout1, "3-005c", NULL), + CLK_LOOKUP(clkout1, "3-005d", NULL), + CLK_LOOKUP(clkout1, "sec-cam", NULL), + + /* prcmu */ + CLK_LOOKUP(sgaclk, "mali", NULL), + CLK_LOOKUP(uartclk, "UART", NULL), + CLK_LOOKUP(msp02clk, "MSP02", NULL), + CLK_LOOKUP(i2cclk, "I2C", NULL), + CLK_LOOKUP(sdmmcclk, "sdmmc", NULL), + CLK_LOOKUP(slimclk, "slim", NULL), + CLK_LOOKUP(per1clk, "PERIPH1", NULL), + CLK_LOOKUP(per2clk, "PERIPH2", NULL), + CLK_LOOKUP(per3clk, "PERIPH3", NULL), + CLK_LOOKUP(per5clk, "PERIPH5", NULL), + CLK_LOOKUP(per6clk, "PERIPH6", NULL), + CLK_LOOKUP(per7clk, "PERIPH7", NULL), + CLK_LOOKUP(lcdclk, "lcd", NULL), + CLK_LOOKUP(bmlclk, "bml", NULL), + CLK_LOOKUP(p2_ssitx_kclk, "ste_hsi.0", "hsit_hsitxclk"), + CLK_LOOKUP(p2_ssirx_kclk, "ste_hsi.0", "hsir_hsirxclk"), + CLK_LOOKUP(lcdclk, "mcde", "lcd"), + CLK_LOOKUP(hdmiclk, "hdmi", NULL), + CLK_LOOKUP(hdmiclk, "mcde", "hdmi"), + CLK_LOOKUP(apeatclk, "apeat", NULL), + CLK_LOOKUP(apetraceclk, "apetrace", NULL), + CLK_LOOKUP(mcdeclk, "mcde", NULL), + CLK_LOOKUP(mcdeclk, "mcde", "mcde"), + CLK_LOOKUP(ipi2cclk, "ipi2", NULL), + CLK_LOOKUP(dmaclk, "dma40.0", NULL), + CLK_LOOKUP(b2r2clk, "b2r2", NULL), + CLK_LOOKUP(b2r2clk, "b2r2_core", NULL), + CLK_LOOKUP(b2r2clk, "U8500-B2R2.0", NULL), + CLK_LOOKUP(tvclk, "tv", NULL), + CLK_LOOKUP(tvclk, "mcde", "tv"), + CLK_LOOKUP(msp1clk, "MSP1", NULL), + CLK_LOOKUP(dsialtclk, "dsialt", NULL), + CLK_LOOKUP(sspclk, "SSP", NULL), + CLK_LOOKUP(rngclk, "rngclk", NULL), + CLK_LOOKUP(uiccclk, "uicc", NULL), + CLK_LOOKUP(dsi0clk, "mcde", "dsihs0"), + CLK_LOOKUP(dsi1clk, "mcde", "dsihs1"), + CLK_LOOKUP(dsi_pll, "mcde", "dsihs2"), + CLK_LOOKUP(dsi0escclk, "mcde", "dsilp0"), + CLK_LOOKUP(dsi1escclk, "mcde", "dsilp1"), + CLK_LOOKUP(dsi2escclk, "mcde", "dsilp2"), + + /* PERIPH 1 */ + CLK_LOOKUP(p1_msp3_clk, "msp3", NULL), + CLK_LOOKUP(p1_msp3_clk, "ux500-msp-i2s.3", NULL), + CLK_LOOKUP(p1_msp3_kclk, "ab8500-codec.0", "msp3-kernel"), + CLK_LOOKUP(p1_pclk11, "ab8500-codec.0", "msp3-bus"), + CLK_LOOKUP(p1_uart0_clk, "uart0", NULL), + CLK_LOOKUP(p1_uart1_clk, "uart1", NULL), + CLK_LOOKUP(p1_i2c1_clk, "nmk-i2c.1", NULL), + CLK_LOOKUP(p1_msp0_clk, "msp0", NULL), + CLK_LOOKUP(p1_msp0_clk, "ux500-msp-i2s.0", NULL), + CLK_LOOKUP(p1_sdi0_clk, "sdi0", NULL), + CLK_LOOKUP(p1_i2c2_clk, "nmk-i2c.2", NULL), + CLK_LOOKUP(p1_slimbus0_clk, "slimbus0", NULL), + CLK_LOOKUP(p1_pclk9, "gpio.0", NULL), + CLK_LOOKUP(p1_pclk9, "gpio.1", NULL), + CLK_LOOKUP(p1_pclk9, "gpioblock0", NULL), + CLK_LOOKUP(p1_msp1_clk, "msp1", NULL), + CLK_LOOKUP(p1_msp1_clk, "ux500-msp-i2s.1", NULL), + CLK_LOOKUP(p1_msp1_kclk, "ab8500-codec.0", "msp1-kernel"), + CLK_LOOKUP(p1_pclk4, "ab8500-codec.0", "msp1-bus"), + CLK_LOOKUP(p1_pclk7, "spi3", NULL), + CLK_LOOKUP(p1_i2c4_clk, "nmk-i2c.4", NULL), + + /* PERIPH 2 */ + CLK_LOOKUP(p2_i2c3_clk, "nmk-i2c.3", NULL), + CLK_LOOKUP(p2_pclk1, "spi2", NULL), + CLK_LOOKUP(p2_pclk2, "spi1", NULL), + CLK_LOOKUP(p2_pclk3, "pwl", NULL), + CLK_LOOKUP(p2_sdi4_clk, "sdi4", NULL), + CLK_LOOKUP(p2_msp2_clk, "msp2", NULL), + CLK_LOOKUP(p2_msp2_clk, "ux500-msp-i2s.2", NULL), + CLK_LOOKUP(p2_sdi1_clk, "sdi1", NULL), + CLK_LOOKUP(p2_sdi3_clk, "sdi3", NULL), + CLK_LOOKUP(p2_pclk8, "spi0", NULL), + CLK_LOOKUP(p2_pclk9, "ste_hsi.0", "hsir_hclk"), + CLK_LOOKUP(p2_pclk10, "ste_hsi.0", "hsit_hclk"), + CLK_LOOKUP(p2_pclk11, "gpio.6", NULL), + CLK_LOOKUP(p2_pclk11, "gpio.7", NULL), + CLK_LOOKUP(p2_pclk11, "gpioblock1", NULL), + + /* PERIPH 3 */ + CLK_LOOKUP(p3_pclk0, NULL, "fsmc"), + CLK_LOOKUP(p3_i2c0_clk, "nmk-i2c.0", NULL), + CLK_LOOKUP(p3_sdi2_clk, "sdi2", NULL), + CLK_LOOKUP(p3_ske_clk, "ske", NULL), + CLK_LOOKUP(p3_ske_clk, "nmk-ske-keypad", NULL), + CLK_LOOKUP(p3_uart2_clk, "uart2", NULL), + CLK_LOOKUP(p3_sdi5_clk, "sdi5", NULL), + CLK_LOOKUP(p3_pclk8, "gpio.2", NULL), + CLK_LOOKUP(p3_pclk8, "gpio.3", NULL), + CLK_LOOKUP(p3_pclk8, "gpio.4", NULL), + CLK_LOOKUP(p3_pclk8, "gpio.5", NULL), + CLK_LOOKUP(p3_pclk8, "gpioblock2", NULL), + CLK_LOOKUP(p3_ssp0_clk, "ssp0", NULL), + CLK_LOOKUP(p3_ssp1_clk, "ssp1", NULL), + + /* PERIPH 5 */ + CLK_LOOKUP(p5_pclk1, "gpio.8", NULL), + CLK_LOOKUP(p5_pclk1, "gpioblock3", NULL), + CLK_LOOKUP(p5_pclk0, "musb-ux500.0", "usb"), + + /* PERIPH 6 */ + CLK_LOOKUP(p6_pclk1, "cryp0", NULL), + CLK_LOOKUP(p6_pclk2, "hash0", NULL), + CLK_LOOKUP(p6_pclk3, "pka", NULL), + CLK_LOOKUP(p6_pclk5, "cfgreg", NULL), + CLK_LOOKUP(p6_mtu0_clk, "mtu0", NULL), + CLK_LOOKUP(p6_mtu1_clk, "mtu1", NULL), + CLK_LOOKUP(p6_pclk4, "hash1", NULL), + CLK_LOOKUP(p6_pclk1, "cryp1", NULL), + CLK_LOOKUP(p6_rng_clk, "rng", NULL), + +}; + +static struct clk_lookup u8500_v2_sysclks[] = { + CLK_LOOKUP(sysclk2, NULL, "sysclk2"), + CLK_LOOKUP(sysclk3, NULL, "sysclk3"), + CLK_LOOKUP(sysclk4, NULL, "sysclk4"), +}; + +static void sysclk_init_disable(struct work_struct *not_used) +{ + int i; + + mutex_lock(&sysclk_mutex); + + /* Enable SWAT */ + if (ab8500_sysctrl_set(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE)) + goto err_swat; + + for (i = 0; i < ARRAY_SIZE(u8500_v2_sysclks); i++) { + struct clk *clk = u8500_v2_sysclks[i].clk; + + /* Disable sysclks */ + if (!clk->enabled && clk->cg_sel) { + if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + (u8)clk->cg_sel)) + goto err_sysclk; + } + } + goto unlock_and_exit; + +err_sysclk: + pr_err("clock: Disable %s failed", u8500_v2_sysclks[i].clk->name); + ab8500_sysctrl_clear(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE); + goto unlock_and_exit; + +err_swat: + pr_err("clock: Enable SWAT failed"); + +unlock_and_exit: + mutex_unlock(&sysclk_mutex); +} + +static struct clk *db8500_dbg_clks[] __initdata = { + /* Clock sources */ + &soc0_pll, + &soc1_pll, + &ddr_pll, + &ulp38m4, + &sysclk, + &rtc32k, + /* PRCMU clocks */ + &sgaclk, + &uartclk, + &msp02clk, + &msp1clk, + &i2cclk, + &sdmmcclk, + &slimclk, + &per1clk, + &per2clk, + &per3clk, + &per5clk, + &per6clk, + &per7clk, + &lcdclk, + &bmlclk, + &hsitxclk, + &hsirxclk, + &hdmiclk, + &apeatclk, + &apetraceclk, + &mcdeclk, + &ipi2cclk, + &dsialtclk, + &dsi_pll, + &dsi0clk, + &dsi1clk, + &dsi0escclk, + &dsi1escclk, + &dsi2escclk, + &dmaclk, + &b2r2clk, + &tvclk, + &sspclk, + &rngclk, + &uiccclk, + &sysclk2, + &clkout0, + &clkout1, + &p1_pclk0, + &p1_pclk1, + &p1_pclk2, + &p1_pclk3, + &p1_pclk4, + &p1_pclk5, + &p1_pclk6, + &p1_pclk7, + &p1_pclk8, + &p1_pclk9, + &p1_pclk10, + &p1_pclk11, + &p2_pclk0, + &p2_pclk1, + &p2_pclk2, + &p2_pclk3, + &p2_pclk4, + &p2_pclk5, + &p2_pclk6, + &p2_pclk7, + &p2_pclk8, + &p2_pclk9, + &p2_pclk10, + &p2_pclk11, + &p3_pclk0, + &p3_pclk1, + &p3_pclk2, + &p3_pclk3, + &p3_pclk4, + &p3_pclk5, + &p3_pclk6, + &p3_pclk7, + &p3_pclk8, + &p5_pclk0, + &p5_pclk1, + &p6_pclk0, + &p6_pclk1, + &p6_pclk2, + &p6_pclk3, + &p6_pclk4, + &p6_pclk5, + &p6_pclk6, + &p6_pclk7, +}; + +/* List of clocks which might be enabled from the bootloader */ + +/* + * SOC settings enable bus + kernel clocks of all periphs without + * properly configuring the parents of the kernel clocks for all units. + * Enable and Disable them all to get them into a known and working state. + */ +static struct clk *loader_enabled_clk[] __initdata = { + /* periph 1 */ + &p1_uart0_clk, + &p1_uart1_clk, + &p1_i2c1_clk, + &p1_msp0_clk, + &p1_msp1_clk, + &p1_sdi0_clk, + &p1_i2c2_clk, + &p1_pclk7, /* spi3 */ + &p1_pclk9, /* gpioctrl */ + &p1_i2c4_clk, + + /* periph 2 */ + &p2_i2c3_clk, + &p2_pclk1, /* spi2 */ + &p2_pclk2, /* spi1 */ + /* pwl has an unknown kclk parent, ignore it */ + &p2_sdi4_clk, + &p2_msp2_clk, + &p2_sdi1_clk, + &p2_sdi3_clk, + &p2_pclk8, /* spi0 */ + &p2_ssirx_kclk, /* hsir kernel */ + &p2_ssitx_kclk, /* hsit kernel */ + &p2_pclk9, /* hsir bus */ + &p2_pclk10, /* hsit bus */ + &p2_pclk11, /* gpioctrl */ + /* periph 3 */ + &p3_pclk0, /* fsmc */ + &p3_ssp0_clk, + &p3_ssp1_clk, + &p3_i2c0_clk, + &p3_sdi2_clk, + &p3_ske_clk, + &p3_uart2_clk, + &p3_sdi5_clk, + &p3_pclk8, /* gpio */ + /* periph 5 */ + &p5_pclk0, /* usb */ + &p5_pclk1, /* gpio */ + /* periph 6 */ + /* Leave out rng, cryp0, hash0 and pka */ + &p6_pclk4, /* hash1 */ + &p6_pclk5, /* cr */ + &p6_mtu0_clk, + &p6_mtu1_clk, + /* periph 7 */ + &per7clk, /* PERIPH7 */ + + &bmlclk, /* BML */ + &dsialtclk, /* dsialt */ + &hsirxclk, /* hsirx */ + &hsitxclk, /* hsitx */ + &ipi2cclk, /* ipi2 */ + &lcdclk, /* mcde */ + &b2r2clk, /* b2r2_bus */ +}; + +static int __init init_clock_states(void) +{ + unsigned int i; + /* + * Disable peripheral clocks enabled by bootloader/default + * but without drivers + */ + for (i = 0; i < ARRAY_SIZE(loader_enabled_clk); i++) + if (!clk_enable(loader_enabled_clk[i])) + clk_disable(loader_enabled_clk[i]); + + /* + * APEATCLK and APETRACECLK are enabled at boot and needed + * in order to debug with Lauterbach + */ + if (!clk_enable(&apeatclk)) { + if (!ux500_jtag_enabled()) + clk_disable(&apeatclk); + } + if (!clk_enable(&apetraceclk)) { + if (!ux500_jtag_enabled()) + clk_disable(&apetraceclk); + } + + INIT_DELAYED_WORK(&sysclk_disable_work, sysclk_init_disable); + schedule_delayed_work(&sysclk_disable_work, 10 * HZ); + + return 0; +} +late_initcall(init_clock_states); + +static void __init configure_c2_clocks(void) +{ + sgaclk.parent = &soc0_pll; + sgaclk.mutex = &soc0_pll_mutex; +} + +int __init db8500_clk_init(void) +{ + struct prcmu_fw_version *fw_version; + + /* + * Disable pwl's and slimbus' bus and kernel clocks without touching + * any parents. Because for slimbus, the prcmu fw has not correctly + * configured the clocks at boot and for pwl the kclk parent + * is unknown. + */ + + /* slimbus' bus and kernel clocks */ + writel(1 << 8, __io_address(U8500_CLKRST1_BASE) + PRCC_PCKDIS); + writel(1 << 8, __io_address(U8500_CLKRST1_BASE) + PRCC_KCKDIS); + /* pwl's bus and kernel clocks */ + writel(1 << 3, __io_address(U8500_CLKRST2_BASE) + PRCC_PCKDIS); + writel(1 << 1, __io_address(U8500_CLKRST2_BASE) + PRCC_KCKDIS); + + fw_version = prcmu_get_fw_version(); + if (fw_version != NULL) + switch (fw_version->project) { + case PRCMU_FW_PROJECT_U8500_C2: + case PRCMU_FW_PROJECT_U9500_C2: + case PRCMU_FW_PROJECT_U8520: + configure_c2_clocks(); + break; + default: + break; + } + clkdev_add_table(u8500_v2_sysclks, + ARRAY_SIZE(u8500_v2_sysclks)); + clkdev_add_table(u8500_clocks, + ARRAY_SIZE(u8500_clocks)); +#ifdef CONFIG_DEBUG_FS + clk_debugfs_add_table(u8500_v2_sysclks, ARRAY_SIZE(u8500_v2_sysclks)); + clk_debugfs_add_table(u8500_clocks, ARRAY_SIZE(u8500_clocks)); +#endif + return 0; +} + +int __init db8500_clk_debug_init(void) +{ + return dbx500_clk_debug_init(db8500_dbg_clks, + ARRAY_SIZE(db8500_dbg_clks)); +} diff --git a/arch/arm/mach-ux500/clock-debug.c b/arch/arm/mach-ux500/clock-debug.c new file mode 100644 index 00000000000..1ebc69fe061 --- /dev/null +++ b/arch/arm/mach-ux500/clock-debug.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST-Ericsson + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> +#include <linux/clk.h> +#include <mach/hardware.h> + +#include "clock.h" + +struct clk_debug_info { + struct clk *clk; + struct dentry *dir; + struct dentry *enable; + struct dentry *requests; + int enabled; +}; + +#ifdef CONFIG_DEBUG_FS + +static struct dentry *clk_dir; +static struct dentry *clk_show; +static struct dentry *clk_show_enabled_only; + +static struct clk_debug_info *cdi; +static int num_clks; + +static int clk_show_print(struct seq_file *s, void *p) +{ + int i; + int enabled_only = (int)s->private; + + seq_printf(s, "\n%-20s %10s %s\n", "name", "rate", + "enabled (kernel + debug)"); + for (i = 0; i < num_clks; i++) { + if (enabled_only && !cdi[i].clk->enabled) + continue; + seq_printf(s, + "%-20s %10lu %5d + %d\n", + cdi[i].clk->name, + clk_get_rate(cdi[i].clk), + cdi[i].clk->enabled - cdi[i].enabled, + cdi[i].enabled); + } + + return 0; +} + +static int clk_show_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_show_print, inode->i_private); +} + +static int clk_enable_print(struct seq_file *s, void *p) +{ + struct clk_debug_info *cdi = s->private; + + return seq_printf(s, "%d\n", cdi->enabled); +} + +static int clk_enable_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_enable_print, inode->i_private); +} + +static ssize_t clk_enable_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct clk_debug_info *cdi; + long user_val; + int err; + + cdi = ((struct seq_file *)(file->private_data))->private; + + err = kstrtol_from_user(user_buf, count, 0, &user_val); + + if (err) + return err; + + if ((user_val > 0) && (!cdi->enabled)) { + err = clk_enable(cdi->clk); + if (err) { + pr_err("clock: clk_enable(%s) failed.\n", + cdi->clk->name); + return -EFAULT; + } + cdi->enabled = 1; + } else if ((user_val <= 0) && (cdi->enabled)) { + clk_disable(cdi->clk); + cdi->enabled = 0; + } + return count; +} + +static int clk_requests_print(struct seq_file *s, void *p) +{ + struct clk_debug_info *cdi = s->private; + + return seq_printf(s, "%d\n", cdi->clk->enabled); +} + +static int clk_requests_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_requests_print, inode->i_private); +} + +static const struct file_operations clk_enable_fops = { + .open = clk_enable_open, + .write = clk_enable_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations clk_requests_fops = { + .open = clk_requests_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations clk_show_fops = { + .open = clk_show_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int create_clk_dirs(struct clk_debug_info *cdi, int size) +{ + int i; + + for (i = 0; i < size; i++) { + cdi[i].dir = debugfs_create_dir(cdi[i].clk->name, clk_dir); + if (!cdi[i].dir) + goto no_dir; + } + + for (i = 0; i < size; i++) { + cdi[i].enable = debugfs_create_file("enable", + (S_IRUGO | S_IWUGO), + cdi[i].dir, &cdi[i], + &clk_enable_fops); + if (!cdi[i].enable) + goto no_enable; + } + for (i = 0; i < size; i++) { + cdi[i].requests = debugfs_create_file("requests", S_IRUGO, + cdi[i].dir, &cdi[i], + &clk_requests_fops); + if (!cdi[i].requests) + goto no_requests; + } + return 0; + +no_requests: + while (i--) + debugfs_remove(cdi[i].requests); + i = size; +no_enable: + while (i--) + debugfs_remove(cdi[i].enable); + i = size; +no_dir: + while (i--) + debugfs_remove(cdi[i].dir); + + return -ENOMEM; +} + +int __init dbx500_clk_debug_init(struct clk **clks, int num) +{ + int i; + + cdi = kcalloc(sizeof(struct clk_debug_info), num, GFP_KERNEL); + if (!cdi) + return -ENOMEM; + + for (i = 0; i < num; i++) + cdi[i].clk = clks[i]; + + num_clks = num; + + clk_dir = debugfs_create_dir("clk", NULL); + if (!clk_dir) + goto no_dir; + + clk_show = debugfs_create_file("show", S_IRUGO, clk_dir, (void *)0, + &clk_show_fops); + if (!clk_show) + goto no_show; + + clk_show_enabled_only = debugfs_create_file("show-enabled-only", + S_IRUGO, clk_dir, (void *)1, + &clk_show_fops); + if (!clk_show_enabled_only) + goto no_enabled_only; + + if (create_clk_dirs(cdi, num)) + goto no_clks; + + return 0; + +no_clks: + debugfs_remove(clk_show_enabled_only); +no_enabled_only: + debugfs_remove(clk_show); +no_show: + debugfs_remove(clk_dir); +no_dir: + kfree(cdi); + return -ENOMEM; +} + +static int __init clk_debug_init(void) +{ + if (cpu_is_u8500()) + db8500_clk_debug_init(); + else if (cpu_is_u5500()) + db5500_clk_debug_init(); + + return 0; +} +module_init(clk_debug_init); + +#endif /* CONFIG_DEBUG_FS */ diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index ec35f0aa566..b8bac2d6966 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -7,18 +7,11 @@ * published by the Free Software Foundation. */ #include <linux/module.h> -#include <linux/kernel.h> -#include <linux/list.h> #include <linux/errno.h> -#include <linux/err.h> -#include <linux/clk.h> #include <linux/io.h> -#include <linux/clkdev.h> -#include <linux/cpufreq.h> - -#include <plat/mtu.h> -#include <mach/hardware.h> -#include "clock.h" +#include <linux/spinlock.h> +#include <linux/mfd/abx500/ab8500-sysctrl.h> +#include <linux/mfd/dbx500-prcmu.h> #ifdef CONFIG_DEBUG_FS #include <linux/debugfs.h> @@ -26,477 +19,495 @@ static LIST_HEAD(clk_list); #endif -#define PRCC_PCKEN 0x00 -#define PRCC_PCKDIS 0x04 -#define PRCC_KCKEN 0x08 -#define PRCC_KCKDIS 0x0C - -#define PRCM_YYCLKEN0_MGT_SET 0x510 -#define PRCM_YYCLKEN1_MGT_SET 0x514 -#define PRCM_YYCLKEN0_MGT_CLR 0x518 -#define PRCM_YYCLKEN1_MGT_CLR 0x51C -#define PRCM_YYCLKEN0_MGT_VAL 0x520 -#define PRCM_YYCLKEN1_MGT_VAL 0x524 - -#define PRCM_SVAMMDSPCLK_MGT 0x008 -#define PRCM_SIAMMDSPCLK_MGT 0x00C -#define PRCM_SGACLK_MGT 0x014 -#define PRCM_UARTCLK_MGT 0x018 -#define PRCM_MSP02CLK_MGT 0x01C -#define PRCM_MSP1CLK_MGT 0x288 -#define PRCM_I2CCLK_MGT 0x020 -#define PRCM_SDMMCCLK_MGT 0x024 -#define PRCM_SLIMCLK_MGT 0x028 -#define PRCM_PER1CLK_MGT 0x02C -#define PRCM_PER2CLK_MGT 0x030 -#define PRCM_PER3CLK_MGT 0x034 -#define PRCM_PER5CLK_MGT 0x038 -#define PRCM_PER6CLK_MGT 0x03C -#define PRCM_PER7CLK_MGT 0x040 -#define PRCM_LCDCLK_MGT 0x044 -#define PRCM_BMLCLK_MGT 0x04C -#define PRCM_HSITXCLK_MGT 0x050 -#define PRCM_HSIRXCLK_MGT 0x054 -#define PRCM_HDMICLK_MGT 0x058 -#define PRCM_APEATCLK_MGT 0x05C -#define PRCM_APETRACECLK_MGT 0x060 -#define PRCM_MCDECLK_MGT 0x064 -#define PRCM_IPI2CCLK_MGT 0x068 -#define PRCM_DSIALTCLK_MGT 0x06C -#define PRCM_DMACLK_MGT 0x074 -#define PRCM_B2R2CLK_MGT 0x078 -#define PRCM_TVCLK_MGT 0x07C -#define PRCM_TCR 0x1C8 -#define PRCM_TCR_STOPPED (1 << 16) -#define PRCM_TCR_DOZE_MODE (1 << 17) -#define PRCM_UNIPROCLK_MGT 0x278 -#define PRCM_SSPCLK_MGT 0x280 -#define PRCM_RNGCLK_MGT 0x284 -#define PRCM_UICCCLK_MGT 0x27C - -#define PRCM_MGT_ENABLE (1 << 8) - -static DEFINE_SPINLOCK(clocks_lock); - -static void __clk_enable(struct clk *clk) -{ - if (clk->enabled++ == 0) { - if (clk->parent_cluster) - __clk_enable(clk->parent_cluster); - - if (clk->parent_periph) - __clk_enable(clk->parent_periph); - - if (clk->ops && clk->ops->enable) - clk->ops->enable(clk); +#include "clock.h" +#include "prcc.h" + +DEFINE_MUTEX(clk_opp100_mutex); +static DEFINE_SPINLOCK(clk_spin_lock); +#define NO_LOCK &clk_spin_lock + +static void __iomem *prcmu_base; + +static void __clk_lock(struct clk *clk, void *last_lock, unsigned long *flags) +{ + if (clk->mutex != last_lock) { + if (clk->mutex == NULL) + spin_lock_irqsave(&clk_spin_lock, *flags); + else + mutex_lock(clk->mutex); } } -int clk_enable(struct clk *clk) +static void __clk_unlock(struct clk *clk, void *last_lock, unsigned long flags) +{ + if (clk->mutex != last_lock) { + if (clk->mutex == NULL) + spin_unlock_irqrestore(&clk_spin_lock, flags); + else + mutex_unlock(clk->mutex); + } +} + +void __clk_disable(struct clk *clk, void *current_lock) { unsigned long flags; - spin_lock_irqsave(&clocks_lock, flags); - __clk_enable(clk); - spin_unlock_irqrestore(&clocks_lock, flags); + if (clk == NULL) + return; - return 0; + __clk_lock(clk, current_lock, &flags); + + if (clk->enabled && (--clk->enabled == 0)) { + if ((clk->ops != NULL) && (clk->ops->disable != NULL)) + clk->ops->disable(clk); + __clk_disable(clk->parent, clk->mutex); + __clk_disable(clk->bus_parent, clk->mutex); + } + + __clk_unlock(clk, current_lock, flags); + + return; } -EXPORT_SYMBOL(clk_enable); -static void __clk_disable(struct clk *clk) +int __clk_enable(struct clk *clk, void *current_lock) { - if (--clk->enabled == 0) { - if (clk->ops && clk->ops->disable) - clk->ops->disable(clk); + int err; + unsigned long flags; - if (clk->parent_periph) - __clk_disable(clk->parent_periph); + if (clk == NULL) + return 0; - if (clk->parent_cluster) - __clk_disable(clk->parent_cluster); + __clk_lock(clk, current_lock, &flags); + + if (!clk->enabled) { + err = __clk_enable(clk->bus_parent, clk->mutex); + if (unlikely(err)) + goto bus_parent_error; + + err = __clk_enable(clk->parent, clk->mutex); + if (unlikely(err)) + goto parent_error; + + if ((clk->ops != NULL) && (clk->ops->enable != NULL)) { + err = clk->ops->enable(clk); + if (unlikely(err)) + goto enable_error; + } } + clk->enabled++; + + __clk_unlock(clk, current_lock, flags); + + return 0; + +enable_error: + __clk_disable(clk->parent, clk->mutex); +parent_error: + __clk_disable(clk->bus_parent, clk->mutex); +bus_parent_error: + + __clk_unlock(clk, current_lock, flags); + + return err; } -void clk_disable(struct clk *clk) +unsigned long __clk_get_rate(struct clk *clk, void *current_lock) { + unsigned long rate; unsigned long flags; - WARN_ON(!clk->enabled); + if (clk == NULL) + return 0; + + __clk_lock(clk, current_lock, &flags); - spin_lock_irqsave(&clocks_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clocks_lock, flags); + if ((clk->ops != NULL) && (clk->ops->get_rate != NULL)) + rate = clk->ops->get_rate(clk); + else if (clk->rate) + rate = clk->rate; + else + rate = __clk_get_rate(clk->parent, clk->mutex); + + __clk_unlock(clk, current_lock, flags); + + return rate; } -EXPORT_SYMBOL(clk_disable); -/* - * The MTU has a separate, rather complex muxing setup - * with alternative parents (peripheral cluster or - * ULP or fixed 32768 Hz) depending on settings - */ -static unsigned long clk_mtu_get_rate(struct clk *clk) +static long __clk_round_rate(struct clk *clk, unsigned long rate) { - void __iomem *addr; - u32 tcr; - int mtu = (int) clk->data; - /* - * One of these is selected eventually - * TODO: Replace the constant with a reference - * to the ULP source once this is modeled. - */ - unsigned long clk32k = 32768; - unsigned long mturate; - unsigned long retclk; - - if (cpu_is_u5500()) - addr = __io_address(U5500_PRCMU_BASE); - else if (cpu_is_u8500()) - addr = __io_address(U8500_PRCMU_BASE); - else - ux500_unknown_soc(); + if ((clk->ops != NULL) && (clk->ops->round_rate != NULL)) + return clk->ops->round_rate(clk, rate); - /* - * On a startup, always conifgure the TCR to the doze mode; - * bootloaders do it for us. Do this in the kernel too. - */ - writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR); + return -ENOSYS; +} - tcr = readl(addr + PRCM_TCR); +static int __clk_set_rate(struct clk *clk, unsigned long rate) +{ + if ((clk->ops != NULL) && (clk->ops->set_rate != NULL)) + return clk->ops->set_rate(clk, rate); - /* Get the rate from the parent as a default */ - if (clk->parent_periph) - mturate = clk_get_rate(clk->parent_periph); - else if (clk->parent_cluster) - mturate = clk_get_rate(clk->parent_cluster); - else - /* We need to be connected SOMEWHERE */ - BUG(); + return -ENOSYS; +} - /* Return the clock selected for this MTU */ - if (tcr & (1 << mtu)) - retclk = clk32k; - else - retclk = mturate; +int clk_enable(struct clk *clk) +{ + if (clk == NULL) + return -EINVAL; - pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk); - return retclk; + return __clk_enable(clk, NO_LOCK); } +EXPORT_SYMBOL(clk_enable); -unsigned long clk_get_rate(struct clk *clk) +void clk_disable(struct clk *clk) { - unsigned long rate; - /* - * If there is a custom getrate callback for this clock, - * it will take precedence. - */ - if (clk->get_rate) - return clk->get_rate(clk); - - if (clk->ops && clk->ops->get_rate) - return clk->ops->get_rate(clk); - - rate = clk->rate; - if (!rate) { - if (clk->parent_periph) - rate = clk_get_rate(clk->parent_periph); - else if (clk->parent_cluster) - rate = clk_get_rate(clk->parent_cluster); - } + if (clk == NULL) + return; - return rate; + WARN_ON(!clk->enabled); + __clk_disable(clk, NO_LOCK); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk == NULL) + return 0; + + return __clk_get_rate(clk, NO_LOCK); } EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - /*TODO*/ - return rate; + long rounded_rate; + unsigned long flags; + + if (clk == NULL) + return -EINVAL; + + __clk_lock(clk, NO_LOCK, &flags); + + rounded_rate = __clk_round_rate(clk, rate); + + __clk_unlock(clk, NO_LOCK, flags); + + return rounded_rate; } EXPORT_SYMBOL(clk_round_rate); +long clk_round_rate_rec(struct clk *clk, unsigned long rate) +{ + long rounded_rate; + unsigned long flags; + + if ((clk == NULL) || (clk->parent == NULL)) + return -EINVAL; + + __clk_lock(clk->parent, clk->mutex, &flags); + + rounded_rate = __clk_round_rate(clk->parent, rate); + + __clk_unlock(clk->parent, clk->mutex, flags); + + return rounded_rate; +} + +static void lock_parent_rate(struct clk *clk) +{ + unsigned long flags; + + if (clk->parent == NULL) + return; + + __clk_lock(clk->parent, clk->mutex, &flags); + + lock_parent_rate(clk->parent); + clk->parent->rate_locked++; + + __clk_unlock(clk->parent, clk->mutex, flags); +} + +static void unlock_parent_rate(struct clk *clk) +{ + unsigned long flags; + + if (clk->parent == NULL) + return; + + __clk_lock(clk->parent, clk->mutex, &flags); + + unlock_parent_rate(clk->parent); + clk->parent->rate_locked--; + + __clk_unlock(clk->parent, clk->mutex, flags); +} + int clk_set_rate(struct clk *clk, unsigned long rate) { - clk->rate = rate; - return 0; + int err; + unsigned long flags; + + if (clk == NULL) + return -EINVAL; + + __clk_lock(clk, NO_LOCK, &flags); + + if (clk->enabled) { + err = -EBUSY; + goto unlock_and_return; + } + if (clk->rate_locked) { + err = -EAGAIN; + goto unlock_and_return; + } + + lock_parent_rate(clk); + err = __clk_set_rate(clk, rate); + unlock_parent_rate(clk); + +unlock_and_return: + __clk_unlock(clk, NO_LOCK, flags); + + return err; } EXPORT_SYMBOL(clk_set_rate); +int clk_set_rate_rec(struct clk *clk, unsigned long rate) +{ + int err; + unsigned long flags; + + if ((clk == NULL) || (clk->parent == NULL)) + return -EINVAL; + + __clk_lock(clk->parent, clk->mutex, &flags); + + if (clk->parent->enabled) { + err = -EBUSY; + goto unlock_and_return; + } + if (clk->parent->rate_locked != 1) { + err = -EAGAIN; + goto unlock_and_return; + } + err = __clk_set_rate(clk->parent, rate); + +unlock_and_return: + __clk_unlock(clk->parent, clk->mutex, flags); + + return err; +} + int clk_set_parent(struct clk *clk, struct clk *parent) { - /*TODO*/ - return -ENOSYS; + int err = 0; + unsigned long flags; + struct clk **p; + + if ((clk == NULL) || (clk->parents == NULL)) + return -EINVAL; + for (p = clk->parents; *p != parent; p++) { + if (*p == NULL) /* invalid parent */ + return -EINVAL; + } + + __clk_lock(clk, NO_LOCK, &flags); + + if ((clk->ops != NULL) && (clk->ops->set_parent != NULL)) { + err = clk->ops->set_parent(clk, parent); + if (err) + goto unlock_and_return; + } else if (clk->enabled) { + err = __clk_enable(parent, clk->mutex); + if (err) + goto unlock_and_return; + __clk_disable(clk->parent, clk->mutex); + } + + clk->parent = parent; + +unlock_and_return: + __clk_unlock(clk, NO_LOCK, flags); + + return err; } -EXPORT_SYMBOL(clk_set_parent); -static void clk_prcmu_enable(struct clk *clk) +/* PRCMU clock operations. */ + +static int prcmu_clk_enable(struct clk *clk) { - void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE) - + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off; + return prcmu_request_clock(clk->cg_sel, true); +} + +static void prcmu_clk_disable(struct clk *clk) +{ + if (prcmu_request_clock(clk->cg_sel, false)) { + pr_err("clock: %s failed to disable %s.\n", __func__, + clk->name); + } +} + +static int request_ape_opp100(bool enable) +{ + static unsigned int requests; + + if (enable) { + if (0 == requests++) { + return prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, + "clock", 100); + } + } else if (1 == requests--) { + prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "clock"); + } + return 0; +} + +static int prcmu_opp100_clk_enable(struct clk *clk) +{ + int r; - writel(1 << clk->prcmu_cg_bit, cg_set_reg); + r = request_ape_opp100(true); + if (r) { + pr_err("clock: %s failed to request APE OPP 100%% for %s.\n", + __func__, clk->name); + return r; + } + return prcmu_request_clock(clk->cg_sel, true); +} + +static void prcmu_opp100_clk_disable(struct clk *clk) +{ + if (prcmu_request_clock(clk->cg_sel, false)) + goto out_error; + if (request_ape_opp100(false)) + goto out_error; + return; + +out_error: + pr_err("clock: %s failed to disable %s.\n", __func__, clk->name); +} + +static unsigned long prcmu_clk_get_rate(struct clk *clk) +{ + return prcmu_clock_rate(clk->cg_sel); } -static void clk_prcmu_disable(struct clk *clk) +static long prcmu_clk_round_rate(struct clk *clk, unsigned long rate) { - void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE) - + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off; + return prcmu_round_clock_rate(clk->cg_sel, rate); +} - writel(1 << clk->prcmu_cg_bit, cg_clr_reg); +static int prcmu_clk_set_rate(struct clk *clk, unsigned long rate) +{ + return prcmu_set_clock_rate(clk->cg_sel, rate); } -static struct clkops clk_prcmu_ops = { - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, +struct clkops prcmu_clk_ops = { + .enable = prcmu_clk_enable, + .disable = prcmu_clk_disable, + .get_rate = prcmu_clk_get_rate, +}; + +struct clkops prcmu_scalable_clk_ops = { + .enable = prcmu_clk_enable, + .disable = prcmu_clk_disable, + .get_rate = prcmu_clk_get_rate, + .round_rate = prcmu_clk_round_rate, + .set_rate = prcmu_clk_set_rate, }; -static unsigned int clkrst_base[] = { - [1] = U8500_CLKRST1_BASE, - [2] = U8500_CLKRST2_BASE, - [3] = U8500_CLKRST3_BASE, - [5] = U8500_CLKRST5_BASE, - [6] = U8500_CLKRST6_BASE, +struct clkops prcmu_opp100_clk_ops = { + .enable = prcmu_opp100_clk_enable, + .disable = prcmu_opp100_clk_disable, + .get_rate = prcmu_clk_get_rate, }; -static void clk_prcc_enable(struct clk *clk) +/* PRCC clock operations. */ + +static int prcc_pclk_enable(struct clk *clk) { - void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + void __iomem *io_base = __io_address(clk->io_base); + + writel(clk->cg_sel, (io_base + PRCC_PCKEN)); + while (!(readl(io_base + PRCC_PCKSR) & clk->cg_sel)) + cpu_relax(); + return 0; +} - if (clk->prcc_kernel != -1) - writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN); +static void prcc_pclk_disable(struct clk *clk) +{ + void __iomem *io_base = __io_address(clk->io_base); - if (clk->prcc_bus != -1) - writel(1 << clk->prcc_bus, addr + PRCC_PCKEN); + writel(clk->cg_sel, (io_base + PRCC_PCKDIS)); } -static void clk_prcc_disable(struct clk *clk) +struct clkops prcc_pclk_ops = { + .enable = prcc_pclk_enable, + .disable = prcc_pclk_disable, +}; + +static int prcc_kclk_enable(struct clk *clk) { - void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + int err; + void __iomem *io_base = __io_address(clk->io_base); + + err = __clk_enable(clk->clock, clk->mutex); + if (err) + return err; - if (clk->prcc_bus != -1) - writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS); + writel(clk->cg_sel, (io_base + PRCC_KCKEN)); + while (!(readl(io_base + PRCC_KCKSR) & clk->cg_sel)) + cpu_relax(); - if (clk->prcc_kernel != -1) - writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS); + __clk_disable(clk->clock, clk->mutex); + + return 0; } -static struct clkops clk_prcc_ops = { - .enable = clk_prcc_enable, - .disable = clk_prcc_disable, +static void prcc_kclk_disable(struct clk *clk) +{ + void __iomem *io_base = __io_address(clk->io_base); + + (void)__clk_enable(clk->clock, clk->mutex); + writel(clk->cg_sel, (io_base + PRCC_KCKDIS)); + __clk_disable(clk->clock, clk->mutex); +} + +struct clkops prcc_kclk_ops = { + .enable = prcc_kclk_enable, + .disable = prcc_kclk_disable, }; -static struct clk clk_32khz = { - .name = "clk_32khz", - .rate = 32000, +struct clkops prcc_kclk_rec_ops = { + .enable = prcc_kclk_enable, + .disable = prcc_kclk_disable, + .round_rate = clk_round_rate_rec, + .set_rate = clk_set_rate_rec, }; -/* - * PRCMU level clock gating - */ +#ifdef CONFIG_CPU_FREQ +extern unsigned long dbx500_cpufreq_getfreq(void); -/* Bank 0 */ -static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK); -static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK); -static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK); -static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000); -static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK); -static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */ -static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000); -static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000); -static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK); -static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK); -static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK); -static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK); -static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK); -static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000); -static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK); -static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK); -static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK); -static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK); -static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK); -static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK); -static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK); -static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK); -static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK); -static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */ -static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK); -static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK); -static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK); -static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */ -static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */ - -/* Bank 1 */ -static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */ -static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ +unsigned long clk_smp_twd_get_rate(struct clk *clk) +{ + return dbx500_cpufreq_getfreq() / 2; +} -/* - * PRCC level clock gating - * Format: per#, clk, PCKEN bit, KCKEN bit, parent - */ +static struct clkops clk_smp_twd_ops = { + .get_rate = clk_smp_twd_get_rate, +}; -/* Peripheral Cluster #1 */ -static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); -static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); -static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); -static DEFINE_PRCC_CLK(1, spi3, 7, -1, NULL); -static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); -static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(1, msp1, 4, 4, &clk_msp1clk); -static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); -static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); -static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); -static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); - -/* Peripheral Cluster #2 */ -static DEFINE_PRCC_CLK(2, gpio1, 11, -1, NULL); -static DEFINE_PRCC_CLK(2, ssitx, 10, 7, NULL); -static DEFINE_PRCC_CLK(2, ssirx, 9, 6, NULL); -static DEFINE_PRCC_CLK(2, spi0, 8, -1, NULL); -static DEFINE_PRCC_CLK(2, sdi3, 7, 5, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, sdi1, 6, 4, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, msp2, 5, 3, &clk_msp02clk); -static DEFINE_PRCC_CLK(2, sdi4, 4, 2, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, pwl, 3, 1, NULL); -static DEFINE_PRCC_CLK(2, spi1, 2, -1, NULL); -static DEFINE_PRCC_CLK(2, spi2, 1, -1, NULL); -static DEFINE_PRCC_CLK(2, i2c3, 0, 0, &clk_i2cclk); - -/* Peripheral Cluster #3 */ -static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); -static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); -static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); -static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); -static DEFINE_PRCC_CLK(3, ssp1, 2, 2, &clk_sspclk); -static DEFINE_PRCC_CLK(3, ssp0, 1, 1, &clk_sspclk); -static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); - -/* Peripheral Cluster #4 is in the always on domain */ - -/* Peripheral Cluster #5 */ -static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); -static DEFINE_PRCC_CLK(5, usb, 0, 0, NULL); - -/* Peripheral Cluster #6 */ - -/* MTU ID in data */ -static DEFINE_PRCC_CLK_CUSTOM(6, mtu1, 8, -1, NULL, clk_mtu_get_rate, 1); -static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 7, -1, NULL, clk_mtu_get_rate, 0); -static DEFINE_PRCC_CLK(6, cfgreg, 6, 6, NULL); -static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); -static DEFINE_PRCC_CLK(6, unipro, 4, 1, &clk_uniproclk); -static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); -static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); -static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); -static DEFINE_PRCC_CLK(6, rng, 0, 0, &clk_rngclk); - -static struct clk clk_dummy_apb_pclk = { - .name = "apb_pclk", +static struct clk clk_smp_twd = { + .name = "smp_twd", + .ops = &clk_smp_twd_ops, }; -static struct clk_lookup u8500_clks[] = { - CLK(dummy_apb_pclk, NULL, "apb_pclk"), - - /* Peripheral Cluster #1 */ - CLK(gpio0, "gpio.0", NULL), - CLK(gpio0, "gpio.1", NULL), - CLK(slimbus0, "slimbus0", NULL), - CLK(i2c2, "nmk-i2c.2", NULL), - CLK(sdi0, "sdi0", NULL), - CLK(msp0, "msp0", NULL), - CLK(i2c1, "nmk-i2c.1", NULL), - CLK(uart1, "uart1", NULL), - CLK(uart0, "uart0", NULL), - - /* Peripheral Cluster #3 */ - CLK(gpio2, "gpio.2", NULL), - CLK(gpio2, "gpio.3", NULL), - CLK(gpio2, "gpio.4", NULL), - CLK(gpio2, "gpio.5", NULL), - CLK(sdi5, "sdi5", NULL), - CLK(uart2, "uart2", NULL), - CLK(ske, "ske", NULL), - CLK(ske, "nmk-ske-keypad", NULL), - CLK(sdi2, "sdi2", NULL), - CLK(i2c0, "nmk-i2c.0", NULL), - CLK(fsmc, "fsmc", NULL), - - /* Peripheral Cluster #5 */ - CLK(gpio3, "gpio.8", NULL), - - /* Peripheral Cluster #6 */ - CLK(hash1, "hash1", NULL), - CLK(pka, "pka", NULL), - CLK(hash0, "hash0", NULL), - CLK(cryp0, "cryp0", NULL), - - /* PRCMU level clock gating */ - - /* Bank 0 */ - CLK(svaclk, "sva", NULL), - CLK(siaclk, "sia", NULL), - CLK(sgaclk, "sga", NULL), - CLK(slimclk, "slim", NULL), - CLK(lcdclk, "lcd", NULL), - CLK(bmlclk, "bml", NULL), - CLK(hsitxclk, "stm-hsi.0", NULL), - CLK(hsirxclk, "stm-hsi.1", NULL), - CLK(hdmiclk, "hdmi", NULL), - CLK(apeatclk, "apeat", NULL), - CLK(apetraceclk, "apetrace", NULL), - CLK(mcdeclk, "mcde", NULL), - CLK(ipi2clk, "ipi2", NULL), - CLK(dmaclk, "dma40.0", NULL), - CLK(b2r2clk, "b2r2", NULL), - CLK(tvclk, "tv", NULL), - - /* Peripheral Cluster #1 */ - CLK(i2c4, "nmk-i2c.4", NULL), - CLK(spi3, "spi3", NULL), - CLK(msp1, "msp1", NULL), - - /* Peripheral Cluster #2 */ - CLK(gpio1, "gpio.6", NULL), - CLK(gpio1, "gpio.7", NULL), - CLK(ssitx, "ssitx", NULL), - CLK(ssirx, "ssirx", NULL), - CLK(spi0, "spi0", NULL), - CLK(sdi3, "sdi3", NULL), - CLK(sdi1, "sdi1", NULL), - CLK(msp2, "msp2", NULL), - CLK(sdi4, "sdi4", NULL), - CLK(pwl, "pwl", NULL), - CLK(spi1, "spi1", NULL), - CLK(spi2, "spi2", NULL), - CLK(i2c3, "nmk-i2c.3", NULL), - - /* Peripheral Cluster #3 */ - CLK(ssp1, "ssp1", NULL), - CLK(ssp0, "ssp0", NULL), - - /* Peripheral Cluster #5 */ - CLK(usb, "musb-ux500.0", "usb"), - - /* Peripheral Cluster #6 */ - CLK(mtu1, "mtu1", NULL), - CLK(mtu0, "mtu0", NULL), - CLK(cfgreg, "cfgreg", NULL), - CLK(hash1, "hash1", NULL), - CLK(unipro, "unipro", NULL), - CLK(rng, "rng", NULL), - - /* PRCMU level clock gating */ - - /* Bank 0 */ - CLK(uniproclk, "uniproclk", NULL), - CLK(dsialtclk, "dsialt", NULL), - - /* Bank 1 */ - CLK(rngclk, "rng", NULL), - CLK(uiccclk, "uicc", NULL), +static struct clk_lookup clk_smp_twd_lookup = { + .clk = &clk_smp_twd, + .dev_id = "smp_twd", }; +#endif #ifdef CONFIG_DEBUG_FS /* @@ -585,8 +596,8 @@ err_out: static int clk_debugfs_register_one(struct clk *c) { - struct clk *pa = c->parent_periph; - struct clk *bpa = c->parent_cluster; + struct clk *pa = c->parent; + struct clk *bpa = c->bus_parent; if (!(bpa && !pa)) { c->dent = clk_debugfs_register_dir(c, @@ -610,8 +621,8 @@ static int clk_debugfs_register_one(struct clk *c) static int clk_debugfs_register(struct clk *c) { int err; - struct clk *pa = c->parent_periph; - struct clk *bpa = c->parent_cluster; + struct clk *pa = c->parent; + struct clk *bpa = c->bus_parent; if (pa && (!pa->dent && !pa->dent_bus)) { err = clk_debugfs_register(pa); @@ -658,66 +669,25 @@ err_out: late_initcall(clk_debugfs_init); #endif /* defined(CONFIG_DEBUG_FS) */ -unsigned long clk_smp_twd_rate = 500000000; - -unsigned long clk_smp_twd_get_rate(struct clk *clk) -{ - return clk_smp_twd_rate; -} - -static struct clk clk_smp_twd = { - .get_rate = clk_smp_twd_get_rate, - .name = "smp_twd", -}; - -static struct clk_lookup clk_smp_twd_lookup = { - .dev_id = "smp_twd", - .clk = &clk_smp_twd, -}; - -#ifdef CONFIG_CPU_FREQ - -static int clk_twd_cpufreq_transition(struct notifier_block *nb, - unsigned long state, void *data) -{ - struct cpufreq_freqs *f = data; - - if (state == CPUFREQ_PRECHANGE) { - /* Save frequency in simple Hz */ - clk_smp_twd_rate = (f->new * 1000) / 2; - } - - return NOTIFY_OK; -} - -static struct notifier_block clk_twd_cpufreq_nb = { - .notifier_call = clk_twd_cpufreq_transition, -}; - -static int clk_init_smp_twd_cpufreq(void) -{ - return cpufreq_register_notifier(&clk_twd_cpufreq_nb, - CPUFREQ_TRANSITION_NOTIFIER); -} -late_initcall(clk_init_smp_twd_cpufreq); - -#endif - int __init clk_init(void) { - if (cpu_is_u5500()) { - /* Clock tree for U5500 not implemented yet */ - clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; - clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; - clk_uartclk.rate = 36360000; - clk_sdmmcclk.rate = 99900000; + if (cpu_is_u8500()) { + prcmu_base = __io_address(U8500_PRCMU_BASE); + } else if (cpu_is_u5500()) { + prcmu_base = __io_address(U5500_PRCMU_BASE); + } else { + pr_err("clock: Unknown DB Asic.\n"); + return -EIO; } - clkdev_add_table(u8500_clks, ARRAY_SIZE(u8500_clks)); - clkdev_add(&clk_smp_twd_lookup); + if (cpu_is_u8500()) + db8500_clk_init(); + else if (cpu_is_u5500()) + db5500_clk_init(); -#ifdef CONFIG_DEBUG_FS - clk_debugfs_add_table(u8500_clks, ARRAY_SIZE(u8500_clks)); +#ifdef CONFIG_CPU_FREQ + clkdev_add(&clk_smp_twd_lookup); #endif + return 0; } diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h index d776ada08db..2403e51dc7f 100644 --- a/arch/arm/mach-ux500/clock.h +++ b/arch/arm/mach-ux500/clock.h @@ -1,11 +1,61 @@ /* - * Copyright (C) 2010 ST-Ericsson + * Copyright (C) 2010 ST-Ericsson SA * Copyright (C) 2009 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#ifndef UX500_CLOCK_H +#define UX500_CLOCK_H + +#include <linux/clkdev.h> + +/** + * struct clk + * @ops: The hardware specific operations defined for the clock. + * @name: The name of the clock. + * @mutex: The mutex to lock when operating on the clock. %NULL means that + * the common clock spinlock will be used. + * @enabled: A reference counter of the enable requests for the clock. + * @rate_locked: A rate lock counter used by clk_set_rate(). + * @opp100: A flag saying whether the clock is requested to run at the + * OPP 100%% frequency. + * @rate: The frequency of the clock. For scalable and scaling clocks, + * this is the OPP 100%% frequency. + * @io_base: An IO memory base address, meaningful only when considered + * together with the defined @ops. + * @cg_sel: Clock gate selector, meaningful only when considered together + * with the specified @ops. + * @parent: The current (or only) parent clock of the clock. + * @bus_parent: The (optional) auxiliary bus clock "parent" of the clock. + * @parents: A list of the possible parents the clock can have. This should + * be a %NULL-terminated &struct_clk array. Present if and only + * if clk_set_parent() is implemented for the clock. + * @regulator: The regulator needed to have the clock functional, if any. + * @clock: The clock needed to control the clock, if any. + */ +struct clk { + const struct clkops *ops; + const char *name; + struct mutex *mutex; + unsigned int enabled; + unsigned int rate_locked; + bool opp100; + unsigned long rate; + unsigned int io_base; + u32 cg_sel; + struct clk *parent; + struct clk *bus_parent; + struct clk **parents; + struct regulator *regulator; + struct clk *clock; + struct list_head list; +#if defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ + struct dentry *dent_bus; /* For visible tree hierarchy */ +#endif +}; /** * struct clkops - ux500 clock operations @@ -18,135 +68,120 @@ * NULL, the rate in the struct clk will be used. */ struct clkops { - void (*enable) (struct clk *); - void (*disable) (struct clk *); - unsigned long (*get_rate) (struct clk *); + int (*enable)(struct clk *); + void (*disable)(struct clk *); + unsigned long (*get_rate)(struct clk *); + int (*set_rate)(struct clk *, unsigned long); + long (*round_rate)(struct clk *, unsigned long); int (*set_parent)(struct clk *, struct clk *); }; -/** - * struct clk - ux500 clock structure - * @ops: pointer to clkops struct used to control this clock - * @name: name, for debugging - * @enabled: refcount. positive if enabled, zero if disabled - * @get_rate: custom callback for getting the clock rate - * @data: custom per-clock data for example for the get_rate - * callback - * @rate: fixed rate for clocks which don't implement - * ops->getrate - * @prcmu_cg_off: address offset of the combined enable/disable register - * (used on u8500v1) - * @prcmu_cg_bit: bit in the combined enable/disable register (used on - * u8500v1) - * @prcmu_cg_mgt: address of the enable/disable register (used on - * u8500ed) - * @cluster: peripheral cluster number - * @prcc_bus: bit for the bus clock in the peripheral's CLKRST - * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST. - * -1 if no kernel clock exists. - * @parent_cluster: pointer to parent's cluster clk struct - * @parent_periph: pointer to parent's peripheral clk struct - * - * Peripherals are organised into clusters, and each cluster has an associated - * bus clock. Some peripherals also have a parent peripheral clock. - * - * In order to enable a clock for a peripheral, we need to enable: - * (1) the parent cluster (bus) clock at the PRCMU level - * (2) the parent peripheral clock (if any) at the PRCMU level - * (3) the peripheral's bus & kernel clock at the PRCC level - * - * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each - * of the cluster and peripheral clocks, and hooking these as the parents of - * the individual peripheral clocks. - * - * (3) is handled by specifying the bits in the PRCC control registers required - * to enable these clocks and modifying them in the ->enable and - * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK). - * - * This structure describes both the PRCMU-level clocks and PRCC-level clocks. - * The prcmu_* fields are only used for the PRCMU clocks, and the cluster, - * prcc, and parent pointers are only used for the PRCC-level clocks. - */ -struct clk { - const struct clkops *ops; - const char *name; - unsigned int enabled; - unsigned long (*get_rate)(struct clk *); - void *data; - - unsigned long rate; - struct list_head list; +extern struct clkops prcmu_clk_ops; +extern struct clkops prcmu_scalable_clk_ops; +extern struct clkops prcmu_opp100_clk_ops; +extern struct mutex clk_opp100_mutex; +extern struct clkops prcc_pclk_ops; +extern struct clkops prcc_kclk_ops; +extern struct clkops prcc_kclk_rec_ops; +extern struct clkops sga_clk_ops; - /* These three are only for PRCMU clks */ +#define CLK_LOOKUP(_clk, _dev_id, _con_id) \ + { .dev_id = _dev_id, .con_id = _con_id, .clk = &_clk } - unsigned int prcmu_cg_off; - unsigned int prcmu_cg_bit; - unsigned int prcmu_cg_mgt; - - /* The rest are only for PRCC clks */ - - int cluster; - unsigned int prcc_bus; - unsigned int prcc_kernel; - - struct clk *parent_cluster; - struct clk *parent_periph; -#if defined(CONFIG_DEBUG_FS) - struct dentry *dent; /* For visible tree hierarchy */ - struct dentry *dent_bus; /* For visible tree hierarchy */ -#endif -}; +/* Define PRCMU Clock */ +#define DEF_PRCMU_CLK(_name, _cg_sel, _rate) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcmu_clk_ops, \ + .cg_sel = _cg_sel, \ + .rate = _rate, \ + } -#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ -struct clk clk_##_name = { \ - .name = #_name, \ - .ops = &clk_prcmu_ops, \ - .prcmu_cg_off = _cg_off, \ - .prcmu_cg_bit = _cg_bit, \ - .prcmu_cg_mgt = PRCM_##_reg##_MGT \ +#define DEF_PRCMU_SCALABLE_CLK(_name, _cg_sel) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcmu_scalable_clk_ops, \ + .cg_sel = _cg_sel, \ } -#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \ -struct clk clk_##_name = { \ - .name = #_name, \ - .ops = &clk_prcmu_ops, \ - .prcmu_cg_off = _cg_off, \ - .prcmu_cg_bit = _cg_bit, \ - .rate = _rate, \ - .prcmu_cg_mgt = PRCM_##_reg##_MGT \ +/* Use this for clocks that are only defined at OPP 100%. */ +#define DEF_PRCMU_OPP100_CLK(_name, _cg_sel, _rate) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcmu_opp100_clk_ops, \ + .cg_sel = _cg_sel, \ + .rate = _rate, \ + .mutex = &clk_opp100_mutex, \ } -#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ -struct clk clk_##_name = { \ - .name = #_name, \ - .ops = &clk_prcc_ops, \ - .cluster = _pclust, \ - .prcc_bus = _bus_en, \ - .prcc_kernel = _kernel_en, \ - .parent_cluster = &clk_per##_pclust##clk, \ - .parent_periph = _kernclk \ +/* Define PRCC clock */ +#define DEF_PRCC_PCLK(_name, _io_base, _cg_bit, _parent) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcc_pclk_ops, \ + .io_base = _io_base, \ + .cg_sel = BIT(_cg_bit), \ + .parent = _parent, \ } -#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \ -struct clk clk_##_name = { \ - .name = #_name, \ - .ops = &clk_prcc_ops, \ - .cluster = _pclust, \ - .prcc_bus = _bus_en, \ - .prcc_kernel = _kernel_en, \ - .parent_cluster = &clk_per##_pclust##clk, \ - .parent_periph = _kernclk, \ - .get_rate = _callback, \ - .data = (void *) _data \ +#define DEF_PRCC_KCLK(_name, _io_base, _cg_bit, _parent, _clock) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &prcc_kclk_ops, \ + .io_base = _io_base, \ + .cg_sel = BIT(_cg_bit), \ + .parent = _parent, \ + .clock = _clock, \ } +#define DEF_PER_CLK(_name, _bus_parent, _parent) \ + struct clk _name = { \ + .name = #_name, \ + .parent = _parent, \ + .bus_parent = _bus_parent, \ + } -#define CLK(_clk, _devname, _conname) \ - { \ - .clk = &clk_##_clk, \ - .dev_id = _devname, \ - .con_id = _conname, \ +#define DEF_MTU_CLK(_cg_sel, _name, _bus_parent) \ + struct clk _name = { \ + .name = #_name, \ + .ops = &mtu_clk_ops, \ + .cg_sel = _cg_sel, \ + .bus_parent = _bus_parent, \ } -int __init clk_db8500_ed_fixup(void); +/* Functions defined in clock.c */ int __init clk_init(void); +void clks_register(struct clk_lookup *clks, size_t num); +int __clk_enable(struct clk *clk, void *current_lock); +void __clk_disable(struct clk *clk, void *current_lock); +unsigned long __clk_get_rate(struct clk *clk, void *current_lock); +long clk_round_rate_rec(struct clk *clk, unsigned long rate); +int clk_set_rate_rec(struct clk *clk, unsigned long rate); + +#ifdef CONFIG_DEBUG_FS +int dbx500_clk_debug_init(struct clk **clks, int num); +void clk_debugfs_add_table(struct clk_lookup *cl, size_t num); +#else +static inline int dbx500_clk_debug_init(struct clk **clks, int num) +{ + return 0; +} +#endif + +#ifdef CONFIG_UX500_SOC_DB8500 +int __init db8500_clk_init(void); +int __init db8500_clk_debug_init(void); +#else +static inline int db8500_clk_init(void) { return 0; } +static inline int db8500_clk_debug_init(void) { return 0; } +#endif + +#ifdef CONFIG_UX500_SOC_DB5500 +int __init db5500_clk_init(void); +int __init db5500_clk_debug_init(void); +#else +static inline int db5500_clk_init(void) { return 0; } +static inline int db5500_clk_debug_init(void) { return 0; } +#endif + +#endif diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index bca47f32082..ab50ca6865f 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -9,20 +9,23 @@ #include <linux/amba/bus.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/gpio/nomadik.h> -#include <asm/mach/map.h> #include <asm/pmu.h> +#include <asm/mach/map.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> -#include <plat/gpio-nomadik.h> +#include <linux/gpio.h> #include <mach/hardware.h> #include <mach/devices.h> #include <mach/setup.h> #include <mach/irqs.h> #include <mach/usb.h> +#include <mach/ste-dma40-db5500.h> #include "devices-db5500.h" -#include "ste-dma40-db5500.h" static struct map_desc u5500_uart_io_desc[] __initdata = { __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K), @@ -35,8 +38,16 @@ static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K), __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K), __IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U5500_MTU1_BASE, SZ_4K), + __IO_DEV_DESC(U5500_RTC_BASE, SZ_4K), + __IO_DEV_DESC(U5500_MTIMER_BASE, SZ_4K), __IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K), + /* Map U5500_PUBLIC_BOOT_ROM_BASE (base+18000) only + * for TEE security driver + * and avoid overlap with asic ID at base+1D000 */ + __MEM_DEV_DESC(U5500_BOOT_ROM_BASE+0x18000, 6*SZ_4K), + __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO2_BASE, SZ_4K), @@ -44,6 +55,11 @@ static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K), __IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K), __IO_DEV_DESC(U5500_PRCMU_TCDM_BASE, SZ_4K), + __IO_DEV_DESC(U5500_CLKRST1_BASE, SZ_4K), + __IO_DEV_DESC(U5500_CLKRST2_BASE, SZ_4K), + __IO_DEV_DESC(U5500_CLKRST3_BASE, SZ_4K), + __IO_DEV_DESC(U5500_CLKRST5_BASE, SZ_4K), + __IO_DEV_DESC(U5500_CLKRST6_BASE, SZ_4K), }; static struct resource mbox0_resources[] = { @@ -130,31 +146,58 @@ static struct platform_device mbox2_device = { .num_resources = ARRAY_SIZE(mbox2_resources), }; +static struct platform_device db5500_prcmu_device = { + .name = "db5500-prcmu", +}; + static struct platform_device *db5500_platform_devs[] __initdata = { + &u5500_gpio_devs[0], + &u5500_gpio_devs[1], + &u5500_gpio_devs[2], + &u5500_gpio_devs[3], + &u5500_gpio_devs[4], + &u5500_gpio_devs[5], + &u5500_gpio_devs[6], + &u5500_gpio_devs[7], &mbox0_device, &mbox1_device, &mbox2_device, + &db5500_prcmu_device, + &u5500_wdt_device, }; -static resource_size_t __initdata db5500_gpio_base[] = { - U5500_GPIOBANK0_BASE, - U5500_GPIOBANK1_BASE, - U5500_GPIOBANK2_BASE, - U5500_GPIOBANK3_BASE, - U5500_GPIOBANK4_BASE, - U5500_GPIOBANK5_BASE, - U5500_GPIOBANK6_BASE, - U5500_GPIOBANK7_BASE, -}; +static u8 db5500_revision; -static void __init db5500_add_gpios(struct device *parent) +bool cpu_is_u5500v1() { - struct nmk_gpio_platform_data pdata = { - /* No custom data yet */ - }; + return db5500_revision == 0xA0; +} - dbx500_add_gpios(parent, ARRAY_AND_SIZE(db5500_gpio_base), - IRQ_DB5500_GPIO0, &pdata); +bool cpu_is_u5500v2() +{ + return (db5500_revision & 0xf0) == 0xB0; +} + +bool cpu_is_u5500v20() +{ + return db5500_revision == 0xB0; +} + +bool cpu_is_u5500v21() +{ + return db5500_revision == 0xB1; +} + +static void db5500_rev_init(void) +{ + unsigned int asicid; + + /* As in devicemaps_init() */ + local_flush_tlb_all(); + flush_cache_all(); + + asicid = readl_relaxed(__io_address(U5500_ASIC_ID_ADDRESS)); + db5500_revision = asicid & 0xff; } void __init u5500_map_io(void) @@ -169,6 +212,8 @@ void __init u5500_map_io(void) iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); _PRCMU_BASE = __io_address(U5500_PRCMU_BASE); + + db5500_rev_init(); } static void __init db5500_pmu_init(void) @@ -229,9 +274,12 @@ struct device * __init u5500_init_devices(void) struct device *parent; int i; +#ifdef CONFIG_STM_TRACE + /* Early init for STM tracing */ + /* platform_device_register(&u5500_stm_device); */ +#endif parent = db5500_soc_device_init(); - db5500_add_gpios(parent); db5500_pmu_init(); db5500_dma_init(parent); db5500_add_rtc(parent); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 9bd8163896c..ac7c4df4996 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -14,20 +14,23 @@ #include <linux/amba/bus.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/gpio/nomadik.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/delay.h> -#include <asm/mach/map.h> #include <asm/pmu.h> -#include <plat/gpio-nomadik.h> +#include <asm/mach/map.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> #include <mach/usb.h> #include <mach/db8500-regs.h> +#include <mach/ste-dma40-db8500.h> #include "devices-db8500.h" -#include "ste-dma40-db8500.h" +#include "prcc.h" /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_uart_io_desc[] __initdata = { @@ -35,28 +38,45 @@ static struct map_desc u8500_uart_io_desc[] __initdata = { __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), }; -static struct map_desc u8500_io_desc[] __initdata = { +/* U8500 and U9540 common io_desc */ +static struct map_desc u8500_common_io_desc[] __initdata = { /* SCU base also covers GIC CPU BASE and TWD with its 4K page */ __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_MTU1_BASE, SZ_4K), + __IO_DEV_DESC(U8500_RTC_BASE, SZ_4K), __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), - __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), - __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), +}; + +/* U8500 IO map specific description */ +static struct map_desc u8500_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), + /* Map U8500_PUBLIC_BOOT_ROM_BASE (base+17000) only + * for TEE security driver + * and avoid overlap with asic ID at base+1D000 */ + __MEM_DEV_DESC(U8500_BOOT_ROM_BASE+0x17000, 6*SZ_4K), __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), }; +/* U9540 IO map specific description */ +static struct map_desc u9540_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K + SZ_8K), + __MEM_DEV_DESC_DB9540_ROM(U9540_BOOT_ROM_BASE, SZ_1M), + __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K), +}; + void __init u8500_map_io(void) { /* @@ -64,9 +84,22 @@ void __init u8500_map_io(void) */ iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc)); + /* + * STE NMF CM driver only used on the U8500 allocate using + * dma_alloc_coherent: + * 8M for SIA and SVA data + 2M for SIA code + 2M for SVA code + * Can't be higher than 14M with VMALLOC_END at 0xFF000000 + */ + init_consistent_dma_size(14*SZ_1M); + ux500_map_io(); - iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); + iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc)); + + if (cpu_is_u9540()) + iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc)); + else + iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); _PRCMU_BASE = __io_address(U8500_PRCMU_BASE); } @@ -115,34 +148,50 @@ static struct platform_device db8500_prcmu_device = { .name = "db8500-prcmu", }; -static struct platform_device *platform_devs[] __initdata = { - &u8500_dma40_device, - &db8500_pmu_device, - &db8500_prcmu_device, +static unsigned int per_clkrst_base[7] = { + 0, + U8500_CLKRST1_BASE, + U8500_CLKRST2_BASE, + U8500_CLKRST3_BASE, + 0, + 0, + U8500_CLKRST6_BASE, }; -static resource_size_t __initdata db8500_gpio_base[] = { - U8500_GPIOBANK0_BASE, - U8500_GPIOBANK1_BASE, - U8500_GPIOBANK2_BASE, - U8500_GPIOBANK3_BASE, - U8500_GPIOBANK4_BASE, - U8500_GPIOBANK5_BASE, - U8500_GPIOBANK6_BASE, - U8500_GPIOBANK7_BASE, - U8500_GPIOBANK8_BASE, -}; - -static void __init db8500_add_gpios(struct device *parent) +void u8500_reset_ip(unsigned char per, unsigned int ip_mask) { - struct nmk_gpio_platform_data pdata = { - .supports_sleepmode = true, - }; + void __iomem *prcc_rst_set, *prcc_rst_clr; + + if (per == 0 || per == 4 || per == 5 || per > 6) + return; - dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base), - IRQ_DB8500_GPIO0, &pdata); + prcc_rst_set = __io_address(per_clkrst_base[per] + PRCC_K_SOFTRST_SET); + prcc_rst_clr = __io_address(per_clkrst_base[per] + PRCC_K_SOFTRST_CLR); + + /* Activate soft reset PRCC_K_SOFTRST_CLR */ + writel(ip_mask, prcc_rst_clr); + udelay(1); + + /* Release soft reset PRCC_K_SOFTRST_SET */ + writel(ip_mask, prcc_rst_set); + udelay(1); } +static struct platform_device *platform_devs[] __initdata = { + &u8500_gpio_devs[0], + &u8500_gpio_devs[1], + &u8500_gpio_devs[2], + &u8500_gpio_devs[3], + &u8500_gpio_devs[4], + &u8500_gpio_devs[5], + &u8500_gpio_devs[6], + &u8500_gpio_devs[7], + &u8500_gpio_devs[8], + &db8500_pmu_device, + &db8500_prcmu_device, + &u8500_wdt_device, +}; + static int usb_db8500_rx_dma_cfg[] = { DB8500_DMA_DEV38_USB_OTG_IEP_1_9, DB8500_DMA_DEV37_USB_OTG_IEP_2_10, @@ -190,10 +239,14 @@ struct device * __init u8500_init_devices(void) struct device *parent; int i; +#ifdef CONFIG_STM_TRACE + /* Early init for STM tracing */ + platform_device_register(&u8500_stm_device); +#endif parent = db8500_soc_device_init(); + db8500_dma_init(parent); db8500_add_rtc(parent); - db8500_add_gpios(parent); db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); platform_device_register_data(parent, diff --git a/arch/arm/mach-ux500/cpu-db8500.h b/arch/arm/mach-ux500/cpu-db8500.h new file mode 100644 index 00000000000..80766f49d60 --- /dev/null +++ b/arch/arm/mach-ux500/cpu-db8500.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL), version 2 + * + * CPU specific routines. + * + * Author: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com> + */ + +#ifndef __CPU_DB8500_H__ +#define __CPU_DB8500_H__ + +/* PER1 IP's softreset masks */ +#define PRCC_K_SOFTRST_UART0_MASK (1 << 0) +#define PRCC_K_SOFTRST_UART1_MASK (1 << 1) +#define PRCC_K_SOFTRST_I2C1_MASK (1 << 2) +#define PRCC_K_SOFTRST_MSP0_MASK (1 << 3) +#define PRCC_K_SOFTRST_MSP1_MASK (1 << 4) +#define PRCC_K_SOFTRST_SDI0_MASK (1 << 5) +#define PRCC_K_SOFTRST_I2C2_MASK (1 << 6) +#define PRCC_K_SOFTRST_SP13_MASK (1 << 7) +#define PRCC_K_SOFTRST_SLIMBUS0_MASK (1 << 8) +#define PRCC_K_SOFTRST_I2C4_MASK (1 << 9) +#define PRCC_K_SOFTRST_MSP3_MASK (1 << 10) +#define PRCC_K_SOFTRST_PER_MSP3_MASK (1 << 11) +#define PRCC_K_SOFTRST_PER_MSP1_MASK (1 << 12) +#define PRCC_K_SOFTRST_PER_MSP0_MASK (1 << 13) +#define PRCC_K_SOFTRST_PER_SLIMBUS_MASK (1 << 14) + +/* PER2 IP's softreset masks */ +#define PRCC_K_SOFTRST_I2C3_MASK (1 << 0) +#define PRCC_K_SOFTRST_PWL_MASK (1 << 1) +#define PRCC_K_SOFTRST_SDI4_MASK (1 << 2) +#define PRCC_K_SOFTRST_MSP2_MASK (1 << 3) +#define PRCC_K_SOFTRST_SDI1_MASK (1 << 4) +#define PRCC_K_SOFTRST_SDI3_MASK (1 << 5) +#define PRCC_K_SOFTRST_HSIRX_MASK (1 << 6) +#define PRCC_K_SOFTRST_HSITX_MASK (1 << 7) +#define PRCC_K_SOFTRST_PER_MSP2_MASK (1 << 8) + +/* PER3 IP's softreset masks */ +#define PRCC_K_SOFTRST_SSP0_MASK (1 << 1) +#define PRCC_K_SOFTRST_SSP1_MASK (1 << 2) +#define PRCC_K_SOFTRST_I2C0_MASK (1 << 3) +#define PRCC_K_SOFTRST_SDI2_MASK (1 << 4) +#define PRCC_K_SOFTRST_SKE_MASK (1 << 5) +#define PRCC_K_SOFTRST_UART2_MASK (1 << 6) +#define PRCC_K_SOFTRST_SDI5_MASK (1 << 7) + +/* PER6 IP's softreset masks */ +#define PRCC_K_SOFTRST_RNG_MASK (1 << 0) + +void u8500_reset_ip(unsigned char per, unsigned int ip_mask); + +#endif diff --git a/arch/arm/mach-ux500/cpu-db9500.c b/arch/arm/mach-ux500/cpu-db9500.c new file mode 100644 index 00000000000..4d900cbe537 --- /dev/null +++ b/arch/arm/mach-ux500/cpu-db9500.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * + * Author: Pawel SZYSZUK <pawel.szyszuk@stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ +#include <linux/types.h> +#include <linux/init.h> + +#include <mach/id.h> + +#include "pins.h" + +/* + * U9500 is currently using U8500v2 HW. Therefore, the platform detection + * is based on the kernel cmd line setting (early_param "pinsfor"). + */ +bool cpu_is_u9500() +{ + if (pins_for_u9500()) + return true; + else + return false; +} diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index d11f3892a27..935d5006261 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -9,6 +9,7 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/mfd/dbx500-prcmu.h> #include <linux/mfd/db8500-prcmu.h> #include <linux/mfd/db5500-prcmu.h> #include <linux/clksrc-dbx500-prcmu.h> @@ -18,13 +19,17 @@ #include <linux/stat.h> #include <linux/of.h> #include <linux/of_irq.h> +#include <linux/delay.h> #include <asm/hardware/gic.h> #include <asm/mach/map.h> +#include <asm/system_misc.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> +#include <mach/reboot_reasons.h> +#include <mach/pm.h> #include "clock.h" @@ -35,6 +40,52 @@ static const struct of_device_id ux500_dt_irq_match[] = { {}, }; +/* + * The reboot reason string can be 255 characters long and the memory + * in which we save the sw reset reason is 2 bytes. Therefore we need to + * convert the string into a 16 bit pattern. + * + * See file reboot_reasons.h for conversion. + */ +static unsigned short map_cmd_to_code(const char *cmd) +{ + int i; + + if (cmd == NULL) + /* normal reboot w/o argument */ + return SW_RESET_NO_ARGUMENT; + + /* Search through reboot reason list */ + for (i = 0; i < reboot_reasons_size; i++) { + if (!strcmp(reboot_reasons[i].reason, cmd)) + return reboot_reasons[i].code; + } + + /* No valid Reboot Reason found */ + return SW_RESET_CRASH; +} + +void ux500_restart(char mode, const char *cmd) +{ + unsigned short reset_code; + + reset_code = map_cmd_to_code(cmd); + prcmu_system_reset(reset_code); + + mdelay(1000); + + /* + * On 5500, the PRCMU firmware waits for up to 2 seconds for the modem + * to respond. + */ + if (cpu_is_u5500()) + mdelay(2000); + + printk(KERN_ERR "Reboot via PRCMU failed -- System halted\n"); + while (1) + ; +} + void __init ux500_init_irq(void) { void __iomem *dist_base; @@ -43,7 +94,7 @@ void __init ux500_init_irq(void) if (cpu_is_u5500()) { dist_base = __io_address(U5500_GIC_DIST_BASE); cpu_base = __io_address(U5500_GIC_CPU_BASE); - } else if (cpu_is_u8500()) { + } else if (cpu_is_u8500() || cpu_is_u9540()) { dist_base = __io_address(U8500_GIC_DIST_BASE); cpu_base = __io_address(U8500_GIC_CPU_BASE); } else @@ -57,13 +108,21 @@ void __init ux500_init_irq(void) gic_init(0, 29, dist_base, cpu_base); /* + * On WD reboot gic is in some cases decoupled. + * This will make sure that the GIC is correctly configured. + */ + ux500_pm_gic_recouple(); + + /* * Init clocks here so that they are available for system timer * initialization. */ if (cpu_is_u5500()) db5500_prcmu_early_init(); - if (cpu_is_u8500()) + if (cpu_is_u8500() || cpu_is_u9540()) db8500_prcmu_early_init(); + + arm_pm_restart = ux500_restart; clk_init(); } diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c new file mode 100644 index 00000000000..b54884bd254 --- /dev/null +++ b/arch/arm/mach-ux500/cpuidle.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM) + * + * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com> + * and Jonas Aaberg <jonas.aberg@stericsson.com>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/cpuidle.h> +#include <linux/clockchips.h> +#include <linux/spinlock.h> +#include <linux/atomic.h> +#include <linux/smp.h> +#include <linux/mfd/dbx500-prcmu.h> + +#include <asm/cpuidle.h> +#include <asm/proc-fns.h> + +static atomic_t master = ATOMIC_INIT(0); +static DEFINE_SPINLOCK(master_lock); +static DEFINE_PER_CPU(struct cpuidle_device, ux500_cpuidle_device); + +static inline int ux500_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + int this_cpu = smp_processor_id(); + bool recouple = false; + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu); + + if (atomic_inc_return(&master) == num_online_cpus()) { + + /* With this lock, we prevent the other cpu to exit and enter + * this function again and become the master */ + if (!spin_trylock(&master_lock)) + goto wfi; + + /* decouple the gic from the A9 cores */ + if (prcmu_gic_decouple()) + goto out; + + /* If an error occur, we will have to recouple the gic + * manually */ + recouple = true; + + /* At this state, as the gic is decoupled, if the other + * cpu is in WFI, we have the guarantee it won't be wake + * up, so we can safely go to retention */ + if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1)) + goto out; + + /* The prcmu will be in charge of watching the interrupts + * and wake up the cpus */ + if (prcmu_copy_gic_settings()) + goto out; + + /* Check in the meantime an interrupt did + * not occur on the gic ... */ + if (prcmu_gic_pending_irq()) + goto out; + + /* ... and the prcmu */ + if (prcmu_pending_irq()) + goto out; + + /* Go to the retention state, the prcmu will wait for the + * cpu to go WFI and this is what happens after exiting this + * 'master' critical section */ + if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true)) + goto out; + + /* When we switch to retention, the prcmu is in charge + * of recoupling the gic automatically */ + recouple = false; + + spin_unlock(&master_lock); + } +wfi: + cpu_do_idle(); +out: + atomic_dec(&master); + + if (recouple) { + prcmu_gic_recouple(); + spin_unlock(&master_lock); + } + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &this_cpu); + + return index; +} + +static struct cpuidle_driver ux500_idle_driver = { + .name = "ux500_idle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states = { + ARM_CPUIDLE_WFI_STATE, + { + .enter = ux500_enter_idle, + .exit_latency = 70, + .target_residency = 260, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "ApIdle", + .desc = "ARM Retention", + }, + }, + .safe_state_index = 0, + .state_count = 2, +}; + +/* + * For each cpu, setup the broadcast timer because we will + * need to migrate the timers for the states >= ApIdle. + */ +static void ux500_setup_broadcast_timer(void *arg) +{ + int cpu = smp_processor_id(); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); +} + +int __init ux500_idle_init(void) +{ + int ret, cpu; + struct cpuidle_device *device; + + /* Configure wake up reasons */ + prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | + PRCMU_WAKEUP(ABB)); + + /* + * Configure the timer broadcast for each cpu, that must + * be done from the cpu context, so we use a smp cross + * call with 'on_each_cpu'. + */ + on_each_cpu(ux500_setup_broadcast_timer, NULL, 1); + + ret = cpuidle_register_driver(&ux500_idle_driver); + if (ret) { + printk(KERN_ERR "failed to register ux500 idle driver\n"); + return ret; + } + + for_each_online_cpu(cpu) { + device = &per_cpu(ux500_cpuidle_device, cpu); + device->cpu = cpu; + ret = cpuidle_register_device(device); + if (ret) { + printk(KERN_ERR "Failed to register cpuidle " + "device for cpu%d\n", cpu); + goto out_unregister; + } + } +out: + return ret; + +out_unregister: + for_each_online_cpu(cpu) { + device = &per_cpu(ux500_cpuidle_device, cpu); + cpuidle_unregister_device(device); + } + + cpuidle_unregister_driver(&ux500_idle_driver); + goto out; +} + +device_initcall(ux500_idle_init); diff --git a/arch/arm/mach-ux500/dbx500_dump.c b/arch/arm/mach-ux500/dbx500_dump.c new file mode 100644 index 00000000000..89470216590 --- /dev/null +++ b/arch/arm/mach-ux500/dbx500_dump.c @@ -0,0 +1,233 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * Author: Johan Bjornstedt <johan.bjornstedt@stericsson.com> + * + * Save DBx500 registers in case of kernel crash + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/kdebug.h> + +#include <mach/hardware.h> +#include <mach/db8500-regs.h> +#include <mach/db5500-regs.h> + +struct dbx500_dump_info { + char *name; + int *data; + int *io_addr; + int phy_addr; + int size; +}; + +static struct dbx500_dump_info db8500_dump[] = { + { + .name = "prcmu_tcdm", + .phy_addr = U8500_PRCMU_TCDM_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_non_sec_1", + .phy_addr = U8500_PRCMU_BASE, + .size = 0x340, + }, + { + .name = "prcmu_pmb", + .phy_addr = (U8500_PRCMU_BASE + 0x344), + .size = 0xC, + }, + { + .name = "prcmu_thermal", + .phy_addr = (U8500_PRCMU_BASE + 0x3C0), + .size = 0x40, + }, + { + .name = "prcmu_non_sec_2", + .phy_addr = (U8500_PRCMU_BASE + 0x404), + .size = 0x1FC, + }, + { + .name = "prcmu_icn_pmu", + .phy_addr = (U8500_PRCMU_BASE + 0xE00), + .size = 0x90, + }, + { + .name = "db8500_fuses", + .phy_addr = (U8500_BACKUPRAM1_BASE + 0xF70), + .size = 0xc, + }, +}; + +static struct dbx500_dump_info db9540_dump[] = { + { + .name = "prcmu_tcdm", + .phy_addr = U9540_PRCMU_TCDM_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_non_sec_1", + .phy_addr = U8500_PRCMU_BASE, + .size = 0x340, + }, + { + .name = "prcmu_pmb", + .phy_addr = (U8500_PRCMU_BASE + 0x344), + .size = 0xC, + }, + { + .name = "prcmu_thermal", + .phy_addr = (U8500_PRCMU_BASE + 0x3C0), + .size = 0x40, + }, + { + .name = "prcmu_non_sec_2", + .phy_addr = (U8500_PRCMU_BASE + 0x404), + .size = 0x1FC, + }, + { + .name = "prcmu_icn_pmu", + .phy_addr = (U8500_PRCMU_BASE + 0xE00), + .size = 0x118, + }, +}; + +static struct dbx500_dump_info db5500_dump[] = { + { + .name = "prcmu_tcdm", + .phy_addr = U5500_PRCMU_TCDM_BASE, + .size = 0x5000, + }, + { + .name = "prcmu_gpio", + .phy_addr = U5500_GPIO2_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_msp1", + .phy_addr = U5500_MSP1_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_sec", + .phy_addr = (U5500_PRCMU_BASE + 0x1000), + .size = 0x1000, + }, + { + .name = "prcmu_unsec", + .phy_addr = U5500_PRCMU_BASE, + .size = 0x1000, + }, +}; + +static struct dbx500_dump_info *dbx500_dump; +static int dbx500_dump_size; +static bool dbx500_dump_done; + +static DEFINE_SPINLOCK(dbx500_dump_lock); + +static int crash_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + int i; + unsigned long flags; + + /* + * Since there are two ways into this function (die and panic) we have + * to make sure we only dump the DB registers once + */ + spin_lock_irqsave(&dbx500_dump_lock, flags); + if (dbx500_dump_done) + return NOTIFY_DONE; + + pr_info("dbx500_dump notified of crash\n"); + + for (i = 0; i < dbx500_dump_size; i++) { + memcpy_fromio(dbx500_dump[i].data, dbx500_dump[i].io_addr, + dbx500_dump[i].size); + } + + dbx500_dump_done = true; + spin_unlock_irqrestore(&dbx500_dump_lock, flags); + + return NOTIFY_DONE; +} + +static void __init init_io_addresses(void) +{ + int i; + + for (i = 0; i < dbx500_dump_size; i++) + dbx500_dump[i].io_addr = ioremap(dbx500_dump[i].phy_addr, + dbx500_dump[i].size); +} + +static struct notifier_block die_notifier = { + .notifier_call = crash_notifier, +}; + +static struct notifier_block panic_notifier = { + .notifier_call = crash_notifier, +}; + +int __init dbx500_dump_init(void) +{ + int err, i; + + if (cpu_is_u5500()) { + dbx500_dump = db5500_dump; + dbx500_dump_size = ARRAY_SIZE(db5500_dump); + } else if (cpu_is_u8500()) { + dbx500_dump = db8500_dump; + dbx500_dump_size = ARRAY_SIZE(db8500_dump); + } else if (cpu_is_u9540()) { + dbx500_dump = db9540_dump; + dbx500_dump_size = ARRAY_SIZE(db9540_dump); + } else { + ux500_unknown_soc(); + } + + for (i = 0; i < dbx500_dump_size; i++) { + dbx500_dump[i].data = kmalloc(dbx500_dump[i].size, GFP_KERNEL); + if (!dbx500_dump[i].data) { + pr_err("dbx500_dump: Could not allocate memory for " + "%s\n", dbx500_dump[i].name); + err = -ENOMEM; + goto free_mem; + } + } + + init_io_addresses(); + + err = atomic_notifier_chain_register(&panic_notifier_list, + &panic_notifier); + if (err != 0) { + pr_err("dbx500_dump: Unable to register a panic notifier %d\n", + err); + goto free_mem; + } + + err = register_die_notifier(&die_notifier); + if (err != 0) { + pr_err("dbx500_dump: Unable to register a die notifier %d\n", + err); + goto free_panic_notifier; + } + pr_info("dbx500_dump: driver initialized\n"); + return err; + +free_panic_notifier: + atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_notifier); + +free_mem: + for (i = i - 1; i >= 0; i--) + kfree(dbx500_dump[i].data); + + return err; +} +arch_initcall(dbx500_dump_init); diff --git a/arch/arm/mach-ux500/dcache.c b/arch/arm/mach-ux500/dcache.c new file mode 100644 index 00000000000..b117d4e8283 --- /dev/null +++ b/arch/arm/mach-ux500/dcache.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Cache handler integration and data cache helpers. + * + * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#include <linux/dma-mapping.h> + +#include <asm/pgtable.h> +#include <asm/cacheflush.h> +#include <asm/outercache.h> +#include <asm/system.h> + +/* + * Values are derived from measurements on HREFP_1.1_V32_OM_S10 running + * u8500-android-2.2_r1.1_v0.21. + * + * A lot of time can be spent trying to figure out the perfect breakpoints but + * for now I've chosen the following simple way. + * + * breakpoint = best_case + (worst_case - best_case) * 0.666 + * The breakpoint is moved slightly towards the worst case because a full + * clean/flush affects the entire system so we should be a bit careful. + * + * BEST CASE: + * Best case is that the cache is empty and the system is idling. The case + * where the cache contains only targeted data could be better in some cases + * but it's hard to do measurements and calculate on that case so I choose the + * easier alternative. + * + * inner_clean_breakpoint = time_2_range_clean_on_empty_cache( + * complete_clean_on_empty_cache_time) + * inner_flush_breakpoint = time_2_range_flush_on_empty_cache( + * complete_flush_on_empty_cache_time) + * + * outer_clean_breakpoint = time_2_range_clean_on_empty_cache( + * complete_clean_on_empty_cache_time) + * outer_flush_breakpoint = time_2_range_flush_on_empty_cache( + * complete_flush_on_empty_cache_time) + * + * WORST CASE: + * Worst case is that the cache is filled with dirty non targeted data that + * will be used after the synchronization and the system is under heavy load. + * + * inner_clean_breakpoint = time_2_range_clean_on_empty_cache( + * complete_clean_on_full_cache_time * 1.5) + * Times 1.5 because it runs on both cores half the time. + * inner_flush_breakpoint = time_2_range_flush_on_empty_cache( + * complete_flush_on_full_cache_time * 1.5 + + * complete_flush_on_full_cache_time / 2) + * Plus "complete_flush_on_full_cache_time / 2" because all data has to be read + * back, here we assume that both cores can fill their cache simultaneously + * (seems to be the case as operations on full and empty inner cache takes + * roughly the same amount of time ie the bus to outer is not the bottle neck). + * + * outer_clean_breakpoint = time_2_range_clean_on_empty_cache( + * complete_clean_on_full_cache_time + + * (complete_clean_on_full_cache_time - + * complete_clean_on_empty_cache_time)) + * Plus "(complete_flush_on_full_cache_time - + * complete_flush_on_empty_cache_time)" because no one else can work when we + * hog the bus with our unecessary transfer. + * outer_flush_breakpoint = time_2_range_flush_on_empty_cache( + * complete_flush_on_full_cache_time * 2 + + * (complete_flush_on_full_cache_time - + * complete_flush_on_empty_cache_time) * 2) + * + * These values might have to be updated if changes are made to the CPU, L2$, + * memory bus or memory. + */ +/* 28930 */ +static const u32 inner_clean_breakpoint = 21324 + (32744 - 21324) * 0.666; +/* 36224 */ +static const u32 inner_flush_breakpoint = 21324 + (43697 - 21324) * 0.666; +/* 254069 */ +static const u32 outer_clean_breakpoint = 68041 + (347363 - 68041) * 0.666; +/* 485414 */ +static const u32 outer_flush_breakpoint = 68041 + (694727 - 68041) * 0.666; + +static void __clean_inner_dcache_all(void *param); +static void clean_inner_dcache_all(void); + +static void __flush_inner_dcache_all(void *param); +static void flush_inner_dcache_all(void); + +static bool is_cache_exclusive(void); + +void drain_cpu_write_buf(void) +{ + dsb(); + outer_cache.sync(); +} + +void clean_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only, + bool *cleaned_everything) +{ + /* + * There is no problem with exclusive caches here as the Cortex-A9 + * documentation (8.1.4. Exclusive L2 cache) says that when a dirty + * line is moved from L2 to L1 it is first written to mem. Because + * of this there is no way a line can avoid the clean by jumping + * between the cache levels. + */ + *cleaned_everything = true; + + if (length < inner_clean_breakpoint) { + /* Inner clean range */ + dmac_map_area(vaddr, length, DMA_TO_DEVICE); + *cleaned_everything = false; + } else { + clean_inner_dcache_all(); + } + + if (!inner_only) { + /* + * There is currently no outer_cache.clean_all() so we use + * flush instead, which is ok as clean is a subset of flush. + * Clean range and flush range take the same amount of time + * so we can use outer_flush_breakpoint here. + */ + if (length < outer_flush_breakpoint) { + outer_cache.clean_range(paddr, paddr + length); + *cleaned_everything = false; + } else { + outer_cache.flush_all(); + } + } +} + +void flush_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only, + bool *flushed_everything) +{ + /* + * There might still be stale data in the caches after this call if the + * cache levels are exclusive. The follwing can happen. + * 1. Clean L1 moves the data to L2. + * 2. Speculative prefetch, preemption or loads on the other core moves + * all the data back to L1, any dirty data will be written to mem as a + * result of this. + * 3. Flush L2 does nothing as there is no targeted data in L2. + * 4. Flush L1 moves the data to L2. Notice that this does not happen + * when the cache levels are non-exclusive as clean pages are not + * written to L2 in that case. + * 5. Stale data is still present in L2! + * I see two possible solutions, don't use exclusive caches or + * (temporarily) disable prefetching to L1, preeemption and the other + * core. + * + * A situation can occur where the operation does not seem atomic from + * the other core's point of view, even on a non-exclusive cache setup. + * Replace step 2 in the previous scenarion with a write from the other + * core. The other core will write on top of the old data but the + * result will not be written to memory. One would expect either that + * the write was performed on top of the old data and was written to + * memory (the write occured before the flush) or that the write was + * performed on top of the new data and was not written to memory (the + * write occured after the flush). The same problem can occur with one + * core if kernel preemption is enabled. The solution is to + * (temporarily) disable the other core and preemption. I can't think + * of any situation where this would be a problem and disabling the + * other core for the duration of this call is mighty expensive so for + * now I just ignore the problem. + */ + + *flushed_everything = true; + + if (!inner_only) { + /* + * Beautiful solution for the exclusive problems :) + */ + if (is_cache_exclusive()) + panic("%s can't handle exclusive CPU caches\n", + __func__); + + if (length < inner_clean_breakpoint) { + /* Inner clean range */ + dmac_map_area(vaddr, length, DMA_TO_DEVICE); + *flushed_everything = false; + } else { + clean_inner_dcache_all(); + } + + if (length < outer_flush_breakpoint) { + outer_cache.flush_range(paddr, paddr + length); + *flushed_everything = false; + } else { + outer_cache.flush_all(); + } + } + + if (length < inner_flush_breakpoint) { + /* Inner flush range */ + dmac_flush_range(vaddr, (void *)((u32)vaddr + length)); + *flushed_everything = false; + } else { + flush_inner_dcache_all(); + } +} + +bool speculative_data_prefetch(void) +{ + return true; +} + +u32 get_dcache_granularity(void) +{ + return 32; +} + +/* + * Local functions + */ + +static void __clean_inner_dcache_all(void *param) +{ + __cpuc_clean_dcache_all(); +} + +static void clean_inner_dcache_all(void) +{ + on_each_cpu(__clean_inner_dcache_all, NULL, 1); +} + +static void __flush_inner_dcache_all(void *param) +{ + __cpuc_flush_dcache_all(); +} + +static void flush_inner_dcache_all(void) +{ + on_each_cpu(__flush_inner_dcache_all, NULL, 1); +} + +static bool is_cache_exclusive(void) +{ + static const u32 CA9_ACTLR_EXCL = 0x80; + + u32 armv7_actlr; + + asm ( + "mrc p15, 0, %0, c1, c0, 1" + : "=r" (armv7_actlr) + ); + + if (armv7_actlr & CA9_ACTLR_EXCL) + return true; + else + return false; +} diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index c5312a4b49f..04f27d7b9c9 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -6,16 +6,19 @@ */ #include <linux/kernel.h> +#include <linux/export.h> #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/irq.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/amba/bus.h> - -#include <plat/gpio-nomadik.h> +#include <linux/pm.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> #include <mach/hardware.h> +#include <mach/pm.h> #include "devices-common.h" @@ -33,6 +36,7 @@ dbx500_add_amba_device(struct device *parent, const char *name, dev->dma_mask = DMA_BIT_MASK(32); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + dev->dev.pm_domain = &ux500_amba_dev_power_domain; dev->irq[0] = irq; @@ -52,6 +56,76 @@ dbx500_add_amba_device(struct device *parent, const char *name, } static struct platform_device * +dbx500_add_platform_device(const char *name, int id, void *pdata, + struct resource *res, int resnum) +{ + struct platform_device *dev; + int ret; + + dev = platform_device_alloc(name, id); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + dev->dev.pm_domain = &ux500_dev_power_domain; + + ret = platform_device_add_resources(dev, res, resnum); + if (ret) + goto out_free; + + dev->dev.platform_data = pdata; + + ret = platform_device_add(dev); + if (ret) + goto out_free; + + return dev; + +out_free: + platform_device_put(dev); + return ERR_PTR(ret); +} + +struct platform_device * +dbx500_add_platform_device_4k1irq(const char *name, int id, + resource_size_t base, + int irq, void *pdata) +{ + struct resource resources[] = { + [0] = { + .start = base, + .end = base + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = irq, + .end = irq, + .flags = IORESOURCE_IRQ, + } + }; + + return dbx500_add_platform_device(name, id, pdata, resources, + ARRAY_SIZE(resources)); +} + +struct platform_device * +dbx500_add_platform_device_noirq(const char *name, int id, + resource_size_t base, void *pdata) +{ + struct resource resources[] = { + [0] = { + .start = base, + .end = base + SZ_4K - 1, + .flags = IORESOURCE_MEM, + } + }; + + return dbx500_add_platform_device(name, id, pdata, resources, + ARRAY_SIZE(resources)); +} + +static struct platform_device * dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq, struct nmk_gpio_platform_data *pdata) { diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 39c74ec82ad..23d65b07795 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -11,6 +11,7 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/sys_soc.h> +#include <linux/amba/serial.h> #include <plat/i2c.h> extern struct amba_device * @@ -18,20 +19,31 @@ dbx500_add_amba_device(struct device *parent, const char *name, resource_size_t base, int irq, void *pdata, unsigned int periphid); -struct spi_master_cntlr; +extern struct platform_device * +dbx500_add_platform_device_4k1irq(const char *name, int id, + resource_size_t base, + int irq, void *pdata); + +extern struct platform_device * +dbx500_add_platform_device_noirq(const char *name, int id, + resource_size_t base, void *pdata); + +struct stm_msp_controller; static inline struct amba_device * dbx500_add_msp_spi(struct device *parent, const char *name, resource_size_t base, int irq, - struct spi_master_cntlr *pdata) + struct stm_msp_controller *pdata) { return dbx500_add_amba_device(parent, name, base, irq, pdata, 0); } +struct pl022_ssp_controller; + static inline struct amba_device * dbx500_add_spi(struct device *parent, const char *name, resource_size_t base, - int irq, struct spi_master_cntlr *pdata, + int irq, struct pl022_ssp_controller *pdata, u32 periphid) { return dbx500_add_amba_device(parent, name, base, irq, @@ -82,12 +94,42 @@ dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq, return platform_device_register_full(&pdevinfo); } +struct msp_i2s_platform_data; + +static inline struct platform_device * +dbx500_add_msp_i2s(struct device *parent, int id, resource_size_t base, int irq, + struct msp_i2s_platform_data *pdata) +{ + /* FIXME parent parameter ignored */ + return dbx500_add_platform_device_4k1irq("ux500-msp-i2s", id, base, irq, + pdata); +} + static inline struct amba_device * dbx500_add_rtc(struct device *parent, resource_size_t base, int irq) { return dbx500_add_amba_device(parent, "rtc-pl031", base, irq, NULL, 0); } +struct cryp_platform_data; + +static inline struct platform_device * +dbx500_add_cryp1(int id, resource_size_t base, int irq, + struct cryp_platform_data *pdata) +{ + return dbx500_add_platform_device_4k1irq("cryp1", id, base, irq, + pdata); +} + +struct hash_platform_data; + +static inline struct platform_device * +dbx500_add_hash1(int id, resource_size_t base, + struct hash_platform_data *pdata) +{ + return dbx500_add_platform_device_noirq("hash1", id, base, pdata); +} + struct nmk_gpio_platform_data; void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c new file mode 100644 index 00000000000..ec7c6378d0e --- /dev/null +++ b/arch/arm/mach-ux500/devices-db5500.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * + * Author: Pierre Peiffer <pierre.peiffer@stericsson.com> for ST-Ericsson. + * for the System Trace Module part. + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/gpio/nomadik.h> + +#include <mach/hardware.h> +#include <mach/devices.h> + +#ifdef CONFIG_FB_MCDE +#include <video/mcde.h> +#endif +#include <mach/db5500-regs.h> + +#include <linux/mfd/dbx500-prcmu.h> +#include <mach/pm.h> + +#define GPIO_DATA(_name, first, num) \ + { \ + .name = _name, \ + .first_gpio = first, \ + .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ + .num_gpio = num, \ + .get_secondary_status = ux500_pm_gpio_read_wake_up_status, \ + .set_ioforce = ux500_pm_prcmu_set_ioforce, \ + } + +#define GPIO_RESOURCE(block) \ + { \ + .start = U5500_GPIOBANK##block##_BASE, \ + .end = U5500_GPIOBANK##block##_BASE + 127, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = IRQ_DB5500_GPIO##block, \ + .end = IRQ_DB5500_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + }, \ + { \ + .start = IRQ_DB5500_PRCMU_GPIO##block, \ + .end = IRQ_DB5500_PRCMU_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + } + +#define GPIO_DEVICE(block) \ + { \ + .name = "gpio", \ + .id = block, \ + .num_resources = 3, \ + .resource = &u5500_gpio_resources[block * 3], \ + .dev = { \ + .platform_data = &u5500_gpio_data[block], \ + }, \ + } + +static struct nmk_gpio_platform_data u5500_gpio_data[] = { + GPIO_DATA("GPIO-0-31", 0, 32), + GPIO_DATA("GPIO-32-63", 32, 4), /* 36..63 not routed to pin */ + GPIO_DATA("GPIO-64-95", 64, 19), /* 83..95 not routed to pin */ + GPIO_DATA("GPIO-96-127", 96, 6), /* 102..127 not routed to pin */ + GPIO_DATA("GPIO-128-159", 128, 21), /* 149..159 not routed to pin */ + GPIO_DATA("GPIO-160-191", 160, 32), + GPIO_DATA("GPIO-192-223", 192, 32), + GPIO_DATA("GPIO-224-255", 224, 4), /* 228..255 not routed to pin */ +}; + +static struct resource u5500_gpio_resources[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), +}; + +struct platform_device u5500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + GPIO_DEVICE(6), + GPIO_DEVICE(7), +}; + +#define U5500_PWM_SIZE 0x20 +static struct resource u5500_pwm0_resource[] = { + { + .name = "PWM_BASE", + .start = U5500_PWM_BASE, + .end = U5500_PWM_BASE + U5500_PWM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource u5500_pwm1_resource[] = { + { + .name = "PWM_BASE", + .start = U5500_PWM_BASE + U5500_PWM_SIZE, + .end = U5500_PWM_BASE + U5500_PWM_SIZE * 2 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource u5500_pwm2_resource[] = { + { + .name = "PWM_BASE", + .start = U5500_PWM_BASE + U5500_PWM_SIZE * 2, + .end = U5500_PWM_BASE + U5500_PWM_SIZE * 3 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource u5500_pwm3_resource[] = { + { + .name = "PWM_BASE", + .start = U5500_PWM_BASE + U5500_PWM_SIZE * 3, + .end = U5500_PWM_BASE + U5500_PWM_SIZE * 4 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device u5500_pwm0_device = { + .id = 0, + .name = "pwm", + .resource = u5500_pwm0_resource, + .num_resources = ARRAY_SIZE(u5500_pwm0_resource), +}; + +struct platform_device u5500_pwm1_device = { + .id = 1, + .name = "pwm", + .resource = u5500_pwm1_resource, + .num_resources = ARRAY_SIZE(u5500_pwm1_resource), +}; + +struct platform_device u5500_pwm2_device = { + .id = 2, + .name = "pwm", + .resource = u5500_pwm2_resource, + .num_resources = ARRAY_SIZE(u5500_pwm2_resource), +}; + +struct platform_device u5500_pwm3_device = { + .id = 3, + .name = "pwm", + .resource = u5500_pwm3_resource, + .num_resources = ARRAY_SIZE(u5500_pwm3_resource), +}; + +#ifdef CONFIG_FB_MCDE +static struct resource mcde_resources[] = { + [0] = { + .name = MCDE_IO_AREA, + .start = U5500_MCDE_BASE, + .end = U5500_MCDE_BASE + U5500_MCDE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = MCDE_IO_AREA, + .start = U5500_DSI_LINK1_BASE, + .end = U5500_DSI_LINK1_BASE + U5500_DSI_LINK_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .name = MCDE_IO_AREA, + .start = U5500_DSI_LINK2_BASE, + .end = U5500_DSI_LINK2_BASE + U5500_DSI_LINK_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [3] = { + .name = MCDE_IRQ, + .start = IRQ_DB5500_DISP, + .end = IRQ_DB5500_DISP, + .flags = IORESOURCE_IRQ, + }, +}; + +static int mcde_platform_enable_dsipll(void) +{ + return prcmu_enable_dsipll(); +} + +static int mcde_platform_disable_dsipll(void) +{ + return prcmu_disable_dsipll(); +} + +static int mcde_platform_set_display_clocks(void) +{ + return prcmu_set_display_clocks(); +} + +static struct mcde_platform_data mcde_pdata = { + .syncmux = 0x01, + .regulator_mcde_epod_id = "vsupply", + .regulator_esram_epod_id = "v-esram12", +#ifdef CONFIG_MCDE_DISPLAY_DSI + .clock_dsi_id = "hdmi", + .clock_dsi_lp_id = "tv", +#endif + .clock_mcde_id = "mcde", + .platform_set_clocks = mcde_platform_set_display_clocks, + .platform_enable_dsipll = mcde_platform_enable_dsipll, + .platform_disable_dsipll = mcde_platform_disable_dsipll, + /* TODO: Remove rotation buffers once ESRAM driver is completed */ + .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x2000, + .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x11000, + .rotbufsize = 0xF000, +}; + +struct platform_device u5500_mcde_device = { + .name = "mcde", + .id = -1, + .dev = { + .platform_data = &mcde_pdata, + }, + .num_resources = ARRAY_SIZE(mcde_resources), + .resource = mcde_resources, +}; +#endif + +struct platform_device u5500_b2r2_blt_device = { + .name = "b2r2_blt", + .id = 0, + .dev = { + .init_name = "b2r2_blt_init", + .coherent_dma_mask = ~0, + }, +}; + +static struct b2r2_platform_data b2r2_platform_data = { + .regulator_id = "vsupply", + .clock_id = "b2r2", +}; + +static struct resource b2r2_resources[] = { + [0] = { + .start = U5500_B2R2_BASE, + .end = U5500_B2R2_BASE + ((4*1024)-1), + .name = "b2r2_base", + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "B2R2_IRQ", + .start = IRQ_DB5500_B2R2, + .end = IRQ_DB5500_B2R2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device u5500_b2r2_device = { + .name = "b2r2", + .id = 0, + .dev = { + .init_name = "b2r2_bus", + .platform_data = &b2r2_platform_data, + .coherent_dma_mask = ~0, + }, + .num_resources = ARRAY_SIZE(b2r2_resources), + .resource = b2r2_resources, +}; + +static struct resource u5500_thsens_resources[] = { + [0] = { + .name = "IRQ_HOTMON_LOW", + .start = IRQ_DB5500_PRCMU_TEMP_SENSOR_LOW, + .end = IRQ_DB5500_PRCMU_TEMP_SENSOR_LOW, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .name = "IRQ_HOTMON_HIGH", + .start = IRQ_DB5500_PRCMU_TEMP_SENSOR_HIGH, + .end = IRQ_DB5500_PRCMU_TEMP_SENSOR_HIGH, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device u5500_thsens_device = { + .name = "db5500_temp", + .resource = u5500_thsens_resources, + .num_resources = ARRAY_SIZE(u5500_thsens_resources), +}; + +struct platform_device u5500_wdt_device = { + .name = "ux500_wdt", + .id = -1, +}; diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h index e70955502c3..22d6086d4dc 100644 --- a/arch/arm/mach-ux500/devices-db5500.h +++ b/arch/arm/mach-ux500/devices-db5500.h @@ -17,6 +17,16 @@ #define db5500_add_i2c3(parent, pdata) \ dbx500_add_i2c(parent, 3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) +struct db5500_keypad_platform_data; + +static inline struct platform_device * +db5500_add_keypad(struct db5500_keypad_platform_data *pdata) +{ + return dbx500_add_platform_device_4k1irq("db5500-keypad", -1, + U5500_KEYPAD_BASE, + IRQ_DB5500_KBD, pdata); +} + #define db5500_add_msp0_spi(parent, pdata) \ dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \ IRQ_DB5500_MSP0, pdata) @@ -44,26 +54,26 @@ ux500_add_usb(parent, U5500_USBOTG_BASE, \ IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) -#define db5500_add_sdi0(parent, pdata) \ +#define db5500_add_sdi0(parent, pdata, pid) \ dbx500_add_sdi(parent, "sdi0", U5500_SDI0_BASE, \ IRQ_DB5500_SDMMC0, pdata, \ - 0x10480180) -#define db5500_add_sdi1(parent, pdata) \ + pid) +#define db5500_add_sdi1(parent, pdata, pid) \ dbx500_add_sdi(parent, "sdi1", U5500_SDI1_BASE, \ IRQ_DB5500_SDMMC1, pdata, \ - 0x10480180) -#define db5500_add_sdi2(parent, pdata) \ + pid) +#define db5500_add_sdi2(parent, pdata, pid) \ dbx500_add_sdi(parent, "sdi2", U5500_SDI2_BASE, \ IRQ_DB5500_SDMMC2, pdata \ - 0x10480180) -#define db5500_add_sdi3(parent, pdata) \ + pid) +#define db5500_add_sdi3(parent, pdata, pid) \ dbx500_add_sdi(parent, "sdi3", U5500_SDI3_BASE, \ - IRQ_DB5500_SDMMC3, pdata \ - 0x10480180) -#define db5500_add_sdi4(parent, pdata) \ + IRQ_DB5500_SDMMC3, pdata, \ + pid) +#define db5500_add_sdi4(parent, pdata, pid) \ dbx500_add_sdi(parent, "sdi4", U5500_SDI4_BASE, \ - IRQ_DB5500_SDMMC4, pdata \ - 0x10480180) + IRQ_DB5500_SDMMC4, pdata, \ + pid) /* This one has a bad peripheral ID in the U5500 silicon */ #define db5500_add_spi0(parent, pdata) \ @@ -76,11 +86,11 @@ 0x10080023) #define db5500_add_spi2(parent, pdata) \ dbx500_add_spi(parent, "spi2", U5500_SPI2_BASE, \ - IRQ_DB5500_SPI2, pdata \ + IRQ_DB5500_SPI2, pdata, \ 0x10080023) #define db5500_add_spi3(parent, pdata) \ dbx500_add_spi(parent, "spi3", U5500_SPI3_BASE, \ - IRQ_DB5500_SPI3, pdata \ + IRQ_DB5500_SPI3, pdata, \ 0x10080023) #define db5500_add_uart0(parent, plat) \ @@ -96,4 +106,9 @@ dbx500_add_uart(parent, "uart3", U5500_UART3_BASE, \ IRQ_DB5500_UART3, plat) +#define db5500_add_cryp1(pdata) \ + dbx500_add_cryp1(-1, U5500_CRYP1_BASE, IRQ_DB5500_CRYP1, pdata) +#define db5500_add_hash1(pdata) \ + dbx500_add_hash1(-1, U5500_HASH1_BASE, pdata) + #endif diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 6e66d3777ed..28f6da58e1e 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -10,166 +10,459 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/gpio/nomadik.h> #include <linux/amba/bus.h> #include <linux/amba/pl022.h> +#include <plat/pincfg.h> #include <plat/ste_dma40.h> +#include <mach/devices.h> #include <mach/hardware.h> #include <mach/setup.h> +#include <mach/pm.h> +#ifdef CONFIG_FB_MCDE +#include <video/mcde.h> +#endif +#include <linux/mfd/dbx500-prcmu.h> +#ifdef CONFIG_HSI +#include <mach/hsi.h> +#endif +#include <mach/ste-dma40-db8500.h> +#ifdef CONFIG_FB_B2R2 +#include <video/b2r2_blt.h> +#endif -#include "ste-dma40-db8500.h" +#include "pins-db8500.h" -static struct resource dma40_resources[] = { +#define GPIO_DATA(_name, first, num) \ + { \ + .name = _name, \ + .first_gpio = first, \ + .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ + .num_gpio = num, \ + .get_secondary_status = ux500_pm_gpio_read_wake_up_status, \ + .set_ioforce = ux500_pm_prcmu_set_ioforce, \ + .supports_sleepmode = true, \ + } + +#define GPIO_RESOURCE(block) \ + { \ + .start = U8500_GPIOBANK##block##_BASE, \ + .end = U8500_GPIOBANK##block##_BASE + 127, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = IRQ_DB8500_GPIO##block, \ + .end = IRQ_DB8500_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + }, \ + { \ + .start = IRQ_PRCMU_GPIO##block, \ + .end = IRQ_PRCMU_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + } + +#define GPIO_DEVICE(block) \ + { \ + .name = "gpio", \ + .id = block, \ + .num_resources = 3, \ + .resource = &u8500_gpio_resources[block * 3], \ + .dev = { \ + .platform_data = &u8500_gpio_data[block], \ + }, \ + } + +static struct nmk_gpio_platform_data u8500_gpio_data[] = { + GPIO_DATA("GPIO-0-31", 0, 32), + GPIO_DATA("GPIO-32-63", 32, 5), /* 37..63 not routed to pin */ + GPIO_DATA("GPIO-64-95", 64, 32), + GPIO_DATA("GPIO-96-127", 96, 2), /* 98..127 not routed to pin */ + GPIO_DATA("GPIO-128-159", 128, 32), + GPIO_DATA("GPIO-160-191", 160, 12), /* 172..191 not routed to pin */ + GPIO_DATA("GPIO-192-223", 192, 32), + GPIO_DATA("GPIO-224-255", 224, 7), /* 231..255 not routed to pin */ + GPIO_DATA("GPIO-256-288", 256, 12), /* 268..288 not routed to pin */ +}; + +static struct resource u8500_gpio_resources[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), + GPIO_RESOURCE(8), +}; + +struct platform_device u8500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + GPIO_DEVICE(6), + GPIO_DEVICE(7), + GPIO_DEVICE(8), +}; + +static struct resource u8500_shrm_resources[] = { [0] = { - .start = U8500_DMA_BASE, - .end = U8500_DMA_BASE + SZ_4K - 1, + .start = U8500_SHRM_GOP_INTERRUPT_BASE, + .end = U8500_SHRM_GOP_INTERRUPT_BASE + ((4*4)-1), + .name = "shrm_gop_register_base", .flags = IORESOURCE_MEM, - .name = "base", }, [1] = { - .start = U8500_DMA_LCPA_BASE, - .end = U8500_DMA_LCPA_BASE + 2 * SZ_1K - 1, - .flags = IORESOURCE_MEM, - .name = "lcpa", + .start = IRQ_CA_WAKE_REQ_V1, + .end = IRQ_CA_WAKE_REQ_V1, + .name = "ca_irq_wake_req", + .flags = IORESOURCE_IRQ, }, [2] = { - .start = IRQ_DB8500_DMA, - .end = IRQ_DB8500_DMA, + .start = IRQ_AC_READ_NOTIFICATION_0_V1, + .end = IRQ_AC_READ_NOTIFICATION_0_V1, + .name = "ac_read_notification_0_irq", + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_AC_READ_NOTIFICATION_1_V1, + .end = IRQ_AC_READ_NOTIFICATION_1_V1, + .name = "ac_read_notification_1_irq", + .flags = IORESOURCE_IRQ, + }, + [4] = { + .start = IRQ_CA_MSG_PEND_NOTIFICATION_0_V1, + .end = IRQ_CA_MSG_PEND_NOTIFICATION_0_V1, + .name = "ca_msg_pending_notification_0_irq", + .flags = IORESOURCE_IRQ, + }, + [5] = { + .start = IRQ_CA_MSG_PEND_NOTIFICATION_1_V1, + .end = IRQ_CA_MSG_PEND_NOTIFICATION_1_V1, + .name = "ca_msg_pending_notification_1_irq", .flags = IORESOURCE_IRQ, } }; -/* Default configuration for physcial memcpy */ -struct stedma40_chan_cfg dma40_memcpy_conf_phy = { - .mode = STEDMA40_MODE_PHYSICAL, - .dir = STEDMA40_MEM_TO_MEM, +struct platform_device u8500_shrm_device = { + .name = "u8500_shrm", + .id = 0, + .dev = { + .init_name = "shrm_bus", + .coherent_dma_mask = ~0, + }, + + .num_resources = ARRAY_SIZE(u8500_shrm_resources), + .resource = u8500_shrm_resources +}; + +#ifdef CONFIG_FB_MCDE +static struct resource mcde_resources[] = { + [0] = { + .name = MCDE_IO_AREA, + .start = U8500_MCDE_BASE, + .end = U8500_MCDE_BASE + U8500_MCDE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = MCDE_IO_AREA, + .start = U8500_DSI_LINK1_BASE, + .end = U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .name = MCDE_IO_AREA, + .start = U8500_DSI_LINK2_BASE, + .end = U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [3] = { + .name = MCDE_IO_AREA, + .start = U8500_DSI_LINK3_BASE, + .end = U8500_DSI_LINK3_BASE + U8500_DSI_LINK_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [4] = { + .name = MCDE_IRQ, + .start = IRQ_DB8500_DISP, + .end = IRQ_DB8500_DISP, + .flags = IORESOURCE_IRQ, + }, +}; + +static int mcde_platform_enable_dsipll(void) +{ + return prcmu_enable_dsipll(); +} + +static int mcde_platform_disable_dsipll(void) +{ + return prcmu_disable_dsipll(); +} + +static int mcde_platform_set_display_clocks(void) +{ + return prcmu_set_display_clocks(); +} + +static struct mcde_platform_data mcde_u8500_pdata = { + /* + * [0] = 3: 24 bits DPI: connect LSB Ch B to D[0:7] + * [3] = 4: 24 bits DPI: connect MID Ch B to D[24:31] + * [4] = 5: 24 bits DPI: connect MSB Ch B to D[32:39] + * + * [1] = 3: TV out : connect LSB Ch B to D[8:15] + */ +#define DONT_CARE 0 + .outmux = { 3, 3, DONT_CARE, 4, 5 }, +#undef DONT_CARE + .syncmux = 0x00, /* DPI channel A and B on output pins A and B resp */ +#ifdef CONFIG_MCDE_DISPLAY_DSI + .regulator_vana_id = "vdddsi1v2", +#endif + .regulator_mcde_epod_id = "vsupply", + .regulator_esram_epod_id = "v-esram34", +#ifdef CONFIG_MCDE_DISPLAY_DSI + .clock_dsi_id = "hdmi", + .clock_dsi_lp_id = "tv", +#endif + .clock_dpi_id = "lcd", + .clock_mcde_id = "mcde", + .platform_set_clocks = mcde_platform_set_display_clocks, + .platform_enable_dsipll = mcde_platform_enable_dsipll, + .platform_disable_dsipll = mcde_platform_disable_dsipll, + /* TODO: Remove rotation buffers once ESRAM driver is completed */ + .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x2000, + .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x11000, + .rotbufsize = 0xF000, +}; + +struct platform_device u8500_mcde_device = { + .name = "mcde", + .id = -1, + .dev = { + .platform_data = &mcde_u8500_pdata, + }, + .num_resources = ARRAY_SIZE(mcde_resources), + .resource = mcde_resources, +}; +#endif /* CONFIG_FB_MCDE */ + +#ifdef CONFIG_FB_B2R2 +struct platform_device u8500_b2r2_blt_device = { + .name = "b2r2_blt", + .id = 0, + .dev = { + .init_name = "b2r2_blt_init", + .coherent_dma_mask = ~0, + }, +}; + +static struct b2r2_platform_data b2r2_platform_data = { + .regulator_id = "vsupply", + .clock_id = "b2r2", +}; - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .src_info.psize = STEDMA40_PSIZE_PHY_1, - .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +static struct resource b2r2_resources[] = { + [0] = { + .start = U8500_B2R2_BASE, + .end = U8500_B2R2_BASE + ((4*1024)-1), + .name = "b2r2_base", + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "B2R2_IRQ", + .start = IRQ_DB8500_B2R2, + .end = IRQ_DB8500_B2R2, + .flags = IORESOURCE_IRQ, + }, +}; - .dst_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.psize = STEDMA40_PSIZE_PHY_1, - .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +struct platform_device u8500_b2r2_device = { + .name = "b2r2", + .id = 0, + .dev = { + .init_name = "b2r2_core", + .platform_data = &b2r2_platform_data, + .coherent_dma_mask = ~0, + }, + .num_resources = ARRAY_SIZE(b2r2_resources), + .resource = b2r2_resources, }; -/* Default configuration for logical memcpy */ -struct stedma40_chan_cfg dma40_memcpy_conf_log = { - .dir = STEDMA40_MEM_TO_MEM, +#endif /* CONFIG_FB_B2R2 */ - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .src_info.psize = STEDMA40_PSIZE_LOG_1, - .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +/* + * WATCHDOG + */ - .dst_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.psize = STEDMA40_PSIZE_LOG_1, - .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +struct platform_device u8500_wdt_device = { + .name = "ux500_wdt", + .id = -1, }; +#ifdef CONFIG_HSI /* - * Mapping between destination event lines and physical device address. - * The event line is tied to a device and therefore the address is constant. - * When the address comes from a primecell it will be configured in runtime - * and we set the address to -1 as a placeholder. + * HSI */ -static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { - /* MUSB - these will be runtime-reconfigured */ - [DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1, - [DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1, - [DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1, - [DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1, - [DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1, - [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1, - [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1, - [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1, - /* PrimeCells - run-time configured */ - [DB8500_DMA_DEV0_SPI0_TX] = -1, - [DB8500_DMA_DEV1_SD_MMC0_TX] = -1, - [DB8500_DMA_DEV2_SD_MMC1_TX] = -1, - [DB8500_DMA_DEV3_SD_MMC2_TX] = -1, - [DB8500_DMA_DEV8_SSP0_TX] = -1, - [DB8500_DMA_DEV9_SSP1_TX] = -1, - [DB8500_DMA_DEV11_UART2_TX] = -1, - [DB8500_DMA_DEV12_UART1_TX] = -1, - [DB8500_DMA_DEV13_UART0_TX] = -1, - [DB8500_DMA_DEV28_SD_MM2_TX] = -1, - [DB8500_DMA_DEV29_SD_MM0_TX] = -1, - [DB8500_DMA_DEV32_SD_MM1_TX] = -1, - [DB8500_DMA_DEV33_SPI2_TX] = -1, - [DB8500_DMA_DEV35_SPI1_TX] = -1, - [DB8500_DMA_DEV40_SPI3_TX] = -1, - [DB8500_DMA_DEV41_SD_MM3_TX] = -1, - [DB8500_DMA_DEV42_SD_MM4_TX] = -1, - [DB8500_DMA_DEV43_SD_MM5_TX] = -1, - [DB8500_DMA_DEV14_MSP2_TX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV30_MSP1_TX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, -}; - -/* Mapping between source event lines and physical device address */ -static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = { - /* MUSB - these will be runtime-reconfigured */ - [DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1, - [DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1, - [DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1, - [DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1, - [DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1, - [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1, - [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1, - [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1, - /* PrimeCells */ - [DB8500_DMA_DEV0_SPI0_RX] = -1, - [DB8500_DMA_DEV1_SD_MMC0_RX] = -1, - [DB8500_DMA_DEV2_SD_MMC1_RX] = -1, - [DB8500_DMA_DEV3_SD_MMC2_RX] = -1, - [DB8500_DMA_DEV8_SSP0_RX] = -1, - [DB8500_DMA_DEV9_SSP1_RX] = -1, - [DB8500_DMA_DEV11_UART2_RX] = -1, - [DB8500_DMA_DEV12_UART1_RX] = -1, - [DB8500_DMA_DEV13_UART0_RX] = -1, - [DB8500_DMA_DEV28_SD_MM2_RX] = -1, - [DB8500_DMA_DEV29_SD_MM0_RX] = -1, - [DB8500_DMA_DEV32_SD_MM1_RX] = -1, - [DB8500_DMA_DEV33_SPI2_RX] = -1, - [DB8500_DMA_DEV35_SPI1_RX] = -1, - [DB8500_DMA_DEV40_SPI3_RX] = -1, - [DB8500_DMA_DEV41_SD_MM3_RX] = -1, - [DB8500_DMA_DEV42_SD_MM4_RX] = -1, - [DB8500_DMA_DEV43_SD_MM5_RX] = -1, - [DB8500_DMA_DEV14_MSP2_RX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV30_MSP3_RX] = U8500_MSP3_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, -}; - -/* Reserved event lines for memcpy only */ -static int dma40_memcpy_event[] = { - DB8500_DMA_MEMCPY_TX_0, - DB8500_DMA_MEMCPY_TX_1, - DB8500_DMA_MEMCPY_TX_2, - DB8500_DMA_MEMCPY_TX_3, - DB8500_DMA_MEMCPY_TX_4, - DB8500_DMA_MEMCPY_TX_5, -}; - -static struct stedma40_platform_data dma40_plat_data = { - .dev_len = DB8500_DMA_NR_DEV, - .dev_rx = dma40_rx_map, - .dev_tx = dma40_tx_map, - .memcpy = dma40_memcpy_event, - .memcpy_len = ARRAY_SIZE(dma40_memcpy_event), - .memcpy_conf_phy = &dma40_memcpy_conf_phy, - .memcpy_conf_log = &dma40_memcpy_conf_log, - .disabled_channels = {-1}, -}; - -struct platform_device u8500_dma40_device = { +#define HSI0_CAWAKE { \ + .start = IRQ_PRCMU_HSI0, \ + .end = IRQ_PRCMU_HSI0, \ + .flags = IORESOURCE_IRQ, \ + .name = "hsi0_cawake" \ +} + +#define HSI0_ACWAKE { \ + .start = 226, \ + .end = 226, \ + .flags = IORESOURCE_IO, \ + .name = "hsi0_acwake" \ +} + +#define HSIR_OVERRUN(num) { \ + .start = IRQ_DB8500_HSIR_CH##num##_OVRRUN, \ + .end = IRQ_DB8500_HSIR_CH##num##_OVRRUN, \ + .flags = IORESOURCE_IRQ, \ + .name = "hsi_rx_overrun_ch"#num \ +} + +#define STE_HSI_PORT0_TX_CHANNEL_CFG(n) { \ + .dir = STEDMA40_MEM_TO_PERIPH, \ + .high_priority = true, \ + .mode = STEDMA40_MODE_LOGICAL, \ + .mode_opt = STEDMA40_LCHAN_SRC_LOG_DST_LOG, \ + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \ + .dst_dev_type = n,\ + .src_info.big_endian = false,\ + .src_info.data_width = STEDMA40_WORD_WIDTH,\ + .dst_info.big_endian = false,\ + .dst_info.data_width = STEDMA40_WORD_WIDTH,\ +}, + +#define STE_HSI_PORT0_RX_CHANNEL_CFG(n) { \ + .dir = STEDMA40_PERIPH_TO_MEM, \ + .high_priority = true, \ + .mode = STEDMA40_MODE_LOGICAL, \ + .mode_opt = STEDMA40_LCHAN_SRC_LOG_DST_LOG, \ + .src_dev_type = n,\ + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \ + .src_info.big_endian = false,\ + .src_info.data_width = STEDMA40_WORD_WIDTH,\ + .dst_info.big_endian = false,\ + .dst_info.data_width = STEDMA40_WORD_WIDTH,\ +}, + +static struct resource u8500_hsi_resources[] = { + { + .start = U8500_HSIR_BASE, + .end = U8500_HSIR_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + .name = "hsi_rx_base" + }, + { + .start = U8500_HSIT_BASE, + .end = U8500_HSIT_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + .name = "hsi_tx_base" + }, + { + .start = IRQ_DB8500_HSIRD0, + .end = IRQ_DB8500_HSIRD0, + .flags = IORESOURCE_IRQ, + .name = "hsi_rx_irq0" + }, + { + .start = IRQ_DB8500_HSITD0, + .end = IRQ_DB8500_HSITD0, + .flags = IORESOURCE_IRQ, + .name = "hsi_tx_irq0" + }, + { + .start = IRQ_DB8500_HSIR_EXCEP, + .end = IRQ_DB8500_HSIR_EXCEP, + .flags = IORESOURCE_IRQ, + .name = "hsi_rx_excep0" + }, + HSIR_OVERRUN(0), + HSIR_OVERRUN(1), + HSIR_OVERRUN(2), + HSIR_OVERRUN(3), + HSIR_OVERRUN(4), + HSIR_OVERRUN(5), + HSIR_OVERRUN(6), + HSIR_OVERRUN(7), + HSI0_CAWAKE, + HSI0_ACWAKE, +}; + +#ifdef CONFIG_STE_DMA40 +static struct stedma40_chan_cfg ste_hsi_port0_dma_tx_cfg[] = { + STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0) + STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1) + STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2) + STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3) +}; + +static struct stedma40_chan_cfg ste_hsi_port0_dma_rx_cfg[] = { + STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0) + STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1) + STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2) + STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3) +}; +#endif + +static struct ste_hsi_port_cfg ste_hsi_port0_cfg = { +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_tx_cfg = ste_hsi_port0_dma_tx_cfg, + .dma_rx_cfg = ste_hsi_port0_dma_rx_cfg +#endif +}; + +struct ste_hsi_platform_data u8500_hsi_platform_data = { + .num_ports = 1, + .use_dma = 1, + .port_cfg = &ste_hsi_port0_cfg, +}; + +struct platform_device u8500_hsi_device = { .dev = { - .platform_data = &dma40_plat_data, + .platform_data = &u8500_hsi_platform_data, }, - .name = "dma40", + .name = "ste_hsi", .id = 0, - .num_resources = ARRAY_SIZE(dma40_resources), - .resource = dma40_resources + .resource = u8500_hsi_resources, + .num_resources = ARRAY_SIZE(u8500_hsi_resources) +}; +#endif /* CONFIG_HSI */ + +/* + * Thermal Sensor + */ + +static struct resource u8500_thsens_resources[] = { + { + .name = "IRQ_HOTMON_LOW", + .start = IRQ_PRCMU_HOTMON_LOW, + .end = IRQ_PRCMU_HOTMON_LOW, + .flags = IORESOURCE_IRQ, + }, + { + .name = "IRQ_HOTMON_HIGH", + .start = IRQ_PRCMU_HOTMON_HIGH, + .end = IRQ_PRCMU_HOTMON_HIGH, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device u8500_thsens_device = { + .name = "dbx500_temp", + .resource = u8500_thsens_resources, + .num_resources = ARRAY_SIZE(u8500_thsens_resources), }; struct resource keypad_resources[] = { diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index 9fd93e9da52..9b20e971cc8 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -124,4 +124,9 @@ db8500_add_ssp(struct device *parent, const char *name, resource_size_t base, dbx500_add_uart(parent, "uart2", U8500_UART2_BASE, \ IRQ_DB8500_UART2, pdata) +#define db8500_add_cryp1(pdata) \ + dbx500_add_cryp1(-1, U8500_CRYP1_BASE, IRQ_DB8500_CRYP1, pdata) +#define db8500_add_hash1(pdata) \ + dbx500_add_hash1(-1, U8500_HASH1_BASE, pdata) + #endif diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c index ea0a2f92ca7..77d8d088460 100644 --- a/arch/arm/mach-ux500/devices.c +++ b/arch/arm/mach-ux500/devices.c @@ -14,6 +14,51 @@ #include <mach/hardware.h> #include <mach/setup.h> +#ifdef CONFIG_STE_TRACE_MODEM +#include <linux/db8500-modem-trace.h> +#endif + +#ifdef CONFIG_STE_TRACE_MODEM +static struct resource trace_resource = { + .start = 0, + .end = 0, + .name = "db8500-trace-area", + .flags = IORESOURCE_MEM +}; + +static struct db8500_trace_platform_data trace_pdata = { + .ape_base = U8500_APE_BASE, + .modem_base = U8500_MODEM_BASE, +}; + +struct platform_device u8500_trace_modem = { + .name = "db8500-modem-trace", + .id = 0, + .dev = { + .init_name = "db8500-modem-trace", + .platform_data = &trace_pdata, + }, + .num_resources = 1, + .resource = &trace_resource, +}; + +static int __init early_trace_modem(char *p) +{ + struct resource *data = &trace_resource; + u32 size = memparse(p, &p); + if (*p == '@') + data->start = memparse(p + 1, &p); + data->end = data->start + size - 1; + return 0; +} + +early_param("mem_mtrace", early_trace_modem); +#endif + +struct platform_device ux500_hwmem_device = { + .name = "hwmem", +}; + void __init amba_add_devices(struct amba_device *devs[], int num) { int i; diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c index 41e9470fa0e..3a56ea8b095 100644 --- a/arch/arm/mach-ux500/dma-db5500.c +++ b/arch/arm/mach-ux500/dma-db5500.c @@ -14,8 +14,8 @@ #include <plat/ste_dma40.h> #include <mach/setup.h> #include <mach/hardware.h> - -#include "ste-dma40-db5500.h" +#include <mach/pm.h> +#include <mach/ste-dma40-db5500.h> static struct resource dma40_resources[] = { [0] = { @@ -72,28 +72,128 @@ static struct stedma40_chan_cfg dma40_memcpy_conf_log = { * now. */ static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = { - [DB5500_DMA_DEV24_SDMMC0_RX] = -1, - [DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1, - [DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1, - [DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1, - [DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1, - [DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1, - [DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1, - [DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1, - [DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -1, + [DB5500_DMA_DEV0_SPI0_RX] = 0, + [DB5500_DMA_DEV1_SPI1_RX] = 0, + [DB5500_DMA_DEV2_SPI2_RX] = 0, + [DB5500_DMA_DEV3_SPI3_RX] = 0, + [DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV7_IRDA_RFS] = 0, + [DB5500_DMA_DEV8_IRDA_FIFO_RX] = 0, + [DB5500_DMA_DEV9_MSP0_RX] = U5500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV10_MSP1_RX] = U5500_MSP1_BASE + MSP_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV11_MSP2_RX] = U5500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV12_UART0_RX] = 0, + [DB5500_DMA_DEV13_UART1_RX] = 0, + [DB5500_DMA_DEV14_UART2_RX] = 0, + [DB5500_DMA_DEV15_UART3_RX] = 0, + [DB5500_DMA_DEV16_USB_OTG_IEP_8] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV17_USB_OTG_IEP_1_9] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV18_USB_OTG_IEP_2_10] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV19_USB_OTG_IEP_3_11] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV24_SDMMC0_RX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV25_SDMMC1_RX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV26_SDMMC2_RX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV27_SDMMC3_RX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV28_SDMMC4_RX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET, + /* 29, 30 not used */ + [DB5500_DMA_DEV31_CRYPTO1_RX] = 0, /* v2 */ + /* 32 not used */ + [DB5500_DMA_DEV33_SDMMC0_RX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV34_SDMMC1_RX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV35_SDMMC2_RX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV36_SDMMC3_RX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV37_SDMMC4_RX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV38_USB_OTG_IEP_8] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV39_USB_OTG_IEP_1_9] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV40_USB_OTG_IEP_2_10] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV41_USB_OTG_IEP_3_11] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV42_USB_OTG_IEP_4_12] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV43_USB_OTG_IEP_5_13] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV44_USB_OTG_IEP_6_14] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV45_USB_OTG_IEP_7_15] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV46_CRYPTO1_RX] = 0, /* v2 */ + [DB5500_DMA_DEV47_MCDE_RX] = 0, + [DB5500_DMA_DEV48_CRYPTO1_RX] = U5500_CRYP1_BASE + CRYP1_RX_REG_OFFSET, + /* 49, 50 not used */ + [DB5500_DMA_DEV49_I2C1_RX] = 0, + [DB5500_DMA_DEV50_I2C3_RX] = 0, + [DB5500_DMA_DEV51_I2C2_RX] = 0, + /* 54 - 60 not used */ + [DB5500_DMA_DEV61_CRYPTO0_RX] = 0, + /* 62, 63 not used */ }; /* Mapping between destination event lines and physical device address */ static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = { - [DB5500_DMA_DEV24_SDMMC0_TX] = -1, - [DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1, - [DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1, - [DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1, - [DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1, - [DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1, - [DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1, - [DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1, - [DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -1, + [DB5500_DMA_DEV0_SPI0_TX] = 0, + [DB5500_DMA_DEV1_SPI1_TX] = 0, + [DB5500_DMA_DEV2_SPI2_TX] = 0, + [DB5500_DMA_DEV3_SPI3_TX] = 0, + [DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV7_IRRC_TX] = 0, + [DB5500_DMA_DEV8_IRDA_FIFO_TX] = 0, + [DB5500_DMA_DEV9_MSP0_TX] = U5500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV10_MSP1_TX] = U5500_MSP1_BASE + MSP_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV11_MSP2_TX] = U5500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV12_UART0_TX] = 0, + [DB5500_DMA_DEV13_UART1_TX] = 0, + [DB5500_DMA_DEV14_UART2_TX] = 0, + [DB5500_DMA_DEV15_UART3_TX] = 0, + [DB5500_DMA_DEV16_USB_OTG_OEP_8] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV17_USB_OTG_OEP_1_9] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV18_USB_OTG_OEP_2_10] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV19_USB_OTG_OEP_3_11] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV24_SDMMC0_TX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV25_SDMMC1_TX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV26_SDMMC2_TX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV27_SDMMC3_TX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV28_SDMMC4_TX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET, + /* 29 not used */ + [DB5500_DMA_DEV30_HASH1_TX] = 0, /* v2 */ + [DB5500_DMA_DEV31_CRYPTO1_TX] = 0, /* v2 */ + [DB5500_DMA_DEV32_FSMC_TX] = 0, + [DB5500_DMA_DEV33_SDMMC0_TX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV34_SDMMC1_TX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV35_SDMMC2_TX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV36_SDMMC3_TX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV37_SDMMC4_TX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB5500_DMA_DEV38_USB_OTG_OEP_8] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV39_USB_OTG_OEP_1_9] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV40_USB_OTG_OEP_2_10] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV41_USB_OTG_OEP_3_11] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV42_USB_OTG_OEP_4_12] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV43_USB_OTG_OEP_5_13] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV44_USB_OTG_OEP_6_14] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV45_USB_OTG_OEP_7_15] = U5500_USBOTG_BASE, + [DB5500_DMA_DEV46_CRYPTO1_TX] = 0, /* v2 */ + [DB5500_DMA_DEV47_STM_TX] = 0, + [DB5500_DMA_DEV48_CRYPTO1_TX] = U5500_CRYP1_BASE + CRYP1_TX_REG_OFFSET, + [DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX] = 0, + [DB5500_DMA_DEV50_HASH1_TX] = U5500_HASH1_BASE + HASH1_TX_REG_OFFSET, + [DB5500_DMA_DEV51_I2C1_TX] = 0, + [DB5500_DMA_DEV52_I2C3_TX] = 0, + [DB5500_DMA_DEV53_I2C2_TX] = 0, + /* 54, 55 not used */ + [DB5500_DMA_MEMCPY_TX_1] = 0, + [DB5500_DMA_MEMCPY_TX_2] = 0, + [DB5500_DMA_MEMCPY_TX_3] = 0, + [DB5500_DMA_MEMCPY_TX_4] = 0, + [DB5500_DMA_MEMCPY_TX_5] = 0, + [DB5500_DMA_DEV61_CRYPTO0_TX] = 0, + [DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX] = 0, + [DB5500_DMA_DEV63_HASH0_TX] = 0, }; static int dma40_memcpy_event[] = { @@ -118,6 +218,9 @@ static struct stedma40_platform_data dma40_plat_data = { static struct platform_device dma40_device = { .dev = { .platform_data = &dma40_plat_data, +#ifdef CONFIG_PM + .pm_domain = &ux500_dev_power_domain, +#endif }, .name = "dma40", .id = 0, @@ -132,6 +235,6 @@ void __init db5500_dma_init(struct device *parent) dma40_device.dev.parent = parent; ret = platform_device_register(&dma40_device); if (ret) - dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); - + dev_err(&dma40_device.dev, "unable to register device: %d\n", + ret); } diff --git a/arch/arm/mach-ux500/dma-db8500.c b/arch/arm/mach-ux500/dma-db8500.c new file mode 100644 index 00000000000..d4363e2efb1 --- /dev/null +++ b/arch/arm/mach-ux500/dma-db8500.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) ST-Ericsson SA 2007-2010 + * + * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <plat/ste_dma40.h> + +#ifdef CONFIG_HSI +#include <mach/hsi.h> +#endif +#include <mach/setup.h> +#include <mach/ste-dma40-db8500.h> +#include <mach/pm.h> +#include <mach/context.h> + + + +static struct resource dma40_resources[] = { + [0] = { + .start = U8500_DMA_BASE, + .end = U8500_DMA_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + .name = "base", + }, + [1] = { + .start = U8500_DMA_LCPA_BASE, + .end = U8500_DMA_LCPA_BASE + 2 * SZ_1K - 1, + .flags = IORESOURCE_MEM, + .name = "lcpa", + }, + [2] = { + .start = IRQ_DB8500_DMA, + .end = IRQ_DB8500_DMA, + .flags = IORESOURCE_IRQ + }, + [3] = { + .start = U8500_DMA_LCLA_BASE, + .end = U8500_DMA_LCLA_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + .name = "lcla_esram", + } +}; + +/* Default configuration for physcial memcpy */ +static struct stedma40_chan_cfg dma40_memcpy_conf_phy = { + .mode = STEDMA40_MODE_PHYSICAL, + .dir = STEDMA40_MEM_TO_MEM, + + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .src_info.psize = STEDMA40_PSIZE_PHY_1, + .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + + .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.psize = STEDMA40_PSIZE_PHY_1, + .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + +}; + +/* Default configuration for logical memcpy */ +static struct stedma40_chan_cfg dma40_memcpy_conf_log = { + .dir = STEDMA40_MEM_TO_MEM, + + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .src_info.psize = STEDMA40_PSIZE_LOG_1, + .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + + .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.psize = STEDMA40_PSIZE_LOG_1, + .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + +}; + +/* + * Mapping between soruce event lines and physical device address + * This was created assuming that the event line is tied to a device and + * therefore the address is constant, however this is not true for at least + * USB, and the values are just placeholders for USB. This table is preserved + * and used for now. + */ +static dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = { + [DB8500_DMA_DEV0_SPI0_RX] = 0, + [DB8500_DMA_DEV1_SD_MMC0_RX] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV2_SD_MMC1_RX] = 0, + [DB8500_DMA_DEV3_SD_MMC2_RX] = 0, + [DB8500_DMA_DEV4_I2C1_RX] = 0, + [DB8500_DMA_DEV5_I2C3_RX] = 0, + [DB8500_DMA_DEV6_I2C2_RX] = 0, + [DB8500_DMA_DEV7_I2C4_RX] = 0, + [DB8500_DMA_DEV8_SSP0_RX] = U8500_SSP0_BASE + SSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV9_SSP1_RX] = 0, + [DB8500_DMA_DEV10_MCDE_RX] = 0, + [DB8500_DMA_DEV11_UART2_RX] = 0, + [DB8500_DMA_DEV12_UART1_RX] = 0, + [DB8500_DMA_DEV13_UART0_RX] = 0, + [DB8500_DMA_DEV14_MSP2_RX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV15_I2C0_RX] = 0, + [DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = U8500_USBOTG_BASE, +#ifdef CONFIG_HSI + [DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0] = U8500_HSIR_BASE + 0x0 + STE_HSI_RX_BUFFERX, + [DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1] = U8500_HSIR_BASE + 0x4 + STE_HSI_RX_BUFFERX, + [DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2] = U8500_HSIR_BASE + 0x8 + STE_HSI_RX_BUFFERX, + [DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3] = U8500_HSIR_BASE + 0xC + STE_HSI_RX_BUFFERX, +#endif + [DB8500_DMA_DEV24_SRC_SXA0_RX_TX] = 0, + [DB8500_DMA_DEV25_SRC_SXA1_RX_TX] = 0, + [DB8500_DMA_DEV26_SRC_SXA2_RX_TX] = 0, + [DB8500_DMA_DEV27_SRC_SXA3_RX_TX] = 0, + [DB8500_DMA_DEV28_SD_MM2_RX] = U8500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV29_SD_MM0_RX] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV30_MSP3_RX] = U8500_MSP3_BASE + MSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV32_SD_MM1_RX] = U8500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV33_SPI2_RX] = 0, + [DB8500_DMA_DEV34_I2C3_RX2] = 0, + [DB8500_DMA_DEV35_SPI1_RX] = 0, + [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV39_USB_OTG_IEP_8] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV40_SPI3_RX] = 0, + [DB8500_DMA_DEV41_SD_MM3_RX] = 0, + [DB8500_DMA_DEV42_SD_MM4_RX] = U8500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV43_SD_MM5_RX] = 0, + [DB8500_DMA_DEV44_SRC_SXA4_RX_TX] = 0, + [DB8500_DMA_DEV45_SRC_SXA5_RX_TX] = 0, + [DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX] = 0, + [DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX] = 0, + [DB8500_DMA_DEV48_CAC1_RX] = U8500_CRYP1_BASE + CRYP1_RX_REG_OFFSET, + /* 49, 50 and 51 are not used */ + [DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4] = 0, + [DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5] = 0, + [DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6] = 0, + [DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7] = 0, + /* 56, 57, 58, 59 and 60 are not used */ + [DB8500_DMA_DEV61_CAC0_RX] = 0, + /* 62 and 63 are not used */ +}; + +/* Mapping between destination event lines and physical device address */ +static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { + [DB8500_DMA_DEV0_SPI0_TX] = 0, + [DB8500_DMA_DEV1_SD_MMC0_TX] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV2_SD_MMC1_TX] = 0, + [DB8500_DMA_DEV3_SD_MMC2_TX] = 0, + [DB8500_DMA_DEV4_I2C1_TX] = 0, + [DB8500_DMA_DEV5_I2C3_TX] = 0, + [DB8500_DMA_DEV6_I2C2_TX] = 0, + [DB8500_DMA_DEV7_I2C4_TX] = 0, + [DB8500_DMA_DEV8_SSP0_TX] = U8500_SSP0_BASE + SSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV9_SSP1_TX] = 0, + /* 10 is not used*/ + [DB8500_DMA_DEV11_UART2_TX] = 0, + [DB8500_DMA_DEV12_UART1_TX] = 0, + [DB8500_DMA_DEV13_UART0_TX] = 0, + [DB8500_DMA_DEV14_MSP2_TX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV15_I2C0_TX] = 0, + [DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = U8500_USBOTG_BASE, +#ifdef CONFIG_HSI + [DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0] = U8500_HSIT_BASE + 0x0 + STE_HSI_TX_BUFFERX, + [DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1] = U8500_HSIT_BASE + 0x4 + STE_HSI_TX_BUFFERX, + [DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2] = U8500_HSIT_BASE + 0x8 + STE_HSI_TX_BUFFERX, + [DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3] = U8500_HSIT_BASE + 0xC + STE_HSI_TX_BUFFERX, +#endif + [DB8500_DMA_DEV24_DST_SXA0_RX_TX] = 0, + [DB8500_DMA_DEV25_DST_SXA1_RX_TX] = 0, + [DB8500_DMA_DEV26_DST_SXA2_RX_TX] = 0, + [DB8500_DMA_DEV27_DST_SXA3_RX_TX] = 0, + [DB8500_DMA_DEV28_SD_MM2_TX] = U8500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV29_SD_MM0_TX] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV30_MSP1_TX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV32_SD_MM1_TX] = U8500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV33_SPI2_TX] = 0, + [DB8500_DMA_DEV34_I2C3_TX2] = 0, + [DB8500_DMA_DEV35_SPI1_TX] = 0, + [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV39_USB_OTG_OEP_8] = U8500_USBOTG_BASE, + [DB8500_DMA_DEV40_SPI3_TX] = 0, + [DB8500_DMA_DEV41_SD_MM3_TX] = 0, + [DB8500_DMA_DEV42_SD_MM4_TX] = U8500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET, + [DB8500_DMA_DEV43_SD_MM5_TX] = 0, + [DB8500_DMA_DEV44_DST_SXA4_RX_TX] = 0, + [DB8500_DMA_DEV45_DST_SXA5_RX_TX] = 0, + [DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX] = 0, + [DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX] = 0, + [DB8500_DMA_DEV48_CAC1_TX] = U8500_CRYP1_BASE + CRYP1_TX_REG_OFFSET, + [DB8500_DMA_DEV49_CAC1_TX_HAC1_TX] = 0, + [DB8500_DMA_DEV50_HAC1_TX] = U8500_HASH1_BASE + HASH1_TX_REG_OFFSET, + [DB8500_DMA_MEMCPY_TX_0] = 0, + [DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4] = 0, + [DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5] = 0, + [DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6] = 0, + [DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7] = 0, + [DB8500_DMA_MEMCPY_TX_1] = 0, + [DB8500_DMA_MEMCPY_TX_2] = 0, + [DB8500_DMA_MEMCPY_TX_3] = 0, + [DB8500_DMA_MEMCPY_TX_4] = 0, + [DB8500_DMA_MEMCPY_TX_5] = 0, + [DB8500_DMA_DEV61_CAC0_TX] = 0, + [DB8500_DMA_DEV62_CAC0_TX_HAC0_TX] = 0, + [DB8500_DMA_DEV63_HAC0_TX] = 0, +}; + +/* Reserved event lines for memcpy only */ +static int dma40_memcpy_event[] = { + DB8500_DMA_MEMCPY_TX_0, + DB8500_DMA_MEMCPY_TX_1, + DB8500_DMA_MEMCPY_TX_2, + DB8500_DMA_MEMCPY_TX_3, + DB8500_DMA_MEMCPY_TX_4, + DB8500_DMA_MEMCPY_TX_5, +}; + +static struct stedma40_platform_data dma40_plat_data = { + .dev_len = ARRAY_SIZE(dma40_rx_map), + .dev_rx = dma40_rx_map, + .dev_tx = dma40_tx_map, + .memcpy = dma40_memcpy_event, + .memcpy_len = ARRAY_SIZE(dma40_memcpy_event), + .memcpy_conf_phy = &dma40_memcpy_conf_phy, + .memcpy_conf_log = &dma40_memcpy_conf_log, + /* Audio is using physical channel 2 from MMDSP */ + .disabled_channels = {2, -1}, + .use_esram_lcla = true, +}; + +#ifdef CONFIG_UX500_CONTEXT +#define D40_DREG_GCC 0x000 +#define D40_DREG_LCPA 0x020 +#define D40_DREG_LCLA 0x024 + +static void __iomem *base; + +static int dma_context_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + static unsigned long lcpa; + static unsigned long lcla; + static unsigned long gcc; + + switch (event) { + case CONTEXT_APE_SAVE: + lcla = readl(base + D40_DREG_LCLA); + lcpa = readl(base + D40_DREG_LCPA); + gcc = readl(base + D40_DREG_GCC); + break; + + case CONTEXT_APE_RESTORE: + writel(gcc, base + D40_DREG_GCC); + writel(lcpa, base + D40_DREG_LCPA); + writel(lcla, base + D40_DREG_LCLA); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block dma_context_notifier = { + .notifier_call = dma_context_notifier_call, +}; + +static void dma_context_notifier_init(void) +{ + base = ioremap(dma40_resources[0].start, + resource_size(&dma40_resources[0])); + if (WARN_ON(!base)) + return; + + WARN_ON(context_ape_notifier_register(&dma_context_notifier)); +} +#else +static void dma_context_notifier_init(void) +{ +} +#endif + +static struct platform_device dma40_device = { + .dev = { + .platform_data = &dma40_plat_data, +#ifdef CONFIG_PM + .pm_domain = &ux500_dev_power_domain, +#endif + }, + .name = "dma40", + .id = 0, + .num_resources = ARRAY_SIZE(dma40_resources), + .resource = dma40_resources +}; + +void __init db8500_dma_init(struct device *parent) +{ + int ret; + + dma40_device.dev.parent = parent; + ret = platform_device_register(&dma40_device); + if (ret) + dev_err(&dma40_device.dev, "unable to register device: %d\n", + ret); + + dma_context_notifier_init(); +} diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index c76f0f456f0..bf7e81705d2 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c @@ -11,20 +11,31 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/smp.h> +#include <linux/completion.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> +#include <mach/context.h> + extern volatile int pen_release; +static DECLARE_COMPLETION(cpu_killed); + static inline void platform_do_lowpower(unsigned int cpu) { flush_cache_all(); - /* we put the platform to just WFI */ for (;;) { - __asm__ __volatile__("dsb\n\t" "wfi\n\t" - : : : "memory"); + + context_varm_save_core(); + context_save_cpu_registers(); + + context_save_to_sram_and_wfi(false); + + context_restore_cpu_registers(); + context_varm_restore_core(); + if (pen_release == cpu_logical_map(cpu)) { /* * OK, proper wakeup, we're done @@ -36,7 +47,7 @@ static inline void platform_do_lowpower(unsigned int cpu) int platform_cpu_kill(unsigned int cpu) { - return 1; + return wait_for_completion_timeout(&cpu_killed, 5000); } /* @@ -46,6 +57,19 @@ int platform_cpu_kill(unsigned int cpu) */ void platform_cpu_die(unsigned int cpu) { +#ifdef DEBUG + unsigned int this_cpu = hard_smp_processor_id(); + + if (cpu != this_cpu) { + printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + this_cpu, cpu); + BUG(); + } +#endif + + printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); + complete(&cpu_killed); + /* directly enter low power state, skipping secure registers */ platform_do_lowpower(cpu); } diff --git a/arch/arm/mach-ux500/hwmem-int.c b/arch/arm/mach-ux500/hwmem-int.c new file mode 100644 index 00000000000..e3fecb8c354 --- /dev/null +++ b/arch/arm/mach-ux500/hwmem-int.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Hardware memory driver integration + * + * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#include <linux/hwmem.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/err.h> +#include <linux/slab.h> + +/* CONA API */ +void *cona_create(const char *name, phys_addr_t region_paddr, + size_t region_size); +void *cona_alloc(void *instance, size_t size); +void cona_free(void *instance, void *alloc); +phys_addr_t cona_get_alloc_paddr(void *alloc); +void *cona_get_alloc_kaddr(void *instance, void *alloc); +size_t cona_get_alloc_size(void *alloc); + +struct hwmem_mem_type_struct *hwmem_mem_types; +unsigned int hwmem_num_mem_types; + +static phys_addr_t hwmem_paddr; +static size_t hwmem_size; + +static phys_addr_t hwmem_prot_paddr; +static size_t hwmem_prot_size; + +static int __init parse_hwmem_prot_param(char *p) +{ + + hwmem_prot_size = memparse(p, &p); + + if (*p != '@') + goto no_at; + + hwmem_prot_paddr = memparse(p + 1, &p); + + return 0; + +no_at: + hwmem_prot_size = 0; + + return -EINVAL; +} +early_param("hwmem_prot", parse_hwmem_prot_param); + +static int __init parse_hwmem_param(char *p) +{ + hwmem_size = memparse(p, &p); + + if (*p != '@') + goto no_at; + + hwmem_paddr = memparse(p + 1, &p); + + return 0; + +no_at: + hwmem_size = 0; + + return -EINVAL; +} +early_param("hwmem", parse_hwmem_param); + +static int __init setup_hwmem(void) +{ + static const unsigned int NUM_MEM_TYPES = 3; + + int ret; + + if (hwmem_paddr != PAGE_ALIGN(hwmem_paddr) || + hwmem_size != PAGE_ALIGN(hwmem_size) || hwmem_size == 0) { + printk(KERN_WARNING "HWMEM: hwmem_paddr !=" + " PAGE_ALIGN(hwmem_paddr) || hwmem_size !=" + " PAGE_ALIGN(hwmem_size) || hwmem_size == 0\n"); + return -ENOMSG; + } + + hwmem_mem_types = kzalloc(sizeof(struct hwmem_mem_type_struct) * + NUM_MEM_TYPES, GFP_KERNEL); + if (hwmem_mem_types == NULL) + return -ENOMEM; + + hwmem_mem_types[0].id = HWMEM_MEM_SCATTERED_SYS; + hwmem_mem_types[0].allocator_api.alloc = cona_alloc; + hwmem_mem_types[0].allocator_api.free = cona_free; + hwmem_mem_types[0].allocator_api.get_alloc_paddr = + cona_get_alloc_paddr; + hwmem_mem_types[0].allocator_api.get_alloc_kaddr = + cona_get_alloc_kaddr; + hwmem_mem_types[0].allocator_api.get_alloc_size = cona_get_alloc_size; + hwmem_mem_types[0].allocator_instance = cona_create("hwmem", + hwmem_paddr, hwmem_size); + if (IS_ERR(hwmem_mem_types[0].allocator_instance)) { + ret = PTR_ERR(hwmem_mem_types[0].allocator_instance); + goto hwmem_ima_init_failed; + } + + hwmem_mem_types[1] = hwmem_mem_types[0]; + hwmem_mem_types[1].id = HWMEM_MEM_CONTIGUOUS_SYS; + + hwmem_mem_types[2] = hwmem_mem_types[1]; + hwmem_mem_types[2].id = HWMEM_MEM_PROTECTED_SYS; + + if (hwmem_prot_size > 0) { + hwmem_mem_types[2].allocator_instance = cona_create("hwmem_prot", + hwmem_prot_paddr, hwmem_prot_size); + if (IS_ERR(hwmem_mem_types[2].allocator_instance)) { + ret = PTR_ERR(hwmem_mem_types[2].allocator_instance); + goto hwmem_ima_init_failed; + } + } + + hwmem_num_mem_types = NUM_MEM_TYPES; + + return 0; + +hwmem_ima_init_failed: + kfree(hwmem_mem_types); + + return ret; +} +arch_initcall_sync(setup_hwmem); + +enum hwmem_alloc_flags cachi_get_cache_settings( + enum hwmem_alloc_flags requested_cache_settings) +{ + static const u32 CACHE_ON_FLAGS_MASK = HWMEM_ALLOC_HINT_CACHED | + HWMEM_ALLOC_HINT_CACHE_WB | HWMEM_ALLOC_HINT_CACHE_WT | + HWMEM_ALLOC_HINT_CACHE_NAOW | HWMEM_ALLOC_HINT_CACHE_AOW | + HWMEM_ALLOC_HINT_INNER_AND_OUTER_CACHE | + HWMEM_ALLOC_HINT_INNER_CACHE_ONLY; + + enum hwmem_alloc_flags cache_settings; + + if (!(requested_cache_settings & CACHE_ON_FLAGS_MASK) && + requested_cache_settings & (HWMEM_ALLOC_HINT_NO_WRITE_COMBINE | + HWMEM_ALLOC_HINT_UNCACHED | HWMEM_ALLOC_HINT_WRITE_COMBINE)) + /* + * We never use uncached as it's extremely slow and there is + * no scenario where it would be better than buffered memory. + */ + return HWMEM_ALLOC_HINT_WRITE_COMBINE; + + /* + * The user has specified cached or nothing at all, both are treated as + * cached. + */ + cache_settings = (requested_cache_settings & + ~(HWMEM_ALLOC_HINT_UNCACHED | + HWMEM_ALLOC_HINT_NO_WRITE_COMBINE | + HWMEM_ALLOC_HINT_INNER_CACHE_ONLY | + HWMEM_ALLOC_HINT_CACHE_NAOW)) | + HWMEM_ALLOC_HINT_WRITE_COMBINE | HWMEM_ALLOC_HINT_CACHED | + HWMEM_ALLOC_HINT_CACHE_AOW | + HWMEM_ALLOC_HINT_INNER_AND_OUTER_CACHE; + if (!(cache_settings & (HWMEM_ALLOC_HINT_CACHE_WB | + HWMEM_ALLOC_HINT_CACHE_WT))) + cache_settings |= HWMEM_ALLOC_HINT_CACHE_WB; + /* + * On ARMv7 "alloc on write" is just a hint so we need to assume the + * worst case ie "alloc on write". We would however like to remember + * the requested "alloc on write" setting so that we can pass it on to + * the hardware, we use the reserved bit in the alloc flags to do that. + */ + if (requested_cache_settings & HWMEM_ALLOC_HINT_CACHE_AOW) + cache_settings |= HWMEM_ALLOC_RESERVED_CHI; + else + cache_settings &= ~HWMEM_ALLOC_RESERVED_CHI; + + return cache_settings; +} + +void cachi_set_pgprot_cache_options(enum hwmem_alloc_flags cache_settings, + pgprot_t *pgprot) +{ + if (cache_settings & HWMEM_ALLOC_HINT_CACHED) { + if (cache_settings & HWMEM_ALLOC_HINT_CACHE_WT) + *pgprot = __pgprot_modify(*pgprot, L_PTE_MT_MASK, + L_PTE_MT_WRITETHROUGH); + else { + if (cache_settings & HWMEM_ALLOC_RESERVED_CHI) + *pgprot = __pgprot_modify(*pgprot, + L_PTE_MT_MASK, L_PTE_MT_WRITEALLOC); + else + *pgprot = __pgprot_modify(*pgprot, + L_PTE_MT_MASK, L_PTE_MT_WRITEBACK); + } + } else { + *pgprot = pgprot_writecombine(*pgprot); + } +} diff --git a/arch/arm/mach-ux500/hwreg.c b/arch/arm/mach-ux500/hwreg.c new file mode 100644 index 00000000000..585f2a2b7be --- /dev/null +++ b/arch/arm/mach-ux500/hwreg.c @@ -0,0 +1,736 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * + * Author: Etienne CARRIERE <etienne.carriere@stericsson.com> for ST-Ericsson + * + * License terms: GNU General Public License (GPL) version 2 + * + * HWREG: debug purpose module to map declared IOs and read/write + * access from debugfs entries. + * + * HWREG 32bit DB8500 v2.0 register access + * ======================================= + * + * 32bit read: + * # echo <addr> > <debugfs>/mem/reg-addr + * # cat <debugfs>/mem/reg-val + * + * 32bit write: + * # echo <addr> > <debugfs>/mem/reg-addr + * # echo <value> > <debugfs>/mem/reg-val + * + * <addr> 0x-prefixed hexadecimal + * <value> decimal or 0x-prefixed hexadecimal + * + * HWREG DB8500 formated read/write access + * ======================================= + * + * Read: read data, data>>SHIFT, data&=MASK, output data + * [0xABCDEF98] shift=12 mask=0xFFF => 0x00000CDE + * Write: read data, data &= ~(MASK<<SHIFT), data |= (VALUE<<SHIFT), write data + * [0xABCDEF98] shift=12 mask=0xFFF value=0x123 => [0xAB123F98] + * + * Usage: + * # echo "CMD [OPTIONS] ADRESS [VALUE]" > $debugfs/mem/hwreg + * + * CMD read read access + * write write access + * + * ADDRESS target reg physical addr (0x-hexa) + * + * VALUE (write) value to be updated + * + * OPTIONS + * -d|-dec (read) output in decimal + * -h|-hexa (read) output in 0x-hexa (default) + * -l|-w|-b 32bit (default), 16bit or 8bit reg access + * -m|-mask MASK 0x-hexa mask (default 0xFFFFFFFF) + * -s|-shift SHIFT bit shift value (read:left, write:right) + * -o|-offset OFFSET address offset to add to ADDRESS value + * + * Warning: bit shift operation is applied to bit-mask. + * Warning: bit shift direction depends on read or right command. + * + * Examples: + * + * before: [*ADDRESS = 0xABCDEF98] + * # echo read -h -mask 0xFFF -shift 12 ADDRESS > hwreg + * # cat hwreg-shift + * 0x0000CDE + * # echo write -h -mask 0xFFF -shift 12 ADDRESS 0x123 > hwreg + * # cat hwreg-shift + * 0x0000123 + * after [*ADDRESS = 0xAB123F98] + * + * before: [*ADDRESS = 0xABCDEF98] + * # echo read -h -mask 0x00F0F000 ADDRESS 0x12345678 > hwreg + * # cat hwreg-shift + * 0x00C0E000 + * # echo write -h -mask 0x00F0F000 ADDRESS 0x12345678 > hwreg + * # cat hwreg-shift + * 0xAB3D5F98 + * after [*ADDRESS = 0xAB123F98] + * + * Read DB8500 version (full ID, chip version ID, chip version ID): + * + * echo read 0x9001DBF4 > hwreg + * cat hwreg + * echo read -m 0xFFFF -s 8 0x9001DBF4 > hwreg + * cat hwreg + * echo read -m 0xFF -s 0 0x9001DBF4 > hwreg + * cat hwreg + * + * Read and Enable/Disable I2C PRCMU clock: + * + * printf "I2CCLK = " && echo read -m 1 -s 8 0x80157520 > hwreg + * cat /sys/kernel/debug/db8500/hwreg + * printf "I2CCLK off" && echo write -m 1 -s 8 0x80157518 1 > hwreg + * printf "I2CCLK on" && echo write -m 1 -s 8 0x80157510 1 > hwreg + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <linux/uaccess.h> +#include <linux/io.h> + +#include <mach/hardware.h> + +/* + * temporary definitions + * The following declarations are to be removed + * when kernel/arch/arm/mach-ux8500/include/mach/db8500-regs.h is up-to-date + */ + +/* DDR-SDRAM chip-select 0 (0x0000 0000 : 0x1FFF FFFF) */ +#ifndef U8500_SCU_CD_R4_BASE +#define U8500_SCU_CD_R4_BASE 0x17c40000 +#endif + +#ifndef U8500_SCU_AD_R4_BASE +#define U8500_SCU_AD_R4_BASE 0x17d40000 +#endif + +#ifndef U8500_HSI2CMODEMR4_BASE +#define U8500_HSI2CMODEMR4_BASE 0x17e02000 +#endif +/* End of temporary definitions */ + +static struct dentry *hwreg_debugfs_dir; + +/* 32bit read/write ressources */ +static u32 debug_address; /* shared: single read/write access */ + +/* hwreg entry ressources */ +struct hwreg_cfg { + uint addr; /* target physical addr to access */ + uint fmt; /* format */ + uint mask; /* read/write mask, applied before any bit shift */ + int shift; /* bit shift (read:right shift, write:left shift */ +}; +#define REG_FMT_DEC(c) ((c)->fmt & 0x1) /* bit 0: 0=hexa, 1=dec */ +#define REG_FMT_HEX(c) (!REG_FMT_DEC(c)) /* bit 0: 0=hexa, 1=dec */ +#define REG_FMT_32B(c) (((c)->fmt & 0x6) == 0x0) /* bit[2:1]=0 => 32b access */ +#define REG_FMT_16B(c) (((c)->fmt & 0x6) == 0x2) /* bit[2:1]=1 => 16b access */ +#define REG_FMT_8B(c) (((c)->fmt & 0x6) == 0x4) /* bit[2:1]=2 => 8b access */ + +static struct hwreg_cfg hwreg_cfg = { + .addr = 0, /* default: invalid phys addr */ + .fmt = 0, /* default: 32bit access, hex output */ + .mask = 0xFFFFFFFF, /* default: no mask */ + .shift = 0, /* default: no bit shift */ +}; + +/* HWREG guts: mapping table */ + +struct hwreg_io_range { + u32 base; + u32 size; + u8 *addr; +}; + +static struct hwreg_io_range *hwreg_io_current_map; + +/* + * HWREG guts: mapping table + */ +static struct hwreg_io_range hwreg_u8500_io_map[] = { + /* Periph1 Peripherals */ + {.base = U8500_PER1_BASE, .size = 0x10000}, + /* Periph2 Peripherals */ + {.base = U8500_PER2_BASE, .size = 0x10000}, + /* Periph3 Peripherals */ + {.base = U8500_PER3_BASE, .size = 0x10000}, + /* Periph4 Peripherals */ + {.base = U8500_PER4_BASE, .size = 0x70000}, + /* Periph5 Periphals */ + {.base = U8500_PER5_BASE, .size = 0x20000}, + /* Periph6 Peripherals */ + {.base = U8500_PER6_BASE, .size = 0x10000}, + /* + * Snoop Control Unit, A9 Private interrupt IF, + * A9 private peripherals, Level-2 Cache Configuration registers, + * and some reserved area + */ + {.base = U8500_SCU_BASE, .size = 0x4000}, + + /* DISPLAY Ctrl. configuration registers */ + {.base = U8500_MCDE_BASE, .size = SZ_4K}, + + /* DSI1 link registers */ + {.base = U8500_DSI_LINK1_BASE, .size = SZ_4K}, + + /* DSI2 link registers */ + {.base = U8500_DSI_LINK2_BASE, .size = SZ_4K}, + + /* DSI3 link registers */ + {.base = U8500_DSI_LINK3_BASE, .size = SZ_4K}, + + /* DMA Ctrl. configuration registers (base address changed in V1) */ + {.base = U8500_DMA_BASE, .size = SZ_4K}, + + /* 0xB7A00000 -> 0xB7E04000: Modem I2C */ + {.base = U8500_MODEM_I2C, .size = 0x404000}, + + /* 0xA0390000 -> 0xA039FFFF: SBAG configuration registers */ + {.base = U8500_SBAG_BASE, .size = SZ_4K}, + + /* 0xA0300000 -> 0xA031FFFF: SGA configuration registers */ + {.base = U8500_SGA_BASE, .size = 0x10000}, + + /* 0xA0200000 -> 0xA02FFFFF: Smart Imaging Acc. Data Memory space (SIA) */ + {.base = U8500_SIA_BASE, .size = 0x60000}, + + /* 0xA0100000 -> 0xA01FFFFF: Smart Video Acc. Data Memory space (SVA) */ + {.base = U8500_SVA_BASE, .size = 0x60000}, + + /* 0x81000000 -> 0x8103FFFF: Main ICN Crossbar configuration registers */ + {.base = U8500_ICN_BASE, .size = 0x2000}, + + /* 0x80140000 -> 0x8014FFFF: HSEM (Semaphores) configuration */ + {.base = U8500_HSEM_BASE, .size = SZ_4K}, + + /* 0x80130000 -> 0x8013FFFF: B2R2 configuration registers */ + {.base = U8500_B2R2_BASE, .size = SZ_4K}, + + /* 0x80100000 -> 0x8010FFFF: STM */ + {.base = U8500_STM_BASE, .size = 0x10000}, + + /* High part of embedded boot ROM */ + {.base = U8500_ASIC_ID_BASE, .size = SZ_4K}, + + /* 0x17C4 0000 : 0x17C4 007C */ + {.base = U8500_SCU_CD_R4_BASE, .size = SZ_4K}, + + /* 0x17D4 0000 : 0x17D4 041C */ + {.base = U8500_SCU_AD_R4_BASE, .size = SZ_4K}, + + /* 0x17E0 2000 : 0x17E0 2FFC */ + {.base = U8500_HSI2CMODEMR4_BASE, .size = SZ_4K}, + + {.base = 0, .size = 0, }, + +}; + +static struct hwreg_io_range hwreg_u9540_io_map[] = { + /* Periph1 Peripherals */ + {.base = U8500_PER1_BASE, .size = 0x10000}, + /* Periph2 Peripherals */ + {.base = U8500_PER2_BASE, .size = 0x10000}, + /* Periph3 Peripherals */ + {.base = U8500_PER3_BASE, .size = 0x10000}, + /* Periph4 Peripherals */ + {.base = U8500_PER4_BASE, .size = 0x70000}, + /* Periph5 Periphals */ + {.base = U8500_PER5_BASE, .size = 0x20000}, + /* Periph6 Peripherals */ + {.base = U8500_PER6_BASE, .size = 0x10000}, + /* + * Snoop Control Unit, A9 Private interrupt IF, + * A9 private peripherals, Level-2 Cache Configuration registers, + * and some reserved area + */ + {.base = U8500_SCU_BASE, .size = 0x4000}, + + /* DISPLAY Ctrl. configuration registers */ + {.base = U8500_MCDE_BASE, .size = SZ_4K}, + + /* DSI1 link registers */ + {.base = U8500_DSI_LINK1_BASE, .size = SZ_4K}, + + /* DSI2 link registers */ + {.base = U8500_DSI_LINK2_BASE, .size = SZ_4K}, + + /* DSI3 link registers */ + {.base = U8500_DSI_LINK3_BASE, .size = SZ_4K}, + + /* DMA Ctrl. configuration registers (base address changed in V1) */ + {.base = U8500_DMA_BASE, .size = SZ_4K}, + + /* 0xB7A00000 -> 0xB7E04000: Modem I2C */ + {.base = U8500_MODEM_I2C, .size = 0x404000}, + + /* 0xA0390000 -> 0xA039FFFF: SBAG configuration registers */ + {.base = U8500_SBAG_BASE, .size = SZ_4K}, + + /* 0xA0300000 -> 0xA031FFFF: SGA configuration registers */ + {.base = U8500_SGA_BASE, .size = 0x10000}, + + /* 0xA0200000 -> 0xA02FFFFF: Smart Imaging Acc. Data Memory space (SIA) + */ + {.base = U8500_SIA_BASE, .size = 0x60000}, + + /* 0xA0100000 -> 0xA01FFFFF: Smart Video Acc. Data Memory space (SVA) */ + {.base = U8500_SVA_BASE, .size = 0x60000}, + + /* 0x81000000 -> 0x8103FFFF: Main ICN Crossbar configuration registers + */ + {.base = U8500_ICN_BASE, .size = 0x2000}, + + /* 0x80140000 -> 0x8014FFFF: HSEM (Semaphores) configuration */ + {.base = U8500_HSEM_BASE, .size = SZ_4K}, + + /* 0x80130000 -> 0x8013FFFF: B2R2 configuration registers */ + {.base = U8500_B2R2_BASE, .size = SZ_4K}, + + /* 0x80100000 -> 0x8010FFFF: STM */ + {.base = U8500_STM_BASE, .size = 0x10000}, + + /* High part of embedded boot ROM */ + {.base = U9540_ASIC_ID_BASE, .size = SZ_4K}, + + {.base = 0, .size = 0, }, + +}; + +static void hwreg_io_init(void) +{ + int i; + + for (i = 0; hwreg_io_current_map[i].base; ++i) { + hwreg_io_current_map[i].addr = + ioremap(hwreg_io_current_map[i].base, + hwreg_io_current_map[i].size); + if (!hwreg_io_current_map[i].addr) + printk(KERN_WARNING + "%s: ioremap for %d (%08x) failed\n", + __func__, i, hwreg_io_current_map[i].base); + } +} + +static void hwreg_io_exit(void) +{ + int i; + + for (i = 0; hwreg_io_current_map[i].base; ++i) + if (hwreg_io_current_map[i].addr) + iounmap(hwreg_io_current_map[i].addr); +} + +static void *hwreg_io_ptov(u32 phys) +{ + int i; + + for (i = 0; hwreg_io_current_map[i].base; ++i) { + u32 base = hwreg_io_current_map[i].base; + u32 size = hwreg_io_current_map[i].size; + u8 *addr = hwreg_io_current_map[i].addr; + + if (phys < base || phys >= base + size) + continue; + + if (addr) + return addr + phys - base; + + break; + } + + return NULL; +} + + +/* + * HWREG 32bit DB8500 register read/write access debugfs part + */ + +static int hwreg_address_print(struct seq_file *s, void *p) +{ + return seq_printf(s, "0x%08X\n", debug_address); +} + +static int hwreg_address_open(struct inode *inode, struct file *file) +{ + return single_open(file, hwreg_address_print, inode->i_private); +} + +static ssize_t hwreg_address_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + int err; + unsigned long user_address; + + err = kstrtoul_from_user(user_buf, count, 0, &user_address); + + if (err) + return err; + + if (hwreg_io_ptov(user_address) == NULL) + return -EADDRNOTAVAIL; + + debug_address = user_address; + return count; +} + +static int hwreg_value_print(struct seq_file *s, void *p) +{ + void *ptr; + + ptr = hwreg_io_ptov(debug_address); + if (ptr == NULL) + return -EADDRNOTAVAIL; + seq_printf(s, "0x%X\n", readl(ptr)); + return 0; +} + +static int hwreg_value_open(struct inode *inode, struct file *file) +{ + return single_open(file, hwreg_value_print, inode->i_private); +} + +static ssize_t hwreg_value_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + int err; + unsigned long user_val; + void *ptr; + + err = kstrtoul_from_user(user_buf, count, 0, &user_val); + + if (err) + return err; + + if ((ptr = hwreg_io_ptov(debug_address)) == NULL) + return -EFAULT; + writel(user_val, ptr); + return count; +} + +static const struct file_operations hwreg_address_fops = { + .open = hwreg_address_open, + .write = hwreg_address_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; +static const struct file_operations hwreg_value_fops = { + .open = hwreg_value_open, + .write = hwreg_value_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +/* 'map' read entry: display current HWREG IO mapping table */ +static int hwreg_map_print(struct seq_file *s, void *p) +{ + int err, i; + + for (i = 0; hwreg_io_current_map[i].base; ++i) { + err = seq_printf(s, "%d: 0x%08X => 0x%08X\n", + i, hwreg_io_current_map[i].base, + hwreg_io_current_map[i].base + + hwreg_io_current_map[i].size); + if (err < 0) + return -ENOMEM; + } + return 0; +} +static int hwreg_map_open(struct inode *inode, struct file *file) +{ + return single_open(file, hwreg_map_print, inode->i_private); +} + +static const struct file_operations hwreg_map_fops = { + .open = hwreg_map_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +/* + * HWREG DB8500 formated routines + */ + +static int hwreg_print(struct seq_file *s, void *d) +{ + struct hwreg_cfg *c = (struct hwreg_cfg *) s->private; + void *p; + uint v; + + if ((c == NULL) || ((p = hwreg_io_ptov(c->addr)) == NULL)) + return -EADDRNOTAVAIL; + + v = (uint) (REG_FMT_32B(c) ? readl(p) : REG_FMT_16B(c) ? readw(p) : readb(p)); + v = (c->shift >= 0) ? v >> c->shift : v << (-c->shift); + v = v & c->mask; + + if (REG_FMT_DEC(c)) + seq_printf(s, "%d\n", v); + else if (REG_FMT_32B(c)) + seq_printf(s, "0x%08X\n", v); + else if (REG_FMT_32B(c)) + seq_printf(s, "0x%04X\n", v); + else + seq_printf(s, "0x%02X\n", v); + return 0; +} + +static int hwreg_open(struct inode *inode, struct file *file) +{ + return single_open(file, hwreg_print, inode->i_private); +} + +/* + * return length of an ASCII numerical value, 0 is string is not a numerical + * value. string shall start at value 1st char. + * string can be tailed with \0 or space or newline chars only. + * value can be decimal or hexadecimal (prefixed 0x or 0X). + */ +static int strval_len(char *b) +{ + char *s = b; + if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) { + s += 2; + for (; *s && (*s != ' ') && (*s != '\n'); s++) { + if (!isxdigit(*s)) + return 0; + } + } else { + if (*s == '-') + s++; + for (; *s && (*s != ' ') && (*s != '\n'); s++) { + if (!isdigit(*s)) + return 0; + } + } + return (int) (s-b); +} + +/* + * parse hwreg input data. + * update global hwreg_cfg only if input data syntax is ok. + */ +static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg) +{ + uint write, val = 0, offset = 0; + struct hwreg_cfg loc = { + .addr = 0, /* default: invalid phys addr */ + .fmt = 0, /* default: 32bit access, hex output */ + .mask = 0xFFFFFFFF, /* default: no mask */ + .shift = 0, /* default: no bit shift */ + }; + + /* read or write ? */ + if (!strncmp(b, "read ", 5)) { + write = 0; + b += 5; + } else if (!strncmp(b, "write ", 6)) { + write = 1; + b += 6; + } else { + return -EINVAL; + } + + /* OPTIONS -l|-w|-b -s -m -o */ + while ((*b == ' ') || (*b == '-')) { + if (*(b-1) != ' ') { + b++; + continue; + } + if ((!strncmp(b, "-d ", 3)) || (!strncmp(b, "-dec ", 5))) { + b += (*(b+2) == ' ') ? 3 : 5; + loc.fmt |= (1<<0); + } else if ((!strncmp(b, "-h ", 3)) || (!strncmp(b, "-hex ", 5))) { + b += (*(b+2) == ' ') ? 3 : 5; + loc.fmt &= ~(1<<0); + } else if ((!strncmp(b, "-m ", 3)) || (!strncmp(b, "-mask ", 6))) { + b += (*(b+2) == ' ') ? 3 : 6; + if (strval_len(b) == 0) + return -EINVAL; + loc.mask = simple_strtoul(b, &b, 0); + } else if ((!strncmp(b, "-s ", 3)) || (!strncmp(b, "-shift ", 7))) { + b += (*(b+2) == ' ') ? 3 : 7; + if (strval_len(b) == 0) + return -EINVAL; + loc.shift = simple_strtol(b, &b, 0); + + } else if ((!strncmp(b, "-o ", 3)) || (!strncmp(b, "-offset ", 8))) { + b += (*(b+2) == ' ') ? 3 : 8; + if (strval_len(b) == 0) + return -EINVAL; + offset = simple_strtol(b, &b, 0); + } else if (!strncmp(b, "-l ", 3)) { + b += 3; + loc.fmt = (loc.fmt & ~(3<<1)) | (0<<1); + } else if (!strncmp(b, "-w ", 3)) { + b += 3; + loc.fmt = (loc.fmt & ~(3<<1)) | (1<<1); + } else if (!strncmp(b, "-b ", 3)) { + b += 3; + loc.fmt = (loc.fmt & ~(3<<1)) | (2<<1); + } else { + return -EINVAL; + } + } + /* get arg ADDRESS */ + if (strval_len(b) == 0) + return -EINVAL; + loc.addr = simple_strtoul(b, &b, 0); + loc.addr += offset; + if (hwreg_io_ptov(loc.addr) == NULL) + return -EINVAL; + + if (write) { + while (*b == ' ') + b++; /* skip spaces up to arg VALUE */ + if (strval_len(b) == 0) + return -EINVAL; + val = simple_strtoul(b, &b, 0); + } + + /* args are ok, update target cfg (mainly for read) */ + *cfg = loc; + +#ifdef DEBUG + printk(KERN_INFO "HWREG request: %s %d-bit reg, %s, addr=0x%08X, " + "mask=0x%X, shift=%d value=0x%X\n", + (write) ? "write" : "read", + REG_FMT_32B(cfg) ? 32 : REG_FMT_16B(cfg) ? 16 : 8, + REG_FMT_DEC(cfg) ? "decimal" : "hexa", + cfg->addr, cfg->mask, cfg->shift, val); +#endif + + if (write) { + void *p = hwreg_io_ptov(cfg->addr); + uint d = (uint) (REG_FMT_32B(cfg)) ? readl(p) : + (REG_FMT_16B(cfg)) ? readw(p) : readb(p); + + if (cfg->shift>=0) { + d &= ~(cfg->mask << (cfg->shift)); + val = (val & cfg->mask) << (cfg->shift); + } else { + d &= ~(cfg->mask >> (-cfg->shift)); + val = (val & cfg->mask) >> (-cfg->shift); + } + val = val | d; + + /* read reg, reset mask field and update value bit-field */ + if (REG_FMT_32B(cfg)) + writel(val, p); + else if (REG_FMT_16B(cfg)) + writew(val, p); + else + writeb(val, p); + } + return 0; +} + +static ssize_t hwreg_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + char buf[128]; + int buf_size, ret; + + /* Get userspace string and assure termination */ + buf_size = min(count, (sizeof(buf)-1)); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + buf[buf_size] = 0; + + /* get args and process */ + ret = hwreg_common_write(buf, &hwreg_cfg); + return (ret) ? ret : buf_size; +} + +static const struct file_operations hwreg_fops = { + .open = hwreg_open, + .write = hwreg_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +/* + * hwreg module init/cleanup + */ +static int __init hwreg_initialize(void) +{ + static struct dentry *file; + + if (cpu_is_u9540()) { + printk(KERN_INFO "hwreg: cpu is U9540\n"); + hwreg_io_current_map = hwreg_u9540_io_map; + } else { + printk(KERN_INFO "hwreg: cpu is U8500\n"); + hwreg_io_current_map = hwreg_u8500_io_map; + } + + hwreg_io_init(); + + hwreg_debugfs_dir = debugfs_create_dir("mem", NULL); + if (!hwreg_debugfs_dir) + goto debugfs_err; + + file = debugfs_create_file("reg-addr", + (S_IRUGO | S_IWUGO), hwreg_debugfs_dir, + NULL, &hwreg_address_fops); + if (!file) + goto debugfs_err; + file = debugfs_create_file("reg-val", + (S_IRUGO | S_IWUGO), hwreg_debugfs_dir, + NULL, &hwreg_value_fops); + if (!file) + goto debugfs_err; + file = debugfs_create_file("reg-map", + (S_IRUGO), + hwreg_debugfs_dir, NULL, &hwreg_map_fops); + if (!file) + goto debugfs_err; + file = debugfs_create_file("hwreg", + (S_IRUGO), + hwreg_debugfs_dir, &hwreg_cfg, &hwreg_fops); + if (!file) + goto debugfs_err; + return 0; + +debugfs_err: + if (hwreg_debugfs_dir) + debugfs_remove_recursive(hwreg_debugfs_dir); + printk(KERN_ERR "hwreg: failed to register debugfs entries.\n"); + return -1; +} + +static void __exit hwreg_finalize(void) +{ + debugfs_remove_recursive(hwreg_debugfs_dir); + hwreg_io_exit(); +} + +module_init(hwreg_initialize); +module_exit(hwreg_finalize); + +MODULE_AUTHOR("ST-Ericsson"); +MODULE_DESCRIPTION("DB8500 HW registers access through debugfs"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c index 15a0f63b2e2..4d12f826386 100644 --- a/arch/arm/mach-ux500/id.c +++ b/arch/arm/mach-ux500/id.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/export.h> #include <asm/cputype.h> #include <asm/tlbflush.h> @@ -18,6 +19,7 @@ #include <mach/setup.h> struct dbx500_asic_id dbx500_id; +EXPORT_SYMBOL(dbx500_id); static unsigned int ux500_read_asicid(phys_addr_t addr) { @@ -38,6 +40,25 @@ static unsigned int ux500_read_asicid(phys_addr_t addr) return readl(__io_address(addr)); } +static unsigned int u9540_read_asicid(phys_addr_t addr) +{ + phys_addr_t base = addr & ~0xfff; + struct map_desc desc = { + .virtual = IO_ADDRESS_DB9540_ROM(base), + .pfn = __phys_to_pfn(base), + .length = SZ_16K, + .type = MT_DEVICE, + }; + + iotable_init(&desc, 1); + + /* As in devicemaps_init() */ + local_flush_tlb_all(); + flush_cache_all(); + + return readl(__io_address_db9540_rom(addr)); +} + static void ux500_print_soc_info(unsigned int asicid) { unsigned int rev = dbx500_revision(); @@ -66,7 +87,9 @@ static unsigned int partnumber(unsigned int asicid) * DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1 * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2 + * AP9500 0x412fc091 0x9001DBF4 0x008500B2 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 + * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx */ void __init ux500_map_io(void) @@ -81,7 +104,7 @@ void __init ux500_map_io(void) addr = 0x9001FFF4; break; - case 0x412fc091: /* DB8520 / DB8500v2 / DB5500v1 */ + case 0x412fc091: /* DB8520 / DB8500v2 / DB5500v1 / AP9500 */ asicid = ux500_read_asicid(0x9001DBF4); if (partnumber(asicid) == 0x8500 || partnumber(asicid) == 0x8520) @@ -91,6 +114,12 @@ void __init ux500_map_io(void) /* DB5500v1 */ addr = 0x9001FFF4; break; + + case 0x413fc090: /* DB9540 */ + addr = 0xFFFFDBF4; + asicid = u9540_read_asicid(addr); + addr = 0; + break; } if (addr) diff --git a/arch/arm/mach-ux500/include/mach/context.h b/arch/arm/mach-ux500/include/mach/context.h new file mode 100644 index 00000000000..a3490121b67 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/context.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> + * Rickard Andersson <rickard.andersson@stericsson.com> for + * ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + * + */ +#ifndef CONTEXT_H +#define CONTEXT_H + +#include <linux/notifier.h> + +#ifdef CONFIG_UX500_CONTEXT + +/* Defines to be with + * context_ape_notifier_register + */ +#define CONTEXT_APE_SAVE 0 /* APE save */ +#define CONTEXT_APE_RESTORE 1 /* APE restore */ + +/* Defines to be with + * context_arm_notifier_register + */ +#define CONTEXT_ARM_CORE_SAVE 0 /* Called for each ARM core */ +#define CONTEXT_ARM_CORE_RESTORE 1 /* Called for each ARM core */ +#define CONTEXT_ARM_COMMON_SAVE 2 /* Called when ARM common is saved */ +#define CONTEXT_ARM_COMMON_RESTORE 3 /* Called when ARM common is restored */ + +int context_ape_notifier_register(struct notifier_block *nb); +int context_ape_notifier_unregister(struct notifier_block *nb); + +int context_arm_notifier_register(struct notifier_block *nb); +int context_arm_notifier_unregister(struct notifier_block *nb); + +void context_vape_save(void); +void context_vape_restore(void); + +void context_fsmc_save(void); +void context_fsmc_restore(void); + +void context_gpio_save(void); +void context_gpio_restore(void); +void context_gpio_restore_mux(void); +void context_gpio_mux_safe_switch(bool begin); + +void context_gic_dist_disable_unneeded_irqs(void); + +void context_varm_save_common(void); +void context_varm_restore_common(void); + +void context_varm_save_core(void); +void context_varm_restore_core(void); + +void context_save_cpu_registers(void); +void context_restore_cpu_registers(void); + +void context_save_to_sram_and_wfi(bool cleanL2cache); + +void context_clean_l1_cache_all(void); +void context_save_arm_registers(u32 **backup_stack); +void context_restore_arm_registers(u32 **backup_stack); + +void context_save_cp15_registers(u32 **backup_stack); +void context_restore_cp15_registers(u32 **backup_stack); + +void context_save_to_sram_and_wfi_internal(u32 backup_sram_storage, + bool cleanL2cache); + +/* DB specific functions in either context-db8500 or context-db5500 */ +void u8500_context_save_icn(void); +void u8500_context_restore_icn(void); +void u8500_context_init(void); + +void u5500_context_save_icn(void); +void u5500_context_restore_icn(void); +void u5500_context_init(void); + +void u9540_context_save_icn(void); +void u9540_context_restore_icn(void); +void u9540_context_init(void); +#else + +static inline void context_varm_save_core(void) {} +static inline void context_save_cpu_registers(void) {} +static inline void context_save_to_sram_and_wfi(bool cleanL2cache) {} +static inline void context_restore_cpu_registers(void) {} +static inline void context_varm_restore_core(void) {} + +#endif + +#endif diff --git a/arch/arm/mach-ux500/include/mach/crypto-ux500.h b/arch/arm/mach-ux500/include/mach/crypto-ux500.h new file mode 100644 index 00000000000..80c4620d633 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/crypto-ux500.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ +#ifndef _CRYPTO_UX500_H +#include <linux/dmaengine.h> +#include <plat/ste_dma40.h> + +struct cryp_platform_data { + struct stedma40_chan_cfg mem_to_engine; + struct stedma40_chan_cfg engine_to_mem; +}; + +struct hash_platform_data { + void *mem_to_engine; + bool (*dma_filter)(struct dma_chan *chan, void *filter_param); +}; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/cw1200_plat.h b/arch/arm/mach-ux500/include/mach/cw1200_plat.h new file mode 100644 index 00000000000..3a73183c9f8 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/cw1200_plat.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CW1200_PLAT_H_INCLUDED +#define CW1200_PLAT_H_INCLUDED + +#include <linux/ioport.h> + +struct cw1200_platform_data { + const char *mmc_id; + const struct resource *irq; + const struct resource *reset; + int (*power_ctrl)(const struct cw1200_platform_data *pdata, + bool enable); + int (*clk_ctrl)(const struct cw1200_platform_data *pdata, + bool enable); + int (*prcmu_ctrl)(const struct cw1200_platform_data *pdata, + bool enable); +}; + +/* Declaration only. Should be implemented in arch/xxx/mach-yyy */ +const struct cw1200_platform_data *cw1200_get_platform_data(void); + +#endif /* CW1200_PLAT_H_INCLUDED */ diff --git a/arch/arm/mach-ux500/include/mach/db5500-keypad.h b/arch/arm/mach-ux500/include/mach/db5500-keypad.h new file mode 100644 index 00000000000..d9d23419ab3 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/db5500-keypad.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License, version 2 + * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson + */ + +#ifndef __DB5500_KEYPAD_H +#define __DB5500_KEYPAD_H + +#include <linux/input/matrix_keypad.h> + +#define KEYPAD_MAX_ROWS 9 +#define KEYPAD_MAX_COLS 8 + +/** + * struct db5500_keypad_platform_data - structure for platform specific data + * @keymap_data: matrix scan code table for keycodes + * @debounce_ms: platform specific debounce time + * @no_autorepeat: flag for auto repetition + * @init : pointer to keypad init function + * @exit : pointer to keypad exit function + * @krow : maximum number of rows + * @kcol : maximum number of cols + * @gpio_input_pins: pointer to gpio input pins + * @gpio_output_pins: pointer to gpio output pins + * @switch_delay : gpio switch_delay + */ +struct db5500_keypad_platform_data { + const struct matrix_keymap_data *keymap_data; + u8 debounce_ms; + bool no_autorepeat; + int (*init)(void); + int (*exit)(void); + u8 krow; + u8 kcol; + int *gpio_input_pins; + int *gpio_output_pins; + int switch_delay; +}; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h index 8e714bcb099..187163bd63d 100644 --- a/arch/arm/mach-ux500/include/mach/db5500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h @@ -34,6 +34,7 @@ #define U5500_ICN_BASE 0xA0040000 #define U5500_B2R2_BASE 0xa0200000 #define U5500_BOOT_ROM_BASE 0x90000000 +#define U5500_ASIC_ID_ADDRESS (U5500_BOOT_ROM_BASE + 0x1FFF4) #define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000) #define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000) diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 9ec20b96d8f..d2cc53d3557 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -41,6 +41,10 @@ /* ASIC ID is at 0xbf4 offset within this region */ #define U8500_ASIC_ID_BASE 0x9001D000 +#define U9540_BOOT_ROM_BASE 0xFFFE0000 +/* ASIC ID is at 0xbf4 offset within this region */ +#define U9540_ASIC_ID_BASE 0xFFFFD000 + #define U8500_PER6_BASE 0xa03c0000 #define U8500_PER7_BASE 0xa03d0000 #define U8500_PER5_BASE 0xa03e0000 @@ -96,7 +100,10 @@ #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) +#define U8500_PRCMU_SEC_BASE (U8500_PER4_BASE + 0x08000) +#define U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000) #define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) +#define U9540_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x6A000) #define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) #define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338) #define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450) diff --git a/arch/arm/mach-ux500/include/mach/dcache.h b/arch/arm/mach-ux500/include/mach/dcache.h new file mode 100644 index 00000000000..83fe618b04f --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/dcache.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Data cache helpers + * + * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef _MACH_UX500_DCACHE_H_ +#define _MACH_UX500_DCACHE_H_ + +#include <linux/types.h> + +void drain_cpu_write_buf(void); +void clean_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only, + bool *cleaned_everything); +void flush_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only, + bool *flushed_everything); +bool speculative_data_prefetch(void); +/* Returns 1 if no cache is present */ +u32 get_dcache_granularity(void); + +#endif /* _MACH_UX500_DCACHE_H_ */ diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 5f6cb71fc62..6d176e93653 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -13,9 +13,27 @@ struct amba_device; extern struct platform_device u5500_gpio_devs[]; extern struct platform_device u8500_gpio_devs[]; +extern struct platform_device u8500_mcde_device; +extern struct platform_device u5500_mcde_device; +extern struct platform_device u8500_shrm_device; +extern struct platform_device u8500_b2r2_blt_device; +extern struct platform_device u5500_b2r2_blt_device; +extern struct platform_device u8500_b2r2_device; +extern struct platform_device u5500_b2r2_device; +extern struct platform_device u8500_trace_modem; +extern struct platform_device ux500_hwmem_device; +extern struct platform_device u8500_stm_device; extern struct amba_device ux500_pl031_device; - -extern struct platform_device u8500_dma40_device; +extern struct platform_device ux500_hash1_device; +extern struct platform_device ux500_cryp1_device; +extern struct platform_device mloader_fw_device; +extern struct platform_device u5500_thsens_device; +extern struct platform_device u8500_thsens_device; extern struct platform_device ux500_ske_keypad_device; +extern struct platform_device u8500_wdt_device; +extern struct platform_device u5500_wdt_device; +extern struct platform_device u8500_hsi_device; +extern struct platform_device ux500_mmio_device; +extern struct platform_device u5500_mmio_device; #endif diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h index c01ef66537f..e0d903af605 100644 --- a/arch/arm/mach-ux500/include/mach/gpio.h +++ b/arch/arm/mach-ux500/include/mach/gpio.h @@ -1,5 +1,29 @@ #ifndef __ASM_ARCH_GPIO_H #define __ASM_ARCH_GPIO_H +/* + * 288 (#267 is the highest one actually hooked up) onchip GPIOs, plus enough + * room for a couple of GPIO expanders. + */ + +#if CONFIG_ARCH_NR_GPIO > 0 +#define ARCH_NR_GPIOS CONFIG_ARCH_NR_GPIO +#else +#define ARCH_NR_GPIOS 366 +#endif + +#define NOMADIK_NR_GPIO 288 + +#include <asm-generic/gpio.h> + +/* Invoke gpiolibs gpio_chip abstraction */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) +#define MOP500_EGPIO_END MOP500_EGPIO(24) +#define AB8500_GPIO_BASE MOP500_EGPIO_END #endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index f84698936d3..88b105d8d89 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -22,15 +22,42 @@ #define IO_ADDRESS(x) \ (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + U8500_IO_VIRTUAL) +/* + * For 9540, ROM code is at address 0xFFFE0000 + * The previous macro cannot be used + * Or else its virtual address would be above 0xFFFFFFFF + */ +#define IO_ADDRESS_DB9540_ROM(x) \ + (((x) & 0x0001ffff) + U8500_IO_VIRTUAL + 0x0B000000) + /* typesafe io address */ #define __io_address(n) IOMEM(IO_ADDRESS(n)) + +#define __io_address_db9540_rom(n) __io(IO_ADDRESS_DB9540_ROM(n)) /* Used by some plat-nomadik code */ #define io_p2v(n) __io_address(n) #include <mach/db8500-regs.h> #include <mach/db5500-regs.h> +/* + * FIFO offsets for IPs + */ #define MSP_TX_RX_REG_OFFSET 0 +#define HASH1_TX_REG_OFFSET 0x4 +#define SSP_TX_RX_REG_OFFSET 0x8 +#define SPI_TX_RX_REG_OFFSET 0x8 +#define SD_MMC_TX_RX_REG_OFFSET 0x80 +#define CRYP1_RX_REG_OFFSET 0x10 +#define CRYP1_TX_REG_OFFSET 0x8 + +#define SSP_0_CONTROLLER 4 +#define SSP_1_CONTROLLER 5 + +#define SPI023_0_CONTROLLER 6 +#define SPI023_1_CONTROLLER 7 +#define SPI023_2_CONTROLLER 8 +#define SPI023_3_CONTROLLER 9 #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h index 833d6a6edc9..240534b19f3 100644 --- a/arch/arm/mach-ux500/include/mach/id.h +++ b/arch/arm/mach-ux500/include/mach/id.h @@ -38,12 +38,47 @@ static inline unsigned int __attribute_const__ dbx500_revision(void) static inline bool __attribute_const__ cpu_is_u8500(void) { - return dbx500_partnumber() == 0x8500; +#ifdef CONFIG_UX500_SOC_DB8500 + /* partnumber 8520 also comes under 8500 */ + return ((dbx500_partnumber() >> 8) & 0xff) == 0x85; +#else + return false; +#endif +} + +static inline bool __attribute_const__ cpu_is_u8520(void) +{ +#ifdef CONFIG_UX500_SOC_DB8500 + return dbx500_partnumber() == 0x8520; +#else + return false; +#endif } static inline bool __attribute_const__ cpu_is_u5500(void) { +#ifdef CONFIG_UX500_SOC_DB5500 return dbx500_partnumber() == 0x5500; +#else + return false; +#endif +} + +#ifdef CONFIG_UX500_SOC_DB8500 +bool cpu_is_u9500(void); +#else +static inline bool cpu_is_u9500(void) +{ + return false; +} +#endif +static inline bool __attribute_const__ cpu_is_u9540(void) +{ +#ifdef CONFIG_UX500_SOC_DB8500 + return dbx500_partnumber() == 0x9540; +#else + return false; +#endif } /* @@ -74,26 +109,6 @@ static inline bool __attribute_const__ cpu_is_u5500v21(void) * 8500 revisions */ -static inline bool __attribute_const__ cpu_is_u8500ed(void) -{ - return cpu_is_u8500() && dbx500_revision() == 0x00; -} - -static inline bool __attribute_const__ cpu_is_u8500v1(void) -{ - return cpu_is_u8500() && (dbx500_revision() & 0xf0) == 0xA0; -} - -static inline bool __attribute_const__ cpu_is_u8500v10(void) -{ - return cpu_is_u8500() && dbx500_revision() == 0xA0; -} - -static inline bool __attribute_const__ cpu_is_u8500v11(void) -{ - return cpu_is_u8500() && dbx500_revision() == 0xA1; -} - static inline bool __attribute_const__ cpu_is_u8500v2(void) { return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0); @@ -109,9 +124,15 @@ static inline bool cpu_is_u8500v21(void) return cpu_is_u8500() && (dbx500_revision() == 0xB1); } +static inline bool cpu_is_u8500v22(void) +{ + return cpu_is_u8500() && (dbx500_revision() == 0xB2); +} + static inline bool cpu_is_u8500v20_or_later(void) { - return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11(); + return cpu_is_u9540() || + (cpu_is_u8500() && ((dbx500_revision() & 0xf0) >= 0xB0)); } static inline bool ux500_is_svp(void) diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index 7d34c52798b..5610e1dc2db 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h @@ -43,6 +43,8 @@ #define MOP500_AB8500_VIR_GPIO_IRQ_BASE \ MOP500_STMPE1601_IRQ_END +#define MOP500_AB8500_VIR_GPIO_IRQ(x) \ + (MOP500_AB8500_VIR_GPIO_IRQ_BASE + (x)) #define MOP500_AB8500_VIR_GPIO_IRQ_END \ (MOP500_AB8500_VIR_GPIO_IRQ_BASE + AB8500_VIR_GPIO_NR_IRQS) @@ -57,7 +59,7 @@ */ #if MOP500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END -#define IRQ_BOARD_END MOP500_IRQ_END +#define IRQ_BOARD_END MOP500_IRQ_END #endif #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h index 29d972c7717..2294a47b3a2 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h @@ -7,13 +7,20 @@ #ifndef __MACH_IRQS_BOARD_U5500_H #define __MACH_IRQS_BOARD_U5500_H -#define AB5500_NR_IRQS 5 +#include <linux/mfd/abx500/ab5500.h> + +#define AB5500_NR_IRQS (AB5500_NUM_IRQ_REGS * 8) #define IRQ_AB5500_BASE IRQ_BOARD_START #define IRQ_AB5500_END (IRQ_AB5500_BASE + AB5500_NR_IRQS) #define U5500_IRQ_END IRQ_AB5500_END -#if IRQ_BOARD_END < U5500_IRQ_END +/* + * We may have several boards, but only one will run at a + * time, so the one with most IRQs will bump this ahead, + * but the IRQ_BOARD_START remains the same for either board. + */ +#if U5500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END #define IRQ_BOARD_END U5500_IRQ_END #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h index 77239776a6f..234cf4ac4e1 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h @@ -85,6 +85,37 @@ #ifdef CONFIG_UX500_SOC_DB5500 +/* Virtual interrupts corresponding to the PRCMU wakeups. */ +#define IRQ_DB5500_PRCMU_BASE IRQ_SOC_START + +#define IRQ_DB5500_PRCMU_RTC (IRQ_DB5500_PRCMU_BASE) +#define IRQ_DB5500_PRCMU_RTT0 (IRQ_DB5500_PRCMU_BASE + 1) +#define IRQ_DB5500_PRCMU_RTT1 (IRQ_DB5500_PRCMU_BASE + 2) +#define IRQ_DB5500_PRCMU_CD_IRQ (IRQ_DB5500_PRCMU_BASE + 3) +#define IRQ_DB5500_PRCMU_SRP_TIM (IRQ_DB5500_PRCMU_BASE + 4) +#define IRQ_DB5500_PRCMU_APE_REQ (IRQ_DB5500_PRCMU_BASE + 5) +#define IRQ_DB5500_PRCMU_USB (IRQ_DB5500_PRCMU_BASE + 6) +#define IRQ_DB5500_PRCMU_ABB (IRQ_DB5500_PRCMU_BASE + 7) +#define IRQ_DB5500_PRCMU_ARM (IRQ_DB5500_PRCMU_BASE + 8) +#define IRQ_DB5500_PRCMU_MODEM_SW_RESET_REQ (IRQ_DB5500_PRCMU_BASE + 9) +#define IRQ_DB5500_PRCMU_AC_WAKE_ACK (IRQ_DB5500_PRCMU_BASE + 10) +#define IRQ_DB5500_PRCMU_GPIO0 (IRQ_DB5500_PRCMU_BASE + 11) +#define IRQ_DB5500_PRCMU_GPIO1 (IRQ_DB5500_PRCMU_BASE + 12) +#define IRQ_DB5500_PRCMU_GPIO2 (IRQ_DB5500_PRCMU_BASE + 13) +#define IRQ_DB5500_PRCMU_GPIO3 (IRQ_DB5500_PRCMU_BASE + 14) +#define IRQ_DB5500_PRCMU_GPIO4 (IRQ_DB5500_PRCMU_BASE + 15) +#define IRQ_DB5500_PRCMU_GPIO5 (IRQ_DB5500_PRCMU_BASE + 16) +#define IRQ_DB5500_PRCMU_GPIO6 (IRQ_DB5500_PRCMU_BASE + 17) +#define IRQ_DB5500_PRCMU_GPIO7 (IRQ_DB5500_PRCMU_BASE + 18) +#define IRQ_DB5500_PRCMU_AC_REL_ACK (IRQ_DB5500_PRCMU_BASE + 19) +#define IRQ_DB5500_PRCMU_LOW_POWER_AUDIO (IRQ_DB5500_PRCMU_BASE + 20) +#define IRQ_DB5500_PRCMU_TEMP_SENSOR_LOW (IRQ_DB5500_PRCMU_BASE + 21) +#define IRQ_DB5500_PRCMU_TEMP_SENSOR_HIGH (IRQ_DB5500_PRCMU_BASE + 22) +#define IRQ_DB5500_PRCMU_END (IRQ_DB5500_PRCMU_BASE + 23) +#define IRQ_DB5500_PRCMU_APE_REL 0x200 + +#define NUM_DB5500_PRCMU_WAKEUPS (IRQ_DB5500_PRCMU_END - IRQ_DB5500_PRCMU_BASE) + /* * After the GPIO ones we reserve a range of IRQ:s in which virtual * IRQ:s representing modem IRQ:s can be allocated diff --git a/arch/arm/mach-ux500/include/mach/irqs-db9540.h b/arch/arm/mach-ux500/include/mach/irqs-db9540.h new file mode 100644 index 00000000000..6a616e4d320 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/irqs-db9540.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Sebastien Pasdeloup <sebastien.pasdeloup-nonst@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __MACH_IRQS_DB9540_H +#define __MACH_IRQS_DB9540_H + +#define IRQ_AP9540_VSENSOR (IRQ_SHPI_START + 30) +#define IRQ_AP9540_SLIMBUS0 (IRQ_SHPI_START + 101) +#define IRQ_AP9540_THSENS (IRQ_SHPI_START + 102) +#define IRQ_AP9540_DDR0 (IRQ_SHPI_START + 103) +#define IRQ_AP9540_CTIEXTRIG0 (IRQ_SHPI_START + 111) +#define IRQ_AP9540_SGX (IRQ_SHPI_START + 112) +#define IRQ_AP9540_CTIEXTRIG1 (IRQ_SHPI_START + 117) +#define IRQ_AP9540_C2C_GENO0 (IRQ_SHPI_START + 128) +#define IRQ_AP9540_C2C_GENO1 (IRQ_SHPI_START + 129) +#define IRQ_AP9540_C2C_GENO2 (IRQ_SHPI_START + 130) +#define IRQ_AP9540_C2C_GENO3 (IRQ_SHPI_START + 131) +#define IRQ_AP9540_C2C_GENO4 (IRQ_SHPI_START + 132) +#define IRQ_AP9540_C2C_GENO5 (IRQ_SHPI_START + 133) +#define IRQ_AP9540_C2C_GENO6 (IRQ_SHPI_START + 134) +#define IRQ_AP9540_C2C_GENO7 (IRQ_SHPI_START + 135) +#define IRQ_AP9540_C2C_GENO8 (IRQ_SHPI_START + 136) +#define IRQ_AP9540_C2C_GENO9 (IRQ_SHPI_START + 137) +#define IRQ_AP9540_C2C_GENO10 (IRQ_SHPI_START + 138) +#define IRQ_AP9540_C2C_GENO11 (IRQ_SHPI_START + 139) +#define IRQ_AP9540_C2C_GENO12 (IRQ_SHPI_START + 140) +#define IRQ_AP9540_C2C_GENO13 (IRQ_SHPI_START + 141) +#define IRQ_AP9540_C2C_GENO14 (IRQ_SHPI_START + 142) +#define IRQ_AP9540_C2C_GENO15 (IRQ_SHPI_START + 143) +#define IRQ_AP9540_C2C_GENO16 (IRQ_SHPI_START + 144) +#define IRQ_AP9540_C2C_GENO17 (IRQ_SHPI_START + 145) +#define IRQ_AP9540_C2C_GENO18 (IRQ_SHPI_START + 146) +#define IRQ_AP9540_C2C_GENO19 (IRQ_SHPI_START + 147) +#define IRQ_AP9540_C2C_GENO20 (IRQ_SHPI_START + 148) +#define IRQ_AP9540_C2C_GENO21 (IRQ_SHPI_START + 149) +#define IRQ_AP9540_C2C_GENO22 (IRQ_SHPI_START + 150) +#define IRQ_AP9540_C2C_GENO23 (IRQ_SHPI_START + 151) +#define IRQ_AP9540_C2C_GENO24 (IRQ_SHPI_START + 152) +#define IRQ_AP9540_C2C_GENO25 (IRQ_SHPI_START + 153) +#define IRQ_AP9540_C2C_GENO26 (IRQ_SHPI_START + 154) +#define IRQ_AP9540_C2C_GENO27 (IRQ_SHPI_START + 155) +#define IRQ_AP9540_C2C_GENO28 (IRQ_SHPI_START + 156) +#define IRQ_AP9540_C2C_GENO29 (IRQ_SHPI_START + 157) +#define IRQ_AP9540_C2C_GENO30 (IRQ_SHPI_START + 158) +#define IRQ_AP9540_C2C_GENO31 (IRQ_SHPI_START + 159) +#define IRQ_AP9540_C2C_IRQ0 (IRQ_SHPI_START + 160) +#define IRQ_AP9540_C2C_IRQ1 (IRQ_SHPI_START + 161) +#define IRQ_AP9540_HVA_ITS (IRQ_SHPI_START + 162) +#define IRQ_AP9540_HVA_ERR (IRQ_SHPI_START + 163) +#define IRQ_AP9540_C2C_G1 (IRQ_SHPI_START + 164) +#define IRQ_AP9540_C2C_DDR1 (IRQ_SHPI_START + 165) +#define IRQ_AP9540_C2C_SGX_IDLE (IRQ_SHPI_START + 166) + +#endif diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index c23a6b5f0c4..f96628fa147 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -11,9 +11,7 @@ #define ASM_ARCH_IRQS_H #include <mach/hardware.h> - -#define IRQ_LOCALTIMER 29 -#define IRQ_LOCALWDOG 30 +#include <linux/gpio.h> /* Shared Peripheral Interrupt (SHPI) */ #define IRQ_SHPI_START 32 @@ -22,26 +20,35 @@ * MTU0 preserved for now until plat-nomadik is taught not to use it. Don't * add any other IRQs here, use the irqs-dbx500.h files. */ -#define IRQ_MTU0 (IRQ_SHPI_START + 4) +#define IRQ_MTU0 (IRQ_SHPI_START + 4) + +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 -#define DBX500_NR_INTERNAL_IRQS 160 +/*********************************************************************/ + +#define DBX500_NR_INTERNAL_IRQS 166 /* After chip-specific IRQ numbers we have the GPIO ones */ -#define NOMADIK_NR_GPIO 288 #define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + DBX500_NR_INTERNAL_IRQS) #define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - DBX500_NR_INTERNAL_IRQS) + +#define GPIO_TO_IRQ NOMADIK_GPIO_TO_IRQ +#define IRQ_TO_GPIO NOMADIK_IRQ_TO_GPIO #define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) -#define IRQ_SOC_START IRQ_GPIO_END +#define IRQ_SOC_START IRQ_GPIO_END /* This will be overridden by SoC-specific irq headers */ -#define IRQ_SOC_END IRQ_SOC_START +#define IRQ_SOC_END IRQ_SOC_START + +#define IRQ_BOARD_START IRQ_SOC_END +/* This will be overridden by board-specific irq headers */ +#define IRQ_BOARD_END IRQ_BOARD_START #include <mach/irqs-db5500.h> #include <mach/irqs-db8500.h> +#include <mach/irqs-db9540.h> -#define IRQ_BOARD_START IRQ_SOC_END -/* This will be overridden by board-specific irq headers */ -#define IRQ_BOARD_END IRQ_BOARD_START #ifdef CONFIG_MACH_MOP500 #include <mach/irqs-board-mop500.h> @@ -51,6 +58,8 @@ #include <mach/irqs-board-u5500.h> #endif +#ifndef NR_IRQS #define NR_IRQS IRQ_BOARD_END +#endif #endif /* ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-ux500/include/mach/isa_ioctl.h b/arch/arm/mach-ux500/include/mach/isa_ioctl.h new file mode 100644 index 00000000000..b1f3ba159da --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/isa_ioctl.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------------*/ +/* Copyright ST Ericsson, 2009. */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +/* See the GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/*---------------------------------------------------------------------------*/ +#ifndef __MODEM_IPC_INCLUDED +#define __MODEM_IPC_INCLUDED + +#define DLP_IOCTL_MAGIC_NUMBER 'M' +#define COMMON_BUFFER_SIZE (1024*1024) + +/** +DLP Message Structure for Userland +*/ +struct t_dlp_message{ + unsigned int offset; + unsigned int size; +}; + +/** +mmap constants. +*/ +enum t_dlp_mmap_params { + MMAP_DLQUEUE, + MMAP_ULQUEUE +}; + +/** +DLP IOCTLs for Userland +*/ +#define DLP_IOC_ALLOCATE_BUFFER \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 0, struct t_dlp_message *) +#define DLP_IOC_DEALLOCATE_BUFFER \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 1, struct t_dlp_message *) +#define DLP_IOC_GET_MESSAGE \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 2, struct t_dlp_message *) +#define DLP_IOC_PUT_MESSAGE \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 3, struct t_dlp_message *) + +#endif /*__MODEM_IPC_INCLUDED*/ diff --git a/arch/arm/mach-ux500/include/mach/mbox-db5500.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h index 7f9da4d2fbd..2da180b8df6 100644 --- a/arch/arm/mach-ux500/include/mach/mbox-db5500.h +++ b/arch/arm/mach-ux500/include/mach/mbox-db5500.h @@ -40,6 +40,7 @@ typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv); * @lock: Spinlock to protect this mailbox instance. * @write_index: Index in internal buffer to write to. * @read_index: Index in internal buffer to read from. + * @irq: mailbox interrupt. * @allocated: Indicates whether this particular mailbox * id has been allocated by someone. */ @@ -57,7 +58,11 @@ struct mbox { spinlock_t lock; u8 write_index; u8 read_index; + int irq; bool allocated; +#if defined(CONFIG_DEBUG_FS) + struct dentry *dentry; +#endif }; /** @@ -84,5 +89,5 @@ struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv); * specify "block" in order to block until send is possible). */ int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block); - +void mbox_state_reset(void); #endif /*INC_STE_MBOX_H*/ diff --git a/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h b/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h new file mode 100644 index 00000000000..69616c4cdec --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com> for ST-Ericsson. + * Bibek Basu <bibek.basu@stericsson.com> + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __INC_MBOX_CHANNELS_H +#define __INC_MBOX_CHANNELS_H + +/* Maximum number of datawords which can be send in one PDU */ +#define MAILBOX_NR_OF_DATAWORDS 3 + +/* Number of buffers */ +#define NUM_DSP_BUFFER 32 + +/** + * mbox_channel_cb_t - Definition of the mailbox channel callback. + * @data: Pointer to the data. + * @length: Length of the data. + * @priv: The client's private data. + * + * This function will be called upon reception of complete mbox channel PDU + * or after completion of send operation. + */ +typedef void mbox_channel_cb_t (u32 *data, u32 length, void *priv); + +/** + * struct mbox_channel_msg - Definition of mbox channel message + * @channel: Channel number. + * @data: Pointer to data to be sent. + * @length: Length of data to be sent. + * @cb: Pointer to the callback function to be called when send + * operation will be finished. + * @priv: The client's private data. + * + * This structure describes mailbox channel message. + */ +struct mbox_channel_msg { + u16 channel; + u32 *data; + u8 length; + mbox_channel_cb_t *cb; + void *priv; +}; + +/** + * mbox_channel_register - Set up a given mailbox channel. + * @channel: Mailbox channel number. + * @cb: Pointer to the callback function to be called when a new message + * is received. + * @priv: Client user data which will be returned in the callback. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_register(u16 channel, mbox_channel_cb_t *cb, void *priv); + +/** + * mbox_channel_send - Send data on given mailbox channel. + * @msg: Mailbox channel message to be sent. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_send(struct mbox_channel_msg *msg); + +/** + * mbox_channel_revoke_messages - Revoke messages on given mailbox channel. + * @channel: Mailbox channel number. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_revoke_messages(u16 channel); + +/** + * mbox_channel_deregister - de-register given mailbox channel. + * @channel: Mailbox channel number. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_deregister(u16 channel); + +#endif /*INC_STE_MBOX_H*/ diff --git a/arch/arm/mach-ux500/include/mach/mloader-dbx500.h b/arch/arm/mach-ux500/include/mach/mloader-dbx500.h new file mode 100644 index 00000000000..68fa55a3f53 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/mloader-dbx500.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef _MLOADER_UX500_H_ +#define _MLOADER_UX500_H_ + +/** + * struct dbx500_ml_area - data structure for modem memory areas description + * @name: name of the area + * @start: start address of the area + * @size: size of the area + */ +struct dbx500_ml_area { + const char *name; + u32 start; + u32 size; +}; + +/** + * struct dbx500_ml_fw - data stucture for modem firmwares description + * @name: firmware name + * @area: area where firmware is uploaded + * @offset: offset in the area where firmware is uploaded + */ +struct dbx500_ml_fw { + const char *name; + struct dbx500_ml_area *area; + u32 offset; +}; + +/** + * struct dbx500_mloader_pdata - data structure for platform specific data + * @fws: pointer on firmwares table + * @nr_fws: number of firmwares + * @areas: pointer on areas table + * @nr_areas: number of areas + */ +struct dbx500_mloader_pdata { + struct dbx500_ml_fw *fws; + int nr_fws; + struct dbx500_ml_area *areas; + int nr_areas; +}; + +#endif /* _MLOADER_UX500_H_ */ diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h new file mode 100644 index 00000000000..9d3bad233fa --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/msp.h @@ -0,0 +1,998 @@ +/* + * Copyright (c) 2009 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +#ifndef _STM_MSP_HEADER +#define _STM_MSP_HEADER +#include <linux/device.h> +#include <linux/spinlock.h> +#include <linux/semaphore.h> +#include <linux/dmaengine.h> +#include <linux/irqreturn.h> +#include <linux/bitops.h> +#include <plat/ste_dma40.h> +#include <linux/gpio.h> +#include <linux/spi/stm_msp.h> + +/* Generic config struct. Use the actual values defined below for global + * control register + */ + +enum msp_state { + MSP_STATE_IDLE = 0, + MSP_STATE_CONFIGURED = 1, + MSP_STATE_RUN = 2, +}; + +enum msp_rx_comparison_enable_mode { + MSP_COMPARISON_DISABLED = 0, + MSP_COMPARISON_NONEQUAL_ENABLED = 2, + MSP_COMPARISON_EQUAL_ENABLED = 3 +}; + +#define RMCEN_BIT 0 +#define RMCSF_BIT 1 +#define RCMPM_BIT 3 +#define TMCEN_BIT 5 +#define TNCSF_BIT 6 + +struct msp_multichannel_config { + bool rx_multichannel_enable; + bool tx_multichannel_enable; + enum msp_rx_comparison_enable_mode rx_comparison_enable_mode; + u8 padding; + u32 comparison_value; + u32 comparison_mask; + u32 rx_channel_0_enable; + u32 rx_channel_1_enable; + u32 rx_channel_2_enable; + u32 rx_channel_3_enable; + u32 tx_channel_0_enable; + u32 tx_channel_1_enable; + u32 tx_channel_2_enable; + u32 tx_channel_3_enable; +}; + +/** + * struct msp_protocol_desc- MSP Protocol desc structure per MSP. + * @rx_phase_mode: rx_phase_mode whether single or dual. + * @tx_phase_mode: tx_phase_mode whether single or dual. + * @rx_phase2_start_mode: rx_phase2_start_mode whether imediate or after + * some delay. + * @tx_phase2_start_mode: tx_phase2_start_mode whether imediate or after + * some delay. + * @rx_bit_transfer_format: MSP or LSB. + * @tx_bit_transfer_format: MSP or LSB. + * @rx_frame_length_1: Frame1 length 1,2,3.. + * @rx_frame_length_2: Frame2 length 1,2,3.. + * @tx_frame_length_1: Frame1 length 1,2,3.. + * @tx_frame_length_2: Frame2 length 1,2,3.. + * @rx_element_length_1: Element1 length 1,2,... + * @rx_element_length_2: Element2 length 1,2,... + * @tx_element_length_1: Element1 length 1,2,... + * @tx_element_length_2: Element2 length 1,2,... + * @rx_data_delay: Delay in clk cycle after frame sync + * @tx_data_delay: Delay in clk cycle after frame sync + * @rx_clock_pol: Rxpol whether rising or falling.It indicates pol of bit clock. + * @tx_clock_pol: Txpol whether rising or falling.It indicates pol of bit clock. + * @rx_frame_sync_pol: Frame sync pol whether rising or Falling. + * @tx_frame_sync_pol: Frame sync pol whether rising or Falling. + * @rx_half_word_swap: Word swap half word, full word. + * @tx_half_word_swap: Word swap half word, full word. + * @compression_mode: Compression mode whether Alaw or Ulaw or disabled. + * @expansion_mode: Compression mode whether Alaw or Ulaw or disabled. + * @spi_clk_mode: Spi clock mode to be enabled or not. + * @spi_burst_mode: Spi burst mode to be enabled or not. + * @frame_sync_ignore: Frame sync to be ignored or not. Ignore in case of Audio + * codec acting as Master. + * @frame_period: Frame period (clk cycles) after which new frame sync occurs. + * @frame_width: Frame width (clk cycles) after which frame sycn changes state. + * @total_clocks_for_one_frame: No. of clk cycles per frame. + * + * Main Msp protocol descriptor data structure to be used to store various info + * in transmit or recevie configuration registers of an MSP. + */ + +struct msp_protocol_desc { + u32 rx_phase_mode; + u32 tx_phase_mode; + u32 rx_phase2_start_mode; + u32 tx_phase2_start_mode; + u32 rx_bit_transfer_format; + u32 tx_bit_transfer_format; + u32 rx_frame_length_1; + u32 rx_frame_length_2; + u32 tx_frame_length_1; + u32 tx_frame_length_2; + u32 rx_element_length_1; + u32 rx_element_length_2; + u32 tx_element_length_1; + u32 tx_element_length_2; + u32 rx_data_delay; + u32 tx_data_delay; + u32 rx_clock_pol; + u32 tx_clock_pol; + u32 rx_frame_sync_pol; + u32 tx_frame_sync_pol; + u32 rx_half_word_swap; + u32 tx_half_word_swap; + u32 compression_mode; + u32 expansion_mode; + u32 spi_clk_mode; + u32 spi_burst_mode; + u32 frame_sync_ignore; + u32 frame_period; + u32 frame_width; + u32 total_clocks_for_one_frame; +}; + +enum i2s_direction_t { + I2S_DIRECTION_TX = 0, + I2S_DIRECTION_RX = 1, + I2S_DIRECTION_BOTH = 2 +}; + +enum i2s_transfer_mode_t { + I2S_TRANSFER_MODE_SINGLE_DMA = 0, + I2S_TRANSFER_MODE_CYCLIC_DMA = 1, + I2S_TRANSFER_MODE_INF_LOOPBACK = 2, + I2S_TRANSFER_MODE_NON_DMA = 4, +}; + +struct i2s_message { + enum i2s_direction_t i2s_direction; + void *txdata; + void *rxdata; + size_t txbytes; + size_t rxbytes; + int dma_flag; + int tx_offset; + int rx_offset; + /* cyclic dma */ + bool cyclic_dma; + dma_addr_t buf_addr; + size_t buf_len; + size_t period_len; +}; + +enum i2s_flag { + DISABLE_ALL = 0, + DISABLE_TRANSMIT = 1, + DISABLE_RECEIVE = 2, +}; + +struct i2s_controller { + struct module *owner; + unsigned int id; + unsigned int class; + const struct i2s_algorithm *algo; /* the algorithm to access the bus */ + void *data; + struct mutex bus_lock; + struct device dev; /* the controller device */ + char name[48]; +}; +#define to_i2s_controller(d) container_of(d, struct i2s_controller, dev) + +/** + * struct trans_data - MSP transfer data structure used during xfer. + * @message: i2s message. + * @msp: msp structure. + * @tx_handler: callback handler for transmit path. + * @rx_handler: callback handler for receive path. + * @tx_callback_data: callback data for transmit. + * @rx_callback_data: callback data for receive. + * + */ +struct trans_data { + struct i2s_message message; + struct msp *msp; + void (*tx_handler) (void *data); + void (*rx_handler) (void *data); + void *tx_callback_data; + void *rx_callback_data; +}; + +/** + * struct msp_config- MSP configuration structure used by i2s client. + * @input_clock_freq: Input clock frequency default is 48MHz. + * @rx_clock_sel: Receive clock selection (Provided by Sample Gen or external + * source). + * @tx_clock_sel: Transmit clock selection (Provided by Sample Gen or external. + * source). + * @srg_clock_sel: APB clock or clock dervied from Slave (Audio codec). + * @rx_frame_sync_pol: Receive frame sync polarity. + * @tx_frame_sync_pol: Transmit frame sync polarity. + * @rx_frame_sync_sel: Rx frame sync signal is provided by which source. + * External source or by frame generator logic. + * @tx_frame_sync_sel: Tx frame sync signal is provided by which source. + * External source or by frame generator logic. + * @rx_fifo_config: Receive fifo enable or not. + * @tx_fifo_config: Transmit fifo enable or not. + * @spi_clk_mode: In case of SPI protocol spi modes: Normal, Zero delay or + * half cycle delay. + * @spi_burst_mode: Spi burst mode is enabled or not. + * @loopback_enable: Loopback mode. + * @tx_data_enable: Transmit extra delay enable. + * @default_protocol_desc: Flag to indicate client defined protocol desc or + * statically defined in msp.h. + * @protocol_desc: Protocol desc structure filled by i2s client driver. + * In case client defined default_prtocol_desc as 0. + * @multichannel_configured: multichannel configuration structure. + * @multichannel_config: multichannel is enabled or not. + * @direction: Transmit, Receive or Both. + * @work_mode: Dma, Polling or Interrupt. + * @protocol: I2S, PCM, etc. + * @frame_freq: Sampling freq at which data is sampled. + * @frame_size: size of element. + * @data_size: data size which defines the format in which data is written on + * transmit or receive fifo. Only three modes 8,16,32 are supported. + * @def_elem_len: Flag to indicate whether default element length is to be used + * or should be changed acc to data size defined by user at run time. + * @iodelay: value for the MSP_IODLY register + * + * Main Msp configuration data structure used by i2s client driver to fill + * various info like data size, frequency etc. + */ +struct msp_config { + unsigned int input_clock_freq; + unsigned int rx_clock_sel; + unsigned int tx_clock_sel; + unsigned int srg_clock_sel; + unsigned int rx_frame_sync_pol; + unsigned int tx_frame_sync_pol; + unsigned int rx_frame_sync_sel; + unsigned int tx_frame_sync_sel; + unsigned int rx_fifo_config; + unsigned int tx_fifo_config; + unsigned int spi_clk_mode; + unsigned int spi_burst_mode; + unsigned int loopback_enable; + unsigned int tx_data_enable; + unsigned int default_protocol_desc; + struct msp_protocol_desc protocol_desc; + int multichannel_configured; + struct msp_multichannel_config multichannel_config; + unsigned int direction; + unsigned int work_mode; + unsigned int protocol; + unsigned int frame_freq; + unsigned int frame_size; + enum msp_data_size data_size; + unsigned int def_elem_len; + unsigned int iodelay; +}; + +/*** Protocols ***/ +enum msp_protocol { + MSP_I2S_PROTOCOL, + MSP_PCM_PROTOCOL, + MSP_PCM_COMPAND_PROTOCOL, + MSP_AC97_PROTOCOL, + MSP_MASTER_SPI_PROTOCOL, + MSP_SLAVE_SPI_PROTOCOL, + MSP_INVALID_PROTOCOL +}; + +/*** Sample Frequencies ***/ +/* These are no longer required, frequencies in Hz can be used directly */ +enum msp_sample_freq { + MSP_SAMPLE_FREQ_NOT_SUPPORTED = -1, + MSP_SAMPLE_FREQ_8KHZ = 8000, + MSP_SAMPLE_FREQ_12KHZ = 12000, + MSP_SAMPLE_FREQ_16KHZ = 16000, + MSP_SAMPLE_FREQ_24KHZ = 24000, + MSP_SAMPLE_FREQ_32KHZ = 32000, + MSP_SAMPLE_FREQ_44KHZ = 44000, + MSP_SAMPLE_FREQ_48KHZ = 48000, + MSP_SAMPLE_FREQ_64KHZ = 64000, + MSP_SAMPLE_FREQ_88KHZ = 88000, + MSP_SAMPLE_FREQ_96KHZ = 96000, + MSP_SAMPLE_FREQ_22KHZ = 22000, + MSP_SAMPLE_FREQ_11KHZ = 11000 +}; + +/*** Input Frequencies ***/ +/* These are no longer required, frequencies in Hz can be used directly */ +enum msp_in_clock_freq { + MSP_INPUT_FREQ_1MHZ = 1000, + MSP_INPUT_FREQ_2MHZ = 2000, + MSP_INPUT_FREQ_3MHZ = 3000, + MSP_INPUT_FREQ_4MHZ = 4000, + MSP_INPUT_FREQ_5MHZ = 5000, + MSP_INPUT_FREQ_6MHZ = 6000, + MSP_INPUT_FREQ_8MHZ = 8000, + MSP_INPUT_FREQ_11MHZ = 11000, + MSP_INPUT_FREQ_12MHZ = 12000, + MSP_INPUT_FREQ_16MHZ = 16000, + MSP_INPUT_FREQ_22MHZ = 22000, + MSP_INPUT_FREQ_24MHZ = 24000, + MSP_INPUT_FREQ_48MHZ = 48000 +}; + +#define MSP_INPUT_FREQ_APB 48000000 + +/*** Stereo mode. Used for APB data accesses as 16 bits accesses (mono), + * 32 bits accesses (stereo). + ***/ +enum msp_stereo_mode { + MSP_MONO, + MSP_STEREO +}; + +/* Direction (Transmit/Receive mode) */ +enum msp_direction { + MSP_TRANSMIT_MODE, + MSP_RECEIVE_MODE, + MSP_BOTH_T_R_MODE +}; + +/* Dma mode should be used for large transfers, + * polling mode should be used for transfers of a few bytes + */ +enum msp_xfer_mode { + MSP_DMA_MODE, + MSP_POLLING_MODE, + MSP_INTERRUPT_MODE +}; + +/* User client for the MSP */ +enum msp_user { + MSP_NO_USER = 0, + MSP_USER_SPI, + MSP_USER_ALSA, + MSP_USER_SAA, +}; + +/*Flag structure for MSPx*/ +struct msp_flag { + struct semaphore lock; + enum msp_user user; +}; + +/* User client for the MSP */ +enum msp_mode { + MSP_NO_MODE = 0, + MSP_MODE_SPI, + MSP_MODE_NON_SPI, +}; + +/* Transmit and receive configuration register */ +#define MSP_BIG_ENDIAN 0x00000000 +#define MSP_LITTLE_ENDIAN 0x00001000 +#define MSP_UNEXPECTED_FS_ABORT 0x00000000 +#define MSP_UNEXPECTED_FS_IGNORE 0x00008000 +#define MSP_NON_MODE_BIT_MASK 0x00009000 + +/* Global configuration register */ +#define RX_ENABLE 0x00000001 +#define RX_FIFO_ENABLE 0x00000002 +#define RX_SYNC_SRG 0x00000010 +#define RX_CLK_POL_RISING 0x00000020 +#define RX_CLK_SEL_SRG 0x00000040 +#define TX_ENABLE 0x00000100 +#define TX_FIFO_ENABLE 0x00000200 +#define TX_SYNC_SRG_PROG 0x00001800 +#define TX_SYNC_SRG_AUTO 0x00001000 +#define TX_CLK_POL_RISING 0x00002000 +#define TX_CLK_SEL_SRG 0x00004000 +#define TX_EXTRA_DELAY_ENABLE 0x00008000 +#define SRG_ENABLE 0x00010000 +#define FRAME_GEN_ENABLE 0x00100000 +#define SRG_CLK_SEL_APB 0x00000000 +#define RX_FIFO_SYNC_HI 0x00000000 +#define TX_FIFO_SYNC_HI 0x00000000 +#define SPI_CLK_MODE_NORMAL 0x00000000 + +/* SPI Clock Modes enumertion + * SPI clock modes of MSP provides compatibility with + * the SPI protocol.MSP supports 2 SPI transfer formats. + * MSP_ZERO_DELAY_SPI_MODE:MSP transmits data over Tx/Rx + * Lines immediately after MSPTCK/MSPRCK rising/falling edge. + * MSP_HALF_CYCLE_DELY_SPI_MODE:MSP transmits data one-half cycle + * ahead of the rising/falling edge of the MSPTCK + */ + +#define MSP_FRAME_SIZE_AUTO -1 + + +#define MSP_DR 0x00 +#define MSP_GCR 0x04 +#define MSP_TCF 0x08 +#define MSP_RCF 0x0c +#define MSP_SRG 0x10 +#define MSP_FLR 0x14 +#define MSP_DMACR 0x18 + +#define MSP_IMSC 0x20 +#define MSP_RIS 0x24 +#define MSP_MIS 0x28 +#define MSP_ICR 0x2c +#define MSP_MCR 0x30 +#define MSP_RCV 0x34 +#define MSP_RCM 0x38 + +#define MSP_TCE0 0x40 +#define MSP_TCE1 0x44 +#define MSP_TCE2 0x48 +#define MSP_TCE3 0x4c + +#define MSP_RCE0 0x60 +#define MSP_RCE1 0x64 +#define MSP_RCE2 0x68 +#define MSP_RCE3 0x6c +#define MSP_IODLY 0x70 + +#define MSP_ITCR 0x80 +#define MSP_ITIP 0x84 +#define MSP_ITOP 0x88 +#define MSP_TSTDR 0x8c + +#define MSP_PID0 0xfe0 +#define MSP_PID1 0xfe4 +#define MSP_PID2 0xfe8 +#define MSP_PID3 0xfec + +#define MSP_CID0 0xff0 +#define MSP_CID1 0xff4 +#define MSP_CID2 0xff8 +#define MSP_CID3 0xffc + +/* Single or dual phase mode */ +enum msp_phase_mode { + MSP_SINGLE_PHASE, + MSP_DUAL_PHASE +}; + +/* Frame length */ +enum msp_frame_length { + MSP_FRAME_LENGTH_1 = 0, + MSP_FRAME_LENGTH_2 = 1, + MSP_FRAME_LENGTH_4 = 3, + MSP_FRAME_LENGTH_8 = 7, + MSP_FRAME_LENGTH_12 = 11, + MSP_FRAME_LENGTH_16 = 15, + MSP_FRAME_LENGTH_20 = 19, + MSP_FRAME_LENGTH_32 = 31, + MSP_FRAME_LENGTH_48 = 47, + MSP_FRAME_LENGTH_64 = 63 +}; + +/* Element length */ +enum msp_elem_length { + MSP_ELEM_LENGTH_8 = 0, + MSP_ELEM_LENGTH_10 = 1, + MSP_ELEM_LENGTH_12 = 2, + MSP_ELEM_LENGTH_14 = 3, + MSP_ELEM_LENGTH_16 = 4, + MSP_ELEM_LENGTH_20 = 5, + MSP_ELEM_LENGTH_24 = 6, + MSP_ELEM_LENGTH_32 = 7 +}; + +enum msp_data_xfer_width { + MSP_DATA_TRANSFER_WIDTH_BYTE, + MSP_DATA_TRANSFER_WIDTH_HALFWORD, + MSP_DATA_TRANSFER_WIDTH_WORD +}; + +enum msp_frame_sync { + MSP_FRAME_SYNC_UNIGNORE = 0, + MSP_FRAME_SYNC_IGNORE = 1, + +}; + +enum msp_phase2_start_mode { + MSP_PHASE2_START_MODE_IMEDIATE, + MSP_PHASE2_START_MODE_FRAME_SYNC +}; + +enum msp_btf { + MSP_BTF_MS_BIT_FIRST = 0, + MSP_BTF_LS_BIT_FIRST = 1 +}; + +enum msp_frame_sync_pol { + MSP_FRAME_SYNC_POL_ACTIVE_HIGH = 0, + MSP_FRAME_SYNC_POL_ACTIVE_LOW = 1 +}; + +/* Data delay (in bit clock cycles) */ +enum msp_delay { + MSP_DELAY_0 = 0, + MSP_DELAY_1 = 1, + MSP_DELAY_2 = 2, + MSP_DELAY_3 = 3 +}; + +/* Configurations of clocks (transmit, receive or sample rate generator) */ +enum msp_edge { + MSP_FALLING_EDGE = 0, + MSP_RISING_EDGE = 1, +}; + +enum msp_hws { + MSP_HWS_NO_SWAP = 0, + MSP_HWS_BYTE_SWAP_IN_WORD = 1, + MSP_HWS_BYTE_SWAP_IN_EACH_HALF_WORD = 2, + MSP_HWS_HALF_WORD_SWAP_IN_WORD = 3 +}; + +enum msp_compress_mode { + MSP_COMPRESS_MODE_LINEAR = 0, + MSP_COMPRESS_MODE_MU_LAW = 2, + MSP_COMPRESS_MODE_A_LAW = 3 +}; + +enum msp_spi_clock_mode { + MSP_SPI_CLOCK_MODE_NON_SPI = 0, + MSP_SPI_CLOCK_MODE_ZERO_DELAY = 2, + MSP_SPI_CLOCK_MODE_HALF_CYCLE_DELAY = 3 +}; + +enum msp_spi_burst_mode { + MSP_SPI_BURST_MODE_DISABLE = 0, + MSP_SPI_BURST_MODE_ENABLE = 1 +}; + +enum msp_expand_mode { + MSP_EXPAND_MODE_LINEAR = 0, + MSP_EXPAND_MODE_LINEAR_SIGNED = 1, + MSP_EXPAND_MODE_MU_LAW = 2, + MSP_EXPAND_MODE_A_LAW = 3 +}; + +/* Protocol dependant parameters list */ +#define RX_ENABLE_MASK BIT(0) +#define RX_FIFO_ENABLE_MASK BIT(1) +#define RX_FRAME_SYNC_MASK BIT(2) +#define DIRECT_COMPANDING_MASK BIT(3) +#define RX_SYNC_SEL_MASK BIT(4) +#define RX_CLK_POL_MASK BIT(5) +#define RX_CLK_SEL_MASK BIT(6) +#define LOOPBACK_MASK BIT(7) +#define TX_ENABLE_MASK BIT(8) +#define TX_FIFO_ENABLE_MASK BIT(9) +#define TX_FRAME_SYNC_MASK BIT(10) +#define TX_MSP_TDR_TSR BIT(11) +#define TX_SYNC_SEL_MASK (BIT(12) | BIT(11)) +#define TX_CLK_POL_MASK BIT(13) +#define TX_CLK_SEL_MASK BIT(14) +#define TX_EXTRA_DELAY_MASK BIT(15) +#define SRG_ENABLE_MASK BIT(16) +#define SRG_CLK_POL_MASK BIT(17) +#define SRG_CLK_SEL_MASK (BIT(19) | BIT(18)) +#define FRAME_GEN_EN_MASK BIT(20) +#define SPI_CLK_MODE_MASK (BIT(22) | BIT(21)) +#define SPI_BURST_MODE_MASK BIT(23) + +#define RXEN_SHIFT 0 +#define RFFEN_SHIFT 1 +#define RFSPOL_SHIFT 2 +#define DCM_SHIFT 3 +#define RFSSEL_SHIFT 4 +#define RCKPOL_SHIFT 5 +#define RCKSEL_SHIFT 6 +#define LBM_SHIFT 7 +#define TXEN_SHIFT 8 +#define TFFEN_SHIFT 9 +#define TFSPOL_SHIFT 10 +#define TFSSEL_SHIFT 11 +#define TCKPOL_SHIFT 13 +#define TCKSEL_SHIFT 14 +#define TXDDL_SHIFT 15 +#define SGEN_SHIFT 16 +#define SCKPOL_SHIFT 17 +#define SCKSEL_SHIFT 18 +#define FGEN_SHIFT 20 +#define SPICKM_SHIFT 21 +#define TBSWAP_SHIFT 28 + +#define RCKPOL_MASK BIT(0) +#define TCKPOL_MASK BIT(0) +#define SPICKM_MASK (BIT(1) | BIT(0)) +#define MSP_RX_CLKPOL_BIT(n) ((n & RCKPOL_MASK) << RCKPOL_SHIFT) +#define MSP_TX_CLKPOL_BIT(n) ((n & TCKPOL_MASK) << TCKPOL_SHIFT) +#define MSP_SPI_CLK_MODE_BITS(n) ((n & SPICKM_MASK) << SPICKM_SHIFT) + + + +/* Use this to clear the clock mode bits to non-spi */ +#define MSP_NON_SPI_CLK_MASK (BIT(22) | BIT(21)) + +#define P1ELEN_SHIFT 0 +#define P1FLEN_SHIFT 3 +#define DTYP_SHIFT 10 +#define ENDN_SHIFT 12 +#define DDLY_SHIFT 13 +#define FSIG_SHIFT 15 +#define P2ELEN_SHIFT 16 +#define P2FLEN_SHIFT 19 +#define P2SM_SHIFT 26 +#define P2EN_SHIFT 27 +#define FRAME_SYNC_SHIFT 15 + + +#define P1ELEN_MASK 0x00000007 +#define P2ELEN_MASK 0x00070000 +#define P1FLEN_MASK 0x00000378 +#define P2FLEN_MASK 0x03780000 +#define DDLY_MASK 0x00003000 +#define DTYP_MASK 0x00000600 +#define P2SM_MASK 0x04000000 +#define P2EN_MASK 0x08000000 +#define ENDN_MASK 0x00001000 +#define TFSPOL_MASK 0x00000400 +#define TBSWAP_MASK 0x30000000 +#define COMPANDING_MODE_MASK 0x00000c00 +#define FRAME_SYNC_MASK 0x00008000 + +#define MSP_P1_ELEM_LEN_BITS(n) (n & P1ELEN_MASK) +#define MSP_P2_ELEM_LEN_BITS(n) (((n) << P2ELEN_SHIFT) & P2ELEN_MASK) +#define MSP_P1_FRAME_LEN_BITS(n) (((n) << P1FLEN_SHIFT) & P1FLEN_MASK) +#define MSP_P2_FRAME_LEN_BITS(n) (((n) << P2FLEN_SHIFT) & P2FLEN_MASK) +#define MSP_DATA_DELAY_BITS(n) (((n) << DDLY_SHIFT) & DDLY_MASK) +#define MSP_DATA_TYPE_BITS(n) (((n) << DTYP_SHIFT) & DTYP_MASK) +#define MSP_P2_START_MODE_BIT(n) ((n << P2SM_SHIFT) & P2SM_MASK) +#define MSP_P2_ENABLE_BIT(n) ((n << P2EN_SHIFT) & P2EN_MASK) +#define MSP_SET_ENDIANNES_BIT(n) ((n << ENDN_SHIFT) & ENDN_MASK) +#define MSP_FRAME_SYNC_POL(n) ((n << TFSPOL_SHIFT) & TFSPOL_MASK) +#define MSP_DATA_WORD_SWAP(n) ((n << TBSWAP_SHIFT) & TBSWAP_MASK) +#define MSP_SET_COMPANDING_MODE(n) ((n << DTYP_SHIFT) & COMPANDING_MODE_MASK) +#define MSP_SET_FRAME_SYNC_IGNORE(n) ((n << FRAME_SYNC_SHIFT) & \ + FRAME_SYNC_MASK) + +/* Flag register */ +#define RX_BUSY BIT(0) +#define RX_FIFO_EMPTY BIT(1) +#define RX_FIFO_FULL BIT(2) +#define TX_BUSY BIT(3) +#define TX_FIFO_EMPTY BIT(4) +#define TX_FIFO_FULL BIT(5) + +#define RBUSY_SHIFT 0 +#define RFE_SHIFT 1 +#define RFU_SHIFT 2 +#define TBUSY_SHIFT 3 +#define TFE_SHIFT 4 +#define TFU_SHIFT 5 + +/* Multichannel control register */ +#define RMCEN_SHIFT 0 +#define RMCSF_SHIFT 1 +#define RCMPM_SHIFT 3 +#define TMCEN_SHIFT 5 +#define TNCSF_SHIFT 6 + +/* Sample rate generator register */ +#define SCKDIV_SHIFT 0 +#define FRWID_SHIFT 10 +#define FRPER_SHIFT 16 + +#define SCK_DIV_MASK 0x0000003FF +#define FRAME_WIDTH_BITS(n) (((n) << FRWID_SHIFT) & 0x0000FC00) +#define FRAME_PERIOD_BITS(n) (((n) << FRPER_SHIFT) & 0x1FFF0000) + +/* DMA controller register */ +#define RX_DMA_ENABLE BIT(0) +#define TX_DMA_ENABLE BIT(1) + +#define RDMAE_SHIFT 0 +#define TDMAE_SHIFT 1 + +/* Interrupt Register */ +#define RECEIVE_SERVICE_INT BIT(0) +#define RECEIVE_OVERRUN_ERROR_INT BIT(1) +#define RECEIVE_FRAME_SYNC_ERR_INT BIT(2) +#define RECEIVE_FRAME_SYNC_INT BIT(3) +#define TRANSMIT_SERVICE_INT BIT(4) +#define TRANSMIT_UNDERRUN_ERR_INT BIT(5) +#define TRANSMIT_FRAME_SYNC_ERR_INT BIT(6) +#define TRANSMIT_FRAME_SYNC_INT BIT(7) +#define ALL_INT 0x000000ff + +/* MSP test control register */ +#define MSP_ITCR_ITEN BIT(0) +#define MSP_ITCR_TESTFIFO BIT(1) + +/* + * Protocol configuration values I2S: + * Single phase, 16 bits, 2 words per frame + */ +#define I2S_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_IMEDIATE, \ + MSP_PHASE2_START_MODE_IMEDIATE, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_ELEM_LENGTH_32, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_RISING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_LOW, \ + MSP_FRAME_SYNC_POL_ACTIVE_LOW, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 31, \ + 15, \ + 32, \ +} + +#define PCM_PROTOCOL_DESC \ +{ \ + MSP_DUAL_PHASE, \ + MSP_DUAL_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_16, \ + MSP_DELAY_0, \ + MSP_DELAY_0, \ + MSP_RISING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +/* Companded PCM: Single phase, 8 bits, 1 word per frame */ +#define PCM_COMPAND_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_0, \ + MSP_DELAY_0, \ + MSP_RISING_EDGE, \ + MSP_RISING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +/* + * AC97: Double phase, 1 element of 16 bits during first phase, + * 12 elements of 20 bits in second phase. + */ +#define AC97_PROTOCOL_DESC \ +{ \ + MSP_DUAL_PHASE, \ + MSP_DUAL_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_12, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_12, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_20, \ + MSP_ELEM_LENGTH_16, \ + MSP_ELEM_LENGTH_20, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_RISING_EDGE, \ + MSP_RISING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +#define SPI_MASTER_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_FALLING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +#define SPI_SLAVE_PROTOCOL_DESC \ +{ \ + MSP_SINGLE_PHASE, \ + MSP_SINGLE_PHASE, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_PHASE2_START_MODE_FRAME_SYNC, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_BTF_MS_BIT_FIRST, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_FRAME_LENGTH_1, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_ELEM_LENGTH_8, \ + MSP_DELAY_1, \ + MSP_DELAY_1, \ + MSP_FALLING_EDGE, \ + MSP_FALLING_EDGE, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \ + MSP_HWS_NO_SWAP, \ + MSP_HWS_NO_SWAP, \ + MSP_COMPRESS_MODE_LINEAR, \ + MSP_EXPAND_MODE_LINEAR, \ + MSP_SPI_CLOCK_MODE_NON_SPI, \ + MSP_SPI_BURST_MODE_DISABLE, \ + MSP_FRAME_SYNC_IGNORE, \ + 255, \ + 0, \ + 256, \ +} + +#define MSP_FRAME_PERIOD_IN_MONO_MODE 256 +#define MSP_FRAME_PERIOD_IN_STEREO_MODE 32 +#define MSP_FRAME_WIDTH_IN_STEREO_MODE 16 + +/* + * No of registers to backup during + * suspend resume + */ +#define MAX_MSP_BACKUP_REGS 36 + +enum enum_i2s_controller { + MSP_0_I2S_CONTROLLER = 0, + MSP_1_I2S_CONTROLLER, + MSP_2_I2S_CONTROLLER, + MSP_3_I2S_CONTROLLER, +}; + +/** + * struct msp - Main msp controller data structure per MSP. + * @work_mode: Mode i.e dma, polling or interrupt. + * @id: Controller id like MSP1 or MSP2 etc. + * @msp_io_error: To indicate error while transferring. + * @registers: MSP's register base address. + * @actual_data_size: Data size in which data needs to send or receive. + * @irq: MSP's irq number. + * @i2s_cont: MSP's Controller's structure pointer created per MSP. + * @lock: semaphore lock acquired while configuring msp. + * @dma_cfg_tx: TX DMA configuration + * @dma_cfg_rx: RX DMA configuration + * @msp_state: Current state of msp. + * @plat_init: MSP's initialization function. + * @plat_exit: MSP's Exit function. + * @def_elem_len: Flag indicates whether default elem len to be used in + * protocol_desc or not. + * @reg_enabled: Flag indicates whether regulator has been enabled or not. + * @vape_opp_constraint: 1 if constraint is applied to have vape at 100OPP; 0 otherwise + * + * Main Msp private data structure to be used to store various info of a + * particular MSP.Longer description + */ +struct msp { + int work_mode; + enum enum_i2s_controller id; + int msp_io_error; + void __iomem *registers; + enum msp_data_size actual_data_size; + struct device *dev; + int irq; + struct i2s_controller *i2s_cont; + struct semaphore lock; + struct stedma40_chan_cfg *dma_cfg_rx; + struct stedma40_chan_cfg *dma_cfg_tx; + enum msp_state msp_state; + int (*plat_init) (void); + int (*plat_exit) (void); + int def_elem_len; + struct clk *clk; + unsigned int direction; + int users; + int reg_enabled; + int loopback_enable; + u32 backup_regs[MAX_MSP_BACKUP_REGS]; + int vape_opp_constraint; +}; + +/** + * struct msp_i2s_platform_data - Main msp controller platform data structure. + * @id: Controller id like MSP1 or MSP2 etc. + * @msp_i2s_dma_rx: RX DMA channel config + * @msp_i2s_dma_tx: RX DMA channel config + * @msp_i2s_init: MSP's initialization function. + * @msp_i2s_exit: MSP's Exit function. + * @backup_regs: used for backup registers during suspend resume. + * + * Platform data structure passed by devices.c file. + */ +struct msp_i2s_platform_data { + enum enum_i2s_controller id; + struct stedma40_chan_cfg *msp_i2s_dma_rx; + struct stedma40_chan_cfg *msp_i2s_dma_tx; + int (*msp_i2s_init) (void); + int (*msp_i2s_exit) (void); +}; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/pm-timer.h b/arch/arm/mach-ux500/include/mach/pm-timer.h new file mode 100644 index 00000000000..f5fafbbaa77 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/pm-timer.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * + * License Terms: GNU General Public License v2 + * + */ + +#ifndef PM_TIMER_H +#define PM_TIMER_H + +#include <linux/ktime.h> + +#ifdef CONFIG_UX500_CPUIDLE_DEBUG +ktime_t u8500_rtc_exit_latency_get(void); +void ux500_rtcrtt_measure_latency(bool enable); +#else +static inline ktime_t u8500_rtc_exit_latency_get(void) +{ + return ktime_set(0, 0); +} +static inline void ux500_rtcrtt_measure_latency(bool enable) { } + +#endif + +void ux500_rtcrtt_off(void); +void ux500_rtcrtt_next(u32 time_us); + +#endif diff --git a/arch/arm/mach-ux500/include/mach/pm.h b/arch/arm/mach-ux500/include/mach/pm.h new file mode 100644 index 00000000000..c6f1b0adca5 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/pm.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Rickard Andersson <rickard.andersson@stericsson.com> for + * ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + * + */ + +#ifndef PM_COMMON_H +#define PM_COMMON_H + +#ifdef CONFIG_PM +#include <linux/mfd/dbx500-prcmu.h> + +/** + * ux500_pm_gic_decouple() + * + * Decouple GIC from the interrupt bus. + */ +void ux500_pm_gic_decouple(void); + +/** + * ux500_pm_gic_recouple() + * + * Recouple GIC with the interrupt bus. + */ +void ux500_pm_gic_recouple(void); + +/** + * ux500_pm_gic_pending_interrupt() + * + * returns true, if there are pending interrupts. + */ +bool ux500_pm_gic_pending_interrupt(void); + +/** + * ux500_pm_prcmu_pending_interrupt() + * + * returns true, if there are pending interrupts. + */ +bool ux500_pm_prcmu_pending_interrupt(void); + +/** + * ux500_pm_prcmu_set_ioforce() + * + * @enable: Enable/disable + * + * Enable/disable the gpio-ring + */ +void ux500_pm_prcmu_set_ioforce(bool enable); + +/** + * ux500_pm_prcmu_copy_gic_settings() + * + * This function copies all the gic interrupt settings to the prcmu. + * This is needed for the system to catch interrupts in ApIdle + */ +void ux500_pm_prcmu_copy_gic_settings(void); + +/** + * ux500_pm_gpio_save_wake_up_status() + * + * This function is called when the prcmu has woken the ARM + * but before ioforce is disabled. + */ +void ux500_pm_gpio_save_wake_up_status(void); + +/** + * ux500_pm_gpio_read_wake_up_status() + * + * @bank_number: The gpio bank. + * + * Returns the WKS register settings for given bank number. + * The WKS register is cleared when ioforce is released therefore + * this function is needed. + */ +u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_number); + +/** + * ux500_pm_other_cpu_wfi() + * + * Returns true if the other CPU is in WFI. + */ +bool ux500_pm_other_cpu_wfi(void); + +struct dev_pm_domain; +extern struct dev_pm_domain ux500_dev_power_domain; +extern struct dev_pm_domain ux500_amba_dev_power_domain; + +#else +u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_number) +{ + return 0; +} + +/** + * ux500_pm_prcmu_set_ioforce() + * + * @enable: Enable/disable + * + * Enable/disable the gpio-ring + */ +static inline void ux500_pm_prcmu_set_ioforce(bool enable) { } + +#endif + +extern int ux500_console_uart_gpio_pin; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/prcmu-debug.h b/arch/arm/mach-ux500/include/mach/prcmu-debug.h new file mode 100644 index 00000000000..38f5ad94864 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/prcmu-debug.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Martin Persson for ST-Ericsson + * Etienne Carriere <etienne.carriere@stericsson.com> for ST-Ericsson + * + */ + +#ifndef PRCMU_DEBUG_H +#define PRCMU_DEBUG_H + +#ifdef CONFIG_DBX500_PRCMU_DEBUG +void prcmu_debug_ape_opp_log(u8 opp); +void prcmu_debug_ddr_opp_log(u8 opp); +void prcmu_debug_arm_opp_log(u32 value); +void prcmu_debug_dump_data_mem(void); +void prcmu_debug_dump_regs(void); +void prcmu_debug_register_interrupt(u32 mailbox); +void prcmu_debug_register_mbox0_event(u32 ev, u32 mask); +#else +static inline void prcmu_debug_ape_opp_log(u8 opp) {} +static inline void prcmu_debug_ddr_opp_log(u8 opp) {} +static inline void prcmu_debug_arm_opp_log(u32 value) {} +static inline void prcmu_debug_dump_data_mem(void) {} +static inline void prcmu_debug_dump_regs(void) {} +static inline void prcmu_debug_register_interrupt(u32 mailbox) {} +static inline void prcmu_debug_register_mbox0_event(u32 ev, u32 mask) {} +#endif +#endif diff --git a/arch/arm/mach-ux500/include/mach/reboot_reasons.h b/arch/arm/mach-ux500/include/mach/reboot_reasons.h new file mode 100644 index 00000000000..4d0592b61d4 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/reboot_reasons.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Rickard Evertsson <rickard.evertsson@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL) version 2 + * + * Use this file to customize your reboot / sw reset reasons. Add, remove or + * modify reasons in reboot_reasons[]. + * The reboot reasons will be saved to a secure location in TCDM memory and + * can be read at bootup by e.g. the bootloader. + */ + +#ifndef _REBOOT_REASONS_H +#define _REBOOT_REASONS_H + +/* + * These defines contains the codes that will be written down to a secure + * location before resetting. These values are just dummy values and does not, + * at the moment, affect anything. + */ +#define SW_RESET_NO_ARGUMENT 0xBEEF +#define SW_RESET_FACTORY_RESET 0x4242 +#define SW_RESET_CRASH 0xDEAD +#define SW_RESET_NORMAL 0xc001 +#define SW_RESET_CHARGING 0xCAFE +#define SW_RESET_COLDSTART 0x0 +#define SW_RESET_RECOVERY 0x5502 +#define SW_RESET_CHGONLY_EXIT 0xCAFF + +/* + * The array reboot_reasons[] is used when you want to map a string to a reboot + * reason code + */ +struct reboot_reason { + const char *reason; + unsigned short code; +}; + +extern struct reboot_reason reboot_reasons[]; + +extern unsigned int reboot_reasons_size; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 3dc00ffa7bf..5caffc97e36 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -14,6 +14,8 @@ #include <asm/mach/time.h> #include <linux/init.h> +extern void ux500_restart(char, const char *); + void __init ux500_map_io(void); extern void __init u5500_map_io(void); extern void __init u8500_map_io(void); @@ -26,6 +28,7 @@ extern void __init ux500_init_irq(void); extern void __init u5500_sdi_init(struct device *parent); extern void __init db5500_dma_init(struct device *parent); +extern void __init db8500_dma_init(struct device *parent); extern struct device *ux500_soc_device_init(const char *soc_id); @@ -49,4 +52,11 @@ extern struct sys_timer ux500_timer; .type = MT_MEMORY, \ } +#define __MEM_DEV_DESC_DB9540_ROM(x, sz) { \ + .virtual = IO_ADDRESS_DB9540_ROM(x), \ + .pfn = __phys_to_pfn(x), \ + .length = sz, \ + .type = MT_MEMORY, \ +} + #endif /* __ASM_ARCH_SETUP_H */ diff --git a/arch/arm/mach-ux500/include/mach/sim_detect.h b/arch/arm/mach-ux500/include/mach/sim_detect.h new file mode 100644 index 00000000000..4dae656b7e0 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/sim_detect.h @@ -0,0 +1,15 @@ +/* + * Copyright ST-Ericsson 2010 SA. + * + * Author: Bibek Basu <bibek.basu@stericsson.com> + * Licensed under GPLv2. + */ + +#ifndef _AB8500_SIM_DETECT_H +#define _AB8500_SIM_DETECT_H + +struct sim_detect_platform_data { + int irq_num; +}; + +#endif diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h index cb2110c3285..0ddd4ab9020 100644 --- a/arch/arm/mach-ux500/ste-dma40-db5500.h +++ b/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h @@ -42,7 +42,9 @@ enum dma_src_dev_type { DB5500_DMA_DEV26_SDMMC2_RX = 26, DB5500_DMA_DEV27_SDMMC3_RX = 27, DB5500_DMA_DEV28_SDMMC4_RX = 28, - /* 29 - 32 not used */ + /* 29, 30 not used */ + DB5500_DMA_DEV31_CRYPTO1_RX = 31, /* v2 */ + /* 32 not used */ DB5500_DMA_DEV33_SDMMC0_RX = 33, DB5500_DMA_DEV34_SDMMC1_RX = 34, DB5500_DMA_DEV35_SDMMC2_RX = 35, @@ -56,7 +58,7 @@ enum dma_src_dev_type { DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43, DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44, DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45, - /* 46 not used */ + DB5500_DMA_DEV46_CRYPTO1_RX = 46, /* v2 */ DB5500_DMA_DEV47_MCDE_RX = 47, DB5500_DMA_DEV48_CRYPTO1_RX = 48, /* 49, 50 not used */ @@ -98,7 +100,9 @@ enum dma_dest_dev_type { DB5500_DMA_DEV26_SDMMC2_TX = 26, DB5500_DMA_DEV27_SDMMC3_TX = 27, DB5500_DMA_DEV28_SDMMC4_TX = 28, - /* 29 - 31 not used */ + /* 29 not used */ + DB5500_DMA_DEV30_HASH1_TX = 30, /* v2 */ + DB5500_DMA_DEV31_CRYPTO1_TX = 31, /* v2 */ DB5500_DMA_DEV32_FSMC_TX = 32, DB5500_DMA_DEV33_SDMMC0_TX = 33, DB5500_DMA_DEV34_SDMMC1_TX = 34, @@ -113,7 +117,7 @@ enum dma_dest_dev_type { DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43, DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44, DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45, - /* 46 not used */ + DB5500_DMA_DEV46_CRYPTO1_TX = 46, /* v2 */ DB5500_DMA_DEV47_STM_TX = 47, DB5500_DMA_DEV48_CRYPTO1_TX = 48, DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49, diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h index a616419bea7..65799a75199 100644 --- a/arch/arm/mach-ux500/ste-dma40-db8500.h +++ b/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h @@ -1,16 +1,19 @@ /* - * arch/arm/mach-ux500/ste_dma40_db8500.h - * DB8500-SoC-specific configuration for DMA40 - * - * Copyright (C) ST-Ericsson 2007-2010 + * Copyright (C) ST-Ericsson SA 2007-2010 + * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson * License terms: GNU General Public License (GPL) version 2 - * Author: Per Friden <per.friden@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * + * DB8500-SoC-specific configuration for DMA40 */ #ifndef STE_DMA40_DB8500_H #define STE_DMA40_DB8500_H #define DB8500_DMA_NR_DEV 64 +/* + * All entries with double names are multiplexed + * and can never be used at the same time. + */ enum dma_src_dev_type { DB8500_DMA_DEV0_SPI0_RX = 0, @@ -20,7 +23,7 @@ enum dma_src_dev_type { DB8500_DMA_DEV4_I2C1_RX = 4, DB8500_DMA_DEV5_I2C3_RX = 5, DB8500_DMA_DEV6_I2C2_RX = 6, - DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */ + DB8500_DMA_DEV7_I2C4_RX = 7, DB8500_DMA_DEV8_SSP0_RX = 8, DB8500_DMA_DEV9_SSP1_RX = 9, DB8500_DMA_DEV10_MCDE_RX = 10, @@ -43,8 +46,6 @@ enum dma_src_dev_type { DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27, DB8500_DMA_DEV28_SD_MM2_RX = 28, DB8500_DMA_DEV29_SD_MM0_RX = 29, - DB8500_DMA_DEV30_MSP1_RX = 30, - /* On DB8500v2, MSP3 RX replaces MSP1 RX */ DB8500_DMA_DEV30_MSP3_RX = 30, DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31, DB8500_DMA_DEV32_SD_MM1_RX = 32, @@ -82,7 +83,7 @@ enum dma_dest_dev_type { DB8500_DMA_DEV4_I2C1_TX = 4, DB8500_DMA_DEV5_I2C3_TX = 5, DB8500_DMA_DEV6_I2C2_TX = 6, - DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */ + DB8500_DMA_DEV7_I2C4_TX = 7, DB8500_DMA_DEV8_SSP0_TX = 8, DB8500_DMA_DEV9_SSP1_TX = 9, /* 10 is not used*/ diff --git a/arch/arm/mach-ux500/include/mach/suspend.h b/arch/arm/mach-ux500/include/mach/suspend.h new file mode 100644 index 00000000000..5a8df72be2e --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/suspend.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ +#ifndef __MACH_SUSPEND_H +#define __MACH_SUSPEND_H + +#ifdef CONFIG_UX500_SUSPEND +void suspend_block_sleep(void); +void suspend_unblock_sleep(void); +void suspend_set_pins_force_fn(void (*force)(void), void (*force_mux)(void)); +#else +static inline void suspend_block_sleep(void) { } +static inline void suspend_unblock_sleep(void) { } +static inline void suspend_set_pins_force_fn(void (*force)(void), + void (*force_mux)(void)) { } +#endif + +#endif /* __MACH_SUSPEND_H */ diff --git a/arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h b/arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h new file mode 100644 index 00000000000..2ac88edfe71 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h @@ -0,0 +1,47 @@ +/* + * Data types and interface for TEE application for starting the modem. + * + * Copyright (C) ST-Ericsson SA 2010 + * Author: Shujuan Chen <shujuan.chen@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef TEE_TA_START_MODEM_H +#define TEE_TA_START_MODEM_H + +#define COMMAND_ID_START_MODEM 0x00000001 + +#define UUID_TEE_TA_START_MODEM_LOW 0x8AD94107 +#define UUID_TEE_TA_START_MODEM_MID 0x6E50 +#define UUID_TEE_TA_START_MODEM_HIGH 0x418E +#define UUID_TEE_TA_START_MODEM_CLOCKSEQ \ + {0xB1, 0x14, 0x75, 0x7D, 0x60, 0x21, 0xBD, 0x36} + +struct mcore_segment_descr { + void *segment; + void *hash; + u32 size; +}; + +struct access_image_descr { + void *elf_hdr; + void *pgm_hdr_tbl; + void *signature; + unsigned long nbr_segment; + struct mcore_segment_descr *descr; +}; + +/* TODO: To be redefined with only info needed by Secure world. */ +struct tee_ta_start_modem { + void *access_mem_start; + u32 shared_mem_size; + u32 access_private_mem_size; + struct access_image_descr access_image_descr; +}; + +/** + * This is the function to handle the modem release. + */ +int tee_ta_start_modem(struct tee_ta_start_modem *data); + +#endif diff --git a/arch/arm/mach-ux500/include/mach/timex.h b/arch/arm/mach-ux500/include/mach/timex.h index d0942c17401..0ba497bd9d7 100644 --- a/arch/arm/mach-ux500/include/mach/timex.h +++ b/arch/arm/mach-ux500/include/mach/timex.h @@ -2,5 +2,6 @@ #define __ASM_ARCH_TIMEX_H #define CLOCK_TICK_RATE 110000000 +#define ARCH_HAS_READ_CURRENT_TIMER #endif diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h index 4c1cc50a595..700d9dbb1be 100644 --- a/arch/arm/mach-ux500/include/mach/usb.h +++ b/arch/arm/mach-ux500/include/mach/usb.h @@ -12,6 +12,8 @@ #define UX500_MUSB_DMA_NUM_RX_CHANNELS 8 #define UX500_MUSB_DMA_NUM_TX_CHANNELS 8 +struct musb; + struct ux500_musb_board_data { void **dma_rx_param_array; void **dma_tx_param_array; @@ -22,4 +24,14 @@ struct ux500_musb_board_data { void ux500_add_usb(struct device *parent, resource_size_t base, int irq, int *dma_rx_cfg, int *dma_tx_cfg); + +/* Only used for u5500 */ +struct abx500_usbgpio_platform_data { + int (*get)(struct device *device); + void (*enable)(void); + void (*disable)(void); + void (*put)(void); + int usb_cs; +}; +void ux500_restore_context(struct musb *musb); #endif diff --git a/arch/arm/mach-ux500/l2x0-prefetch.c b/arch/arm/mach-ux500/l2x0-prefetch.c new file mode 100644 index 00000000000..4085c351f20 --- /dev/null +++ b/arch/arm/mach-ux500/l2x0-prefetch.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/tee.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/hardware/cache-l2x0.h> + +static struct tee_session session; +static struct tee_context context; +static void __iomem *l2x0_base; + +#define L2X0_PREFETCH_CTRL_REG (0x00000F60) +#define L2X0_PREFETCH_CTRL_BIT_DATA_EN (1 << 28) +#define L2X0_PREFETCH_CTRL_BIT_INST_EN (1 << 29) + +#define L2X0_UUID_TEE_TA_START_LOW 0xBC765EDE +#define L2X0_UUID_TEE_TA_START_MID 0x6724 +#define L2X0_UUID_TEE_TA_START_HIGH 0x11DF +#define L2X0_UUID_TEE_TA_START_CLOCKSEQ \ + {0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85} + +static void prefetch_enable(void) +{ + struct tee_operation operation; + u32 data; + int err; + int origin_err; + + data = readl(l2x0_base + L2X0_PREFETCH_CTRL_REG); + + pr_debug("l2x0-prefetch: %s start, preftect_ctrl=0x%08x\n", __func__, + data); + if (!(data & L2X0_PREFETCH_CTRL_BIT_INST_EN) || + !(data & L2X0_PREFETCH_CTRL_BIT_DATA_EN)) { + + data |= (L2X0_PREFETCH_CTRL_BIT_INST_EN | + L2X0_PREFETCH_CTRL_BIT_DATA_EN); + + operation.shm[0].buffer = &data; + operation.shm[0].size = sizeof(data); + operation.shm[0].flags = TEEC_MEM_INPUT; + operation.flags = TEEC_MEMREF_0_USED; + + err = teec_invoke_command(&session, + TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER, + &operation, &origin_err); + if (err) + pr_err("l2x0-prefetch: prefetch enable failed, err=%d", + err); + } + pr_debug("l2x0-prefetch: %s end, prefetch_ctrl=0x%08x\n", __func__, + readl(l2x0_base + L2X0_PREFETCH_CTRL_REG)); +} + +static void prefetch_disable(void) +{ + struct tee_operation operation; + u32 data; + int err; + int origin_err; + + data = readl(l2x0_base + L2X0_PREFETCH_CTRL_REG); + + pr_debug("l2x0-prefetch: %s start, preftect_ctrl=0x%08x\n", __func__, + data); + if (data & (L2X0_PREFETCH_CTRL_BIT_INST_EN | + L2X0_PREFETCH_CTRL_BIT_DATA_EN)) { + + data &= ~(L2X0_PREFETCH_CTRL_BIT_INST_EN | + L2X0_PREFETCH_CTRL_BIT_DATA_EN); + + operation.shm[0].buffer = &data; + operation.shm[0].size = sizeof(data); + operation.shm[0].flags = TEEC_MEM_INPUT; + operation.flags = TEEC_MEMREF_0_USED; + + err = teec_invoke_command(&session, + TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER, + &operation, &origin_err); + if (err) + pr_err("l2x0-prefetch: prefetch disable failed, err=%d", + err); + } + pr_debug("l2x0-prefetch: %s end, prefetch_ctrl=0x%08x\n", __func__, + readl(l2x0_base + L2X0_PREFETCH_CTRL_REG)); +} + +static int __init prefetch_ctrl_init(void) +{ + int err; + int origin_err; + /* Selects trustzone application needed for the job. */ + struct tee_uuid static_uuid = { + L2X0_UUID_TEE_TA_START_LOW, + L2X0_UUID_TEE_TA_START_MID, + L2X0_UUID_TEE_TA_START_HIGH, + L2X0_UUID_TEE_TA_START_CLOCKSEQ, + }; + + /* Get PL310 base address. It will be used as readonly. */ + if (cpu_is_u5500()) + l2x0_base = __io_address(U5500_L2CC_BASE); + else if (cpu_is_u8500() || cpu_is_u9540()) + l2x0_base = __io_address(U8500_L2CC_BASE); + else + ux500_unknown_soc(); + + err = teec_initialize_context(NULL, &context); + if (err) { + pr_err("l2x0-prefetch: unable to initialize tee context," + " err = %d\n", err); + err = -EINVAL; + goto error0; + } + + err = teec_open_session(&context, &session, &static_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &origin_err); + if (err) { + pr_err("l2x0-prefetch: unable to open tee session," + " tee error = %d, origin error = %d\n", + err, origin_err); + err = -EINVAL; + goto error1; + } + + outer_cache.prefetch_enable = prefetch_enable; + outer_cache.prefetch_disable = prefetch_disable; + + pr_info("l2x0-prefetch: initialized.\n"); + + return 0; + +error1: + (void)teec_finalize_context(&context); +error0: + return err; +} + +static void __exit prefetch_ctrl_exit(void) +{ + outer_cache.prefetch_enable = NULL; + outer_cache.prefetch_disable = NULL; + + (void)teec_close_session(&session); + (void)teec_finalize_context(&context); +} + +/* Wait for TEE driver to be initialized. */ +late_initcall(prefetch_ctrl_init); +module_exit(prefetch_ctrl_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("PL310 prefetch control"); diff --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c deleted file mode 100644 index 0127490218c..00000000000 --- a/arch/arm/mach-ux500/mbox-db5500.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson. - * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson. - * License terms: GNU General Public License (GPL), version 2. - */ - -/* - * Mailbox nomenclature: - * - * APE MODEM - * mbox pairX - * .......................... - * . . - * . peer . - * . send ---- . - * . --> | | . - * . | | . - * . ---- . - * . . - * . local . - * . rec ---- . - * . | | <-- . - * . | | . - * . ---- . - * ......................... - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/completion.h> -#include <mach/mbox-db5500.h> - -#define MBOX_NAME "mbox" - -#define MBOX_FIFO_DATA 0x000 -#define MBOX_FIFO_ADD 0x004 -#define MBOX_FIFO_REMOVE 0x008 -#define MBOX_FIFO_THRES_FREE 0x00C -#define MBOX_FIFO_THRES_OCCUP 0x010 -#define MBOX_FIFO_STATUS 0x014 - -#define MBOX_DISABLE_IRQ 0x4 -#define MBOX_ENABLE_IRQ 0x0 -#define MBOX_LATCH 1 - -/* Global list of all mailboxes */ -static struct list_head mboxs = LIST_HEAD_INIT(mboxs); - -static struct mbox *get_mbox_with_id(u8 id) -{ - u8 i; - struct list_head *pos = &mboxs; - for (i = 0; i <= id; i++) - pos = pos->next; - - return (struct mbox *) list_entry(pos, struct mbox, list); -} - -int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block) -{ - int res = 0; - - spin_lock(&mbox->lock); - - dev_dbg(&(mbox->pdev->dev), - "About to buffer 0x%X to mailbox 0x%X." - " ri = %d, wi = %d\n", - mbox_msg, (u32)mbox, mbox->read_index, - mbox->write_index); - - /* Check if write buffer is full */ - while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) { - if (!block) { - dev_dbg(&(mbox->pdev->dev), - "Buffer full in non-blocking call! " - "Returning -ENOMEM!\n"); - res = -ENOMEM; - goto exit; - } - spin_unlock(&mbox->lock); - dev_dbg(&(mbox->pdev->dev), - "Buffer full in blocking call! Sleeping...\n"); - mbox->client_blocked = 1; - wait_for_completion(&mbox->buffer_available); - dev_dbg(&(mbox->pdev->dev), - "Blocking send was woken up! Trying again...\n"); - spin_lock(&mbox->lock); - } - - mbox->buffer[mbox->write_index] = mbox_msg; - mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE; - - /* - * Indicate that we want an IRQ as soon as there is a slot - * in the FIFO - */ - writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - -exit: - spin_unlock(&mbox->lock); - return res; -} -EXPORT_SYMBOL(mbox_send); - -#if defined(CONFIG_DEBUG_FS) -/* - * Expected input: <value> <nbr sends> - * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times - */ -static ssize_t mbox_write_fifo(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - unsigned long mbox_mess; - unsigned long nbr_sends; - unsigned long i; - char int_buf[16]; - char *token; - char *val; - - struct mbox *mbox = (struct mbox *) dev->platform_data; - - strncpy((char *) &int_buf, buf, sizeof(int_buf)); - token = (char *) &int_buf; - - /* Parse message */ - val = strsep(&token, " "); - if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0)) - mbox_mess = 0xDEADBEEF; - - val = strsep(&token, " "); - if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0)) - nbr_sends = 1; - - dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n", - mbox_mess, nbr_sends, (u32) mbox); - - for (i = 0; i < nbr_sends; i++) - mbox_send(mbox, mbox_mess, true); - - return count; -} - -static ssize_t mbox_read_fifo(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int mbox_value; - struct mbox *mbox = (struct mbox *) dev->platform_data; - - if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0) - return sprintf(buf, "Mailbox is empty\n"); - - mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA); - writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE)); - - return sprintf(buf, "0x%X\n", mbox_value); -} - -static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo); - -static int mbox_show(struct seq_file *s, void *data) -{ - struct list_head *pos; - u8 mbox_index = 0; - - list_for_each(pos, &mboxs) { - struct mbox *m = - (struct mbox *) list_entry(pos, struct mbox, list); - if (m == NULL) { - seq_printf(s, - "Unable to retrieve mailbox %d\n", - mbox_index); - continue; - } - - spin_lock(&m->lock); - if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) { - seq_printf(s, "MAILBOX %d not setup or corrupt\n", - mbox_index); - spin_unlock(&m->lock); - continue; - } - - seq_printf(s, - "===========================\n" - " MAILBOX %d\n" - " PEER MAILBOX DUMP\n" - "---------------------------\n" - "FIFO: 0x%X (%d)\n" - "Free Threshold: 0x%.2X (%d)\n" - "Occupied Threshold: 0x%.2X (%d)\n" - "Status: 0x%.2X (%d)\n" - " Free spaces (ot): %d (%d)\n" - " Occup spaces (ot): %d (%d)\n" - "===========================\n" - " LOCAL MAILBOX DUMP\n" - "---------------------------\n" - "FIFO: 0x%.X (%d)\n" - "Free Threshold: 0x%.2X (%d)\n" - "Occupied Threshold: 0x%.2X (%d)\n" - "Status: 0x%.2X (%d)\n" - " Free spaces (ot): %d (%d)\n" - " Occup spaces (ot): %d (%d)\n" - "===========================\n" - "write_index: %d\n" - "read_index : %d\n" - "===========================\n" - "\n", - mbox_index, - readl(m->virtbase_peer + MBOX_FIFO_DATA), - readl(m->virtbase_peer + MBOX_FIFO_DATA), - readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_peer + MBOX_FIFO_STATUS), - readl(m->virtbase_peer + MBOX_FIFO_STATUS), - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7, - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1, - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7, - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1, - readl(m->virtbase_local + MBOX_FIFO_DATA), - readl(m->virtbase_local + MBOX_FIFO_DATA), - readl(m->virtbase_local + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_local + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_local + MBOX_FIFO_STATUS), - readl(m->virtbase_local + MBOX_FIFO_STATUS), - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7, - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1, - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7, - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1, - m->write_index, m->read_index); - mbox_index++; - spin_unlock(&m->lock); - } - - return 0; -} - -static int mbox_open(struct inode *inode, struct file *file) -{ - return single_open(file, mbox_show, NULL); -} - -static const struct file_operations mbox_operations = { - .owner = THIS_MODULE, - .open = mbox_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -static irqreturn_t mbox_irq(int irq, void *arg) -{ - u32 mbox_value; - int nbr_occup; - int nbr_free; - struct mbox *mbox = (struct mbox *) arg; - - spin_lock(&mbox->lock); - - dev_dbg(&(mbox->pdev->dev), - "mbox IRQ [%d] received. ri = %d, wi = %d\n", - irq, mbox->read_index, mbox->write_index); - - /* - * Check if we have any outgoing messages, and if there is space for - * them in the FIFO. - */ - if (mbox->read_index != mbox->write_index) { - /* - * Check by reading FREE for LOCAL since that indicates - * OCCUP for PEER - */ - nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS) - >> 4) & 0x7; - dev_dbg(&(mbox->pdev->dev), - "Status indicates %d empty spaces in the FIFO!\n", - nbr_free); - - while ((nbr_free > 0) && - (mbox->read_index != mbox->write_index)) { - /* Write the message and latch it into the FIFO */ - writel(mbox->buffer[mbox->read_index], - (mbox->virtbase_peer + MBOX_FIFO_DATA)); - writel(MBOX_LATCH, - (mbox->virtbase_peer + MBOX_FIFO_ADD)); - dev_dbg(&(mbox->pdev->dev), - "Wrote message 0x%X to addr 0x%X\n", - mbox->buffer[mbox->read_index], - (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA)); - - nbr_free--; - mbox->read_index = - (mbox->read_index + 1) % MBOX_BUF_SIZE; - } - - /* - * Check if we still want IRQ:s when there is free - * space to send - */ - if (mbox->read_index != mbox->write_index) { - dev_dbg(&(mbox->pdev->dev), - "Still have messages to send, but FIFO full. " - "Request IRQ again!\n"); - writel(MBOX_ENABLE_IRQ, - mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - } else { - dev_dbg(&(mbox->pdev->dev), - "No more messages to send. " - "Do not request IRQ again!\n"); - writel(MBOX_DISABLE_IRQ, - mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - } - - /* - * Check if we can signal any blocked clients that it is OK to - * start buffering again - */ - if (mbox->client_blocked && - (((mbox->write_index + 1) % MBOX_BUF_SIZE) - != mbox->read_index)) { - dev_dbg(&(mbox->pdev->dev), - "Waking up blocked client\n"); - complete(&mbox->buffer_available); - mbox->client_blocked = 0; - } - } - - /* Check if we have any incoming messages */ - nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7; - if (nbr_occup == 0) - goto exit; - - if (mbox->cb == NULL) { - dev_dbg(&(mbox->pdev->dev), "No receive callback registered, " - "leaving %d incoming messages in fifo!\n", nbr_occup); - goto exit; - } - - /* Read and acknowledge the message */ - mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA); - writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE)); - - /* Notify consumer of new mailbox message */ - dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n", - mbox_value); - mbox->cb(mbox_value, mbox->client_data); - -exit: - dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n", - mbox->read_index, mbox->write_index); - spin_unlock(&mbox->lock); - - return IRQ_HANDLED; -} - -/* Setup is executed once for each mbox pair */ -struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv) -{ - struct resource *resource; - int irq; - int res; - struct mbox *mbox; - - mbox = get_mbox_with_id(mbox_id); - if (mbox == NULL) { - dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n", - mbox_id); - goto exit; - } - - /* - * Check if mailbox has been allocated to someone else, - * otherwise allocate it - */ - if (mbox->allocated) { - dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n", - mbox_id); - mbox = NULL; - goto exit; - } - mbox->allocated = true; - - dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n", - mbox_id, (u32)mbox); - - mbox->client_data = priv; - mbox->cb = mbox_cb; - - /* Get addr for peer mailbox and ioremap it */ - resource = platform_get_resource_byname(mbox->pdev, - IORESOURCE_MEM, - "mbox_peer"); - if (resource == NULL) { - dev_err(&(mbox->pdev->dev), - "Unable to retrieve mbox peer resource\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "Resource name: %s start: 0x%X, end: 0x%X\n", - resource->name, resource->start, resource->end); - mbox->virtbase_peer = ioremap(resource->start, resource_size(resource)); - if (!mbox->virtbase_peer) { - dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n", - resource->start, resource->end, (u32) mbox->virtbase_peer); - - /* Get addr for local mailbox and ioremap it */ - resource = platform_get_resource_byname(mbox->pdev, - IORESOURCE_MEM, - "mbox_local"); - if (resource == NULL) { - dev_err(&(mbox->pdev->dev), - "Unable to retrieve mbox local resource\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "Resource name: %s start: 0x%X, end: 0x%X\n", - resource->name, resource->start, resource->end); - mbox->virtbase_local = ioremap(resource->start, resource_size(resource)); - if (!mbox->virtbase_local) { - dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n", - resource->start, resource->end, (u32) mbox->virtbase_peer); - - init_completion(&mbox->buffer_available); - mbox->client_blocked = 0; - - /* Get IRQ for mailbox and allocate it */ - irq = platform_get_irq_byname(mbox->pdev, "mbox_irq"); - if (irq < 0) { - dev_err(&(mbox->pdev->dev), - "Unable to retrieve mbox irq resource\n"); - mbox = NULL; - goto exit; - } - - dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq); - res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox); - if (res < 0) { - dev_err(&(mbox->pdev->dev), - "Unable to allocate mbox irq %d\n", irq); - mbox = NULL; - goto exit; - } - - /* Set up mailbox to not launch IRQ on free space in mailbox */ - writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - - /* - * Set up mailbox to launch IRQ on new message if we have - * a callback set. If not, do not raise IRQ, but keep message - * in FIFO for manual retrieval - */ - if (mbox_cb != NULL) - writel(MBOX_ENABLE_IRQ, - mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP); - else - writel(MBOX_DISABLE_IRQ, - mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP); - -#if defined(CONFIG_DEBUG_FS) - res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo); - if (res != 0) - dev_warn(&(mbox->pdev->dev), - "Unable to create mbox sysfs entry"); - - (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL, - NULL, &mbox_operations); -#endif - - dev_info(&(mbox->pdev->dev), - "Mailbox driver with index %d initiated!\n", mbox_id); - -exit: - return mbox; -} -EXPORT_SYMBOL(mbox_setup); - - -int __init mbox_probe(struct platform_device *pdev) -{ - struct mbox local_mbox; - struct mbox *mbox; - int res = 0; - dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev); - - memset(&local_mbox, 0x0, sizeof(struct mbox)); - - /* Associate our mbox data with the platform device */ - res = platform_device_add_data(pdev, - (void *) &local_mbox, - sizeof(struct mbox)); - if (res != 0) { - dev_err(&(pdev->dev), - "Unable to allocate driver platform data!\n"); - goto exit; - } - - mbox = (struct mbox *) pdev->dev.platform_data; - mbox->pdev = pdev; - mbox->write_index = 0; - mbox->read_index = 0; - - INIT_LIST_HEAD(&(mbox->list)); - list_add_tail(&(mbox->list), &mboxs); - - sprintf(mbox->name, "%s", MBOX_NAME); - spin_lock_init(&mbox->lock); - - dev_info(&(pdev->dev), "Mailbox driver loaded\n"); - -exit: - return res; -} - -static struct platform_driver mbox_driver = { - .driver = { - .name = MBOX_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init mbox_init(void) -{ - return platform_driver_probe(&mbox_driver, mbox_probe); -} - -module_init(mbox_init); - -void __exit mbox_exit(void) -{ - platform_driver_unregister(&mbox_driver); -} - -module_exit(mbox_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MBOX driver"); diff --git a/arch/arm/mach-ux500/mloader-db5500.c b/arch/arm/mach-ux500/mloader-db5500.c new file mode 100644 index 00000000000..bc3a57af28b --- /dev/null +++ b/arch/arm/mach-ux500/mloader-db5500.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Authors: Jonas Aaberg <jonas.aberg@stericsson.com> + * Paer-Olof Haakansson <par-olof.hakansson@stericsson.com> + * for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/module.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> +#include <linux/sysfs.h> +#include <linux/slab.h> + +static ssize_t db5500_mloader_sysfs_addr(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t db5500_mloader_sysfs_finalize(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +static ssize_t db5500_mloader_sysfs_itpmode(struct device *dev, + struct device_attribute *attr, + char *buf); + +static DEVICE_ATTR(addr, S_IRUSR|S_IRGRP, db5500_mloader_sysfs_addr, NULL); +static DEVICE_ATTR(finalize, S_IWUSR, NULL, db5500_mloader_sysfs_finalize); +static DEVICE_ATTR(is_itpmode, S_IRUSR|S_IRGRP, db5500_mloader_sysfs_itpmode, NULL); + +static unsigned int db5500_bootargs_memmap_modem_start; +static unsigned int db5500_bootargs_memmap_modem_total_size; +static unsigned int db5500_mloader_itpmode; +static unsigned int db5500_mloader_shm_total_size; +module_param_named(shm_total_size, db5500_mloader_shm_total_size, uint, 0600); +MODULE_PARM_DESC(shm_total_size, "Total Size of SHM shared memory"); + +static int __init db5500_bootargs_modem_memmap(char *p) +{ + db5500_bootargs_memmap_modem_total_size = memparse(p, &p); + if (*p == '@') + db5500_bootargs_memmap_modem_start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_modem", db5500_bootargs_modem_memmap); + +static int __init db5500_bootargs_shm_total_size(char *str) +{ + int ret; + ret = strict_strtoul(str, 0, &db5500_mloader_shm_total_size); + if (ret < 0) + return -EINVAL; + return 1; +} +early_param("mloader.shm_total_size", db5500_bootargs_shm_total_size); + +static int __init db5500_bootargs_itpmode(char *p) +{ + int ret; + int count = 3; + if (!memcmp(p, "itp", count)) + db5500_mloader_itpmode = true; + else + db5500_mloader_itpmode = false; + return 1; +} +early_param("modem_boot_type", db5500_bootargs_itpmode); + +static int __exit db5500_mloader_remove(struct platform_device *pdev) +{ + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_addr.attr); + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_finalize.attr); + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_is_itpmode.attr); + + return 0; +} + + +static struct platform_driver db5500_mloader_driver = { + .driver = { + .name = "db5500_mloader", + }, + .remove = __exit_p(db5500_mloader_remove), +}; + +struct db5500_mloader { + struct work_struct work; + struct platform_device *pdev; +}; + +static void db5500_mloader_clean_up(struct work_struct *work) +{ + struct db5500_mloader *m = container_of(work, + struct db5500_mloader, + work); + + /* Remove this module */ + platform_device_unregister(m->pdev); + + platform_driver_unregister(&db5500_mloader_driver); + kfree(m); + +} + +static ssize_t db5500_mloader_sysfs_addr(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "0x%x 0x%x 0x%x\n", + db5500_bootargs_memmap_modem_start, + db5500_bootargs_memmap_modem_total_size, + db5500_mloader_shm_total_size); +} + +static ssize_t db5500_mloader_sysfs_itpmode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "0x%x\n", + db5500_mloader_itpmode); +} + +static ssize_t db5500_mloader_sysfs_finalize(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct db5500_mloader *m; + + m = kmalloc(sizeof(struct db5500_mloader), GFP_KERNEL); + + m->pdev = container_of(dev, + struct platform_device, + dev); + + INIT_WORK(&m->work, db5500_mloader_clean_up); + + /* The module can not remove itself while being in a sysfs function, + * it has to use a workqueue. + */ + schedule_work(&m->work); + + return count; +} + +static void db5500_mloader_release(struct device *dev) +{ + /* Nothing to release */ +} + +static int __init db5500_mloader_probe(struct platform_device *pdev) +{ + int ret = 0; + + pdev->dev.release = db5500_mloader_release; + + ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_addr.attr); + if (ret) + return ret; + ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_finalize.attr); + + if (ret) { + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_addr.attr); + return ret; + } + ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_is_itpmode.attr); + if (ret) { + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_finalize.attr); + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_addr.attr); + return ret; + } + return 0; + +} + +static int __init db5500_mloader_init(void) +{ +/* + * mloader for Fairbanks. It exports the physical + * address where the modem side ELF should be located in a sysfs + * file to make it available for a user space utility. + * When the mLoader utility has picked up these settings, this module is no + * longer needed and can be removed by writing to sysfs finalize. + * + * The modem side should be loaded via mmap'ed /dev/mem + * + */ + + return platform_driver_probe(&db5500_mloader_driver, + db5500_mloader_probe); +} +module_init(db5500_mloader_init); + + +static void __exit mloader_exit(void) +{ + platform_driver_unregister(&db5500_mloader_driver); +} +module_exit(mloader_exit); + +MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-ux500/mloader-db8500.c b/arch/arm/mach-ux500/mloader-db8500.c new file mode 100644 index 00000000000..8f08e6af969 --- /dev/null +++ b/arch/arm/mach-ux500/mloader-db8500.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * + * Author: Maxime Coquelin <maxime.coquelin-nonst@stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ +#include <linux/types.h> +#include <linux/platform_device.h> + +#include <mach/mloader-dbx500.h> +#include <mach/hardware.h> + +static struct dbx500_ml_area modem_areas[] = { + { .name = "modem_trace", .start = 0x6000000, .size = 0xf00000 }, + { .name = "modem_shared", .start = 0x6f00000, .size = 0x100000 }, + { .name = "modem_priv", .start = 0x7000000, .size = 0x1000000 }, +}; + +static struct dbx500_ml_fw modem_fws[] = { + { .name = "MODEM", .area = &modem_areas[0], .offset = 0x0 }, + { .name = "IPL", .area = &modem_areas[1], .offset = 0x00 }, +}; + +static struct dbx500_mloader_pdata mloader_fw_data = { + .fws = modem_fws, + .nr_fws = ARRAY_SIZE(modem_fws), + .areas = modem_areas, + .nr_areas = ARRAY_SIZE(modem_areas), +}; + +static struct resource mloader_fw_rsrc[] = { + { + .start = (U8500_BACKUPRAM1_BASE + 0xF70), + .end = (U8500_BACKUPRAM1_BASE + 0xF7C), + .flags = IORESOURCE_MEM + } +}; + +struct platform_device mloader_fw_device = { + .name = "dbx500_mloader_fw", + .id = -1, + .dev = { + .platform_data = &mloader_fw_data, + }, + .resource = mloader_fw_rsrc, + .num_resources = ARRAY_SIZE(mloader_fw_rsrc) +}; + +/* Default areas can be overloaded in cmdline */ +static int __init early_modem_priv(char *p) +{ + struct dbx500_ml_area *area = &modem_areas[2]; + + area->size = memparse(p, &p); + + if (*p == '@') + area->start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_modem", early_modem_priv); + +static int __init early_modem_shared(char *p) +{ + struct dbx500_ml_area *area = &modem_areas[1]; + + area->size = memparse(p, &p); + + if (*p == '@') + area->start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_mshared", early_modem_shared); + +static int __init early_modem_trace(char *p) +{ + struct dbx500_ml_area *area = &modem_areas[0]; + + area->size = memparse(p, &p); + + if (*p == '@') + area->start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_mtrace", early_modem_trace); diff --git a/arch/arm/mach-ux500/modem-irq-db5500.c b/arch/arm/mach-ux500/modem-irq-db5500.c index 6b86416c94c..7c2947af984 100644 --- a/arch/arm/mach-ux500/modem-irq-db5500.c +++ b/arch/arm/mach-ux500/modem-irq-db5500.c @@ -81,7 +81,7 @@ static irqreturn_t modem_cpu_irq_handler(int irq, void *data) virt_irq); if (virt_irq != 0) - generic_handle_irq(virt_irq); + handle_nested_irq(virt_irq); pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq); @@ -91,6 +91,7 @@ static irqreturn_t modem_cpu_irq_handler(int irq, void *data) static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip) { irq_set_chip_and_handler(irq, modem_irq_chip, handle_simple_irq); + irq_set_nested_thread(irq, 1); set_irq_flags(irq, IRQF_VALID); pr_debug("modem_irq: Created virtual IRQ %d\n", irq); @@ -131,7 +132,8 @@ static int modem_irq_init(void) create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip); err = request_threaded_irq(IRQ_DB5500_MODEM, NULL, - modem_cpu_irq_handler, IRQF_ONESHOT, + modem_cpu_irq_handler, + IRQF_NO_SUSPEND | IRQF_ONESHOT, "modem_irq", mi); if (err) pr_err("modem_irq: Could not register IRQ %d\n", diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h index 8b1d1a7a679..062c7acf457 100644 --- a/arch/arm/mach-ux500/pins-db8500.h +++ b/arch/arm/mach-ux500/pins-db8500.h @@ -35,40 +35,40 @@ #define GPIO4_GPIO PIN_CFG(4, GPIO) #define GPIO4_U1_RXD PIN_CFG(4, ALT_A) -#define GPIO4_I2C4_SCL PIN_CFG_INPUT(4, ALT_B, PULLUP) +#define GPIO4_I2C4_SCL PIN_CFG(4, ALT_B) #define GPIO4_IP_TRSTn PIN_CFG(4, ALT_C) #define GPIO5_GPIO PIN_CFG(5, GPIO) #define GPIO5_U1_TXD PIN_CFG(5, ALT_A) -#define GPIO5_I2C4_SDA PIN_CFG_INPUT(5, ALT_B, PULLUP) +#define GPIO5_I2C4_SDA PIN_CFG(5, ALT_B) #define GPIO5_IP_GPIO6 PIN_CFG(5, ALT_C) #define GPIO6_GPIO PIN_CFG(6, GPIO) #define GPIO6_U1_CTSn PIN_CFG(6, ALT_A) -#define GPIO6_I2C1_SCL PIN_CFG_INPUT(6, ALT_B, PULLUP) +#define GPIO6_I2C1_SCL PIN_CFG(6, ALT_B) #define GPIO6_IP_GPIO0 PIN_CFG(6, ALT_C) #define GPIO7_GPIO PIN_CFG(7, GPIO) #define GPIO7_U1_RTSn PIN_CFG(7, ALT_A) -#define GPIO7_I2C1_SDA PIN_CFG_INPUT(7, ALT_B, PULLUP) +#define GPIO7_I2C1_SDA PIN_CFG(7, ALT_B) #define GPIO7_IP_GPIO1 PIN_CFG(7, ALT_C) #define GPIO8_GPIO PIN_CFG(8, GPIO) -#define GPIO8_IPI2C_SDA PIN_CFG_INPUT(8, ALT_A, PULLUP) -#define GPIO8_I2C2_SDA PIN_CFG_INPUT(8, ALT_B, PULLUP) +#define GPIO8_IPI2C_SDA PIN_CFG(8, ALT_A) +#define GPIO8_I2C2_SDA PIN_CFG(8, ALT_B) #define GPIO9_GPIO PIN_CFG(9, GPIO) -#define GPIO9_IPI2C_SCL PIN_CFG_INPUT(9, ALT_A, PULLUP) -#define GPIO9_I2C2_SCL PIN_CFG_INPUT(9, ALT_B, PULLUP) +#define GPIO9_IPI2C_SCL PIN_CFG(9, ALT_A) +#define GPIO9_I2C2_SCL PIN_CFG(9, ALT_B) #define GPIO10_GPIO PIN_CFG(10, GPIO) -#define GPIO10_IPI2C_SDA PIN_CFG_INPUT(10, ALT_A, PULLUP) -#define GPIO10_I2C2_SDA PIN_CFG_INPUT(10, ALT_B, PULLUP) +#define GPIO10_IPI2C_SDA PIN_CFG(10, ALT_A) +#define GPIO10_I2C2_SDA PIN_CFG(10, ALT_B) #define GPIO10_IP_GPIO3 PIN_CFG(10, ALT_C) #define GPIO11_GPIO PIN_CFG(11, GPIO) -#define GPIO11_IPI2C_SCL PIN_CFG_INPUT(11, ALT_A, PULLUP) -#define GPIO11_I2C2_SCL PIN_CFG_INPUT(11, ALT_B, PULLUP) +#define GPIO11_IPI2C_SCL PIN_CFG(11, ALT_A) +#define GPIO11_I2C2_SCL PIN_CFG(11, ALT_B) #define GPIO11_IP_GPIO2 PIN_CFG(11, ALT_C) #define GPIO12_GPIO PIN_CFG(12, GPIO) @@ -87,12 +87,12 @@ #define GPIO16_GPIO PIN_CFG(16, GPIO) #define GPIO16_MSP0_RFS PIN_CFG(16, ALT_A) -#define GPIO16_I2C1_SCL PIN_CFG_INPUT(16, ALT_B, PULLUP) +#define GPIO16_I2C1_SCL PIN_CFG(16, ALT_B) #define GPIO16_SLIM0_DAT PIN_CFG(16, ALT_C) #define GPIO17_GPIO PIN_CFG(17, GPIO) #define GPIO17_MSP0_RCK PIN_CFG(17, ALT_A) -#define GPIO17_I2C1_SDA PIN_CFG_INPUT(17, ALT_B, PULLUP) +#define GPIO17_I2C1_SDA PIN_CFG(17, ALT_B) #define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C) #define GPIO18_GPIO PIN_CFG(18, GPIO) @@ -434,10 +434,10 @@ #define GPIO146_SSP0_TXD PIN_CFG(146, ALT_A) #define GPIO147_GPIO PIN_CFG(147, GPIO) -#define GPIO147_I2C0_SCL PIN_CFG_INPUT(147, ALT_A, PULLUP) +#define GPIO147_I2C0_SCL PIN_CFG(147, ALT_A) #define GPIO148_GPIO PIN_CFG(148, GPIO) -#define GPIO148_I2C0_SDA PIN_CFG_INPUT(148, ALT_A, PULLUP) +#define GPIO148_I2C0_SDA PIN_CFG(148, ALT_A) #define GPIO149_GPIO PIN_CFG(149, GPIO) #define GPIO149_IP_GPIO0 PIN_CFG(149, ALT_A) @@ -459,82 +459,82 @@ #define GPIO152_KP_O9 PIN_CFG(152, ALT_C) #define GPIO153_GPIO PIN_CFG(153, GPIO) -#define GPIO153_KP_I7 PIN_CFG_INPUT(153, ALT_A, PULLDOWN) +#define GPIO153_KP_I7 PIN_CFG(153, ALT_A) #define GPIO153_LCD_D24 PIN_CFG(153, ALT_B) #define GPIO153_U2_RXD PIN_CFG(153, ALT_C) #define GPIO154_GPIO PIN_CFG(154, GPIO) -#define GPIO154_KP_I6 PIN_CFG_INPUT(154, ALT_A, PULLDOWN) +#define GPIO154_KP_I6 PIN_CFG(154, ALT_A) #define GPIO154_LCD_D25 PIN_CFG(154, ALT_B) #define GPIO154_U2_TXD PIN_CFG(154, ALT_C) #define GPIO155_GPIO PIN_CFG(155, GPIO) -#define GPIO155_KP_I5 PIN_CFG_INPUT(155, ALT_A, PULLDOWN) +#define GPIO155_KP_I5 PIN_CFG(155, ALT_A) #define GPIO155_LCD_D26 PIN_CFG(155, ALT_B) #define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C) #define GPIO156_GPIO PIN_CFG(156, GPIO) -#define GPIO156_KP_I4 PIN_CFG_INPUT(156, ALT_A, PULLDOWN) +#define GPIO156_KP_I4 PIN_CFG(156, ALT_A) #define GPIO156_LCD_D27 PIN_CFG(156, ALT_B) #define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C) #define GPIO157_GPIO PIN_CFG(157, GPIO) -#define GPIO157_KP_O7 PIN_CFG_INPUT(157, ALT_A, PULLUP) +#define GPIO157_KP_O7 PIN_CFG(157, ALT_A) #define GPIO157_LCD_D28 PIN_CFG(157, ALT_B) #define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C) #define GPIO158_GPIO PIN_CFG(158, GPIO) -#define GPIO158_KP_O6 PIN_CFG_INPUT(158, ALT_A, PULLUP) +#define GPIO158_KP_O6 PIN_CFG(158, ALT_A) #define GPIO158_LCD_D29 PIN_CFG(158, ALT_B) #define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C) #define GPIO159_GPIO PIN_CFG(159, GPIO) -#define GPIO159_KP_O5 PIN_CFG_INPUT(159, ALT_A, PULLUP) +#define GPIO159_KP_O5 PIN_CFG(159, ALT_A) #define GPIO159_LCD_D30 PIN_CFG(159, ALT_B) #define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C) #define GPIO160_GPIO PIN_CFG(160, GPIO) -#define GPIO160_KP_O4 PIN_CFG_INPUT(160, ALT_A, PULLUP) +#define GPIO160_KP_O4 PIN_CFG(160, ALT_A) #define GPIO160_LCD_D31 PIN_CFG(160, ALT_B) #define GPIO160_NONE PIN_CFG(160, ALT_C) #define GPIO161_GPIO PIN_CFG(161, GPIO) -#define GPIO161_KP_I3 PIN_CFG_INPUT(161, ALT_A, PULLDOWN) +#define GPIO161_KP_I3 PIN_CFG(161, ALT_A) #define GPIO161_LCD_D32 PIN_CFG(161, ALT_B) #define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C) #define GPIO162_GPIO PIN_CFG(162, GPIO) -#define GPIO162_KP_I2 PIN_CFG_INPUT(162, ALT_A, PULLDOWN) +#define GPIO162_KP_I2 PIN_CFG(162, ALT_A) #define GPIO162_LCD_D33 PIN_CFG(162, ALT_B) #define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C) #define GPIO163_GPIO PIN_CFG(163, GPIO) -#define GPIO163_KP_I1 PIN_CFG_INPUT(163, ALT_A, PULLDOWN) +#define GPIO163_KP_I1 PIN_CFG(163, ALT_A) #define GPIO163_LCD_D34 PIN_CFG(163, ALT_B) #define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C) #define GPIO164_GPIO PIN_CFG(164, GPIO) -#define GPIO164_KP_I0 PIN_CFG_INPUT(164, ALT_A, PULLUP) +#define GPIO164_KP_I0 PIN_CFG(164, ALT_A) #define GPIO164_LCD_D35 PIN_CFG(164, ALT_B) #define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C) #define GPIO165_GPIO PIN_CFG(165, GPIO) -#define GPIO165_KP_O3 PIN_CFG_INPUT(165, ALT_A, PULLUP) +#define GPIO165_KP_O3 PIN_CFG(165, ALT_A) #define GPIO165_LCD_D36 PIN_CFG(165, ALT_B) #define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C) #define GPIO166_GPIO PIN_CFG(166, GPIO) -#define GPIO166_KP_O2 PIN_CFG_INPUT(166, ALT_A, PULLUP) +#define GPIO166_KP_O2 PIN_CFG(166, ALT_A) #define GPIO166_LCD_D37 PIN_CFG(166, ALT_B) #define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C) #define GPIO167_GPIO PIN_CFG(167, GPIO) -#define GPIO167_KP_O1 PIN_CFG_INPUT(167, ALT_A, PULLUP) +#define GPIO167_KP_O1 PIN_CFG(167, ALT_A) #define GPIO167_LCD_D38 PIN_CFG(167, ALT_B) #define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C) #define GPIO168_GPIO PIN_CFG(168, GPIO) -#define GPIO168_KP_O0 PIN_CFG_INPUT(168, ALT_A, PULLUP) +#define GPIO168_KP_O0 PIN_CFG(168, ALT_A) #define GPIO168_LCD_D39 PIN_CFG(168, ALT_B) #define GPIO168_NONE PIN_CFG(168, ALT_C) @@ -637,7 +637,7 @@ #define GPIO216_GPIO PIN_CFG(216, GPIO) #define GPIO216_MC1_DAT2DIR PIN_CFG(216, ALT_A) #define GPIO216_MC3_CMDDIR PIN_CFG(216, ALT_B) -#define GPIO216_I2C3_SDA PIN_CFG_INPUT(216, ALT_C, PULLUP) +#define GPIO216_I2C3_SDA PIN_CFG(216, ALT_C) #define GPIO216_SPI2_FRM PIN_CFG(216, ALT_C) #define GPIO217_GPIO PIN_CFG(217, GPIO) @@ -649,7 +649,7 @@ #define GPIO218_GPIO PIN_CFG(218, GPIO) #define GPIO218_MC1_DAT31DIR PIN_CFG(218, ALT_A) #define GPIO218_MC3_DAT0DIR PIN_CFG(218, ALT_B) -#define GPIO218_I2C3_SCL PIN_CFG_INPUT(218, ALT_C, PULLUP) +#define GPIO218_I2C3_SCL PIN_CFG(218, ALT_C) #define GPIO218_SPI2_RXD PIN_CFG(218, ALT_C) #define GPIO219_GPIO PIN_CFG(219, GPIO) @@ -698,12 +698,12 @@ #define GPIO229_GPIO PIN_CFG(229, GPIO) #define GPIO229_CLKOUT1 PIN_CFG(229, ALT_A) #define GPIO229_PWL PIN_CFG(229, ALT_B) -#define GPIO229_I2C3_SDA PIN_CFG_INPUT(229, ALT_C, PULLUP) +#define GPIO229_I2C3_SDA PIN_CFG(229, ALT_C) #define GPIO230_GPIO PIN_CFG(230, GPIO) #define GPIO230_CLKOUT2 PIN_CFG(230, ALT_A) #define GPIO230_PWL PIN_CFG(230, ALT_B) -#define GPIO230_I2C3_SCL PIN_CFG_INPUT(230, ALT_C, PULLUP) +#define GPIO230_I2C3_SCL PIN_CFG(230, ALT_C) #define GPIO256_GPIO PIN_CFG(256, GPIO) #define GPIO256_USB_NXT PIN_CFG(256, ALT_A) diff --git a/arch/arm/mach-ux500/pins.c b/arch/arm/mach-ux500/pins.c new file mode 100644 index 00000000000..ed2ed7333ff --- /dev/null +++ b/arch/arm/mach-ux500/pins.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/err.h> +#include <plat/pincfg.h> +#include <linux/gpio.h> + +#include "pins.h" + +static LIST_HEAD(pin_lookups); +static DEFINE_MUTEX(pin_lookups_mutex); +static DEFINE_SPINLOCK(pins_lock); + +void __init ux500_pins_add(struct ux500_pin_lookup *pl, size_t num) +{ + mutex_lock(&pin_lookups_mutex); + + while (num--) { + list_add_tail(&pl->node, &pin_lookups); + pl++; + } + + mutex_unlock(&pin_lookups_mutex); +} + +struct ux500_pins *ux500_pins_get(const char *name) +{ + struct ux500_pins *pins = NULL; + struct ux500_pin_lookup *pl; + + mutex_lock(&pin_lookups_mutex); + + list_for_each_entry(pl, &pin_lookups, node) { + if (!strcmp(pl->name, name)) { + pins = pl->pins; + goto out; + } + } + +out: + mutex_unlock(&pin_lookups_mutex); + return pins; +} + +int ux500_pins_enable(struct ux500_pins *pins) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&pins_lock, flags); + + if (pins->usage++ == 0) + ret = nmk_config_pins(pins->cfg, pins->num); + + spin_unlock_irqrestore(&pins_lock, flags); + return ret; +} + +int ux500_pins_disable(struct ux500_pins *pins) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&pins_lock, flags); + + if (WARN_ON(pins->usage == 0)) + goto out; + + if (--pins->usage == 0) + ret = nmk_config_pins_sleep(pins->cfg, pins->num); + +out: + spin_unlock_irqrestore(&pins_lock, flags); + return ret; +} + +void ux500_pins_put(struct ux500_pins *pins) +{ + WARN_ON(!pins); +} + +void __init ux500_offchip_gpio_init(struct ux500_pins *pins) +{ + int err; + int i; + int gpio; + int output; + int value; + pin_cfg_t cfg; + + for (i = 0; i < pins->num; i++) { + cfg = pins->cfg[i]; + gpio = PIN_NUM(cfg); + output = PIN_DIR(cfg); + value = PIN_VAL(cfg); + + err = gpio_request(gpio, "offchip_gpio_init"); + if (err < 0) { + pr_err("pins: gpio_request for gpio=%d failed with" + "err: %d\n", gpio, err); + /* Pin already requested. Try to configure rest. */ + continue; + } + + if (!output) { + err = gpio_direction_input(gpio); + if (err < 0) + pr_err("pins: gpio_direction_input for gpio=%d" + "failed with err: %d\n", gpio, err); + } else { + err = gpio_direction_output(gpio, value); + if (err < 0) + pr_err("pins: gpio_direction_output for gpio=" + "%d failed with err: %d\n", gpio, err); + } + gpio_free(gpio); + } +} + +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <linux/gpio/nomadik.h> + +#include <mach/gpio.h> + +static void show_pin(struct seq_file *s, pin_cfg_t pin) +{ + static char *afnames[] = { + [NMK_GPIO_ALT_GPIO] = "GPIO", + [NMK_GPIO_ALT_A] = "A", + [NMK_GPIO_ALT_B] = "B", + [NMK_GPIO_ALT_C] = "C" + }; + static char *pullnames[] = { + [NMK_GPIO_PULL_NONE] = "none", + [NMK_GPIO_PULL_UP] = "up", + [NMK_GPIO_PULL_DOWN] = "down", + [3] /* illegal */ = "??" + }; + + int pin_num = PIN_NUM(pin); + int pull = PIN_PULL(pin); + int af = PIN_ALT(pin); + int slpm = PIN_SLPM(pin); + int output = PIN_DIR(pin); + int val = PIN_VAL(pin); + int slpm_pull = PIN_SLPM_PULL(pin); + int slpm_dir = PIN_SLPM_DIR(pin); + int slpm_val = PIN_SLPM_VAL(pin); + + seq_printf(s, + " pin %d [%#lx]: af %s, pull %s (%s%s) - slpm: %s%s%s%s\n", + pin_num, pin, afnames[af], + pullnames[pull], + output ? "output " : "input", + output ? (val ? "high" : "low") : "", + slpm ? "no-change/no-wakeup " : "input/wakeup ", + slpm_dir ? (slpm_dir == 1 ? "input " : "output ") : "", + slpm_dir == 1 ? (slpm_pull == 0 ? "pull: none " : + (slpm_pull == NMK_GPIO_PULL_UP ? + "pull: up " : "pull: down ") ): "", + slpm_dir == 2 ? (slpm_val == 1 ? "low " : "high ") : ""); +} + +static int pins_dbg_show(struct seq_file *s, void *iter) +{ + struct ux500_pin_lookup *pl; + int i; + bool *pins; + int prev = -2; + int first = 0; + + pins = kzalloc(sizeof(bool) * NOMADIK_NR_GPIO, GFP_KERNEL); + + mutex_lock(&pin_lookups_mutex); + + list_for_each_entry(pl, &pin_lookups, node) { + seq_printf(s, "\n%s (%d) usage: %d\n", + pl->name, pl->pins->num, pl->pins->usage); + for (i = 0; i < pl->pins->num; i++) { + show_pin(s, pl->pins->cfg[i]); + pins[PIN_NUM(pl->pins->cfg[i])] = true; + } + } + mutex_unlock(&pin_lookups_mutex); + + seq_printf(s, "\nSummary allocated pins:\n"); + for (i = 0; i < NOMADIK_NR_GPIO; i++) { + if (prev == i - 1) { + if (pins[i]) + prev = i; + else + if (prev > 0) { + if (first != prev) + seq_printf(s, "-%d, ", prev); + else + seq_printf(s, ", "); + } + continue; + } + if (pins[i]) { + seq_printf(s, "%d", i); + prev = i; + first = i; + } + } + if (prev == i - 1 && first != prev) + seq_printf(s, "-%d", prev); + + seq_printf(s, "\n"); + + kfree(pins); + + return 0; +} + +static int pins_dbg_open(struct inode *inode, + struct file *file) +{ + return single_open(file, pins_dbg_show, inode->i_private); +} + +static const struct file_operations pins_fops = { + .open = pins_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int __init pins_dbg_init(void) +{ + (void) debugfs_create_file("pins", S_IRUGO, + NULL, + NULL, + &pins_fops); + return 0; +} +late_initcall(pins_dbg_init); +#endif diff --git a/arch/arm/mach-ux500/pins.h b/arch/arm/mach-ux500/pins.h new file mode 100644 index 00000000000..0d36af2e7d9 --- /dev/null +++ b/arch/arm/mach-ux500/pins.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef __MACH_UX500_PINS_H +#define __MACH_UX500_PINS_H + +#include <linux/list.h> +#include <plat/pincfg.h> + +#define PIN_LOOKUP(_name, _pins) \ +{ \ + .name = _name, \ + .pins = _pins, \ +} + +#define UX500_PINS(name, pins...) \ +struct ux500_pins name = { \ + .cfg = (pin_cfg_t[]) {pins}, \ + .num = ARRAY_SIZE(((pin_cfg_t[]) {pins})), \ +} + +struct ux500_pins { + int usage; + int num; + pin_cfg_t *cfg; +}; + +struct ux500_pin_lookup { + struct list_head node; + const char *name; + struct ux500_pins *pins; +}; + +void __init ux500_pins_add(struct ux500_pin_lookup *pl, size_t num); +void __init ux500_offchip_gpio_init(struct ux500_pins *pins); +struct ux500_pins *ux500_pins_get(const char *name); +int ux500_pins_enable(struct ux500_pins *pins); +int ux500_pins_disable(struct ux500_pins *pins); +void ux500_pins_put(struct ux500_pins *pins); +int pins_for_u9500(void); + +#endif diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index eff5842f623..dc661de8bca 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -50,7 +50,7 @@ static void __iomem *scu_base_addr(void) { if (cpu_is_u5500()) return __io_address(U5500_SCU_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500() || cpu_is_u9540()) return __io_address(U8500_SCU_BASE); else ux500_unknown_soc(); @@ -122,7 +122,7 @@ static void __init wakeup_secondary(void) if (cpu_is_u5500()) backupram = __io_address(U5500_BACKUPRAM0_BASE); - else if (cpu_is_u8500()) + else if (cpu_is_u8500() || cpu_is_u9540()) backupram = __io_address(U8500_BACKUPRAM0_BASE); else ux500_unknown_soc(); diff --git a/arch/arm/mach-ux500/pm/Kconfig b/arch/arm/mach-ux500/pm/Kconfig new file mode 100644 index 00000000000..12004ba9858 --- /dev/null +++ b/arch/arm/mach-ux500/pm/Kconfig @@ -0,0 +1,70 @@ +config DBX500_PRCMU_QOS_POWER + bool "DBX500 PRCMU power QoS support" + depends on (MFD_DB5500_PRCMU || MFD_DB8500_PRCMU) + default y + help + Add support for PRCMU power Quality of Service + +config UX500_CONTEXT + bool "Context save/restore support for UX500" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && PM + help + This is needed for ApSleep and deeper sleep states. + +config UX500_PM_PERFORMANCE + bool "Performance supervision" + depends on DBX500_PRCMU_QOS_POWER + default y + help + Enable supervision of events which may require a boost + of platform performance. + +config UX500_CONSOLE_UART_GPIO_PIN + int "The pin number of the console UART GPIO pin" + default 29 + depends on UX500_SUSPEND_DBG_WAKE_ON_UART || UX500_CPUIDLE_DEBUG + help + GPIO pin number of the GPIO pin connected to the console UART RX line. + + Board-specific code can change this. + +config UX500_SUSPEND + bool "Suspend to mem and standby support" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && PM && SUSPEND + select UX500_CONTEXT + help + Add support for suspend. + +config UX500_SUSPEND_STANDBY + bool "Suspend Standby goes to ApSleep" + depends on UX500_SUSPEND + help + If yes, echo standby > /sys/power/state puts the system into ApSleep. + +config UX500_SUSPEND_MEM + bool "Suspend Mem goes to ApDeepSleep" + depends on UX500_SUSPEND + help + If yes, echo mem > /sys/power/state puts the system into ApDeepSleep else + it will do the same as echo standby > /sys/power/state. + +config UX500_SUSPEND_DBG + bool "Suspend debug" + depends on UX500_SUSPEND && DEBUG_FS + help + Add debug support for suspend. + +config UX500_SUSPEND_DBG_WAKE_ON_UART + bool "Suspend wakes on console UART" + depends on UX500_SUSPEND_DBG + help + Wake up on uart interrupts. Makes it possible for the console to wake up system. + +config UX500_USECASE_GOVERNOR + bool "UX500 use-case governor" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && \ + (CPU_FREQ && CPU_IDLE && HOTPLUG_CPU && \ + EARLYSUSPEND && UX500_L2X0_PREFETCH_CTRL && PM) + default y + help + Adjusts CPU_IDLE, CPU_FREQ, HOTPLUG_CPU and L2 cache parameters diff --git a/arch/arm/mach-ux500/pm/Makefile b/arch/arm/mach-ux500/pm/Makefile new file mode 100644 index 00000000000..ef33bdf0d4e --- /dev/null +++ b/arch/arm/mach-ux500/pm/Makefile @@ -0,0 +1,12 @@ +# +# Power save related files +# +obj-y := pm.o runtime.o + +obj-$(CONFIG_DBX500_PRCMU_QOS_POWER) += prcmu-qos-power.o +obj-$(CONFIG_UX500_CONTEXT) += context.o context_arm.o context-db8500.o context-db5500.o context-db9540.o +obj-$(CONFIG_UX500_CPUIDLE) += timer.o +obj-$(CONFIG_UX500_SUSPEND) += suspend.o +obj-$(CONFIG_UX500_SUSPEND_DBG) += suspend_dbg.o +obj-$(CONFIG_UX500_PM_PERFORMANCE) += performance.o +obj-$(CONFIG_UX500_USECASE_GOVERNOR) += usecase_gov.o diff --git a/arch/arm/mach-ux500/pm/context-db5500.c b/arch/arm/mach-ux500/pm/context-db5500.c new file mode 100644 index 00000000000..9842785c05a --- /dev/null +++ b/arch/arm/mach-ux500/pm/context-db5500.c @@ -0,0 +1,407 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>, + * Rickard Andersson <rickard.andersson@stericsson.com>, + * Sundar Iyer <sundar.iyer@stericsson.com>, + * ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + * + */ + +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/context.h> + +/* These registers are DB5500 specific */ +#define NODE_HIBW1_ESRAM_IN_0_PRIORITY 0x0 +#define NODE_HIBW1_ESRAM_IN_1_PRIORITY 0x4 + +#define NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT 0x18 +#define NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT 0x1C +#define NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT 0x20 + +#define NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT 0x24 +#define NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT 0x28 +#define NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT 0x2C + +#define NODE_HIBW1_DDR_IN_0_PRIORITY 0x400 +#define NODE_HIBW1_DDR_IN_1_PRIORITY 0x404 +#define NODE_HIBW1_DDR_IN_2_PRIORITY 0x408 + +#define NODE_HIBW1_DDR_IN_0_LIMIT 0x424 +#define NODE_HIBW1_DDR_IN_1_LIMIT 0x428 +#define NODE_HIBW1_DDR_IN_2_LIMIT 0x42C + +#define NODE_HIBW1_DDR_OUT_0_PRIORITY 0x430 + +#define NODE_HIBW2_ESRAM_IN_0_PRIORITY 0x800 +#define NODE_HIBW2_ESRAM_IN_1_PRIORITY 0x804 + +#define NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT 0x818 +#define NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT 0x81C +#define NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT 0x820 + +#define NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT 0x824 +#define NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT 0x828 +#define NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT 0x82C + +#define NODE_HIBW2_DDR_IN_0_PRIORITY 0xC00 +#define NODE_HIBW2_DDR_IN_1_PRIORITY 0xC04 +#define NODE_HIBW2_DDR_IN_2_PRIORITY 0xC08 +#define NODE_HIBW2_DDR_IN_3_PRIORITY 0xC0C + +#define NODE_HIBW2_DDR_IN_0_LIMIT 0xC30 +#define NODE_HIBW2_DDR_IN_1_LIMIT 0xC34 +#define NODE_HIBW2_DDR_IN_2_LIMIT 0xC38 +#define NODE_HIBW2_DDR_IN_3_LIMIT 0xC3C + +#define NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC40 + +#define NODE_ESRAM0_IN_0_PRIORITY 0x1000 +#define NODE_ESRAM0_IN_1_PRIORITY 0x1004 +#define NODE_ESRAM0_IN_2_PRIORITY 0x1008 + +#define NODE_ESRAM0_IN_0_LIMIT 0x1024 +#define NODE_ESRAM0_IN_1_LIMIT 0x1028 +#define NODE_ESRAM0_IN_2_LIMIT 0x102C +#define NODE_ESRAM0_OUT_0_PRIORITY 0x1030 + +#define NODE_ESRAM1_2_IN_0_PRIORITY 0x1400 +#define NODE_ESRAM1_2_IN_1_PRIORITY 0x1404 +#define NODE_ESRAM1_2_IN_2_PRIORITY 0x1408 + +#define NODE_ESRAM1_2_IN_0_ARB_1_LIMIT 0x1424 +#define NODE_ESRAM1_2_IN_1_ARB_1_LIMIT 0x1428 +#define NODE_ESRAM1_2_IN_2_ARB_1_LIMIT 0x142C +#define NODE_ESRAM1_2_OUT_0_PRIORITY 0x1430 + +#define NODE_ESRAM3_4_IN_0_PRIORITY 0x1800 +#define NODE_ESRAM3_4_IN_1_PRIORITY 0x1804 +#define NODE_ESRAM3_4_IN_2_PRIORITY 0x1808 + +#define NODE_ESRAM3_4_IN_0_ARB_1_LIMIT 0x1824 +#define NODE_ESRAM3_4_IN_1_ARB_1_LIMIT 0x1828 +#define NODE_ESRAM3_4_IN_2_ARB_1_LIMIT 0x182C +#define NODE_ESRAM3_4_OUT_0_PRIORITY 0x1830 + +/* + * Save ICN (Interconnect or Interconnect nodes) configuration registers + * TODO: This can be optimized, for example if we have + * a static ICN configuration. + */ + +static struct { + void __iomem *base; + u32 hibw1_esram_in_pri[2]; + u32 hibw1_esram_in0_arb[3]; + u32 hibw1_esram_in1_arb[3]; + u32 hibw1_ddr_in_prio[3]; + u32 hibw1_ddr_in_limit[3]; + u32 hibw1_ddr_out_prio_reg; + + /* HiBw2 node registers */ + u32 hibw2_esram_in_pri[2]; + u32 hibw2_esram_in0_arblimit[3]; + u32 hibw2_esram_in1_arblimit[3]; + u32 hibw2_ddr_in_prio[4]; + u32 hibw2_ddr_in_limit[4]; + u32 hibw2_ddr_out_prio_reg; + + /* ESRAM node registers */ + u32 esram_in_prio[3]; + u32 esram_in_lim[3]; + u32 esram_out_prio_reg; + + u32 esram12_in_prio[3]; + u32 esram12_in_arb_lim[3]; + u32 esram12_out_prio_reg; + + u32 esram34_in_prio[3]; + u32 esram34_in_arb_lim[3]; + u32 esram34_out_prio; +} context_icn; + + +void u5500_context_save_icn(void) +{ + void __iomem *base = context_icn.base; + + /* hibw1 */ + context_icn.hibw1_esram_in_pri[0] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_0_PRIORITY); + context_icn.hibw1_esram_in_pri[1] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_1_PRIORITY); + + context_icn.hibw1_esram_in0_arb[0] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); + context_icn.hibw1_esram_in0_arb[1] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); + context_icn.hibw1_esram_in0_arb[2] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); + + context_icn.hibw1_esram_in1_arb[0] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); + context_icn.hibw1_esram_in1_arb[1] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); + context_icn.hibw1_esram_in1_arb[2] = + readl_relaxed(base + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); + + context_icn.hibw1_ddr_in_prio[0] = + readl_relaxed(base + NODE_HIBW1_DDR_IN_0_PRIORITY); + context_icn.hibw1_ddr_in_prio[1] = + readl_relaxed(base + NODE_HIBW1_DDR_IN_1_PRIORITY); + context_icn.hibw1_ddr_in_prio[2] = + readl_relaxed(base + NODE_HIBW1_DDR_IN_2_PRIORITY); + + context_icn.hibw1_ddr_in_limit[0] = + readl_relaxed(base + NODE_HIBW1_DDR_IN_0_LIMIT); + context_icn.hibw1_ddr_in_limit[1] = + readl_relaxed(base + NODE_HIBW1_DDR_IN_1_LIMIT); + context_icn.hibw1_ddr_in_limit[2] = + readl_relaxed(base + NODE_HIBW1_DDR_IN_2_LIMIT); + + context_icn.hibw1_ddr_out_prio_reg = + readl_relaxed(base + NODE_HIBW1_DDR_OUT_0_PRIORITY); + + /* hibw2 */ + context_icn.hibw2_esram_in_pri[0] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_0_PRIORITY); + context_icn.hibw2_esram_in_pri[1] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_1_PRIORITY); + + context_icn.hibw2_esram_in0_arblimit[0] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); + context_icn.hibw2_esram_in0_arblimit[1] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); + context_icn.hibw2_esram_in0_arblimit[2] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); + + context_icn.hibw2_esram_in1_arblimit[0] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); + context_icn.hibw2_esram_in1_arblimit[1] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); + context_icn.hibw2_esram_in1_arblimit[2] = + readl_relaxed(base + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); + + context_icn.hibw2_ddr_in_prio[0] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_0_PRIORITY); + context_icn.hibw2_ddr_in_prio[1] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_1_PRIORITY); + context_icn.hibw2_ddr_in_prio[2] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_2_PRIORITY); + context_icn.hibw2_ddr_in_prio[3] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_3_PRIORITY); + + context_icn.hibw2_ddr_in_limit[0] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_0_LIMIT); + context_icn.hibw2_ddr_in_limit[1] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_1_LIMIT); + context_icn.hibw2_ddr_in_limit[2] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_2_LIMIT); + context_icn.hibw2_ddr_in_limit[3] = + readl_relaxed(base + NODE_HIBW2_DDR_IN_3_LIMIT); + + context_icn.hibw2_ddr_out_prio_reg = + readl_relaxed(base + NODE_HIBW2_DDR_OUT_0_PRIORITY); + + /* ESRAM0 */ + context_icn.esram_in_prio[0] = + readl_relaxed(base + NODE_ESRAM0_IN_0_PRIORITY); + context_icn.esram_in_prio[1] = + readl_relaxed(base + NODE_ESRAM0_IN_1_PRIORITY); + context_icn.esram_in_prio[2] = + readl_relaxed(base + NODE_ESRAM0_IN_2_PRIORITY); + + context_icn.esram_in_lim[0] = + readl_relaxed(base + NODE_ESRAM0_IN_0_LIMIT); + context_icn.esram_in_lim[1] = + readl_relaxed(base + NODE_ESRAM0_IN_1_LIMIT); + context_icn.esram_in_lim[2] = + readl_relaxed(base + NODE_ESRAM0_IN_2_LIMIT); + + context_icn.esram_out_prio_reg = + readl_relaxed(base + NODE_ESRAM0_OUT_0_PRIORITY); + + /* ESRAM1-2 */ + context_icn.esram12_in_prio[0] = + readl_relaxed(base + NODE_ESRAM1_2_IN_0_PRIORITY); + context_icn.esram12_in_prio[1] = + readl_relaxed(base + NODE_ESRAM1_2_IN_1_PRIORITY); + context_icn.esram12_in_prio[2] = + readl_relaxed(base + NODE_ESRAM1_2_IN_2_PRIORITY); + + context_icn.esram12_in_arb_lim[0] = + readl_relaxed(base + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[1] = + readl_relaxed(base + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[2] = + readl_relaxed(base + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); + + context_icn.esram12_out_prio_reg = + readl_relaxed(base + NODE_ESRAM1_2_OUT_0_PRIORITY); + + /* ESRAM3-4 */ + context_icn.esram34_in_prio[0] = + readl_relaxed(base + NODE_ESRAM3_4_IN_0_PRIORITY); + context_icn.esram34_in_prio[1] = + readl_relaxed(base + NODE_ESRAM3_4_IN_1_PRIORITY); + context_icn.esram34_in_prio[2] = + readl_relaxed(base + NODE_ESRAM3_4_IN_2_PRIORITY); + + context_icn.esram34_in_arb_lim[0] = + readl_relaxed(base + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[1] = + readl_relaxed(base + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[2] = + readl_relaxed(base + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); + + context_icn.esram34_out_prio = + readl_relaxed(base + NODE_ESRAM3_4_OUT_0_PRIORITY); +} + +/* + * Restore ICN configuration registers + */ +void u5500_context_restore_icn(void) +{ + void __iomem *base = context_icn.base; + + /* hibw1 */ + writel_relaxed(context_icn.hibw1_esram_in_pri[0], + base + NODE_HIBW1_ESRAM_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw1_esram_in_pri[1], + base + NODE_HIBW1_ESRAM_IN_1_PRIORITY); + + writel_relaxed(context_icn.hibw1_esram_in0_arb[0], + base + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in0_arb[1], + base + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in0_arb[2], + base + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_esram_in1_arb[0], + base + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in1_arb[1], + base + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in1_arb[2], + base + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_ddr_in_prio[0], + base + NODE_HIBW1_DDR_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr_in_prio[1], + base + NODE_HIBW1_DDR_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr_in_prio[2], + base + NODE_HIBW1_DDR_IN_2_PRIORITY); + + writel_relaxed(context_icn.hibw1_ddr_in_limit[0], + base + NODE_HIBW1_DDR_IN_0_LIMIT); + writel_relaxed(context_icn.hibw1_ddr_in_limit[1], + base + NODE_HIBW1_DDR_IN_1_LIMIT); + writel_relaxed(context_icn.hibw1_ddr_in_limit[2], + base + NODE_HIBW1_DDR_IN_2_LIMIT); + + writel_relaxed(context_icn.hibw1_ddr_out_prio_reg, + base + NODE_HIBW1_DDR_OUT_0_PRIORITY); + + /* hibw2 */ + writel_relaxed(context_icn.hibw2_esram_in_pri[0], + base + NODE_HIBW2_ESRAM_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw2_esram_in_pri[1], + base + NODE_HIBW2_ESRAM_IN_1_PRIORITY); + + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[0], + base + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[1], + base + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[2], + base + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[0], + base + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[1], + base + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[2], + base + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw2_ddr_in_prio[0], + base + NODE_HIBW2_DDR_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr_in_prio[1], + base + NODE_HIBW2_DDR_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr_in_prio[2], + base + NODE_HIBW2_DDR_IN_2_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr_in_prio[3], + base + NODE_HIBW2_DDR_IN_3_PRIORITY); + + writel_relaxed(context_icn.hibw2_ddr_in_limit[0], + base + NODE_HIBW2_DDR_IN_0_LIMIT); + writel_relaxed(context_icn.hibw2_ddr_in_limit[1], + base + NODE_HIBW2_DDR_IN_1_LIMIT); + writel_relaxed(context_icn.hibw2_ddr_in_limit[2], + base + NODE_HIBW2_DDR_IN_2_LIMIT); + writel_relaxed(context_icn.hibw2_ddr_in_limit[3], + base + NODE_HIBW2_DDR_IN_3_LIMIT); + + writel_relaxed(context_icn.hibw2_ddr_out_prio_reg, + base + NODE_HIBW2_DDR_OUT_0_PRIORITY); + + /* ESRAM0 */ + writel_relaxed(context_icn.esram_in_prio[0], + base + NODE_ESRAM0_IN_0_PRIORITY); + writel_relaxed(context_icn.esram_in_prio[1], + base + NODE_ESRAM0_IN_1_PRIORITY); + writel_relaxed(context_icn.esram_in_prio[2], + base + NODE_ESRAM0_IN_2_PRIORITY); + + writel_relaxed(context_icn.esram_in_lim[0], + base + NODE_ESRAM0_IN_0_LIMIT); + writel_relaxed(context_icn.esram_in_lim[1], + base + NODE_ESRAM0_IN_1_LIMIT); + writel_relaxed(context_icn.esram_in_lim[2], + base + NODE_ESRAM0_IN_2_LIMIT); + + writel_relaxed(context_icn.esram_out_prio_reg, + base + NODE_ESRAM0_OUT_0_PRIORITY); + + /* ESRAM1-2 */ + writel_relaxed(context_icn.esram12_in_prio[0], + base + NODE_ESRAM1_2_IN_0_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[1], + base + NODE_ESRAM1_2_IN_1_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[2], + base + NODE_ESRAM1_2_IN_2_PRIORITY); + + writel_relaxed(context_icn.esram12_in_arb_lim[0], + base + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[1], + base + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[2], + base + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); + + writel_relaxed(context_icn.esram12_out_prio_reg, + base + NODE_ESRAM1_2_OUT_0_PRIORITY); + + /* ESRAM3-4 */ + writel_relaxed(context_icn.esram34_in_prio[0], + base + NODE_ESRAM3_4_IN_0_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[1], + base + NODE_ESRAM3_4_IN_1_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[2], + base + NODE_ESRAM3_4_IN_2_PRIORITY); + + writel_relaxed(context_icn.esram34_in_arb_lim[0], + base + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[1], + base + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[2], + base + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); + + writel_relaxed(context_icn.esram34_out_prio, + base + NODE_ESRAM3_4_OUT_0_PRIORITY); + +} + +void u5500_context_init(void) +{ + context_icn.base = ioremap(U5500_ICN_BASE, SZ_8K); +} diff --git a/arch/arm/mach-ux500/pm/context-db8500.c b/arch/arm/mach-ux500/pm/context-db8500.c new file mode 100644 index 00000000000..3ba73e51a6d --- /dev/null +++ b/arch/arm/mach-ux500/pm/context-db8500.c @@ -0,0 +1,456 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * License Terms: GNU General Public License v2 + * Author: Sundar Iyer for ST-Ericsson + * + */ + +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/context.h> + +/* + * ST-Interconnect context + */ + +/* priority, bw limiter register offsets */ +#define NODE_HIBW1_ESRAM_IN_0_PRIORITY 0x00 +#define NODE_HIBW1_ESRAM_IN_1_PRIORITY 0x04 +#define NODE_HIBW1_ESRAM_IN_2_PRIORITY 0x08 +#define NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT 0x24 +#define NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT 0x28 +#define NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT 0x2C +#define NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT 0x30 +#define NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT 0x34 +#define NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT 0x38 +#define NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT 0x3C +#define NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT 0x40 +#define NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT 0x44 +#define NODE_HIBW1_DDR_IN_0_PRIORITY 0x400 +#define NODE_HIBW1_DDR_IN_1_PRIORITY 0x404 +#define NODE_HIBW1_DDR_IN_2_PRIORITY 0x408 +#define NODE_HIBW1_DDR_IN_0_LIMIT 0x424 +#define NODE_HIBW1_DDR_IN_1_LIMIT 0x428 +#define NODE_HIBW1_DDR_IN_2_LIMIT 0x42C +#define NODE_HIBW1_DDR_OUT_0_PRIORITY 0x430 +#define NODE_HIBW2_ESRAM_IN_0_PRIORITY 0x800 +#define NODE_HIBW2_ESRAM_IN_1_PRIORITY 0x804 +#define NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT 0x818 +#define NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT 0x81C +#define NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT 0x820 +#define NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT 0x824 +#define NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT 0x828 +#define NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT 0x82C +#define NODE_HIBW2_DDR_IN_0_PRIORITY 0xC00 +#define NODE_HIBW2_DDR_IN_1_PRIORITY 0xC04 +#define NODE_HIBW2_DDR_IN_2_PRIORITY 0xC08 + +#define NODE_HIBW2_DDR_IN_0_LIMIT 0xC24 +#define NODE_HIBW2_DDR_IN_1_LIMIT 0xC28 +#define NODE_HIBW2_DDR_IN_2_LIMIT 0xC2C +#define NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC30 + +/* + * Note the following addresses are presented in + * db8500 design spec v3.1 and v3.3, table 10. + * But their addresses are not the same as in the + * description. The addresses in the description + * of each registers are correct. + * NODE_HIBW2_DDR_IN_3_LIMIT is only present in v1. + * + * Faulty registers addresses in table 10: + * NODE_HIBW2_DDR_IN_2_LIMIT 0xC38 + * NODE_HIBW2_DDR_IN_3_LIMIT 0xC3C + * NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC40 + */ + +#define NODE_ESRAM0_IN_0_PRIORITY 0x1000 +#define NODE_ESRAM0_IN_1_PRIORITY 0x1004 +#define NODE_ESRAM0_IN_2_PRIORITY 0x1008 +#define NODE_ESRAM0_IN_3_PRIORITY 0x100C +#define NODE_ESRAM0_IN_0_LIMIT 0x1030 +#define NODE_ESRAM0_IN_1_LIMIT 0x1034 +#define NODE_ESRAM0_IN_2_LIMIT 0x1038 +#define NODE_ESRAM0_IN_3_LIMIT 0x103C +/* common */ +#define NODE_ESRAM1_2_IN_0_PRIORITY 0x1400 +#define NODE_ESRAM1_2_IN_1_PRIORITY 0x1404 +#define NODE_ESRAM1_2_IN_2_PRIORITY 0x1408 +#define NODE_ESRAM1_2_IN_3_PRIORITY 0x140C +#define NODE_ESRAM1_2_IN_0_ARB_1_LIMIT 0x1430 +#define NODE_ESRAM1_2_IN_0_ARB_2_LIMIT 0x1434 +#define NODE_ESRAM1_2_IN_1_ARB_1_LIMIT 0x1438 +#define NODE_ESRAM1_2_IN_1_ARB_2_LIMIT 0x143C +#define NODE_ESRAM1_2_IN_2_ARB_1_LIMIT 0x1440 +#define NODE_ESRAM1_2_IN_2_ARB_2_LIMIT 0x1444 +#define NODE_ESRAM1_2_IN_3_ARB_1_LIMIT 0x1448 +#define NODE_ESRAM1_2_IN_3_ARB_2_LIMIT 0x144C + +#define NODE_ESRAM3_4_IN_0_PRIORITY 0x1800 +#define NODE_ESRAM3_4_IN_1_PRIORITY 0x1804 +#define NODE_ESRAM3_4_IN_2_PRIORITY 0x1808 +#define NODE_ESRAM3_4_IN_3_PRIORITY 0x180C +#define NODE_ESRAM3_4_IN_0_ARB_1_LIMIT 0x1830 +#define NODE_ESRAM3_4_IN_0_ARB_2_LIMIT 0x1834 +#define NODE_ESRAM3_4_IN_1_ARB_1_LIMIT 0x1838 +#define NODE_ESRAM3_4_IN_1_ARB_2_LIMIT 0x183C +#define NODE_ESRAM3_4_IN_2_ARB_1_LIMIT 0x1840 +#define NODE_ESRAM3_4_IN_2_ARB_2_LIMIT 0x1844 +#define NODE_ESRAM3_4_IN_3_ARB_1_LIMIT 0x1848 +#define NODE_ESRAM3_4_IN_3_ARB_2_LIMIT 0x184C + +static struct { + void __iomem *base; + u32 hibw1_esram_in_pri[3]; + u32 hibw1_esram_in0_arb[3]; + u32 hibw1_esram_in1_arb[3]; + u32 hibw1_esram_in2_arb[3]; + u32 hibw1_ddr_in_prio[3]; + u32 hibw1_ddr_in_limit[3]; + u32 hibw1_ddr_out_prio; + + /* HiBw2 node registers */ + u32 hibw2_esram_in_pri[2]; + u32 hibw2_esram_in0_arblimit[3]; + u32 hibw2_esram_in1_arblimit[3]; + u32 hibw2_ddr_in_prio[4]; + u32 hibw2_ddr_in_limit[4]; + u32 hibw2_ddr_out_prio; + + /* ESRAM node registers */ + u32 esram_in_prio[4]; + u32 esram_in_lim[4]; + u32 esram0_in_prio[4]; + u32 esram0_in_lim[4]; + u32 esram12_in_prio[4]; + u32 esram12_in_arb_lim[8]; + u32 esram34_in_prio[4]; + u32 esram34_in_arb_lim[8]; +} context_icn; + +/** + * u8500_context_save_icn() - save ICN context + * + */ +void u8500_context_save_icn(void) +{ + void __iomem *b = context_icn.base; + + context_icn.hibw1_esram_in_pri[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_PRIORITY); + context_icn.hibw1_esram_in_pri[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_PRIORITY); + context_icn.hibw1_esram_in_pri[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_PRIORITY); + + context_icn.hibw1_esram_in0_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); + context_icn.hibw1_esram_in0_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); + context_icn.hibw1_esram_in0_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); + + context_icn.hibw1_esram_in1_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); + context_icn.hibw1_esram_in1_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); + context_icn.hibw1_esram_in1_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); + + context_icn.hibw1_esram_in2_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT); + context_icn.hibw1_esram_in2_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT); + context_icn.hibw1_esram_in2_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT); + + context_icn.hibw1_ddr_in_prio[0] = + readl_relaxed(b + NODE_HIBW1_DDR_IN_0_PRIORITY); + context_icn.hibw1_ddr_in_prio[1] = + readl_relaxed(b + NODE_HIBW1_DDR_IN_1_PRIORITY); + context_icn.hibw1_ddr_in_prio[2] = + readl_relaxed(b + NODE_HIBW1_DDR_IN_2_PRIORITY); + + context_icn.hibw1_ddr_in_limit[0] = + readl_relaxed(b + NODE_HIBW1_DDR_IN_0_LIMIT); + context_icn.hibw1_ddr_in_limit[1] = + readl_relaxed(b + NODE_HIBW1_DDR_IN_1_LIMIT); + context_icn.hibw1_ddr_in_limit[2] = + readl_relaxed(b + NODE_HIBW1_DDR_IN_2_LIMIT); + + context_icn.hibw1_ddr_out_prio = + readl_relaxed(b + NODE_HIBW1_DDR_OUT_0_PRIORITY); + + context_icn.hibw2_esram_in_pri[0] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_PRIORITY); + context_icn.hibw2_esram_in_pri[1] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_PRIORITY); + + context_icn.hibw2_esram_in0_arblimit[0] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); + context_icn.hibw2_esram_in0_arblimit[1] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); + context_icn.hibw2_esram_in0_arblimit[2] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); + + context_icn.hibw2_esram_in1_arblimit[0] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); + context_icn.hibw2_esram_in1_arblimit[1] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); + context_icn.hibw2_esram_in1_arblimit[2] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); + + context_icn.hibw2_ddr_in_prio[0] = + readl_relaxed(b + NODE_HIBW2_DDR_IN_0_PRIORITY); + context_icn.hibw2_ddr_in_prio[1] = + readl_relaxed(b + NODE_HIBW2_DDR_IN_1_PRIORITY); + context_icn.hibw2_ddr_in_prio[2] = + readl_relaxed(b + NODE_HIBW2_DDR_IN_2_PRIORITY); + + context_icn.hibw2_ddr_in_limit[0] = + readl_relaxed(b + NODE_HIBW2_DDR_IN_0_LIMIT); + context_icn.hibw2_ddr_in_limit[1] = + readl_relaxed(b + NODE_HIBW2_DDR_IN_1_LIMIT); + + context_icn.hibw2_ddr_in_limit[2] = + readl_relaxed(b + NODE_HIBW2_DDR_IN_2_LIMIT); + + context_icn.hibw2_ddr_out_prio = + readl_relaxed(b + NODE_HIBW2_DDR_OUT_0_PRIORITY); + + context_icn.esram0_in_prio[0] = + readl_relaxed(b + NODE_ESRAM0_IN_0_PRIORITY); + context_icn.esram0_in_prio[1] = + readl_relaxed(b + NODE_ESRAM0_IN_1_PRIORITY); + context_icn.esram0_in_prio[2] = + readl_relaxed(b + NODE_ESRAM0_IN_2_PRIORITY); + context_icn.esram0_in_prio[3] = + readl_relaxed(b + NODE_ESRAM0_IN_3_PRIORITY); + + context_icn.esram0_in_lim[0] = + readl_relaxed(b + NODE_ESRAM0_IN_0_LIMIT); + context_icn.esram0_in_lim[1] = + readl_relaxed(b + NODE_ESRAM0_IN_1_LIMIT); + context_icn.esram0_in_lim[2] = + readl_relaxed(b + NODE_ESRAM0_IN_2_LIMIT); + context_icn.esram0_in_lim[3] = + readl_relaxed(b + NODE_ESRAM0_IN_3_LIMIT); + + context_icn.esram12_in_prio[0] = + readl_relaxed(b + NODE_ESRAM1_2_IN_0_PRIORITY); + context_icn.esram12_in_prio[1] = + readl_relaxed(b + NODE_ESRAM1_2_IN_1_PRIORITY); + context_icn.esram12_in_prio[2] = + readl_relaxed(b + NODE_ESRAM1_2_IN_2_PRIORITY); + context_icn.esram12_in_prio[3] = + readl_relaxed(b + NODE_ESRAM1_2_IN_3_PRIORITY); + + context_icn.esram12_in_arb_lim[0] = + readl_relaxed(b + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[1] = + readl_relaxed(b + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT); + context_icn.esram12_in_arb_lim[2] = + readl_relaxed(b + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[3] = + readl_relaxed(b + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT); + context_icn.esram12_in_arb_lim[4] = + readl_relaxed(b + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[5] = + readl_relaxed(b + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT); + context_icn.esram12_in_arb_lim[6] = + readl_relaxed(b + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[7] = + readl_relaxed(b + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT); + + context_icn.esram34_in_prio[0] = + readl_relaxed(b + NODE_ESRAM3_4_IN_0_PRIORITY); + context_icn.esram34_in_prio[1] = + readl_relaxed(b + NODE_ESRAM3_4_IN_1_PRIORITY); + context_icn.esram34_in_prio[2] = + readl_relaxed(b + NODE_ESRAM3_4_IN_2_PRIORITY); + context_icn.esram34_in_prio[3] = + readl_relaxed(b + NODE_ESRAM3_4_IN_3_PRIORITY); + + context_icn.esram34_in_arb_lim[0] = + readl_relaxed(b + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[1] = + readl_relaxed(b + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT); + context_icn.esram34_in_arb_lim[2] = + readl_relaxed(b + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[3] = + readl_relaxed(b + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT); + context_icn.esram34_in_arb_lim[4] = + readl_relaxed(b + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[5] = + readl_relaxed(b + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT); + context_icn.esram34_in_arb_lim[6] = + readl_relaxed(b + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[7] = + readl_relaxed(b + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT); +} + +/** + * u8500_context_restore_icn() - restore ICN context + * + */ +void u8500_context_restore_icn(void) +{ + void __iomem *b = context_icn.base; + + writel_relaxed(context_icn.hibw1_esram_in_pri[0], + b + NODE_HIBW1_ESRAM_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw1_esram_in_pri[1], + b + NODE_HIBW1_ESRAM_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw1_esram_in_pri[2], + b + NODE_HIBW1_ESRAM_IN_2_PRIORITY); + + writel_relaxed(context_icn.hibw1_esram_in0_arb[0], + b + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in0_arb[1], + b + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in0_arb[2], + b + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_esram_in1_arb[0], + b + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in1_arb[1], + b + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in1_arb[2], + b + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_esram_in2_arb[0], + b + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in2_arb[1], + b + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in2_arb[2], + b + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_ddr_in_prio[0], + b + NODE_HIBW1_DDR_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr_in_prio[1], + b + NODE_HIBW1_DDR_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr_in_prio[2], + b + NODE_HIBW1_DDR_IN_2_PRIORITY); + + writel_relaxed(context_icn.hibw1_ddr_in_limit[0], + b + NODE_HIBW1_DDR_IN_0_LIMIT); + writel_relaxed(context_icn.hibw1_ddr_in_limit[1], + b + NODE_HIBW1_DDR_IN_1_LIMIT); + writel_relaxed(context_icn.hibw1_ddr_in_limit[2], + b + NODE_HIBW1_DDR_IN_2_LIMIT); + + writel_relaxed(context_icn.hibw1_ddr_out_prio, + b + NODE_HIBW1_DDR_OUT_0_PRIORITY); + + writel_relaxed(context_icn.hibw2_esram_in_pri[0], + b + NODE_HIBW2_ESRAM_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw2_esram_in_pri[1], + b + NODE_HIBW2_ESRAM_IN_1_PRIORITY); + + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[0], + b + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[1], + b + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[2], + b + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[0], + b + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[1], + b + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[2], + b + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw2_ddr_in_prio[0], + b + NODE_HIBW2_DDR_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr_in_prio[1], + b + NODE_HIBW2_DDR_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr_in_prio[2], + b + NODE_HIBW2_DDR_IN_2_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr_in_limit[0], + b + NODE_HIBW2_DDR_IN_0_LIMIT); + writel_relaxed(context_icn.hibw2_ddr_in_limit[1], + b + NODE_HIBW2_DDR_IN_1_LIMIT); + writel_relaxed(context_icn.hibw2_ddr_in_limit[2], + b + NODE_HIBW2_DDR_IN_2_LIMIT); + writel_relaxed(context_icn.hibw2_ddr_out_prio, + b + NODE_HIBW2_DDR_OUT_0_PRIORITY); + + writel_relaxed(context_icn.esram0_in_prio[0], + b + NODE_ESRAM0_IN_0_PRIORITY); + writel_relaxed(context_icn.esram0_in_prio[1], + b + NODE_ESRAM0_IN_1_PRIORITY); + writel_relaxed(context_icn.esram0_in_prio[2], + b + NODE_ESRAM0_IN_2_PRIORITY); + writel_relaxed(context_icn.esram0_in_prio[3], + b + NODE_ESRAM0_IN_3_PRIORITY); + + writel_relaxed(context_icn.esram0_in_lim[0], + b + NODE_ESRAM0_IN_0_LIMIT); + writel_relaxed(context_icn.esram0_in_lim[1], + b + NODE_ESRAM0_IN_1_LIMIT); + writel_relaxed(context_icn.esram0_in_lim[2], + b + NODE_ESRAM0_IN_2_LIMIT); + writel_relaxed(context_icn.esram0_in_lim[3], + b + NODE_ESRAM0_IN_3_LIMIT); + + writel_relaxed(context_icn.esram12_in_prio[0], + b + NODE_ESRAM1_2_IN_0_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[1], + b + NODE_ESRAM1_2_IN_1_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[2], + b + NODE_ESRAM1_2_IN_2_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[3], + b + NODE_ESRAM1_2_IN_3_PRIORITY); + + writel_relaxed(context_icn.esram12_in_arb_lim[0], + b + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[1], + b + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[2], + b + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[3], + b + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[4], + b + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[5], + b + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[6], + b + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[7], + b + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT); + + writel_relaxed(context_icn.esram34_in_prio[0], + b + NODE_ESRAM3_4_IN_0_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[1], + b + NODE_ESRAM3_4_IN_1_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[2], + b + NODE_ESRAM3_4_IN_2_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[3], + b + NODE_ESRAM3_4_IN_3_PRIORITY); + + writel_relaxed(context_icn.esram34_in_arb_lim[0], + b + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[1], + b + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[2], + b + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[3], + b + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[4], + b + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[5], + b + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[6], + b + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[7], + b + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT); +} + +void u8500_context_init(void) +{ + context_icn.base = ioremap(U8500_ICN_BASE, SZ_8K); +} diff --git a/arch/arm/mach-ux500/pm/context-db9540.c b/arch/arm/mach-ux500/pm/context-db9540.c new file mode 100644 index 00000000000..8d8aaeb9d8f --- /dev/null +++ b/arch/arm/mach-ux500/pm/context-db9540.c @@ -0,0 +1,651 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * License Terms: GNU General Public License v2 + * Author: Sundar Iyer for ST-Ericsson + * + */ + +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/context.h> + +/* + * ST-Interconnect context + */ + +/* priority, bw limiter register offsets */ +#define NODE_HIBW1_ESRAM_IN_0_PRIORITY 0x00 +#define NODE_HIBW1_ESRAM_IN_1_PRIORITY 0x04 +#define NODE_HIBW1_ESRAM_IN_2_PRIORITY 0x08 +#define NODE_HIBW1_ESRAM_IN_3_PRIORITY 0x0C +#define NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT 0x30 +#define NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT 0x34 +#define NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT 0x38 +#define NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT 0x3C +#define NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT 0x40 +#define NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT 0x44 +#define NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT 0x48 +#define NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT 0x4C +#define NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT 0x50 +#define NODE_HIBW1_ESRAM_IN_3_ARB_1_LIMIT 0x54 +#define NODE_HIBW1_ESRAM_IN_3_ARB_2_LIMIT 0x58 +#define NODE_HIBW1_ESRAM_IN_3_ARB_3_LIMIT 0x5C +#define NODE_HIBW1_DDR0_IN_0_PRIORITY 0x400 +#define NODE_HIBW1_DDR0_IN_1_PRIORITY 0x404 +#define NODE_HIBW1_DDR0_IN_2_PRIORITY 0x408 +#define NODE_HIBW1_DDR0_IN_3_PRIORITY 0x40C +#define NODE_HIBW1_DDR0_IN_0_LIMIT 0x430 +#define NODE_HIBW1_DDR0_IN_1_LIMIT 0x434 +#define NODE_HIBW1_DDR0_IN_2_LIMIT 0x438 +#define NODE_HIBW1_DDR0_IN_3_LIMIT 0x43C +#define NODE_HIBW1_DDR0_OUT_0_PRIORITY 0x440 +#define NODE_HIBW2_ESRAM_IN_0_PRIORITY 0x800 +#define NODE_HIBW2_ESRAM_IN_1_PRIORITY 0x804 +#define NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT 0x818 +#define NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT 0x81C +#define NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT 0x820 +#define NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT 0x824 +#define NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT 0x828 +#define NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT 0x82C + +#define NODE_HIBW2_DDR0_IN_0_PRIORITY 0xC00 +#define NODE_HIBW2_DDR0_IN_1_PRIORITY 0xC04 + +#define NODE_HIBW2_DDR0_IN_0_LIMIT 0xC18 +#define NODE_HIBW2_DDR0_IN_1_LIMIT 0xC1C + +#define NODE_HIBW2_DDR0_OUT_0_PRIORITY 0xC20 + +/* + * Note the following addresses are presented in + * db8500 design spec v3.1 and v3.3, table 10. + * But their addresses are not the same as in the + * description. The addresses in the description + * of each registers are correct. + * NODE_HIBW2_DDR_IN_3_LIMIT is only present in v1. + * + * Faulty registers addresses in table 10: + * NODE_HIBW2_DDR_IN_2_LIMIT 0xC38 + * NODE_HIBW2_DDR_IN_3_LIMIT 0xC3C + * NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC40 + */ + +#define NODE_ESRAM0_IN_0_PRIORITY 0x1000 +#define NODE_ESRAM0_IN_1_PRIORITY 0x1004 +#define NODE_ESRAM0_IN_2_PRIORITY 0x1008 +#define NODE_ESRAM0_IN_3_PRIORITY 0x100C +#define NODE_ESRAM0_IN_0_LIMIT 0x1030 +#define NODE_ESRAM0_IN_1_LIMIT 0x1034 +#define NODE_ESRAM0_IN_2_LIMIT 0x1038 +#define NODE_ESRAM0_IN_3_LIMIT 0x103C +#define NODE_ESRAM0_OUT_0_PRIORITY 0x1040 + +/* common */ +#define NODE_ESRAM1_2_IN_0_PRIORITY 0x1400 +#define NODE_ESRAM1_2_IN_1_PRIORITY 0x1404 +#define NODE_ESRAM1_2_IN_2_PRIORITY 0x1408 +#define NODE_ESRAM1_2_IN_3_PRIORITY 0x140C +#define NODE_ESRAM1_2_IN_0_ARB_1_LIMIT 0x1430 +#define NODE_ESRAM1_2_IN_0_ARB_2_LIMIT 0x1434 +#define NODE_ESRAM1_2_IN_1_ARB_1_LIMIT 0x1438 +#define NODE_ESRAM1_2_IN_1_ARB_2_LIMIT 0x143C +#define NODE_ESRAM1_2_IN_2_ARB_1_LIMIT 0x1440 +#define NODE_ESRAM1_2_IN_2_ARB_2_LIMIT 0x1444 +#define NODE_ESRAM1_2_IN_3_ARB_1_LIMIT 0x1448 +#define NODE_ESRAM1_2_IN_3_ARB_2_LIMIT 0x144C + +#define NODE_ESRAM3_4_IN_0_PRIORITY 0x1800 +#define NODE_ESRAM3_4_IN_1_PRIORITY 0x1804 +#define NODE_ESRAM3_4_IN_2_PRIORITY 0x1808 +#define NODE_ESRAM3_4_IN_3_PRIORITY 0x180C +#define NODE_ESRAM3_4_IN_0_ARB_1_LIMIT 0x1830 +#define NODE_ESRAM3_4_IN_0_ARB_2_LIMIT 0x1834 +#define NODE_ESRAM3_4_IN_1_ARB_1_LIMIT 0x1838 +#define NODE_ESRAM3_4_IN_1_ARB_2_LIMIT 0x183C +#define NODE_ESRAM3_4_IN_2_ARB_1_LIMIT 0x1840 +#define NODE_ESRAM3_4_IN_2_ARB_2_LIMIT 0x1844 +#define NODE_ESRAM3_4_IN_3_ARB_1_LIMIT 0x1848 +#define NODE_ESRAM3_4_IN_3_ARB_2_LIMIT 0x184C + +#define NODE_HIBW1_DDR1_IN_0_PRIORITY_REG 0x1C00 +#define NODE_HIBW1_DDR1_IN_1_PRIORITY_REG 0x1C04 +#define NODE_HIBW1_DDR1_IN_2_PRIORITY_REG 0x1C08 +#define NODE_HIBW1_DDR1_IN_3_PRIORITY_REG 0x1C0C + +#define NODE_HIBW1_DDR1_IN_0_LIMIT_REG 0x1C30 +#define NODE_HIBW1_DDR1_IN_1_LIMIT_REG 0x1C34 +#define NODE_HIBW1_DDR1_IN_2_LIMIT_REG 0x1C38 +#define NODE_HIBW1_DDR1_IN_3_LIMIT_REG 0x1C3C + +#define NODE_HIBW1_DDR1_OUT_0_PRIORITY_REG 0x1C40 + +#define NODE_HIBW2_DDR1_IN_0_PRIORITY_REG 0x2000 +#define NODE_HIBW2_DDR1_IN_1_PRIORITY_REG 0x2004 + +#define NODE_HIBW2_DDR1_IN_0_LIMIT_REG 0x2018 +#define NODE_HIBW2_DDR1_IN_1_LIMIT_REG 0x201C +#define NODE_HIBW2_DDR1_OUT_0_PRIORITY_REG 0x2020 +#define NODE_DDR_AWQOS_DSP_DDR0_REG 0x340C +#define NODE_DDR_AWQOS_DSP_DDR1_REG 0x3400 +#define NODE_DDR_ARQOS_DSP_DDR0_REG 0x3408 +#define NODE_DDR_ARQOS_DSP_DDR1_REG 0x3404 +#define NODE_DDR_AWQOS_ARM_DDR_REG 0x3410 +#define NODE_DDR_ARQOS_ARM_DDR_REG 0x3414 +#define NODE_SGA_AWQOS_DDR0_HIBW2_REG 0x3418 +#define NODE_SGA_ARQOS_DDR0_HIBW2_REG 0x341C +#define NODE_SGA_AWQOS_SGA_HIBW2_REG 0x3420 +#define NODE_SGA_ARQOS_SGA_HIBW2_REG 0x3424 + +static struct { + void __iomem *base; + u32 hibw1_esram_in_pri[4]; + u32 hibw1_esram_in0_arb[3]; + u32 hibw1_esram_in1_arb[3]; + u32 hibw1_esram_in2_arb[3]; + u32 hibw1_esram_in3_arb[3]; + u32 hibw1_ddr0_in_prio[4]; + u32 hibw1_ddr0_in_limit[4]; + u32 hibw1_ddr0_out_prio; + u32 hibw1_ddr1_in_prio[4]; + u32 hibw1_ddr1_in_limit[4]; + u32 hibw1_ddr1_out_prio; + + /* HiBw2 node registers */ + u32 hibw2_esram_in_pri[2]; + u32 hibw2_esram_in0_arblimit[3]; + u32 hibw2_esram_in1_arblimit[3]; + u32 hibw2_ddr0_in_prio[2]; + u32 hibw2_ddr0_in_limit[2]; + u32 hibw2_ddr0_out_prio; + u32 hibw2_ddr1_in_prio[2]; + u32 hibw2_ddr1_in_limit[2]; + u32 hibw2_ddr1_out_prio; + + /* ESRAM node registers */ + u32 esram0_in_prio[4]; + u32 esram0_in_lim[4]; + u32 esram0_out_prio; + u32 esram12_in_prio[4]; + u32 esram12_in_arb_lim[8]; + u32 esram34_in_prio[4]; + u32 esram34_in_arb_lim[8]; + + u32 ddr_awqos_dsp_ddr0; + u32 ddr_awqos_dsp_ddr1; + u32 ddr_arqos_dsp_ddr0; + u32 ddr_arqos_dsp_ddr1; + u32 ddr_awqos_arm_ddr; + u32 ddr_arqos_arm_ddr; + + u32 sga_awqos_ddr0_hibw2; + u32 sga_arqos_ddr0_hibw2; + + u32 sga_awqos_sga_hibw2; + u32 sga_arqos_sga_hibw2; +} context_icn; + +/** + * u8500_context_save_icn() - save ICN context + * + */ +void u9540_context_save_icn(void) +{ + void __iomem *b = context_icn.base; + + context_icn.hibw1_esram_in_pri[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_PRIORITY); + context_icn.hibw1_esram_in_pri[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_PRIORITY); + context_icn.hibw1_esram_in_pri[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_PRIORITY); + context_icn.hibw1_esram_in_pri[3] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_3_PRIORITY); + + context_icn.hibw1_esram_in0_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); + context_icn.hibw1_esram_in0_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); + context_icn.hibw1_esram_in0_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); + + context_icn.hibw1_esram_in1_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); + context_icn.hibw1_esram_in1_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); + context_icn.hibw1_esram_in1_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); + + context_icn.hibw1_esram_in2_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT); + context_icn.hibw1_esram_in2_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT); + context_icn.hibw1_esram_in2_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT); + + context_icn.hibw1_esram_in3_arb[0] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_3_ARB_1_LIMIT); + context_icn.hibw1_esram_in3_arb[1] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_3_ARB_2_LIMIT); + context_icn.hibw1_esram_in3_arb[2] = + readl_relaxed(b + NODE_HIBW1_ESRAM_IN_3_ARB_3_LIMIT); + + context_icn.hibw1_ddr0_in_prio[0] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_0_PRIORITY); + context_icn.hibw1_ddr0_in_prio[1] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_1_PRIORITY); + context_icn.hibw1_ddr0_in_prio[2] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_2_PRIORITY); + context_icn.hibw1_ddr0_in_prio[3] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_3_PRIORITY); + + context_icn.hibw1_ddr0_in_limit[0] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_0_LIMIT); + context_icn.hibw1_ddr0_in_limit[1] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_1_LIMIT); + context_icn.hibw1_ddr0_in_limit[2] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_2_LIMIT); + context_icn.hibw1_ddr0_in_limit[3] = + readl_relaxed(b + NODE_HIBW1_DDR0_IN_3_LIMIT); + + context_icn.hibw1_ddr0_out_prio = + readl_relaxed(b + NODE_HIBW1_DDR0_OUT_0_PRIORITY); + + context_icn.hibw1_ddr1_in_prio[0] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_0_PRIORITY_REG); + context_icn.hibw1_ddr1_in_prio[1] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_1_PRIORITY_REG); + context_icn.hibw1_ddr1_in_prio[2] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_2_PRIORITY_REG); + context_icn.hibw1_ddr1_in_prio[3] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_3_PRIORITY_REG); + + context_icn.hibw1_ddr1_in_limit[0] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_0_LIMIT_REG); + context_icn.hibw1_ddr1_in_limit[1] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_1_LIMIT_REG); + context_icn.hibw1_ddr1_in_limit[2] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_2_LIMIT_REG); + context_icn.hibw1_ddr1_in_limit[3] = + readl_relaxed(b + NODE_HIBW1_DDR1_IN_3_LIMIT_REG); + + context_icn.hibw1_ddr1_out_prio = + readl_relaxed(b + NODE_HIBW1_DDR1_OUT_0_PRIORITY_REG); + + context_icn.hibw2_esram_in_pri[0] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_PRIORITY); + context_icn.hibw2_esram_in_pri[1] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_PRIORITY); + + context_icn.hibw2_esram_in0_arblimit[0] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); + context_icn.hibw2_esram_in0_arblimit[1] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); + context_icn.hibw2_esram_in0_arblimit[2] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); + + context_icn.hibw2_esram_in1_arblimit[0] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); + context_icn.hibw2_esram_in1_arblimit[1] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); + context_icn.hibw2_esram_in1_arblimit[2] = + readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); + + context_icn.hibw2_ddr0_in_prio[0] = + readl_relaxed(b + NODE_HIBW2_DDR0_IN_0_PRIORITY); + context_icn.hibw2_ddr0_in_prio[1] = + readl_relaxed(b + NODE_HIBW2_DDR0_IN_1_PRIORITY); + + context_icn.hibw2_ddr0_in_limit[0] = + readl_relaxed(b + NODE_HIBW2_DDR0_IN_0_LIMIT); + context_icn.hibw2_ddr0_in_limit[1] = + readl_relaxed(b + NODE_HIBW2_DDR0_IN_1_LIMIT); + + context_icn.hibw2_ddr0_out_prio = + readl_relaxed(b + NODE_HIBW2_DDR0_OUT_0_PRIORITY); + + context_icn.hibw2_ddr1_in_prio[0] = + readl_relaxed(b + NODE_HIBW2_DDR1_IN_0_PRIORITY_REG); + context_icn.hibw2_ddr1_in_prio[1] = + readl_relaxed(b + NODE_HIBW2_DDR1_IN_1_PRIORITY_REG); + + context_icn.hibw2_ddr1_in_limit[0] = + readl_relaxed(b + NODE_HIBW2_DDR1_IN_0_LIMIT_REG); + context_icn.hibw2_ddr1_in_limit[1] = + readl_relaxed(b + NODE_HIBW2_DDR1_IN_1_LIMIT_REG); + + context_icn.hibw2_ddr1_out_prio = + readl_relaxed(b + NODE_HIBW2_DDR1_OUT_0_PRIORITY_REG); + + context_icn.esram0_in_prio[0] = + readl_relaxed(b + NODE_ESRAM0_IN_0_PRIORITY); + context_icn.esram0_in_prio[1] = + readl_relaxed(b + NODE_ESRAM0_IN_1_PRIORITY); + context_icn.esram0_in_prio[2] = + readl_relaxed(b + NODE_ESRAM0_IN_2_PRIORITY); + context_icn.esram0_in_prio[3] = + readl_relaxed(b + NODE_ESRAM0_IN_3_PRIORITY); + + context_icn.esram0_in_lim[0] = + readl_relaxed(b + NODE_ESRAM0_IN_0_LIMIT); + context_icn.esram0_in_lim[1] = + readl_relaxed(b + NODE_ESRAM0_IN_1_LIMIT); + context_icn.esram0_in_lim[2] = + readl_relaxed(b + NODE_ESRAM0_IN_2_LIMIT); + context_icn.esram0_in_lim[3] = + readl_relaxed(b + NODE_ESRAM0_IN_3_LIMIT); + + context_icn.esram0_out_prio = + readl_relaxed(b + NODE_ESRAM0_OUT_0_PRIORITY); + + context_icn.esram12_in_prio[0] = + readl_relaxed(b + NODE_ESRAM1_2_IN_0_PRIORITY); + context_icn.esram12_in_prio[1] = + readl_relaxed(b + NODE_ESRAM1_2_IN_1_PRIORITY); + context_icn.esram12_in_prio[2] = + readl_relaxed(b + NODE_ESRAM1_2_IN_2_PRIORITY); + context_icn.esram12_in_prio[3] = + readl_relaxed(b + NODE_ESRAM1_2_IN_3_PRIORITY); + + context_icn.esram12_in_arb_lim[0] = + readl_relaxed(b + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[1] = + readl_relaxed(b + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT); + context_icn.esram12_in_arb_lim[2] = + readl_relaxed(b + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[3] = + readl_relaxed(b + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT); + context_icn.esram12_in_arb_lim[4] = + readl_relaxed(b + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[5] = + readl_relaxed(b + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT); + context_icn.esram12_in_arb_lim[6] = + readl_relaxed(b + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT); + context_icn.esram12_in_arb_lim[7] = + readl_relaxed(b + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT); + + context_icn.esram34_in_prio[0] = + readl_relaxed(b + NODE_ESRAM3_4_IN_0_PRIORITY); + context_icn.esram34_in_prio[1] = + readl_relaxed(b + NODE_ESRAM3_4_IN_1_PRIORITY); + context_icn.esram34_in_prio[2] = + readl_relaxed(b + NODE_ESRAM3_4_IN_2_PRIORITY); + context_icn.esram34_in_prio[3] = + readl_relaxed(b + NODE_ESRAM3_4_IN_3_PRIORITY); + + context_icn.esram34_in_arb_lim[0] = + readl_relaxed(b + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[1] = + readl_relaxed(b + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT); + context_icn.esram34_in_arb_lim[2] = + readl_relaxed(b + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[3] = + readl_relaxed(b + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT); + context_icn.esram34_in_arb_lim[4] = + readl_relaxed(b + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[5] = + readl_relaxed(b + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT); + context_icn.esram34_in_arb_lim[6] = + readl_relaxed(b + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT); + context_icn.esram34_in_arb_lim[7] = + readl_relaxed(b + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT); + + context_icn.ddr_awqos_dsp_ddr0 = + readl_relaxed(b + NODE_DDR_AWQOS_DSP_DDR0_REG); + context_icn.ddr_awqos_dsp_ddr1 = + readl_relaxed(b + NODE_DDR_AWQOS_DSP_DDR1_REG); + context_icn.ddr_arqos_dsp_ddr0 = + readl_relaxed(b + NODE_DDR_ARQOS_DSP_DDR0_REG); + context_icn.ddr_arqos_dsp_ddr1 = + readl_relaxed(b + NODE_DDR_ARQOS_DSP_DDR1_REG); + context_icn.ddr_awqos_arm_ddr = + readl_relaxed(b + NODE_DDR_AWQOS_ARM_DDR_REG); + context_icn.ddr_arqos_arm_ddr = + readl_relaxed(b + NODE_DDR_ARQOS_ARM_DDR_REG); + + context_icn.sga_awqos_ddr0_hibw2 = + readl_relaxed(b + NODE_SGA_AWQOS_DDR0_HIBW2_REG); + context_icn.sga_arqos_ddr0_hibw2 = + readl_relaxed(b + NODE_SGA_ARQOS_DDR0_HIBW2_REG); + + context_icn.sga_awqos_sga_hibw2 = + readl_relaxed(b + NODE_SGA_AWQOS_SGA_HIBW2_REG); + context_icn.sga_arqos_sga_hibw2 = + readl_relaxed(b + NODE_SGA_ARQOS_SGA_HIBW2_REG); +} + +/** + * u9540_context_restore_icn() - restore ICN context + * + */ +void u9540_context_restore_icn(void) +{ + void __iomem *b = context_icn.base; + + writel_relaxed(context_icn.hibw1_esram_in_pri[0], + b + NODE_HIBW1_ESRAM_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw1_esram_in_pri[1], + b + NODE_HIBW1_ESRAM_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw1_esram_in_pri[2], + b + NODE_HIBW1_ESRAM_IN_2_PRIORITY); + writel_relaxed(context_icn.hibw1_esram_in_pri[3], + b + NODE_HIBW1_ESRAM_IN_3_PRIORITY); + + writel_relaxed(context_icn.hibw1_esram_in0_arb[0], + b + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in0_arb[1], + b + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in0_arb[2], + b + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_esram_in1_arb[0], + b + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in1_arb[1], + b + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in1_arb[2], + b + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_esram_in2_arb[0], + b + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in2_arb[1], + b + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in2_arb[2], + b + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_esram_in3_arb[0], + b + NODE_HIBW1_ESRAM_IN_3_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in3_arb[1], + b + NODE_HIBW1_ESRAM_IN_3_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw1_esram_in3_arb[2], + b + NODE_HIBW1_ESRAM_IN_3_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw1_ddr0_in_prio[0], + b + NODE_HIBW1_DDR0_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr0_in_prio[1], + b + NODE_HIBW1_DDR0_IN_1_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr0_in_prio[2], + b + NODE_HIBW1_DDR0_IN_2_PRIORITY); + writel_relaxed(context_icn.hibw1_ddr0_in_prio[3], + b + NODE_HIBW1_DDR0_IN_3_PRIORITY); + + writel_relaxed(context_icn.hibw1_ddr0_in_limit[0], + b + NODE_HIBW1_DDR0_IN_0_LIMIT); + writel_relaxed(context_icn.hibw1_ddr0_in_limit[1], + b + NODE_HIBW1_DDR0_IN_1_LIMIT); + writel_relaxed(context_icn.hibw1_ddr0_in_limit[2], + b + NODE_HIBW1_DDR0_IN_2_LIMIT); + writel_relaxed(context_icn.hibw1_ddr0_in_limit[3], + b + NODE_HIBW1_DDR0_IN_3_LIMIT); + + writel_relaxed(context_icn.hibw1_ddr0_out_prio, + b + NODE_HIBW1_DDR0_OUT_0_PRIORITY); + + writel_relaxed(context_icn.hibw1_ddr1_in_prio[0], + b + NODE_HIBW1_DDR1_IN_0_PRIORITY_REG); + writel_relaxed(context_icn.hibw1_ddr1_in_prio[1], + b + NODE_HIBW1_DDR1_IN_1_PRIORITY_REG); + writel_relaxed(context_icn.hibw1_ddr1_in_prio[2], + b + NODE_HIBW1_DDR1_IN_2_PRIORITY_REG); + writel_relaxed(context_icn.hibw1_ddr1_in_prio[3], + b + NODE_HIBW1_DDR1_IN_3_PRIORITY_REG); + + writel_relaxed(context_icn.hibw1_ddr1_in_limit[0], + b + NODE_HIBW1_DDR1_IN_0_LIMIT_REG); + writel_relaxed(context_icn.hibw1_ddr1_in_limit[1], + b + NODE_HIBW1_DDR1_IN_1_LIMIT_REG); + writel_relaxed(context_icn.hibw1_ddr1_in_limit[2], + b + NODE_HIBW1_DDR1_IN_2_LIMIT_REG); + writel_relaxed(context_icn.hibw1_ddr1_in_limit[3], + b + NODE_HIBW1_DDR1_IN_3_LIMIT_REG); + + writel_relaxed(context_icn.hibw1_ddr1_out_prio, + b + NODE_HIBW1_DDR1_OUT_0_PRIORITY_REG); + + writel_relaxed(context_icn.hibw2_esram_in_pri[0], + b + NODE_HIBW2_ESRAM_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw2_esram_in_pri[1], + b + NODE_HIBW2_ESRAM_IN_1_PRIORITY); + + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[0], + b + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[1], + b + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in0_arblimit[2], + b + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[0], + b + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[1], + b + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.hibw2_esram_in1_arblimit[2], + b + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); + + writel_relaxed(context_icn.hibw2_ddr0_in_prio[0], + b + NODE_HIBW2_DDR0_IN_0_PRIORITY); + writel_relaxed(context_icn.hibw2_ddr0_in_prio[1], + b + NODE_HIBW2_DDR0_IN_1_PRIORITY); + + writel_relaxed(context_icn.hibw2_ddr0_in_limit[0], + b + NODE_HIBW2_DDR0_IN_0_LIMIT); + writel_relaxed(context_icn.hibw2_ddr0_in_limit[1], + b + NODE_HIBW2_DDR0_IN_1_LIMIT); + + writel_relaxed(context_icn.hibw2_ddr0_out_prio, + b + NODE_HIBW2_DDR0_OUT_0_PRIORITY); + + writel_relaxed(context_icn.hibw2_ddr1_in_prio[0], + b + NODE_HIBW2_DDR1_IN_0_PRIORITY_REG); + writel_relaxed(context_icn.hibw2_ddr1_in_prio[1], + b + NODE_HIBW2_DDR1_IN_1_PRIORITY_REG); + + writel_relaxed(context_icn.hibw2_ddr1_in_limit[0], + b + NODE_HIBW2_DDR1_IN_0_LIMIT_REG); + writel_relaxed(context_icn.hibw2_ddr1_in_limit[1], + b + NODE_HIBW2_DDR1_IN_1_LIMIT_REG); + + writel_relaxed(context_icn.hibw2_ddr1_out_prio, + b + NODE_HIBW2_DDR1_OUT_0_PRIORITY_REG); + + writel_relaxed(context_icn.esram0_in_prio[0], + b + NODE_ESRAM0_IN_0_PRIORITY); + writel_relaxed(context_icn.esram0_in_prio[1], + b + NODE_ESRAM0_IN_1_PRIORITY); + writel_relaxed(context_icn.esram0_in_prio[2], + b + NODE_ESRAM0_IN_2_PRIORITY); + writel_relaxed(context_icn.esram0_in_prio[3], + b + NODE_ESRAM0_IN_3_PRIORITY); + + writel_relaxed(context_icn.esram0_in_lim[0], + b + NODE_ESRAM0_IN_0_LIMIT); + writel_relaxed(context_icn.esram0_in_lim[1], + b + NODE_ESRAM0_IN_1_LIMIT); + writel_relaxed(context_icn.esram0_in_lim[2], + b + NODE_ESRAM0_IN_2_LIMIT); + writel_relaxed(context_icn.esram0_in_lim[3], + b + NODE_ESRAM0_IN_3_LIMIT); + + writel_relaxed(context_icn.esram0_out_prio, + b + NODE_ESRAM0_OUT_0_PRIORITY); + + writel_relaxed(context_icn.esram12_in_prio[0], + b + NODE_ESRAM1_2_IN_0_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[1], + b + NODE_ESRAM1_2_IN_1_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[2], + b + NODE_ESRAM1_2_IN_2_PRIORITY); + writel_relaxed(context_icn.esram12_in_prio[3], + b + NODE_ESRAM1_2_IN_3_PRIORITY); + + writel_relaxed(context_icn.esram12_in_arb_lim[0], + b + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[1], + b + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[2], + b + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[3], + b + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[4], + b + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[5], + b + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[6], + b + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT); + writel_relaxed(context_icn.esram12_in_arb_lim[7], + b + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT); + + writel_relaxed(context_icn.esram34_in_prio[0], + b + NODE_ESRAM3_4_IN_0_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[1], + b + NODE_ESRAM3_4_IN_1_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[2], + b + NODE_ESRAM3_4_IN_2_PRIORITY); + writel_relaxed(context_icn.esram34_in_prio[3], + b + NODE_ESRAM3_4_IN_3_PRIORITY); + + writel_relaxed(context_icn.esram34_in_arb_lim[0], + b + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[1], + b + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[2], + b + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[3], + b + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[4], + b + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[5], + b + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[6], + b + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT); + writel_relaxed(context_icn.esram34_in_arb_lim[7], + b + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT); + + writel_relaxed(context_icn.ddr_awqos_dsp_ddr0, + b + NODE_DDR_AWQOS_DSP_DDR0_REG); + writel_relaxed(context_icn.ddr_awqos_dsp_ddr1, + b + NODE_DDR_AWQOS_DSP_DDR1_REG); + writel_relaxed(context_icn.ddr_arqos_dsp_ddr0, + b + NODE_DDR_ARQOS_DSP_DDR0_REG); + writel_relaxed(context_icn.ddr_arqos_dsp_ddr1, + b + NODE_DDR_ARQOS_DSP_DDR1_REG); + writel_relaxed(context_icn.ddr_awqos_arm_ddr, + b + NODE_DDR_AWQOS_ARM_DDR_REG); + writel_relaxed(context_icn.ddr_arqos_arm_ddr, + b + NODE_DDR_ARQOS_ARM_DDR_REG); + + writel_relaxed(context_icn.sga_awqos_ddr0_hibw2, + b + NODE_SGA_AWQOS_DDR0_HIBW2_REG); + writel_relaxed(context_icn.sga_arqos_ddr0_hibw2, + b + NODE_SGA_ARQOS_DDR0_HIBW2_REG); + + writel_relaxed(context_icn.sga_awqos_sga_hibw2, + b + NODE_SGA_AWQOS_SGA_HIBW2_REG); + writel_relaxed(context_icn.sga_arqos_sga_hibw2, + b + NODE_SGA_ARQOS_SGA_HIBW2_REG); +} + +void u9540_context_init(void) +{ + context_icn.base = ioremap(U8500_ICN_BASE, SZ_16K); +} diff --git a/arch/arm/mach-ux500/pm/context.c b/arch/arm/mach-ux500/pm/context.c new file mode 100644 index 00000000000..5902b861930 --- /dev/null +++ b/arch/arm/mach-ux500/pm/context.c @@ -0,0 +1,1002 @@ +/* + * Copyright (C) ST-Ericsson SA 2010-2011 + * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>, + * Rickard Andersson <rickard.andersson@stericsson.com>, + * Jonas Aaberg <jonas.aberg@stericsson.com>, + * Sundar Iyer for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + * + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/smp.h> +#include <linux/percpu.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/notifier.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/gpio/nomadik.h> + +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/pm.h> +#include <mach/context.h> + +#include <asm/hardware/gic.h> +#include <asm/smp_twd.h> + +#include "scu.h" +#include "../product.h" +#include "../prcc.h" + +#include "../board-pins-sleep-force.h" + +#define GPIO_NUM_BANKS 9 +#define GPIO_NUM_SAVE_REGISTERS 7 + +/* + * TODO: + * - Use the "UX500*"-macros instead where possible + */ + +#define U8500_BACKUPRAM_SIZE SZ_64K + +#define U8500_PUBLIC_BOOT_ROM_BASE (U8500_BOOT_ROM_BASE + 0x17000) +#define U9540_PUBLIC_BOOT_ROM_BASE (U9540_BOOT_ROM_BASE + 0x17000) +#define U5500_PUBLIC_BOOT_ROM_BASE (U5500_BOOT_ROM_BASE + 0x18000) + +/* + * Special dedicated addresses in backup RAM. The 5500 addresses are identical + * to the 8500 ones. + */ +#define U8500_EXT_RAM_LOC_BACKUPRAM_ADDR 0x80151FDC +#define U8500_CPU0_CP15_CR_BACKUPRAM_ADDR 0x80151F80 +#define U8500_CPU1_CP15_CR_BACKUPRAM_ADDR 0x80151FA0 + +#define U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR 0x80151FD8 +#define U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR 0x80151FE0 + +#define GIC_DIST_ENABLE_NS 0x0 + +/* 32 interrupts fits in 4 bytes */ +#define GIC_DIST_ENABLE_SET_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - \ + IRQ_SHPI_START) / 32) +#define GIC_DIST_ENABLE_SET_CPU_NUM (IRQ_SHPI_START / 32) +#define GIC_DIST_ENABLE_SET_SPI0 GIC_DIST_ENABLE_SET +#define GIC_DIST_ENABLE_SET_SPI32 (GIC_DIST_ENABLE_SET + IRQ_SHPI_START / 8) + +#define GIC_DIST_ENABLE_CLEAR_0 GIC_DIST_ENABLE_CLEAR +#define GIC_DIST_ENABLE_CLEAR_32 (GIC_DIST_ENABLE_CLEAR + 4) +#define GIC_DIST_ENABLE_CLEAR_64 (GIC_DIST_ENABLE_CLEAR + 8) +#define GIC_DIST_ENABLE_CLEAR_96 (GIC_DIST_ENABLE_CLEAR + 12) +#define GIC_DIST_ENABLE_CLEAR_128 (GIC_DIST_ENABLE_CLEAR + 16) + +#define GIC_DIST_PRI_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - IRQ_SHPI_START) / 4) +#define GIC_DIST_PRI_CPU_NUM (IRQ_SHPI_START / 4) +#define GIC_DIST_PRI_SPI0 GIC_DIST_PRI +#define GIC_DIST_PRI_SPI32 (GIC_DIST_PRI + IRQ_SHPI_START) + +#define GIC_DIST_SPI_TARGET_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - \ + IRQ_SHPI_START) / 4) +#define GIC_DIST_SPI_TARGET_CPU_NUM (IRQ_SHPI_START / 4) +#define GIC_DIST_SPI_TARGET_SPI0 GIC_DIST_TARGET +#define GIC_DIST_SPI_TARGET_SPI32 (GIC_DIST_TARGET + IRQ_SHPI_START) + +/* 16 interrupts per 4 bytes */ +#define GIC_DIST_CONFIG_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - IRQ_SHPI_START) \ + / 16) +#define GIC_DIST_CONFIG_CPU_NUM (IRQ_SHPI_START / 16) +#define GIC_DIST_CONFIG_SPI0 GIC_DIST_CONFIG +#define GIC_DIST_CONFIG_SPI32 (GIC_DIST_CONFIG + IRQ_SHPI_START / 4) + +/* TODO! Move STM reg offsets to suitable place */ +#define STM_CR_OFFSET 0x00 +#define STM_MMC_OFFSET 0x08 +#define STM_TER_OFFSET 0x10 + +#define TPIU_PORT_SIZE 0x4 +#define TPIU_TRIGGER_COUNTER 0x104 +#define TPIU_TRIGGER_MULTIPLIER 0x108 +#define TPIU_CURRENT_TEST_PATTERN 0x204 +#define TPIU_TEST_PATTERN_REPEAT 0x208 +#define TPIU_FORMATTER 0x304 +#define TPIU_FORMATTER_SYNC 0x308 +#define TPIU_LOCK_ACCESS_REGISTER 0xFB0 + +#define TPIU_UNLOCK_CODE 0xc5acce55 + +#define SCU_FILTER_STARTADDR 0x40 +#define SCU_FILTER_ENDADDR 0x44 +#define SCU_ACCESS_CTRL_SAC 0x50 + +/* The context of the Trace Port Interface Unit (TPIU) */ +static struct { + void __iomem *base; + u32 port_size; + u32 trigger_counter; + u32 trigger_multiplier; + u32 current_test_pattern; + u32 test_pattern_repeat; + u32 formatter; + u32 formatter_sync; +} context_tpiu; + +static struct { + void __iomem *base; + u32 cr; + u32 mmc; + u32 ter; +} context_stm_ape; + +struct context_gic_cpu { + void __iomem *base; + u32 ctrl; + u32 primask; + u32 binpoint; +}; +static DEFINE_PER_CPU(struct context_gic_cpu, context_gic_cpu); + +static struct { + void __iomem *base; + u32 ns; + u32 enable_set[GIC_DIST_ENABLE_SET_COMMON_NUM]; /* IRQ 32 to 160 */ + u32 priority_level[GIC_DIST_PRI_COMMON_NUM]; + u32 spi_target[GIC_DIST_SPI_TARGET_COMMON_NUM]; + u32 config[GIC_DIST_CONFIG_COMMON_NUM]; +} context_gic_dist_common; + +struct context_gic_dist_cpu { + void __iomem *base; + u32 enable_set[GIC_DIST_ENABLE_SET_CPU_NUM]; /* IRQ 0 to 31 */ + u32 priority_level[GIC_DIST_PRI_CPU_NUM]; + u32 spi_target[GIC_DIST_SPI_TARGET_CPU_NUM]; + u32 config[GIC_DIST_CONFIG_CPU_NUM]; +}; +static DEFINE_PER_CPU(struct context_gic_dist_cpu, context_gic_dist_cpu); + +static struct { + void __iomem *base; + u32 ctrl; + u32 cpu_pwrstatus; + u32 inv_all_nonsecure; + u32 filter_start_addr; + u32 filter_end_addr; + u32 access_ctrl_sac; +} context_scu; + +#define UX500_NR_PRCC_BANKS 5 +static struct { + void __iomem *base; + struct clk *clk; + u32 bus_clk; + u32 kern_clk; +} context_prcc[UX500_NR_PRCC_BANKS]; + +static u32 backup_sram_storage[NR_CPUS] = { + IO_ADDRESS(U8500_CPU0_CP15_CR_BACKUPRAM_ADDR), + IO_ADDRESS(U8500_CPU1_CP15_CR_BACKUPRAM_ADDR), +}; + +static u32 gpio_bankaddr[GPIO_NUM_BANKS] = {IO_ADDRESS(U8500_GPIOBANK0_BASE), + IO_ADDRESS(U8500_GPIOBANK1_BASE), + IO_ADDRESS(U8500_GPIOBANK2_BASE), + IO_ADDRESS(U8500_GPIOBANK3_BASE), + IO_ADDRESS(U8500_GPIOBANK4_BASE), + IO_ADDRESS(U8500_GPIOBANK5_BASE), + IO_ADDRESS(U8500_GPIOBANK6_BASE), + IO_ADDRESS(U8500_GPIOBANK7_BASE), + IO_ADDRESS(U8500_GPIOBANK8_BASE) +}; + +static u32 gpio_save[GPIO_NUM_BANKS][GPIO_NUM_SAVE_REGISTERS]; + +void __iomem *fsmc_base_addr; +static u32 fsmc_bcr0; +/* + * Stacks and stack pointers + */ +static DEFINE_PER_CPU(u32[128], varm_registers_backup_stack); +static DEFINE_PER_CPU(u32 *, varm_registers_pointer); + +static DEFINE_PER_CPU(u32[128], varm_cp15_backup_stack); +static DEFINE_PER_CPU(u32 *, varm_cp15_pointer); + +static ATOMIC_NOTIFIER_HEAD(context_ape_notifier_list); +static ATOMIC_NOTIFIER_HEAD(context_arm_notifier_list); + +/* + * Register a simple callback for handling vape context save/restore + */ +int context_ape_notifier_register(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&context_ape_notifier_list, nb); +} +EXPORT_SYMBOL(context_ape_notifier_register); + +/* + * Remove a previously registered callback + */ +int context_ape_notifier_unregister(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&context_ape_notifier_list, + nb); +} +EXPORT_SYMBOL(context_ape_notifier_unregister); + +/* + * Register a simple callback for handling varm context save/restore + */ +int context_arm_notifier_register(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&context_arm_notifier_list, nb); +} +EXPORT_SYMBOL(context_arm_notifier_register); + +/* + * Remove a previously registered callback + */ +int context_arm_notifier_unregister(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&context_arm_notifier_list, + nb); +} +EXPORT_SYMBOL(context_arm_notifier_unregister); + +static void save_prcc(void) +{ + int i; + + for (i = 0; i < UX500_NR_PRCC_BANKS; i++) { + clk_enable(context_prcc[i].clk); + + context_prcc[i].bus_clk = + readl(context_prcc[i].base + PRCC_PCKSR); + context_prcc[i].kern_clk = + readl(context_prcc[i].base + PRCC_KCKSR); + + clk_disable(context_prcc[i].clk); + } +} + +static void restore_prcc(void) +{ + int i; + + for (i = 0; i < UX500_NR_PRCC_BANKS; i++) { + clk_enable(context_prcc[i].clk); + + writel(~context_prcc[i].bus_clk, + context_prcc[i].base + PRCC_PCKDIS); + writel(~context_prcc[i].kern_clk, + context_prcc[i].base + PRCC_KCKDIS); + + writel(context_prcc[i].bus_clk, + context_prcc[i].base + PRCC_PCKEN); + writel(context_prcc[i].kern_clk, + context_prcc[i].base + PRCC_KCKEN); + /* + * Consider having a while over KCK/BCK_STATUS + * to check that all clocks get disabled/enabled + */ + + clk_disable(context_prcc[i].clk); + } +} + +static void save_stm_ape(void) +{ + /* + * TODO: Check with PRCMU developers how STM is handled by PRCMU + * firmware. According to DB5500 design spec there is a "flush" + * mechanism supposed to be used by the PRCMU before power down, + * PRCMU fw might save/restore the following three registers + * at the same time. + */ + context_stm_ape.cr = readl(context_stm_ape.base + + STM_CR_OFFSET); + context_stm_ape.mmc = readl(context_stm_ape.base + + STM_MMC_OFFSET); + context_stm_ape.ter = readl(context_stm_ape.base + + STM_TER_OFFSET); +} + +static void restore_stm_ape(void) +{ + writel(context_stm_ape.ter, + context_stm_ape.base + STM_TER_OFFSET); + writel(context_stm_ape.mmc, + context_stm_ape.base + STM_MMC_OFFSET); + writel(context_stm_ape.cr, + context_stm_ape.base + STM_CR_OFFSET); +} + +static bool inline tpiu_clocked(void) +{ + return ux500_jtag_enabled(); +} + +/* + * Save the context of the Trace Port Interface Unit (TPIU). + * Saving/restoring is needed for the PTM tracing to work together + * with the sleep states ApSleep and ApDeepSleep. + */ +static void save_tpiu(void) +{ + if (!tpiu_clocked()) + return; + + context_tpiu.port_size = readl(context_tpiu.base + + TPIU_PORT_SIZE); + context_tpiu.trigger_counter = readl(context_tpiu.base + + TPIU_TRIGGER_COUNTER); + context_tpiu.trigger_multiplier = readl(context_tpiu.base + + TPIU_TRIGGER_MULTIPLIER); + context_tpiu.current_test_pattern = readl(context_tpiu.base + + TPIU_CURRENT_TEST_PATTERN); + context_tpiu.test_pattern_repeat = readl(context_tpiu.base + + TPIU_TEST_PATTERN_REPEAT); + context_tpiu.formatter = readl(context_tpiu.base + + TPIU_FORMATTER); + context_tpiu.formatter_sync = readl(context_tpiu.base + + TPIU_FORMATTER_SYNC); +} + +/* + * Restore the context of the Trace Port Interface Unit (TPIU). + * Saving/restoring is needed for the PTM tracing to work together + * with the sleep states ApSleep and ApDeepSleep. + */ +static void restore_tpiu(void) +{ + if (!tpiu_clocked()) + return; + + writel(TPIU_UNLOCK_CODE, + context_tpiu.base + TPIU_LOCK_ACCESS_REGISTER); + + writel(context_tpiu.port_size, + context_tpiu.base + TPIU_PORT_SIZE); + writel(context_tpiu.trigger_counter, + context_tpiu.base + TPIU_TRIGGER_COUNTER); + writel(context_tpiu.trigger_multiplier, + context_tpiu.base + TPIU_TRIGGER_MULTIPLIER); + writel(context_tpiu.current_test_pattern, + context_tpiu.base + TPIU_CURRENT_TEST_PATTERN); + writel(context_tpiu.test_pattern_repeat, + context_tpiu.base + TPIU_TEST_PATTERN_REPEAT); + writel(context_tpiu.formatter, + context_tpiu.base + TPIU_FORMATTER); + writel(context_tpiu.formatter_sync, + context_tpiu.base + TPIU_FORMATTER_SYNC); +} + +/* + * Save GIC CPU IF registers + * + * This is per cpu so it needs to be called for each one. + */ +static void save_gic_if_cpu(struct context_gic_cpu *c_gic_cpu) +{ + c_gic_cpu->ctrl = readl_relaxed(c_gic_cpu->base + GIC_CPU_CTRL); + c_gic_cpu->primask = readl_relaxed(c_gic_cpu->base + GIC_CPU_PRIMASK); + c_gic_cpu->binpoint = readl_relaxed(c_gic_cpu->base + GIC_CPU_BINPOINT); +} + +/* + * Restore GIC CPU IF registers + * + * This is per cpu so it needs to be called for each one. + */ +static void restore_gic_if_cpu(struct context_gic_cpu *c_gic_cpu) +{ + writel_relaxed(c_gic_cpu->ctrl, c_gic_cpu->base + GIC_CPU_CTRL); + writel_relaxed(c_gic_cpu->primask, c_gic_cpu->base + GIC_CPU_PRIMASK); + writel_relaxed(c_gic_cpu->binpoint, c_gic_cpu->base + GIC_CPU_BINPOINT); +} + +/* + * Save GIC Distributor Common registers + * + * This context is common. Only one CPU needs to call. + * + * Save SPI (Shared Peripheral Interrupt) settings, IRQ 32-159. + */ +static void save_gic_dist_common(void) +{ + int i; + + context_gic_dist_common.ns = readl_relaxed(context_gic_dist_common.base + + GIC_DIST_ENABLE_NS); + + for (i = 0; i < GIC_DIST_ENABLE_SET_COMMON_NUM; i++) + context_gic_dist_common.enable_set[i] = + readl_relaxed(context_gic_dist_common.base + + GIC_DIST_ENABLE_SET_SPI32 + i * 4); + + for (i = 0; i < GIC_DIST_PRI_COMMON_NUM; i++) + context_gic_dist_common.priority_level[i] = + readl_relaxed(context_gic_dist_common.base + + GIC_DIST_PRI_SPI32 + i * 4); + + for (i = 0; i < GIC_DIST_SPI_TARGET_COMMON_NUM; i++) + context_gic_dist_common.spi_target[i] = + readl_relaxed(context_gic_dist_common.base + + GIC_DIST_SPI_TARGET_SPI32 + i * 4); + + for (i = 0; i < GIC_DIST_CONFIG_COMMON_NUM; i++) + context_gic_dist_common.config[i] = + readl_relaxed(context_gic_dist_common.base + + GIC_DIST_CONFIG_SPI32 + i * 4); +} + +/* + * Restore GIC Distributor Common registers + * + * This context is common. Only one CPU needs to call. + * + * Save SPI (Shared Peripheral Interrupt) settings, IRQ 32-159. + */ +static void restore_gic_dist_common(void) +{ + int i; + + for (i = 0; i < GIC_DIST_CONFIG_COMMON_NUM; i++) + writel_relaxed(context_gic_dist_common.config[i], + context_gic_dist_common.base + + GIC_DIST_CONFIG_SPI32 + i * 4); + + for (i = 0; i < GIC_DIST_SPI_TARGET_COMMON_NUM; i++) + writel_relaxed(context_gic_dist_common.spi_target[i], + context_gic_dist_common.base + + GIC_DIST_SPI_TARGET_SPI32 + i * 4); + + for (i = 0; i < GIC_DIST_PRI_COMMON_NUM; i++) + writel_relaxed(context_gic_dist_common.priority_level[i], + context_gic_dist_common.base + + GIC_DIST_PRI_SPI32 + i * 4); + + for (i = 0; i < GIC_DIST_ENABLE_SET_COMMON_NUM; i++) + writel_relaxed(context_gic_dist_common.enable_set[i], + context_gic_dist_common.base + + GIC_DIST_ENABLE_SET_SPI32 + i * 4); + + writel_relaxed(context_gic_dist_common.ns, + context_gic_dist_common.base + GIC_DIST_ENABLE_NS); +} + +/* + * Save GIC Dist CPU registers + * + * This needs to be called by all cpu:s which will not call + * save_gic_dist_common(). Only the registers of the GIC which are + * banked will be saved. + */ +static void save_gic_dist_cpu(struct context_gic_dist_cpu *c_gic) +{ + int i; + + for (i = 0; i < GIC_DIST_ENABLE_SET_CPU_NUM; i++) + c_gic->enable_set[i] = + readl_relaxed(c_gic->base + + GIC_DIST_ENABLE_SET_SPI0 + i * 4); + + for (i = 0; i < GIC_DIST_PRI_CPU_NUM; i++) + c_gic->priority_level[i] = + readl_relaxed(c_gic->base + + GIC_DIST_PRI_SPI0 + i * 4); + + for (i = 0; i < GIC_DIST_SPI_TARGET_CPU_NUM; i++) + c_gic->spi_target[i] = + readl_relaxed(c_gic->base + + GIC_DIST_SPI_TARGET_SPI0 + i * 4); + + for (i = 0; i < GIC_DIST_CONFIG_CPU_NUM; i++) + c_gic->config[i] = + readl_relaxed(c_gic->base + + GIC_DIST_CONFIG_SPI0 + i * 4); +} + +/* + * Restore GIC Dist CPU registers + * + * This needs to be called by all cpu:s which will not call + * restore_gic_dist_common(). Only the registers of the GIC which are + * banked will be saved. + */ +static void restore_gic_dist_cpu(struct context_gic_dist_cpu *c_gic) +{ + int i; + + for (i = 0; i < GIC_DIST_CONFIG_CPU_NUM; i++) + writel_relaxed(c_gic->config[i], + c_gic->base + + GIC_DIST_CONFIG_SPI0 + i * 4); + + for (i = 0; i < GIC_DIST_SPI_TARGET_CPU_NUM; i++) + writel_relaxed(c_gic->spi_target[i], + c_gic->base + + GIC_DIST_SPI_TARGET_SPI0 + i * 4); + + for (i = 0; i < GIC_DIST_PRI_CPU_NUM; i++) + writel_relaxed(c_gic->priority_level[i], + c_gic->base + + GIC_DIST_PRI_SPI0 + i * 4); + + for (i = 0; i < GIC_DIST_ENABLE_SET_CPU_NUM; i++) + writel_relaxed(c_gic->enable_set[i], + c_gic->base + + GIC_DIST_ENABLE_SET_SPI0 + i * 4); +} + +/* + * Disable interrupts that are not necessary + * to have turned on during ApDeepSleep. + */ +void context_gic_dist_disable_unneeded_irqs(void) +{ + writel(0xffffffff, + context_gic_dist_common.base + + GIC_DIST_ENABLE_CLEAR_0); + + writel(0xffffffff, + context_gic_dist_common.base + + GIC_DIST_ENABLE_CLEAR_32); + + /* Leave PRCMU IRQ 0 and 1 enabled */ + writel(0xffff3fff, + context_gic_dist_common.base + + GIC_DIST_ENABLE_CLEAR_64); + + writel(0xffffffff, + context_gic_dist_common.base + + GIC_DIST_ENABLE_CLEAR_96); + + writel(0xffffffff, + context_gic_dist_common.base + + GIC_DIST_ENABLE_CLEAR_128); +} + +static void save_scu(void) +{ + context_scu.ctrl = + readl_relaxed(context_scu.base + SCU_CTRL); + context_scu.cpu_pwrstatus = + readl_relaxed(context_scu.base + SCU_CPU_STATUS); + context_scu.inv_all_nonsecure = + readl_relaxed(context_scu.base + SCU_INVALIDATE); + context_scu.filter_start_addr = + readl_relaxed(context_scu.base + SCU_FILTER_STARTADDR); + context_scu.filter_end_addr = + readl_relaxed(context_scu.base + SCU_FILTER_ENDADDR); + context_scu.access_ctrl_sac = + readl_relaxed(context_scu.base + SCU_ACCESS_CTRL_SAC); +} + +static void restore_scu(void) +{ + writel_relaxed(context_scu.ctrl, + context_scu.base + SCU_CTRL); + writel_relaxed(context_scu.cpu_pwrstatus, + context_scu.base + SCU_CPU_STATUS); + writel_relaxed(context_scu.inv_all_nonsecure, + context_scu.base + SCU_INVALIDATE); + writel_relaxed(context_scu.filter_start_addr, + context_scu.base + SCU_FILTER_STARTADDR); + writel_relaxed(context_scu.filter_end_addr, + context_scu.base + SCU_FILTER_ENDADDR); + writel_relaxed(context_scu.access_ctrl_sac, + context_scu.base + SCU_ACCESS_CTRL_SAC); +} + +/* + * Save VAPE context + */ +void context_vape_save(void) +{ + atomic_notifier_call_chain(&context_ape_notifier_list, + CONTEXT_APE_SAVE, NULL); + + if (cpu_is_u5500()) + u5500_context_save_icn(); + if (cpu_is_u8500()) + u8500_context_save_icn(); + if (cpu_is_u9540()) + u9540_context_save_icn(); + + save_stm_ape(); + + save_tpiu(); + + save_prcc(); +} + +/* + * Restore VAPE context + */ +void context_vape_restore(void) +{ + restore_prcc(); + + restore_tpiu(); + + restore_stm_ape(); + + if (cpu_is_u5500()) + u5500_context_restore_icn(); + if (cpu_is_u8500()) + u8500_context_restore_icn(); + if (cpu_is_u9540()) + u9540_context_restore_icn(); + + atomic_notifier_call_chain(&context_ape_notifier_list, + CONTEXT_APE_RESTORE, NULL); +} + +/* + * Save FSMC registers that will be reset + * during power save. + */ +void context_fsmc_save(void) +{ + fsmc_base_addr = ioremap_nocache(U8500_FSMC_BASE, 8); + fsmc_bcr0 = readl(fsmc_base_addr); +} + +/* + * Restore FSMC registers that will be reset + * during power save. + */ +void context_fsmc_restore(void) +{ + writel(fsmc_bcr0, fsmc_base_addr); + iounmap(fsmc_base_addr); +} + +/* + * Save GPIO registers that might be modified + * for power save reasons. + */ +void context_gpio_save(void) +{ + int i; + + for (i = 0; i < GPIO_NUM_BANKS; i++) { + gpio_save[i][0] = readl(gpio_bankaddr[i] + NMK_GPIO_AFSLA); + gpio_save[i][1] = readl(gpio_bankaddr[i] + NMK_GPIO_AFSLB); + gpio_save[i][2] = readl(gpio_bankaddr[i] + NMK_GPIO_PDIS); + gpio_save[i][3] = readl(gpio_bankaddr[i] + NMK_GPIO_DIR); + gpio_save[i][4] = readl(gpio_bankaddr[i] + NMK_GPIO_DAT); + gpio_save[i][6] = readl(gpio_bankaddr[i] + NMK_GPIO_SLPC); + } + +} + +/* + * Restore GPIO registers that might be modified + * for power save reasons. + */ +void context_gpio_restore(void) +{ + int i; + u32 output_state; + u32 pull_up; + u32 pull_down; + u32 pull; + + for (i = 0; i < GPIO_NUM_BANKS; i++) { + writel(gpio_save[i][2], gpio_bankaddr[i] + NMK_GPIO_PDIS); + + writel(gpio_save[i][3], gpio_bankaddr[i] + NMK_GPIO_DIR); + + /* Set the high outputs. outpute_state = GPIO_DIR & GPIO_DAT */ + output_state = gpio_save[i][3] & gpio_save[i][4]; + writel(output_state, gpio_bankaddr[i] + NMK_GPIO_DATS); + + /* + * Set the low outputs. + * outpute_state = ~(GPIO_DIR & GPIO_DAT) & GPIO_DIR + */ + output_state = ~(gpio_save[i][3] & gpio_save[i][4]) & + gpio_save[i][3]; + writel(output_state, gpio_bankaddr[i] + NMK_GPIO_DATC); + + /* + * Restore pull up/down. + * Only write pull up/down settings on inputs where + * PDIS is not set. + * pull = (~GPIO_DIR & ~GPIO_PDIS) + */ + pull = (~gpio_save[i][3] & ~gpio_save[i][2]); + nmk_gpio_read_pull(i, &pull_up); + + pull_down = pull & ~pull_up; + pull_up = pull & pull_up; + /* Set pull ups */ + writel(pull_up, gpio_bankaddr[i] + NMK_GPIO_DATS); + /* Set pull downs */ + writel(pull_down, gpio_bankaddr[i] + NMK_GPIO_DATC); + + writel(gpio_save[i][6], gpio_bankaddr[i] + NMK_GPIO_SLPC); + } + +} + +/* + * Restore GPIO mux registers that might be modified + * for power save reasons. + */ +void context_gpio_restore_mux(void) +{ + int i; + + /* Change mux settings */ + for (i = 0; i < GPIO_NUM_BANKS; i++) { + writel(gpio_save[i][0], gpio_bankaddr[i] + NMK_GPIO_AFSLA); + writel(gpio_save[i][1], gpio_bankaddr[i] + NMK_GPIO_AFSLB); + } +} + +/* + * Safe sequence used to switch IOs between GPIO and Alternate-C mode: + * - Save SLPM registers (Not done.) + * - Set SLPM=0 for the IOs you want to switch. (We assume that all + * SLPM registers already are 0 except for the ones that wants to + * have the mux connected in sleep (e.g modem STM)). + * - Configure the GPIO registers for the IOs that are being switched + * - Set IOFORCE=1 + * - Modify the AFLSA/B registers for the IOs that are being switched + * - Set IOFORCE=0 + * - Restore SLPM registers (Not done.) + * - Any spurious wake up event during switch sequence to be ignored + * and cleared + */ +void context_gpio_mux_safe_switch(bool begin) +{ + int i; + + static u32 rwimsc[GPIO_NUM_BANKS]; + static u32 fwimsc[GPIO_NUM_BANKS]; + + if (begin) { + for (i = 0; i < GPIO_NUM_BANKS; i++) { + /* Save registers */ + rwimsc[i] = readl(gpio_bankaddr[i] + NMK_GPIO_RWIMSC); + fwimsc[i] = readl(gpio_bankaddr[i] + NMK_GPIO_FWIMSC); + + /* Prevent spurious wakeups */ + writel(0, gpio_bankaddr[i] + NMK_GPIO_RWIMSC); + writel(0, gpio_bankaddr[i] + NMK_GPIO_FWIMSC); + } + + ux500_pm_prcmu_set_ioforce(true); + } else { + ux500_pm_prcmu_set_ioforce(false); + + /* Restore wake up settings */ + for (i = 0; i < GPIO_NUM_BANKS; i++) { + writel(rwimsc[i], gpio_bankaddr[i] + NMK_GPIO_RWIMSC); + writel(fwimsc[i], gpio_bankaddr[i] + NMK_GPIO_FWIMSC); + } + } +} + +/* + * Save common + * + * This function must be called once for all cores before going to deep sleep. + */ +void context_varm_save_common(void) +{ + atomic_notifier_call_chain(&context_arm_notifier_list, + CONTEXT_ARM_COMMON_SAVE, NULL); + + /* Save common parts */ + save_gic_dist_common(); + save_scu(); +} + +/* + * Restore common + * + * This function must be called once for all cores when waking up from deep + * sleep. + */ +void context_varm_restore_common(void) +{ + /* Restore common parts */ + restore_scu(); + restore_gic_dist_common(); + + atomic_notifier_call_chain(&context_arm_notifier_list, + CONTEXT_ARM_COMMON_RESTORE, NULL); +} + +/* + * Save core + * + * This function must be called once for each cpu core before going to deep + * sleep. + */ +void context_varm_save_core(void) +{ + int cpu = smp_processor_id(); + + atomic_notifier_call_chain(&context_arm_notifier_list, + CONTEXT_ARM_CORE_SAVE, NULL); + + per_cpu(varm_cp15_pointer, cpu) = per_cpu(varm_cp15_backup_stack, cpu); + + /* Save core */ + twd_save(); + save_gic_if_cpu(&per_cpu(context_gic_cpu, cpu)); + save_gic_dist_cpu(&per_cpu(context_gic_dist_cpu, cpu)); + context_save_cp15_registers(&per_cpu(varm_cp15_pointer, cpu)); +} + +/* + * Restore core + * + * This function must be called once for each cpu core when waking up from + * deep sleep. + */ +void context_varm_restore_core(void) +{ + int cpu = smp_processor_id(); + + /* Restore core */ + context_restore_cp15_registers(&per_cpu(varm_cp15_pointer, cpu)); + restore_gic_dist_cpu(&per_cpu(context_gic_dist_cpu, cpu)); + restore_gic_if_cpu(&per_cpu(context_gic_cpu, cpu)); + twd_restore(); + + atomic_notifier_call_chain(&context_arm_notifier_list, + CONTEXT_ARM_CORE_RESTORE, NULL); +} + +/* + * Save CPU registers + * + * This function saves ARM registers. + */ +void context_save_cpu_registers(void) +{ + int cpu = smp_processor_id(); + + per_cpu(varm_registers_pointer, cpu) = + per_cpu(varm_registers_backup_stack, cpu); + context_save_arm_registers(&per_cpu(varm_registers_pointer, cpu)); +} + +/* + * Restore CPU registers + * + * This function restores ARM registers. + */ +void context_restore_cpu_registers(void) +{ + int cpu = smp_processor_id(); + + context_restore_arm_registers(&per_cpu(varm_registers_pointer, cpu)); +} + +/* + * This function stores CP15 registers related to cache and mmu + * in backup SRAM. It also stores stack pointer, CPSR + * and return address for the PC in backup SRAM and + * does wait for interrupt. + */ +void context_save_to_sram_and_wfi(bool cleanL2cache) +{ + int cpu = smp_processor_id(); + + context_save_to_sram_and_wfi_internal(backup_sram_storage[cpu], + cleanL2cache); +} + +static int __init context_init(void) +{ + int i; + void __iomem *ux500_backup_ptr; + + /* allocate backup pointer for RAM data */ + ux500_backup_ptr = (void *)__get_free_pages(GFP_KERNEL, + get_order(U8500_BACKUPRAM_SIZE)); + + if (!ux500_backup_ptr) { + pr_warning("context: could not allocate backup memory\n"); + return -ENOMEM; + } + + /* + * ROM code addresses to store backup contents, + * pass the physical address of back up to ROM code + */ + writel(virt_to_phys(ux500_backup_ptr), + IO_ADDRESS(U8500_EXT_RAM_LOC_BACKUPRAM_ADDR)); + + if (cpu_is_u5500()) { + writel(IO_ADDRESS(U5500_PUBLIC_BOOT_ROM_BASE), + IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); + + writel(IO_ADDRESS(U5500_PUBLIC_BOOT_ROM_BASE), + IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); + + context_tpiu.base = ioremap(U5500_TPIU_BASE, SZ_4K); + context_stm_ape.base = ioremap(U5500_STM_REG_BASE, SZ_4K); + context_scu.base = ioremap(U5500_SCU_BASE, SZ_4K); + + context_prcc[0].base = ioremap(U5500_CLKRST1_BASE, SZ_4K); + context_prcc[1].base = ioremap(U5500_CLKRST2_BASE, SZ_4K); + context_prcc[2].base = ioremap(U5500_CLKRST3_BASE, SZ_4K); + context_prcc[3].base = ioremap(U5500_CLKRST5_BASE, SZ_4K); + context_prcc[4].base = ioremap(U5500_CLKRST6_BASE, SZ_4K); + + context_gic_dist_common.base = ioremap(U5500_GIC_DIST_BASE, SZ_4K); + per_cpu(context_gic_cpu, 0).base = ioremap(U5500_GIC_CPU_BASE, SZ_4K); + } else if (cpu_is_u8500() || cpu_is_u9540()) { + /* Give logical address to backup RAM. For both CPUs */ + if (cpu_is_u9540()) { + writel(IO_ADDRESS_DB9540_ROM(U9540_PUBLIC_BOOT_ROM_BASE), + IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); + + writel(IO_ADDRESS_DB9540_ROM(U9540_PUBLIC_BOOT_ROM_BASE), + IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); + } else { + writel(IO_ADDRESS(U8500_PUBLIC_BOOT_ROM_BASE), + IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); + + writel(IO_ADDRESS(U8500_PUBLIC_BOOT_ROM_BASE), + IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); + } + + context_tpiu.base = ioremap(U8500_TPIU_BASE, SZ_4K); + context_stm_ape.base = ioremap(U8500_STM_REG_BASE, SZ_4K); + context_scu.base = ioremap(U8500_SCU_BASE, SZ_4K); + + /* PERIPH4 is always on, so no need saving prcc */ + context_prcc[0].base = ioremap(U8500_CLKRST1_BASE, SZ_4K); + context_prcc[1].base = ioremap(U8500_CLKRST2_BASE, SZ_4K); + context_prcc[2].base = ioremap(U8500_CLKRST3_BASE, SZ_4K); + context_prcc[3].base = ioremap(U8500_CLKRST5_BASE, SZ_4K); + context_prcc[4].base = ioremap(U8500_CLKRST6_BASE, SZ_4K); + + context_gic_dist_common.base = ioremap(U8500_GIC_DIST_BASE, SZ_4K); + per_cpu(context_gic_cpu, 0).base = ioremap(U8500_GIC_CPU_BASE, SZ_4K); + } + + per_cpu(context_gic_dist_cpu, 0).base = context_gic_dist_common.base; + + for (i = 1; i < num_possible_cpus(); i++) { + per_cpu(context_gic_cpu, i).base + = per_cpu(context_gic_cpu, 0).base; + per_cpu(context_gic_dist_cpu, i).base + = per_cpu(context_gic_dist_cpu, 0).base; + } + + for (i = 0; i < ARRAY_SIZE(context_prcc); i++) { + const int clusters[] = {1, 2, 3, 5, 6}; + char clkname[10]; + + snprintf(clkname, sizeof(clkname), "PERIPH%d", clusters[i]); + + context_prcc[i].clk = clk_get_sys(clkname, NULL); + BUG_ON(IS_ERR(context_prcc[i].clk)); + } + + if (cpu_is_u8500()) { + u8500_context_init(); + } else if (cpu_is_u5500()) { + u5500_context_init(); + } else if (cpu_is_u9540()) { + u9540_context_init(); + } else { + printk(KERN_ERR "context: unknown hardware!\n"); + return -EINVAL; + } + + return 0; +} +subsys_initcall(context_init); diff --git a/arch/arm/mach-ux500/pm/context_arm.S b/arch/arm/mach-ux500/pm/context_arm.S new file mode 100644 index 00000000000..edb894d6a35 --- /dev/null +++ b/arch/arm/mach-ux500/pm/context_arm.S @@ -0,0 +1,409 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> + * Rickard Andersson <rickard.andersson@stericsson.com> for + * ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + * + */ + +#include <linux/linkage.h> +#include <mach/hardware.h> +#include <asm/hardware/cache-l2x0.h> + +/* + * Save and increment macro + */ +.macro SAVE_AND_INCREMENT FROM_REG TO_REG + str \FROM_REG, [\TO_REG], #+4 +.endm + +/* + * Decrement and restore macro + */ +.macro DECREMENT_AND_RESTORE FROM_REG TO_REG + ldr \TO_REG, [\FROM_REG, #-4]! +.endm + +/* + * Save ARM registers + * + * This function must be called in supervisor mode. + * + * r0 = address to backup stack pointer + * + * Backup stack operations: + * + {sp, lr}^ + * + cpsr + * + {r3, r8-r14} (FIQ mode: r3=spsr) + * + {r3, r13, r14} (IRQ mode: r3=spsr) + * + {r3, r13, r14} (abort mode: r3=spsr) + * + {r3, r13, r14} (undef mode: r3=spsr) + */ + .align + .section ".text", "ax" +ENTRY(context_save_arm_registers) + stmfd sp!, {r1, r2, r3, lr} @ Save on stack + ldr r1, [r0] @ Read backup stack pointer + +ARM( stmia r1, {sp, lr}^ ) @ Store user mode sp and lr + @ registers +ARM( add r1, r1, #8 ) @ Update backup pointer (not + @ done in previous instruction) +THUMB( str sp, [r1], #+4 ) +THUMB( str lr, [r1], #+4 ) + + mrs r2, cpsr @ Get CPSR + SAVE_AND_INCREMENT r2 r1 @ Save CPSR register + orr r2, r2, #0xc0 @ Disable FIQ and IRQ + bic r2, r2, #0x1f @ Setup r2 to change mode + + @ The suffix to CPSR refers to which field(s) of the CPSR is + @ rereferenced (you can specify one or more). Defined fields are: + @ + @ c - control + @ x - extension + @ s - status + @ f - flags + + orr r3, r2, #0x11 @ Save FIQ mode registers + msr cpsr_cxsf, r3 + mrs r3, spsr +ARM( stmia r1!, {r3, r8-r14} ) +THUMB( stmia r1!, {r3, r8-r12, r14} ) +THUMB( str r13, [r1], #+4 ) + + + orr r3, r2, #0x12 @ Save IRQ mode registers + msr cpsr_cxsf, r3 + mrs r3, spsr +ARM( stmia r1!, {r3, r13, r14} ) +THUMB( stmia r1!, {r3, r14} ) +THUMB( str r13, [r1], #+4 ) + + orr r3, r2, #0x17 @ Save abort mode registers + + @ common mode registers + msr cpsr_cxsf, r3 + mrs r3, spsr +ARM( stmia r1!, {r3, r13, r14} ) +THUMB( stmia r1!, {r3, r14} ) +THUMB( str r13, [r1], #+4 ) + + orr r3, r2, #0x1B @ Save undef mode registers + msr cpsr_cxsf, r3 + mrs r3, spsr +ARM( stmia r1!, {r3, r13, r14} ) +THUMB( stmia r1!, {r3, r14} ) +THUMB( str r13, [r1], #+4 ) + + orr r3, r2, #0x13 @ Return to supervisor mode + msr cpsr_cxsf, r3 + + str r1, [r0] @ Write backup stack pointer + ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return + + + +/* + * Restore ARM registers + * + * This function must be called in supervisor mode. + * + * r0 = address to backup stack pointer + * + * Backup stack operations: + * - {r3, r13, r14} (undef mode: spsr=r3) + * - {r3, r13, r14} (abort mode: spsr=r3) + * - {r3, r13, r14} (IRQ mode: spsr=r3) + * - {r3, r8-r14} (FIQ mode: spsr=r3) + * - cpsr + * - {sp, lr}^ + */ + .align + .section ".text", "ax" +ENTRY(context_restore_arm_registers) + stmfd sp!, {r1, r2, r3, lr} @ Save on stack + ldr r1, [r0] @ Read backup stack pointer + + mrs r2, cpsr @ Get CPSR + orr r2, r2, #0xc0 @ Disable FIQ and IRQ + bic r2, r2, #0x1f @ Setup r2 to change mode + + orr r3, r2, #0x1b @ Restore undef mode registers + msr cpsr_cxsf, r3 +ARM( ldmdb r1!, {r3, r13, r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r14} ) + msr spsr_cxsf, r3 + + orr r3, r2, #0x17 @ Restore abort mode registers + msr cpsr_cxsf, r3 +ARM( ldmdb r1!, {r3, r13, r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r14} ) + msr spsr_cxsf, r3 + + orr r3, r2, #0x12 @ Restore IRQ mode registers + msr cpsr_cxsf, r3 +ARM( ldmdb r1!, {r3, r13, r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r14} ) + msr spsr_cxsf, r3 + + orr r3, r2, #0x11 @ Restore FIQ mode registers + msr cpsr_cxsf, r3 +ARM( ldmdb r1!, {r3, r8-r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r8-r12, r14} ) + + msr spsr_cxsf, r3 + + DECREMENT_AND_RESTORE r1 r3 @ Restore cpsr register + msr cpsr_cxsf, r3 + +ARM( ldmdb r1, {sp, lr}^ ) @ Restore sp and lr registers +ARM( sub r1, r1, #8 ) @ Update backup pointer (not + @ done in previous instruction) +THUMB( ldr lr, [r1], #-4 ) +THUMB( ldr sp, [r1], #-4 ) + + str r1, [r0] @ Write backup stack pointer + ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return + + + +/* + * Save CP15 registers + * + * This function must be called in supervisor mode. + * + * r0 = address to backup stack pointer + * + * TTBR0, TTBR1, TTBRC, DACR CP15 registers are restored by boot ROM from SRAM. + */ + .align 4 + .section ".text", "ax" +ENTRY(context_save_cp15_registers) + stmfd sp!, {r1, r2, r3, lr} @ Save on stack (r3 is saved due + @ to 8 byte aligned stack) + ldr r1, [r0] @ Read backup stack pointer + + mrc p15, 0, r2, c12, c0, 0 @ Read Non-secure Vector Base + @ Address Register + SAVE_AND_INCREMENT r2 r1 + + mrc p15, 0, r2, c10, c2, 0 @ Access primary memory region + @ remap register + SAVE_AND_INCREMENT r2 r1 + + mrc p15, 0, r2, c10, c2, 1 @ Access normal memory region + @ remap register + SAVE_AND_INCREMENT r2 r1 + + mrc p15, 0, r2, c13, c0, 1 @ Read Context ID Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c13, c0, 2 @ Read Thread ID registers, + @ this register is both user + @ and privileged R/W accessible + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c13, c0, 3 @ Read Thread ID registers, + @ this register is user + @ read-only and privileged R/W + @ accessible. + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c13, c0, 4 @ Read Thread ID registers, + @ this register is privileged + @ R/W accessible only. + SAVE_AND_INCREMENT r2 r1 + + mrc p15, 2, r2, c0, c0, 0 @ Cache Size Selection Register + SAVE_AND_INCREMENT r2 r1 + + mrc p15, 0, r2, c9, c12, 0 @ Read PMNC Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c12, 1 @ Read PMCNTENSET Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c12, 5 @ Read PMSELR Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c13, 0 @ Read PMCCNTR Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c13, 1 @ Read PMXEVTYPER Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c14, 0 @ Read PMUSERENR Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c14, 1 @ Read PMINTENSET Register + SAVE_AND_INCREMENT r2 r1 + mrc p15, 0, r2, c9, c14, 2 @ Read PMINTENCLR Register + SAVE_AND_INCREMENT r2 r1 + + mrc p15, 0, r2, c1, c0, 2 @ Read CPACR Register + SAVE_AND_INCREMENT r2 r1 + + str r1, [r0] @ Write backup stack pointer + ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return + + + +/* + * Restore CP15 registers + * + * This function must be called in supervisor mode. + * + * r0 = address to backup stack pointer + */ + .align 4 + .section ".text", "ax" +ENTRY(context_restore_cp15_registers) + stmfd sp!, {r1, r2, r3, lr} @ Save on stack (r3 is saved due + @ to 8 byte aligned stack) + ldr r1, [r0] @ Read backup stack pointer + + DECREMENT_AND_RESTORE r1 r2 @ Write CPACR register + mcr p15, 0, r2, c1, c0, 2 + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c14, 2 @ Write PMINTENCLR Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c14, 1 @ Write PMINTENSET Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c14, 0 @ Write PMUSERENR Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c13, 1 @ Write PMXEVTYPER Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c13, 0 @ Write PMCCNTR Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c12, 5 @ Write PMSELR Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c12, 1 @ Write PMCNTENSET Register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c9, c12, 0 @ Write PMNC Register + + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 2, r2, c0, c0, 0 @ Cache Size Selection Register + + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c13, c0, 4 @ Write Thread ID registers, + @ this register is privileged + @ R/W accessible only + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c13, c0, 3 @ Write Thread ID registers, + @ this register is user + @ read-only and privileged R/W + @ accessible + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c13, c0, 2 @ Write Thread ID registers, + @ this register is both user + @ and privileged R/W accessible + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c13, c0, 1 @ Write Context ID Register + + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c10, c2, 1 @ Access normal memory region + @ remap register + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c10, c2, 0 @ Access primary memory region + @ remap register + + DECREMENT_AND_RESTORE r1 r2 + mcr p15, 0, r2, c12, c0, 0 @ Write Non-secure Vector Base + @ Address Register + + str r1, [r0] @ Write backup stack pointer + ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return + + +/* + * L1 cache clean function. Commit 'dirty' data from L1 + * to L2 cache. + * + * r0, r1, r2, used locally + * + */ + .align 4 + .section ".text", "ax" +ENTRY(context_clean_l1_cache_all) + + mov r0, #0 @ swith to cache level 0 + @ (L1 cache) + mcr p15, 2, r0, c0, c0, 0 @ select current cache level + @ in cssr + + dmb + mov r1, #0 @ r1 = way index +wayLoopL1clean: + mov r0, #0 @ r0 = line index +lineLoopL1clean: + mov r2, r1, lsl #30 @ TODO: OK to hard-code + @ SoC-specific L1 cache details? + mov r3, r0, lsl #5 + add r2, r3 +@ add r2, r0, lsl #5 + mcr p15, 0, r2, c7, c10, 2 @ Clean cache by set/way + add r0, r0, #1 + cmp r0, #256 @ TODO: Ok with hard-coded + @ set/way sizes or do we have to + @ read them from ARM regs? Is it + @ set correctly in silicon? + bne lineLoopL1clean + add r1, r1, #1 + cmp r1, #4 @ TODO: Ditto, sizes... + bne wayLoopL1clean + + dsb + isb + mov pc, lr + +ENDPROC(context_clean_l1_cache_all) + +/* + * Last saves to backup RAM, cache clean and WFI + * + * r0 = address to backup_sram_storage base adress + * r1 = indicate whether also L2 cache should be cleaned + */ + .align 4 + .section ".text", "ax" +ENTRY(context_save_to_sram_and_wfi_internal) + + stmfd sp!, {r2-r12, lr} @ save on stack. + + mrc p15, 0, r2, c1, c0, 0 @ read cp15 system control + @ register + str r2, [r0, #0x00] + mrc p15, 0, r2, c2, c0, 0 @ read cp15 ttb0 register + str r2, [r0, #0x04] + mrc p15, 0, r2, c2, c0, 1 @ read cp15 ttb1 register + str r2, [r0, #0x08] + mrc p15, 0, r2, c2, c0, 2 @ read cp15 ttb control register + str r2, [r0, #0x0C] + mrc p15, 0, r2, c3, c0, 0 @ read domain access control + @ register + str r2, [r0, #0x10] + + ldr r2, =return_here + str r2, [r0, #0x14] @ save program counter restore + @ value to backup_sram_storage + mrs r2, cpsr + str r2, [r0, #0x18] @ save cpsr to + @ backup_sram_storage + str sp, [r0, #0x1c] @ save sp to backup_sram_storage + + mov r4, r1 @ Set r4 = cleanL2cache, r1 + @ will be destroyed by + @ v7_clean_l1_cache_all + + bl context_clean_l1_cache_all @ Commit all dirty data in L1 + @ cache to L2 without + @ invalidating + + dsb @ data synchronization barrier + isb @ instruction synchronization + @ barrier + wfi @ wait for interrupt + +return_here: @ both cores return here + @ now we are out deep sleep + @ with all the context lost + @ except pc, sp and cpsr + + ldmfd sp!, {r2-r12, pc} @ restore from stack + diff --git a/arch/arm/mach-ux500/pm/performance.c b/arch/arm/mach-ux500/pm/performance.c new file mode 100644 index 00000000000..04aca3cb5bd --- /dev/null +++ b/arch/arm/mach-ux500/pm/performance.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Johan Rudholm <johan.rudholm@stericsson.com> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + */ + +#include <linux/kernel.h> +#include <linux/genhd.h> +#include <linux/major.h> +#include <linux/cdev.h> +#include <linux/kernel_stat.h> +#include <linux/workqueue.h> +#include <linux/kernel.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/cpu.h> +#include <linux/pm_qos.h> + +#include <mach/irqs.h> + +#define WLAN_PROBE_DELAY 3000 /* 3 seconds */ +#define WLAN_LIMIT (3000/3) /* If we have more than 1000 irqs per second */ + +/* + * MMC TODO: + * o Develop a more power-aware algorithm + * o Make the parameters visible through debugfs + * o Get the value of CONFIG_MMC_BLOCK_MINORS in runtime instead, since + * it may be altered by drivers/mmc/card/block.c + */ + +/* Sample reads and writes every n ms */ +#define PERF_MMC_PROBE_DELAY 1000 +/* Read threshold, sectors/second */ +#define PERF_MMC_LIMIT_READ 10240 +/* Write threshold, sectors/second */ +#define PERF_MMC_LIMIT_WRITE 8192 +/* Nr of MMC devices */ +#define PERF_MMC_HOSTS 8 + +/* + * Rescan for new MMC devices every + * PERF_MMC_PROBE_DELAY * PERF_MMC_RESCAN_CYCLES ms + */ +#define PERF_MMC_RESCAN_CYCLES 10 + +#ifdef CONFIG_MMC_BLOCK +static struct delayed_work work_mmc; +#endif + +static struct delayed_work work_wlan_workaround; +static struct pm_qos_request wlan_pm_qos_latency; +static bool wlan_pm_qos_is_latency_0; + +static void wlan_load(struct work_struct *work) +{ + int cpu; + unsigned int num_irqs = 0; + static unsigned int old_num_irqs = UINT_MAX; + + for_each_online_cpu(cpu) + num_irqs += kstat_irqs_cpu(IRQ_DB8500_SDMMC1, cpu); + + if ((num_irqs > old_num_irqs) && + (num_irqs - old_num_irqs) > WLAN_LIMIT) { + prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "wlan", 125); + if (!wlan_pm_qos_is_latency_0) { + /* + * The wake up latency is set to 0 to prevent + * the system from going to sleep. This improves + * the wlan throughput in DMA mode. + * The wake up latency from sleep adds ~5% overhead + * for TX in some cases. + * This change doesn't increase performance for wlan + * PIO since the CPU usage prevents sleep in this mode. + */ + pm_qos_add_request(&wlan_pm_qos_latency, + PM_QOS_CPU_DMA_LATENCY, 0); + wlan_pm_qos_is_latency_0 = true; + } + } else { + prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "wlan", 25); + if (wlan_pm_qos_is_latency_0) { + pm_qos_remove_request(&wlan_pm_qos_latency); + wlan_pm_qos_is_latency_0 = false; + } + } + + old_num_irqs = num_irqs; + + schedule_delayed_work_on(0, + &work_wlan_workaround, + msecs_to_jiffies(WLAN_PROBE_DELAY)); +} + +#ifdef CONFIG_MMC_BLOCK +/* + * Loop through every CONFIG_MMC_BLOCK_MINORS'th minor device for + * MMC_BLOCK_MAJOR, get the struct gendisk for each device. Returns + * nr of found disks. Populate mmc_disks. + */ +static int scan_mmc_devices(struct gendisk *mmc_disks[]) +{ + dev_t devnr; + int i, j = 0, part; + struct gendisk *mmc_devices[256 / CONFIG_MMC_BLOCK_MINORS]; + + memset(&mmc_devices, 0, sizeof(mmc_devices)); + + for (i = 0; i * CONFIG_MMC_BLOCK_MINORS < 256; i++) { + devnr = MKDEV(MMC_BLOCK_MAJOR, i * CONFIG_MMC_BLOCK_MINORS); + mmc_devices[i] = get_gendisk(devnr, &part); + + /* Invalid capacity of device, do not add to list */ + if (!mmc_devices[i] || !get_capacity(mmc_devices[i])) + continue; + + mmc_disks[j] = mmc_devices[i]; + j++; + + if (j == PERF_MMC_HOSTS) + break; + } + + return j; +} + +/* + * Sample sectors read and written to any MMC devices, update PRCMU + * qos requirement + */ +static void mmc_load(struct work_struct *work) +{ + static unsigned long long old_sectors_read[PERF_MMC_HOSTS]; + static unsigned long long old_sectors_written[PERF_MMC_HOSTS]; + static struct gendisk *mmc_disks[PERF_MMC_HOSTS]; + static int cycle, nrdisk; + static bool old_mode; + unsigned long long sectors; + bool new_mode = false; + int i; + + if (!cycle) { + memset(&mmc_disks, 0, sizeof(mmc_disks)); + nrdisk = scan_mmc_devices(mmc_disks); + cycle = PERF_MMC_RESCAN_CYCLES; + } + cycle--; + + for (i = 0; i < nrdisk; i++) { + sectors = part_stat_read(&(mmc_disks[i]->part0), + sectors[READ]); + + if (old_sectors_read[i] && + sectors > old_sectors_read[i] && + (sectors - old_sectors_read[i]) > + PERF_MMC_LIMIT_READ) + new_mode = true; + + old_sectors_read[i] = sectors; + sectors = part_stat_read(&(mmc_disks[i]->part0), + sectors[WRITE]); + + if (old_sectors_written[i] && + sectors > old_sectors_written[i] && + (sectors - old_sectors_written[i]) > + PERF_MMC_LIMIT_WRITE) + new_mode = true; + + old_sectors_written[i] = sectors; + } + + if (!old_mode && new_mode) + prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "mmc", 125); + + if (old_mode && !new_mode) + prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "mmc", 25); + + old_mode = new_mode; + + schedule_delayed_work(&work_mmc, + msecs_to_jiffies(PERF_MMC_PROBE_DELAY)); + +} +#endif /* CONFIG_MMC_BLOCK */ + +static int __init performance_register(void) +{ + int ret; + +#ifdef CONFIG_MMC_BLOCK + ret = prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "mmc", 25); + if (ret) { + pr_err("%s: Failed to add PRCMU req for mmc\n", __func__); + goto out; + } + + INIT_DELAYED_WORK_DEFERRABLE(&work_mmc, mmc_load); + + schedule_delayed_work(&work_mmc, + msecs_to_jiffies(PERF_MMC_PROBE_DELAY)); +#endif + + ret = prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "wlan", 25); + if (ret) { + pr_err("%s: Failed to add PRCMU req for wlan\n", __func__); + goto out; + } + + INIT_DELAYED_WORK_DEFERRABLE(&work_wlan_workaround, + wlan_load); + + schedule_delayed_work_on(0, &work_wlan_workaround, + msecs_to_jiffies(WLAN_PROBE_DELAY)); +out: + return ret; +} +late_initcall(performance_register); diff --git a/arch/arm/mach-ux500/pm/pm.c b/arch/arm/mach-ux500/pm/pm.c new file mode 100644 index 00000000000..880e9763a0f --- /dev/null +++ b/arch/arm/mach-ux500/pm/pm.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Rickard Andersson <rickard.andersson@stericsson.com> for + * ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2 + * + */ + +#include <linux/io.h> +#include <linux/percpu.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> +#include <linux/mfd/dbx500-prcmu.h> + +#include <asm/hardware/gic.h> +#include <asm/processor.h> + +#include <mach/hardware.h> +#include <mach/pm.h> + +#define STABILIZATION_TIME 30 /* us */ +#define GIC_FREEZE_DELAY 1 /* us */ + +#define PRCM_ARM_WFI_STANDBY_CPU0_WFI 0x8 +#define PRCM_ARM_WFI_STANDBY_CPU1_WFI 0x10 + +/* Dual A9 core interrupt management unit registers */ +#define PRCM_A9_MASK_REQ 0x328 +#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1 +#define PRCM_A9_MASK_ACK 0x32c + +#define PRCM_ARMITMSK31TO0 0x11c +#define PRCM_ARMITMSK63TO32 0x120 +#define PRCM_ARMITMSK95TO64 0x124 +#define PRCM_ARMITMSK127TO96 0x128 +#define PRCM_POWER_STATE_VAL 0x25C +#define PRCM_ARMITVAL31TO0 0x260 +#define PRCM_ARMITVAL63TO32 0x264 +#define PRCM_ARMITVAL95TO64 0x268 +#define PRCM_ARMITVAL127TO96 0x26C + +/* ARM WFI Standby signal register */ +#define PRCM_ARM_WFI_STANDBY 0x130 + +/* IO force */ +#define PRCM_IOCR 0x310 +#define PRCM_IOCR_IOFORCE 0x1 +#ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART +int ux500_console_uart_gpio_pin = CONFIG_UX500_CONSOLE_UART_GPIO_PIN; +#endif +static u32 u8500_gpio_banks[] = {U8500_GPIOBANK0_BASE, + U8500_GPIOBANK1_BASE, + U8500_GPIOBANK2_BASE, + U8500_GPIOBANK3_BASE, + U8500_GPIOBANK4_BASE, + U8500_GPIOBANK5_BASE, + U8500_GPIOBANK6_BASE, + U8500_GPIOBANK7_BASE, + U8500_GPIOBANK8_BASE}; + +static u32 u5500_gpio_banks[] = {U5500_GPIOBANK0_BASE, + U5500_GPIOBANK1_BASE, + U5500_GPIOBANK2_BASE, + U5500_GPIOBANK3_BASE, + U5500_GPIOBANK4_BASE, + U5500_GPIOBANK5_BASE, + U5500_GPIOBANK6_BASE, + U5500_GPIOBANK7_BASE}; + +static u32 ux500_gpio_wks[ARRAY_SIZE(u8500_gpio_banks)]; + +inline int ux500_pm_arm_on_ext_clk(bool leave_arm_pll_on) +{ + return 0; +} + +/* Decouple GIC from the interrupt bus */ +void ux500_pm_gic_decouple(void) +{ + prcmu_write_masked(PRCM_A9_MASK_REQ, + PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, + PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ); + + (void)prcmu_read(PRCM_A9_MASK_REQ); + + /* TODO: Use the ack bit when possible */ + udelay(GIC_FREEZE_DELAY); /* Wait for the GIC to freeze */ +} + +/* Recouple GIC with the interrupt bus */ +void ux500_pm_gic_recouple(void) +{ + prcmu_write_masked(PRCM_A9_MASK_REQ, + PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, + 0); + + /* TODO: Use the ack bit when possible */ +} + +#define GIC_NUMBER_REGS 5 +bool ux500_pm_gic_pending_interrupt(void) +{ + u32 pr; /* Pending register */ + u32 er; /* Enable register */ + int i; + + /* 5 registers. STI & PPI not skipped */ + for (i = 0; i < GIC_NUMBER_REGS; i++) { + + pr = readl_relaxed(__io_address(U8500_GIC_DIST_BASE) + + GIC_DIST_PENDING_SET + i * 4); + er = readl_relaxed(__io_address(U8500_GIC_DIST_BASE) + + GIC_DIST_ENABLE_SET + i * 4); + + if (pr & er) + return true; /* There is a pending interrupt */ + } + return false; +} + +#define GIC_NUMBER_SPI_REGS 4 +bool ux500_pm_prcmu_pending_interrupt(void) +{ + u32 it; + u32 im; + int i; + + for (i = 0; i < GIC_NUMBER_SPI_REGS; i++) { /* There are 4 registers */ + + it = prcmu_read(PRCM_ARMITVAL31TO0 + i * 4); + im = prcmu_read(PRCM_ARMITMSK31TO0 + i * 4); + + if (it & im) + return true; /* There is a pending interrupt */ + } + + return false; +} + +void ux500_pm_prcmu_set_ioforce(bool enable) +{ + if (enable) + prcmu_write_masked(PRCM_IOCR, + PRCM_IOCR_IOFORCE, + PRCM_IOCR_IOFORCE); + else + prcmu_write_masked(PRCM_IOCR, + PRCM_IOCR_IOFORCE, + 0); +} + +void ux500_pm_prcmu_copy_gic_settings(void) +{ + u32 er; /* Enable register */ + int i; + + for (i = 0; i < GIC_NUMBER_SPI_REGS; i++) { /* 4*32 SPI interrupts */ + /* +1 due to skip STI and PPI */ + er = readl_relaxed(__io_address(U8500_GIC_DIST_BASE) + + GIC_DIST_ENABLE_SET + (i + 1) * 4); + prcmu_write(PRCM_ARMITMSK31TO0 + i * 4, er); + } +} + +void ux500_pm_gpio_save_wake_up_status(void) +{ + int num_banks; + u32 *banks; + int i; + + if (cpu_is_u5500()) { + num_banks = ARRAY_SIZE(u5500_gpio_banks); + banks = u5500_gpio_banks; + } else { + num_banks = ARRAY_SIZE(u8500_gpio_banks); + banks = u8500_gpio_banks; + } + + nmk_gpio_clocks_enable(); + + for (i = 0; i < num_banks; i++) + ux500_gpio_wks[i] = readl(__io_address(banks[i]) + NMK_GPIO_WKS); + + nmk_gpio_clocks_disable(); +} + +u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_num) +{ + if (WARN_ON(cpu_is_u5500() && bank_num >= + ARRAY_SIZE(u5500_gpio_banks))) + return 0; + + if (WARN_ON(cpu_is_u8500() && bank_num >= + ARRAY_SIZE(u8500_gpio_banks))) + return 0; + + return ux500_gpio_wks[bank_num]; +} + +/* Check if the other CPU is in WFI */ +bool ux500_pm_other_cpu_wfi(void) +{ + if (smp_processor_id()) { + /* We are CPU 1 => check if CPU0 is in WFI */ + if (prcmu_read(PRCM_ARM_WFI_STANDBY) & + PRCM_ARM_WFI_STANDBY_CPU0_WFI) + return true; + } else { + /* We are CPU 0 => check if CPU1 is in WFI */ + if (prcmu_read(PRCM_ARM_WFI_STANDBY) & + PRCM_ARM_WFI_STANDBY_CPU1_WFI) + return true; + } + + return false; +} diff --git a/arch/arm/mach-ux500/pm/prcmu-qos-power.c b/arch/arm/mach-ux500/pm/prcmu-qos-power.c new file mode 100644 index 00000000000..3bd99b766af --- /dev/null +++ b/arch/arm/mach-ux500/pm/prcmu-qos-power.c @@ -0,0 +1,711 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * Author: Martin Persson + * Per Fransson <per.xx.fransson@stericsson.com> + * + * Quality of Service for the U8500 PRCM Unit interface driver + * + * Strongly influenced by kernel/pm_qos_params.c. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/uaccess.h> +#include <linux/cpufreq.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/cpufreq-dbx500.h> + +#include <mach/prcmu-debug.h> + +#define ARM_THRESHOLD_FREQ (400000) + +static int qos_delayed_cpufreq_notifier(struct notifier_block *, + unsigned long, void *); + +static s32 cpufreq_requirement_queued; +static s32 cpufreq_requirement_set; + +/* + * locking rule: all changes to requirements or prcmu_qos_object list + * and prcmu_qos_objects need to happen with prcmu_qos_lock + * held, taken with _irqsave. One lock to rule them all + */ +struct requirement_list { + struct list_head list; + union { + s32 value; + s32 usec; + s32 kbps; + }; + char *name; +}; + +static s32 max_compare(s32 v1, s32 v2); + +struct prcmu_qos_object { + struct requirement_list requirements; + struct blocking_notifier_head *notifiers; + struct miscdevice prcmu_qos_power_miscdev; + char *name; + s32 default_value; + s32 force_value; + atomic_t target_value; + s32 (*comparitor)(s32, s32); +}; + +static struct prcmu_qos_object null_qos; +static BLOCKING_NOTIFIER_HEAD(prcmu_ape_opp_notifier); +static BLOCKING_NOTIFIER_HEAD(prcmu_ddr_opp_notifier); + +static struct prcmu_qos_object ape_opp_qos = { + .requirements = { + LIST_HEAD_INIT(ape_opp_qos.requirements.list) + }, + .notifiers = &prcmu_ape_opp_notifier, + .name = "ape_opp", + /* Target value in % APE OPP */ + .default_value = 50, + .force_value = 0, + .target_value = ATOMIC_INIT(50), + .comparitor = max_compare +}; + +static struct prcmu_qos_object ddr_opp_qos = { + .requirements = { + LIST_HEAD_INIT(ddr_opp_qos.requirements.list) + }, + .notifiers = &prcmu_ddr_opp_notifier, + .name = "ddr_opp", + /* Target value in % DDR OPP */ + .default_value = 25, + .force_value = 0, + .target_value = ATOMIC_INIT(25), + .comparitor = max_compare +}; + +static struct prcmu_qos_object arm_opp_qos = { + .requirements = { + LIST_HEAD_INIT(arm_opp_qos.requirements.list) + }, + /* + * No notifier on ARM opp qos request, since this won't actually + * do anything, except changing limits for cpufreq + */ + .name = "arm_opp", + /* Target value in % ARM OPP, note can be 125% */ + .default_value = 25, + .force_value = 0, + .target_value = ATOMIC_INIT(25), + .comparitor = max_compare +}; + +static struct prcmu_qos_object *prcmu_qos_array[] = { + &null_qos, + &ape_opp_qos, + &ddr_opp_qos, + &arm_opp_qos, +}; + +static DEFINE_MUTEX(prcmu_qos_mutex); +static DEFINE_SPINLOCK(prcmu_qos_lock); + +static bool ape_opp_50_partly_25_enabled; + +static unsigned long cpufreq_opp_delay = HZ / 5; + +unsigned long prcmu_qos_get_cpufreq_opp_delay(void) +{ + return cpufreq_opp_delay; +} + +static struct notifier_block qos_delayed_cpufreq_notifier_block = { + .notifier_call = qos_delayed_cpufreq_notifier, +}; + +void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) +{ + if (n == 0) { + cpufreq_unregister_notifier(&qos_delayed_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", + PRCMU_QOS_DEFAULT_VALUE); + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "cpufreq", + PRCMU_QOS_DEFAULT_VALUE); + cpufreq_requirement_set = PRCMU_QOS_DEFAULT_VALUE; + cpufreq_requirement_queued = PRCMU_QOS_DEFAULT_VALUE; + } else if (cpufreq_opp_delay != 0) { + cpufreq_register_notifier(&qos_delayed_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + cpufreq_opp_delay = n; +} +#ifdef CONFIG_CPU_FREQ +static void update_cpu_limits(s32 extreme_value) +{ + int cpu; + struct cpufreq_policy policy; + int ret; + int min_freq, max_freq; + + for_each_online_cpu(cpu) { + ret = cpufreq_get_policy(&policy, cpu); + if (ret) { + pr_err("prcmu qos: get cpufreq policy failed (cpu%d)\n", + cpu); + continue; + } + + ret = dbx500_cpufreq_get_limits(cpu, extreme_value, + &min_freq, &max_freq); + if (ret) + continue; + /* + * cpufreq fw does not allow frequency change if + * "current min freq" > "new max freq" or + * "current max freq" < "new min freq". + * Thus the intermediate steps below. + */ + if (policy.min > max_freq) { + ret = cpufreq_update_freq(cpu, min_freq, policy.max); + if (ret) + pr_err("prcmu qos: update min cpufreq failed (1)\n"); + } + if (policy.max < min_freq) { + ret = cpufreq_update_freq(cpu, policy.min, max_freq); + if (ret) + pr_err("prcmu qos: update max cpufreq failed (2)\n"); + } + + ret = cpufreq_update_freq(cpu, min_freq, max_freq); + if (ret) + pr_err("prcmu qos: update max cpufreq failed (3)\n"); + } + +} +#else +static inline void update_cpu_limits(s32 extreme_value) { } +#endif +/* static helper function */ +static s32 max_compare(s32 v1, s32 v2) +{ + return max(v1, v2); +} + +static void update_target(int target) +{ + s32 extreme_value; + struct requirement_list *node; + unsigned long flags; + bool update = false; + u8 op; + + mutex_lock(&prcmu_qos_mutex); + + spin_lock_irqsave(&prcmu_qos_lock, flags); + extreme_value = prcmu_qos_array[target]->default_value; + + if (prcmu_qos_array[target]->force_value != 0) { + extreme_value = prcmu_qos_array[target]->force_value; + update = true; + } else { + list_for_each_entry(node, + &prcmu_qos_array[target]->requirements.list, + list) { + extreme_value = prcmu_qos_array[target]->comparitor( + extreme_value, node->value); + } + if (atomic_read(&prcmu_qos_array[target]->target_value) + != extreme_value) { + update = true; + atomic_set(&prcmu_qos_array[target]->target_value, + extreme_value); + pr_debug("prcmu qos: new target for qos %d is %d\n", + target, atomic_read( + &prcmu_qos_array[target]->target_value + )); + } + } + + spin_unlock_irqrestore(&prcmu_qos_lock, flags); + + if (!update) + goto unlock_and_return; + + if (prcmu_qos_array[target]->notifiers) + blocking_notifier_call_chain(prcmu_qos_array[target]->notifiers, + (unsigned long)extreme_value, + NULL); + switch (target) { + case PRCMU_QOS_DDR_OPP: + switch (extreme_value) { + case 50: + op = DDR_50_OPP; + pr_debug("prcmu qos: set ddr opp to 50%%\n"); + break; + case 100: + op = DDR_100_OPP; + pr_debug("prcmu qos: set ddr opp to 100%%\n"); + break; + case 25: + /* 25% DDR OPP is not supported on 5500 */ + if (!cpu_is_u5500()) { + op = DDR_25_OPP; + pr_debug("prcmu qos: set ddr opp to 25%%\n"); + break; + } + default: + pr_err("prcmu qos: Incorrect ddr target value (%d)", + extreme_value); + goto unlock_and_return; + } + prcmu_set_ddr_opp(op); + prcmu_debug_ddr_opp_log(op); + break; + case PRCMU_QOS_APE_OPP: + switch (extreme_value) { + case 50: + if (ape_opp_50_partly_25_enabled) + op = APE_50_PARTLY_25_OPP; + else + op = APE_50_OPP; + pr_debug("prcmu qos: set ape opp to 50%%\n"); + break; + case 100: + op = APE_100_OPP; + pr_debug("prcmu qos: set ape opp to 100%%\n"); + break; + default: + pr_err("prcmu qos: Incorrect ape target value (%d)", + extreme_value); + goto unlock_and_return; + } + (void)prcmu_set_ape_opp(op); + prcmu_debug_ape_opp_log(op); + break; + case PRCMU_QOS_ARM_OPP: + { + mutex_unlock(&prcmu_qos_mutex); + /* + * We can't hold the mutex since changing cpufreq + * will trigger an prcmu fw callback. + */ + update_cpu_limits(extreme_value); + /* Return since the lock is unlocked */ + return; + + break; + } + default: + pr_err("prcmu qos: Incorrect target\n"); + break; + } + +unlock_and_return: + mutex_unlock(&prcmu_qos_mutex); +} + +void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) +{ + prcmu_qos_array[prcmu_qos_class]->force_value = i; + update_target(prcmu_qos_class); +} + +void prcmu_qos_voice_call_override(bool enable) +{ + int ape_opp; + + mutex_lock(&prcmu_qos_mutex); + + ape_opp_50_partly_25_enabled = enable; + + ape_opp = prcmu_get_ape_opp(); + + if (ape_opp == APE_50_OPP) { + if (enable) + prcmu_set_ape_opp(APE_50_PARTLY_25_OPP); + else + prcmu_set_ape_opp(APE_50_OPP); + } + + mutex_unlock(&prcmu_qos_mutex); +} + +/** + * prcmu_qos_requirement - returns current prcmu qos expectation + * @prcmu_qos_class: identification of which qos value is requested + * + * This function returns the current target value in an atomic manner. + */ +int prcmu_qos_requirement(int prcmu_qos_class) +{ + return atomic_read(&prcmu_qos_array[prcmu_qos_class]->target_value); +} +EXPORT_SYMBOL_GPL(prcmu_qos_requirement); + +/** + * prcmu_qos_add_requirement - inserts new qos request into the list + * @prcmu_qos_class: identifies which list of qos request to us + * @name: identifies the request + * @value: defines the qos request + * + * This function inserts a new entry in the prcmu_qos_class list of requested + * qos performance characteristics. It recomputes the aggregate QoS + * expectations for the prcmu_qos_class of parameters. + */ +int prcmu_qos_add_requirement(int prcmu_qos_class, char *name, s32 value) +{ + struct requirement_list *dep; + unsigned long flags; + + dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL); + if (dep == NULL) + return -ENOMEM; + + if (value == PRCMU_QOS_DEFAULT_VALUE) + dep->value = prcmu_qos_array[prcmu_qos_class]->default_value; + else + dep->value = value; + dep->name = kstrdup(name, GFP_KERNEL); + if (!dep->name) + goto cleanup; + + spin_lock_irqsave(&prcmu_qos_lock, flags); + list_add(&dep->list, + &prcmu_qos_array[prcmu_qos_class]->requirements.list); + spin_unlock_irqrestore(&prcmu_qos_lock, flags); + update_target(prcmu_qos_class); + + return 0; + +cleanup: + kfree(dep); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(prcmu_qos_add_requirement); + +/** + * prcmu_qos_update_requirement - modifies an existing qos request + * @prcmu_qos_class: identifies which list of qos request to us + * @name: identifies the request + * @value: defines the qos request + * + * Updates an existing qos requirement for the prcmu_qos_class of parameters + * along with updating the target prcmu_qos_class value. + * + * If the named request isn't in the list then no change is made. + */ +int prcmu_qos_update_requirement(int prcmu_qos_class, char *name, s32 new_value) +{ + unsigned long flags; + struct requirement_list *node; + int pending_update = 0; + + spin_lock_irqsave(&prcmu_qos_lock, flags); + list_for_each_entry(node, + &prcmu_qos_array[prcmu_qos_class]->requirements.list, list) { + if (strcmp(node->name, name) == 0) { + if (new_value == PRCMU_QOS_DEFAULT_VALUE) + node->value = + prcmu_qos_array[prcmu_qos_class]->default_value; + else + node->value = new_value; + pending_update = 1; + break; + } + } + spin_unlock_irqrestore(&prcmu_qos_lock, flags); + if (pending_update) + update_target(prcmu_qos_class); + + return 0; +} +EXPORT_SYMBOL_GPL(prcmu_qos_update_requirement); + +/** + * prcmu_qos_remove_requirement - modifies an existing qos request + * @prcmu_qos_class: identifies which list of qos request to us + * @name: identifies the request + * + * Will remove named qos request from prcmu_qos_class list of parameters and + * recompute the current target value for the prcmu_qos_class. + */ +void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) +{ + unsigned long flags; + struct requirement_list *node; + int pending_update = 0; + + spin_lock_irqsave(&prcmu_qos_lock, flags); + list_for_each_entry(node, + &prcmu_qos_array[prcmu_qos_class]->requirements.list, list) { + if (strcmp(node->name, name) == 0) { + kfree(node->name); + list_del(&node->list); + kfree(node); + pending_update = 1; + break; + } + } + spin_unlock_irqrestore(&prcmu_qos_lock, flags); + if (pending_update) + update_target(prcmu_qos_class); +} +EXPORT_SYMBOL_GPL(prcmu_qos_remove_requirement); + +/** + * prcmu_qos_add_notifier - sets notification entry for changes to target value + * @prcmu_qos_class: identifies which qos target changes should be notified. + * @notifier: notifier block managed by caller. + * + * will register the notifier into a notification chain that gets called + * upon changes to the prcmu_qos_class target value. + */ +int prcmu_qos_add_notifier(int prcmu_qos_class, struct notifier_block *notifier) +{ + int retval = -EINVAL; + + if (prcmu_qos_array[prcmu_qos_class]->notifiers) + retval = blocking_notifier_chain_register( + prcmu_qos_array[prcmu_qos_class]->notifiers, notifier); + + return retval; +} +EXPORT_SYMBOL_GPL(prcmu_qos_add_notifier); + +/** + * prcmu_qos_remove_notifier - deletes notification entry from chain. + * @prcmu_qos_class: identifies which qos target changes are notified. + * @notifier: notifier block to be removed. + * + * will remove the notifier from the notification chain that gets called + * upon changes to the prcmu_qos_class target value. + */ +int prcmu_qos_remove_notifier(int prcmu_qos_class, + struct notifier_block *notifier) +{ + int retval = -EINVAL; + if (prcmu_qos_array[prcmu_qos_class]->notifiers) + retval = blocking_notifier_chain_unregister( + prcmu_qos_array[prcmu_qos_class]->notifiers, notifier); + + return retval; +} +EXPORT_SYMBOL_GPL(prcmu_qos_remove_notifier); + +#define USER_QOS_NAME_LEN 32 + +static int prcmu_qos_power_open(struct inode *inode, struct file *filp, + long prcmu_qos_class) +{ + int ret; + char name[USER_QOS_NAME_LEN]; + + filp->private_data = (void *)prcmu_qos_class; + snprintf(name, USER_QOS_NAME_LEN, "file_%08x", (unsigned int)filp); + ret = prcmu_qos_add_requirement(prcmu_qos_class, name, + PRCMU_QOS_DEFAULT_VALUE); + if (ret >= 0) + return 0; + + return -EPERM; +} + + +static int prcmu_qos_ape_power_open(struct inode *inode, struct file *filp) +{ + return prcmu_qos_power_open(inode, filp, PRCMU_QOS_APE_OPP); +} + +static int prcmu_qos_ddr_power_open(struct inode *inode, struct file *filp) +{ + return prcmu_qos_power_open(inode, filp, PRCMU_QOS_DDR_OPP); +} + +static int prcmu_qos_arm_power_open(struct inode *inode, struct file *filp) +{ + return prcmu_qos_power_open(inode, filp, PRCMU_QOS_ARM_OPP); +} + +static int prcmu_qos_power_release(struct inode *inode, struct file *filp) +{ + int prcmu_qos_class; + char name[USER_QOS_NAME_LEN]; + + prcmu_qos_class = (long)filp->private_data; + snprintf(name, USER_QOS_NAME_LEN, "file_%08x", (unsigned int)filp); + prcmu_qos_remove_requirement(prcmu_qos_class, name); + + return 0; +} + +static ssize_t prcmu_qos_power_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + s32 value; + int prcmu_qos_class; + char name[USER_QOS_NAME_LEN]; + + prcmu_qos_class = (long)filp->private_data; + if (count != sizeof(s32)) + return -EINVAL; + if (copy_from_user(&value, buf, sizeof(s32))) + return -EFAULT; + snprintf(name, USER_QOS_NAME_LEN, "file_%08x", (unsigned int)filp); + prcmu_qos_update_requirement(prcmu_qos_class, name, value); + + return sizeof(s32); +} + +/* Functions to provide QoS to user space */ +static const struct file_operations prcmu_qos_ape_power_fops = { + .write = prcmu_qos_power_write, + .open = prcmu_qos_ape_power_open, + .release = prcmu_qos_power_release, +}; + +/* Functions to provide QoS to user space */ +static const struct file_operations prcmu_qos_ddr_power_fops = { + .write = prcmu_qos_power_write, + .open = prcmu_qos_ddr_power_open, + .release = prcmu_qos_power_release, +}; + +static const struct file_operations prcmu_qos_arm_power_fops = { + .write = prcmu_qos_power_write, + .open = prcmu_qos_arm_power_open, + .release = prcmu_qos_power_release, +}; + +static int register_prcmu_qos_misc(struct prcmu_qos_object *qos, + const struct file_operations *fops) +{ + qos->prcmu_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR; + qos->prcmu_qos_power_miscdev.name = qos->name; + qos->prcmu_qos_power_miscdev.fops = fops; + + return misc_register(&qos->prcmu_qos_power_miscdev); +} + +static void qos_delayed_work_up_fn(struct work_struct *work) +{ + prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", 100); + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "cpufreq", 100); + cpufreq_requirement_set = 100; +} + +static void qos_delayed_work_down_fn(struct work_struct *work) +{ + prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", + PRCMU_QOS_DEFAULT_VALUE); + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "cpufreq", + PRCMU_QOS_DEFAULT_VALUE); + cpufreq_requirement_set = PRCMU_QOS_DEFAULT_VALUE; +} + +static DECLARE_DELAYED_WORK(qos_delayed_work_up, qos_delayed_work_up_fn); +static DECLARE_DELAYED_WORK(qos_delayed_work_down, qos_delayed_work_down_fn); + +static int qos_delayed_cpufreq_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct cpufreq_freqs *freq = data; + s32 new_ddr_target; + + /* Only react once per transition and only for one core, e.g. core 0 */ + if (event != CPUFREQ_POSTCHANGE || freq->cpu != 0) + return 0; + + /* + * APE and DDR OPP are always handled together in this solution. + * Hence no need to check both DDR and APE opp in the code below. + */ + + /* Which DDR OPP are we aiming for? */ + if (freq->new > ARM_THRESHOLD_FREQ) + new_ddr_target = 100; + else + new_ddr_target = PRCMU_QOS_DEFAULT_VALUE; + + if (new_ddr_target == cpufreq_requirement_queued) { + /* + * We're already at, or going to, the target requirement. + * This is only a fluctuation within the interval + * corresponding to the same DDR requirement. + */ + return 0; + } + cpufreq_requirement_queued = new_ddr_target; + + if (freq->new > ARM_THRESHOLD_FREQ) { + cancel_delayed_work_sync(&qos_delayed_work_down); + /* + * Only schedule this requirement if it is not the current + * one. + */ + if (new_ddr_target != cpufreq_requirement_set) + schedule_delayed_work(&qos_delayed_work_up, + cpufreq_opp_delay); + } else { + cancel_delayed_work_sync(&qos_delayed_work_up); + /* + * Only schedule this requirement if it is not the current + * one. + */ + if (new_ddr_target != cpufreq_requirement_set) + schedule_delayed_work(&qos_delayed_work_down, + cpufreq_opp_delay); + } + + return 0; +} + +static int __init prcmu_qos_power_init(void) +{ + int ret; + + /* 25% DDR OPP is not supported on u5500 */ + if (cpu_is_u5500()) { + ddr_opp_qos.default_value = 50; + atomic_set(&ddr_opp_qos.target_value, 50); + } + + ret = register_prcmu_qos_misc(&ape_opp_qos, &prcmu_qos_ape_power_fops); + if (ret < 0) { + pr_err("prcmu ape qos: setup failed\n"); + return ret; + } + + ret = register_prcmu_qos_misc(&ddr_opp_qos, &prcmu_qos_ddr_power_fops); + if (ret < 0) { + pr_err("prcmu ddr qos: setup failed\n"); + return ret; + } + + ret = register_prcmu_qos_misc(&arm_opp_qos, &prcmu_qos_arm_power_fops); + if (ret < 0) { + pr_err("prcmu arm qos: setup failed\n"); + return ret; + } + + prcmu_qos_add_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", + PRCMU_QOS_DEFAULT_VALUE); + prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, "cpufreq", + PRCMU_QOS_DEFAULT_VALUE); + cpufreq_requirement_set = PRCMU_QOS_DEFAULT_VALUE; + cpufreq_requirement_queued = PRCMU_QOS_DEFAULT_VALUE; + + cpufreq_register_notifier(&qos_delayed_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + + return ret; +} + +late_initcall(prcmu_qos_power_init); diff --git a/arch/arm/mach-ux500/pm/runtime.c b/arch/arm/mach-ux500/pm/runtime.c new file mode 100644 index 00000000000..8608c43479e --- /dev/null +++ b/arch/arm/mach-ux500/pm/runtime.c @@ -0,0 +1,514 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Rabin Vincent <rabin.vincent@stericsson> for ST-Ericsson + * + * Based on: + * Runtime PM support code for SuperH Mobile ARM + * Copyright (C) 2009-2010 Magnus Damm + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/pm_runtime.h> +#include <linux/platform_device.h> +#include <linux/amba/bus.h> +#include <linux/regulator/dbx500-prcmu.h> +#include <linux/clk.h> +#include <linux/gfp.h> +#include <plat/pincfg.h> + +#include "../pins.h" + +#ifdef CONFIG_PM_RUNTIME +#define BIT_ONCE 0 +#define BIT_ACTIVE 1 +#define BIT_ENABLED 2 + +struct pm_runtime_data { + unsigned long flags; + struct ux500_regulator *regulator; + struct ux500_pins *pins; +}; + +static void __devres_release(struct device *dev, void *res) +{ + struct pm_runtime_data *prd = res; + + dev_dbg(dev, "__devres_release()\n"); + + if (test_bit(BIT_ENABLED, &prd->flags)) { + if (prd->pins) + ux500_pins_disable(prd->pins); + if (prd->regulator) + ux500_regulator_atomic_disable(prd->regulator); + } + + if (test_bit(BIT_ACTIVE, &prd->flags)) { + if (prd->pins) + ux500_pins_put(prd->pins); + if (prd->regulator) + ux500_regulator_put(prd->regulator); + } +} + +static struct pm_runtime_data *__to_prd(struct device *dev) +{ + return devres_find(dev, __devres_release, NULL, NULL); +} + +static void platform_pm_runtime_init(struct device *dev, + struct pm_runtime_data *prd) +{ + prd->pins = ux500_pins_get(dev_name(dev)); + + prd->regulator = ux500_regulator_get(dev); + if (IS_ERR(prd->regulator)) + prd->regulator = NULL; + + if (prd->pins || prd->regulator) { + dev_info(dev, "managed by runtime pm: %s%s\n", + prd->pins ? "pins " : "", + prd->regulator ? "regulator " : ""); + + set_bit(BIT_ACTIVE, &prd->flags); + } +} + +static void platform_pm_runtime_bug(struct device *dev, + struct pm_runtime_data *prd) +{ + if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) + dev_err(dev, "runtime pm suspend before resume\n"); +} + +static void platform_pm_runtime_used(struct device *dev, + struct pm_runtime_data *prd) +{ + if (prd) + set_bit(BIT_ONCE, &prd->flags); +} + +static int ux500_pd_runtime_idle(struct device *dev) +{ + return pm_runtime_suspend(dev); +} + +static void ux500_pd_disable(struct pm_runtime_data *prd) +{ + if (prd && test_bit(BIT_ACTIVE, &prd->flags)) { + + if (prd->pins) + ux500_pins_disable(prd->pins); + + if (prd->regulator) + ux500_regulator_atomic_disable(prd->regulator); + + clear_bit(BIT_ENABLED, &prd->flags); + } +} + +static int ux500_pd_runtime_suspend(struct device *dev) +{ + int ret; + struct pm_runtime_data *prd = __to_prd(dev); + + dev_vdbg(dev, "%s()\n", __func__); + + platform_pm_runtime_bug(dev, prd); + + ret = pm_generic_runtime_suspend(dev); + if (ret) + return ret; + + ux500_pd_disable(prd); + + return 0; +} + +static void ux500_pd_enable(struct pm_runtime_data *prd) +{ + if (prd && test_bit(BIT_ACTIVE, &prd->flags)) { + if (prd->pins) + ux500_pins_enable(prd->pins); + + if (prd->regulator) + ux500_regulator_atomic_enable(prd->regulator); + + set_bit(BIT_ENABLED, &prd->flags); + } +} + +static int ux500_pd_runtime_resume(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + + dev_vdbg(dev, "%s()\n", __func__); + + platform_pm_runtime_used(dev, prd); + ux500_pd_enable(prd); + + return pm_generic_runtime_resume(dev); +} + +static int ux500_pd_suspend_noirq(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + + dev_vdbg(dev, "%s()\n", __func__); + + /* Only handle devices that use runtime pm */ + if (!prd || !test_bit(BIT_ONCE, &prd->flags)) + return 0; + + /* Already is runtime suspended? Nothing to do. */ + if (pm_runtime_status_suspended(dev)) + return 0; + + /* + * We get here only if the device was not runtime suspended for some + * reason. We still need to do the power save stuff when going into + * suspend, so force it here. + */ + return ux500_pd_runtime_suspend(dev); +} + +static int ux500_pd_resume_noirq(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + + dev_vdbg(dev, "%s()\n", __func__); + + /* Only handle devices that use runtime pm */ + if (!prd || !test_bit(BIT_ONCE, &prd->flags)) + return 0; + + /* + * Already was runtime suspended? No need to resume here, runtime + * resume will take care of it. + */ + if (pm_runtime_status_suspended(dev)) + return 0; + + /* + * We get here only if the device was not runtime suspended, + * but we forced it down in suspend_noirq above. Bring it + * up since pm-runtime thinks it is not suspended. + */ + return ux500_pd_runtime_resume(dev); +} +#ifdef CONFIG_UX500_SUSPEND +static int ux500_pd_amba_suspend_noirq(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + int (*callback)(struct device *) = NULL; + int ret = 0; + bool is_suspended = pm_runtime_status_suspended(dev); + + dev_vdbg(dev, "%s()\n", __func__); + + /* + * Do not bypass AMBA bus pm functions by calling generic + * pm directly. A future fix could be to implement a + * "pm_bus_generic_*" API which we can use instead. + */ + if (dev->bus && dev->bus->pm) + callback = dev->bus->pm->suspend_noirq; + + if (callback) + ret = callback(dev); + else + ret = pm_generic_suspend_noirq(dev); + + if (!ret && !is_suspended) + ux500_pd_disable(prd); + + return ret; +} + +static int ux500_pd_amba_resume_noirq(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + int (*callback)(struct device *) = NULL; + int ret = 0; + bool is_suspended = pm_runtime_status_suspended(dev); + + dev_vdbg(dev, "%s()\n", __func__); + + /* + * Do not bypass AMBA bus pm functions by calling generic + * pm directly. A future fix could be to implement a + * "pm_bus_generic_*" API which we can use instead. + */ + if (dev->bus && dev->bus->pm) + callback = dev->bus->pm->resume_noirq; + + if (callback) + ret = callback(dev); + else + ret = pm_generic_resume_noirq(dev); + + if (!ret && !is_suspended) + ux500_pd_enable(prd); + + return ret; +} +#else +static int ux500_pd_amba_suspend_noirq(struct device *dev) +{ + return 0; +} +static int ux500_pd_amba_resume_noirq(struct device *dev) +{ + return 0; +} +#endif +static int ux500_pd_amba_runtime_suspend(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + int (*callback)(struct device *) = NULL; + int ret; + + dev_vdbg(dev, "%s()\n", __func__); + + /* + * Do this first, to make sure pins is not in undefined state after + * drivers has run their runtime suspend. This also means that drivers + * are not able to use their pins/regulators during runtime suspend. + */ + ux500_pd_disable(prd); + + /* + * Do not bypass AMBA bus pm functions by calling generic + * pm directly. A future fix could be to implement a + * "pm_bus_generic_*" API which we can use instead. + */ + if (dev->bus && dev->bus->pm) + callback = dev->bus->pm->runtime_suspend; + + if (callback) + ret = callback(dev); + else + ret = pm_generic_runtime_suspend(dev); + + if (ret) + ux500_pd_enable(prd); + + return ret; +} + +static int ux500_pd_amba_runtime_resume(struct device *dev) +{ + struct pm_runtime_data *prd = __to_prd(dev); + int (*callback)(struct device *) = NULL; + int ret; + + dev_vdbg(dev, "%s()\n", __func__); + + /* + * Do not bypass AMBA bus pm functions by calling generic + * pm directly. A future fix could be to implement a + * "pm_bus_generic_*" API which we can use instead. + */ + if (dev->bus && dev->bus->pm) + callback = dev->bus->pm->runtime_resume; + + if (callback) + ret = callback(dev); + else + ret = pm_generic_runtime_resume(dev); + + /* + * Restore pins/regulator after drivers has runtime resumed, due + * to that we must not have pins in undefined state. This also means + * that drivers are not able to use their pins/regulators during + * runtime resume. + */ + if (!ret) + ux500_pd_enable(prd); + + return ret; +} + +static int ux500_pd_amba_runtime_idle(struct device *dev) +{ + int (*callback)(struct device *) = NULL; + int ret; + + dev_vdbg(dev, "%s()\n", __func__); + + /* + * Do not bypass AMBA bus runtime functions by calling generic runtime + * directly. A future fix could be to implement a + * "pm_bus_generic_runtime_*" API which we can use instead. + */ + if (dev->bus && dev->bus->pm) + callback = dev->bus->pm->runtime_idle; + + if (callback) + ret = callback(dev); + else + ret = pm_generic_runtime_idle(dev); + + return ret; +} + +static int ux500_pd_bus_notify(struct notifier_block *nb, + unsigned long action, + void *data, + bool enable) +{ + struct device *dev = data; + struct pm_runtime_data *prd; + + dev_dbg(dev, "%s() %ld !\n", __func__, action); + + if (action == BUS_NOTIFY_BIND_DRIVER) { + prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL); + if (prd) { + devres_add(dev, prd); + platform_pm_runtime_init(dev, prd); + if (enable) + ux500_pd_enable(prd); + } else + dev_err(dev, "unable to alloc memory for runtime pm\n"); + } + + return 0; +} + +static int ux500_pd_plat_bus_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + return ux500_pd_bus_notify(nb, action, data, false); +} + +static int ux500_pd_amba_bus_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + return ux500_pd_bus_notify(nb, action, data, true); +} + +#else /* CONFIG_PM_RUNTIME */ + +#define ux500_pd_suspend_noirq NULL +#define ux500_pd_resume_noirq NULL +#define ux500_pd_runtime_idle NULL +#define ux500_pd_runtime_suspend NULL +#define ux500_pd_runtime_resume NULL + +static int ux500_pd_bus_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct ux500_regulator *regulator = NULL; + struct ux500_pins *pins = NULL; + struct device *dev = data; + const char *onoff = NULL; + + dev_dbg(dev, "%s() %ld !\n", __func__, action); + + switch (action) { + case BUS_NOTIFY_BIND_DRIVER: + pins = ux500_pins_get(dev_name(dev)); + if (pins) { + ux500_pins_enable(pins); + ux500_pins_put(pins); + } + + regulator = ux500_regulator_get(dev); + if (IS_ERR(regulator)) + regulator = NULL; + else { + ux500_regulator_atomic_enable(regulator); + ux500_regulator_put(regulator); + } + + onoff = "on"; + break; + case BUS_NOTIFY_UNBOUND_DRIVER: + pins = ux500_pins_get(dev_name(dev)); + if (pins) { + ux500_pins_disable(pins); + ux500_pins_put(pins); + } + + regulator = ux500_regulator_get(dev); + if (IS_ERR(regulator)) + regulator = NULL; + else { + ux500_regulator_atomic_disable(regulator); + ux500_regulator_put(regulator); + } + + onoff = "off"; + break; + } + + if (pins || regulator) { + dev_info(dev, "runtime pm disabled, forced %s: %s%s\n", + onoff, + pins ? "pins " : "", + regulator ? "regulator " : ""); + } + + return 0; +} + +#endif /* CONFIG_PM_RUNTIME */ + +struct dev_pm_domain ux500_amba_dev_power_domain = { + .ops = { + .suspend = amba_pm_suspend, + .resume = amba_pm_resume, + .freeze = amba_pm_freeze, + .thaw = amba_pm_thaw, + .poweroff = amba_pm_poweroff, + .restore = amba_pm_restore, + SET_RUNTIME_PM_OPS(ux500_pd_amba_runtime_suspend, + ux500_pd_amba_runtime_resume, + ux500_pd_amba_runtime_idle) + .suspend_noirq = ux500_pd_amba_suspend_noirq, + .resume_noirq = ux500_pd_amba_resume_noirq, + }, +}; + +struct dev_pm_domain ux500_dev_power_domain = { + .ops = { + SET_RUNTIME_PM_OPS(ux500_pd_runtime_suspend, + ux500_pd_runtime_resume, + ux500_pd_runtime_idle) + USE_PLATFORM_PM_SLEEP_OPS + .suspend_noirq = ux500_pd_suspend_noirq, + .resume_noirq = ux500_pd_resume_noirq, + }, +}; + +static struct notifier_block ux500_pd_platform_notifier = { + .notifier_call = ux500_pd_plat_bus_notify, +}; + +static struct notifier_block ux500_pd_amba_notifier = { + .notifier_call = ux500_pd_amba_bus_notify, +}; + +static int __init ux500_pm_runtime_platform_init(void) +{ + bus_register_notifier(&platform_bus_type, &ux500_pd_platform_notifier); + return 0; +} +core_initcall(ux500_pm_runtime_platform_init); + +/* + * The amba bus itself gets registered in a core_initcall, so we can't use + * that. + */ +static int __init ux500_pm_runtime_amba_init(void) +{ + bus_register_notifier(&amba_bustype, &ux500_pd_amba_notifier); + return 0; +} +arch_initcall(ux500_pm_runtime_amba_init); diff --git a/arch/arm/mach-ux500/pm/scu.h b/arch/arm/mach-ux500/pm/scu.h new file mode 100644 index 00000000000..a09e86a9d3c --- /dev/null +++ b/arch/arm/mach-ux500/pm/scu.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __ASMARM_ARCH_SCU_H +#define __ASMARM_ARCH_SCU_H + +#include <mach/hardware.h> + +#define SCU_BASE U8500_SCU_BASE +/* + * * SCU registers + * */ +#define SCU_CTRL 0x00 +#define SCU_CONFIG 0x04 +#define SCU_CPU_STATUS 0x08 +#define SCU_INVALIDATE 0x0c +#define SCU_FPGA_REVISION 0x10 + +#endif diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c new file mode 100644 index 00000000000..df527964182 --- /dev/null +++ b/arch/arm/mach-ux500/pm/suspend.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * License Terms: GNU General Public License v2 + * + * Authors: Rickard Andersson <rickard.andersson@stericsson.com>, + * Jonas Aaberg <jonas.aberg@stericsson.com>, + * Sundar Iyer for ST-Ericsson. + */ + +#include <linux/suspend.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/gpio/nomadik.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/ab8500-debug.h> +#include <linux/regulator/dbx500-prcmu.h> + +#include <mach/context.h> +#include <mach/pm.h> +#include <mach/id.h> + +#include "suspend_dbg.h" + +static void (*pins_suspend_force)(void); +static void (*pins_suspend_force_mux)(void); + +static suspend_state_t suspend_state = PM_SUSPEND_ON; + +void suspend_set_pins_force_fn(void (*force)(void), void (*force_mux)(void)) +{ + pins_suspend_force = force; + pins_suspend_force_mux = force_mux; +} + +static atomic_t block_sleep = ATOMIC_INIT(0); + +void suspend_block_sleep(void) +{ + atomic_inc(&block_sleep); +} + +void suspend_unblock_sleep(void) +{ + atomic_dec(&block_sleep); +} + +static bool sleep_is_blocked(void) +{ + return (atomic_read(&block_sleep) != 0); +} + +static int suspend(bool do_deepsleep) +{ + bool pins_force = pins_suspend_force_mux && pins_suspend_force; + int ret = 0; + + if (sleep_is_blocked()) { + pr_info("suspend/resume: interrupted by modem.\n"); + return -EBUSY; + } + + nmk_gpio_clocks_enable(); + + ux500_suspend_dbg_add_wake_on_uart(); + + nmk_gpio_wakeups_suspend(); + + /* configure the prcm for a sleep wakeup */ + if (cpu_is_u9500()) + prcmu_enable_wakeups(PRCMU_WAKEUP(ABB) | PRCMU_WAKEUP(HSI0)); + else +#if defined(CONFIG_RTC_DRV_PL031) + prcmu_enable_wakeups(PRCMU_WAKEUP(ABB) | PRCMU_WAKEUP(RTC)); +#else + prcmu_enable_wakeups(PRCMU_WAKEUP(ABB)); +#endif + + context_vape_save(); + + context_fsmc_save(); + + if (pins_force) { + /* + * Save GPIO settings before applying power save + * settings + */ + context_gpio_save(); + + /* Apply GPIO power save mux settings */ + context_gpio_mux_safe_switch(true); + pins_suspend_force_mux(); + context_gpio_mux_safe_switch(false); + + /* Apply GPIO power save settings */ + pins_suspend_force(); + } + + ux500_pm_gic_decouple(); + + if (ux500_pm_gic_pending_interrupt()) { + pr_info("suspend/resume: pending interrupt\n"); + + /* Recouple GIC with the interrupt bus */ + ux500_pm_gic_recouple(); + ret = -EBUSY; + + goto exit; + } + ux500_pm_prcmu_set_ioforce(true); + + if (do_deepsleep) { + context_varm_save_common(); + context_varm_save_core(); + context_gic_dist_disable_unneeded_irqs(); + context_save_cpu_registers(); + + /* + * Due to we have only 100us between requesting a powerstate + * and wfi, we clean the cache before as well to assure the + * final cache clean before wfi has as little as possible to + * do. + */ + context_clean_l1_cache_all(); + + (void) prcmu_set_power_state(PRCMU_AP_DEEP_SLEEP, + false, false); + context_save_to_sram_and_wfi(true); + + context_restore_cpu_registers(); + context_varm_restore_core(); + context_varm_restore_common(); + + } else { + + context_clean_l1_cache_all(); + (void) prcmu_set_power_state(APEXECUTE_TO_APSLEEP, + false, false); + dsb(); + __asm__ __volatile__("wfi\n\t" : : : "memory"); + } + + context_vape_restore(); + + context_fsmc_restore(); + + /* If GPIO woke us up then save the pins that caused the wake up */ + ux500_pm_gpio_save_wake_up_status(); + + ux500_suspend_dbg_sleep_status(do_deepsleep); + + /* APE was turned off, restore IO ring */ + ux500_pm_prcmu_set_ioforce(false); + +exit: + if (pins_force) { + /* Restore gpio settings */ + context_gpio_mux_safe_switch(true); + context_gpio_restore_mux(); + context_gpio_mux_safe_switch(false); + context_gpio_restore(); + } + + /* This is what cpuidle wants */ + if (cpu_is_u9500()) + prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | + PRCMU_WAKEUP(ABB) | PRCMU_WAKEUP(HSI0)); + else + prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | + PRCMU_WAKEUP(ABB)); + + nmk_gpio_wakeups_resume(); + + ux500_suspend_dbg_remove_wake_on_uart(); + + nmk_gpio_clocks_disable(); + + return ret; +} + +static int ux500_suspend_enter(suspend_state_t state) +{ + if (ux500_suspend_enabled()) { + if (ux500_suspend_deepsleep_enabled() && + state == PM_SUSPEND_MEM) + return suspend(true); + if (ux500_suspend_sleep_enabled()) + return suspend(false); + } + + ux500_suspend_dbg_add_wake_on_uart(); + /* + * Set IOFORCE in order to wake on GPIO the same way + * as in deeper sleep. + * (U5500 is not ready for IOFORCE) + */ + if (!cpu_is_u5500()) + ux500_pm_prcmu_set_ioforce(true); + + dsb(); + __asm__ __volatile__("wfi\n\t" : : : "memory"); + + if (!cpu_is_u5500()) + ux500_pm_prcmu_set_ioforce(false); + ux500_suspend_dbg_remove_wake_on_uart(); + + return 0; +} + +static int ux500_suspend_valid(suspend_state_t state) +{ + return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; +} + +static int ux500_suspend_prepare(void) +{ + int ret; + + ret = regulator_suspend_prepare(suspend_state); + if (ret < 0) + return ret; + + return 0; +} + +static int ux500_suspend_prepare_late(void) +{ + /* ESRAM to retention instead of OFF until ROM is fixed */ + (void) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); + + ab8500_regulator_debug_force(); + ux500_regulator_suspend_debug(); + return 0; +} + +static void ux500_suspend_wake(void) +{ + ux500_regulator_resume_debug(); + ab8500_regulator_debug_restore(); + (void) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); +} + +static void ux500_suspend_finish(void) +{ + (void)regulator_suspend_finish(); +} + +static int ux500_suspend_begin(suspend_state_t state) +{ + (void) prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "suspend", 125); + suspend_state = state; + return ux500_suspend_dbg_begin(state); +} + +static void ux500_suspend_end(void) +{ + (void) prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "suspend", 25); + suspend_state = PM_SUSPEND_ON; +} + +static struct platform_suspend_ops ux500_suspend_ops = { + .enter = ux500_suspend_enter, + .valid = ux500_suspend_valid, + .prepare = ux500_suspend_prepare, + .prepare_late = ux500_suspend_prepare_late, + .wake = ux500_suspend_wake, + .finish = ux500_suspend_finish, + .begin = ux500_suspend_begin, + .end = ux500_suspend_end, +}; + +static __init int ux500_suspend_init(void) +{ + ux500_suspend_dbg_init(); + prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "suspend", 25); + suspend_set_ops(&ux500_suspend_ops); + return 0; +} +device_initcall(ux500_suspend_init); diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.c b/arch/arm/mach-ux500/pm/suspend_dbg.c new file mode 100644 index 00000000000..1b7d871ba52 --- /dev/null +++ b/arch/arm/mach-ux500/pm/suspend_dbg.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Rickard Andersson <rickard.andersson@stericsson.com>, + * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + */ +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/suspend.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> +#include <linux/mfd/dbx500-prcmu.h> + +#include <mach/pm.h> + +#ifdef CONFIG_UX500_SUSPEND_STANDBY +static u32 sleep_enabled = 1; +#else +static u32 sleep_enabled; +#endif + +#ifdef CONFIG_UX500_SUSPEND_MEM +static u32 deepsleep_enabled = 1; +#else +static u32 deepsleep_enabled; +#endif + +static u32 suspend_enabled = 1; + +static u32 deepsleeps_done; +static u32 deepsleeps_failed; +static u32 sleeps_done; +static u32 sleeps_failed; +static u32 suspend_count; + +#ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART +void ux500_suspend_dbg_add_wake_on_uart(void) +{ + irq_set_irq_wake(GPIO_TO_IRQ(ux500_console_uart_gpio_pin), 1); + irq_set_irq_type(GPIO_TO_IRQ(ux500_console_uart_gpio_pin), + IRQ_TYPE_EDGE_BOTH); +} + +void ux500_suspend_dbg_remove_wake_on_uart(void) +{ + irq_set_irq_wake(GPIO_TO_IRQ(ux500_console_uart_gpio_pin), 0); +} +#endif + +bool ux500_suspend_enabled(void) +{ + return suspend_enabled != 0; +} + +bool ux500_suspend_sleep_enabled(void) +{ + return sleep_enabled != 0; +} + +bool ux500_suspend_deepsleep_enabled(void) +{ + return deepsleep_enabled != 0; +} + +void ux500_suspend_dbg_sleep_status(bool is_deepsleep) +{ + enum prcmu_power_status prcmu_status; + + prcmu_status = prcmu_get_power_state_result(); + + if (is_deepsleep) { + pr_info("Returning from ApDeepSleep. PRCMU ret: 0x%x - %s\n", + prcmu_status, + prcmu_status == PRCMU_DEEP_SLEEP_OK ? + "Success" : "Fail!"); + if (prcmu_status == PRCMU_DEEP_SLEEP_OK) + deepsleeps_done++; + else + deepsleeps_failed++; + } else { + pr_info("Returning from ApSleep. PRCMU ret: 0x%x - %s\n", + prcmu_status, + prcmu_status == PRCMU_SLEEP_OK ? "Success" : "Fail!"); + if (prcmu_status == PRCMU_SLEEP_OK) + sleeps_done++; + else + sleeps_failed++; + } +} + +int ux500_suspend_dbg_begin(suspend_state_t state) +{ + suspend_count++; + return 0; +} + +void ux500_suspend_dbg_init(void) +{ + struct dentry *suspend_dir; + struct dentry *file; + + suspend_dir = debugfs_create_dir("suspend", NULL); + if (IS_ERR_OR_NULL(suspend_dir)) + return; + + file = debugfs_create_bool("sleep", S_IWUGO | S_IRUGO, + suspend_dir, + &sleep_enabled); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_bool("deepsleep", S_IWUGO | S_IRUGO, + suspend_dir, + &deepsleep_enabled); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_bool("enable", S_IWUGO | S_IRUGO, + suspend_dir, + &suspend_enabled); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("count", S_IRUGO, + suspend_dir, + &suspend_count); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("sleep_count", S_IRUGO, + suspend_dir, + &sleeps_done); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("deepsleep_count", S_IRUGO, + suspend_dir, + &deepsleeps_done); + if (IS_ERR_OR_NULL(file)) + goto error; + + + file = debugfs_create_u32("sleep_failed", S_IRUGO, + suspend_dir, + &sleeps_failed); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("deepsleep_failed", S_IRUGO, + suspend_dir, + &deepsleeps_failed); + if (IS_ERR_OR_NULL(file)) + goto error; + + return; +error: + if (!IS_ERR_OR_NULL(suspend_dir)) + debugfs_remove_recursive(suspend_dir); +} diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.h b/arch/arm/mach-ux500/pm/suspend_dbg.h new file mode 100644 index 00000000000..29bfec7e269 --- /dev/null +++ b/arch/arm/mach-ux500/pm/suspend_dbg.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + */ + +#ifndef UX500_SUSPEND_DBG_H +#define UX500_SUSPEND_DBG_H + +#include <linux/kernel.h> +#include <linux/suspend.h> + +#ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART +void ux500_suspend_dbg_add_wake_on_uart(void); +void ux500_suspend_dbg_remove_wake_on_uart(void); +#else +static inline void ux500_suspend_dbg_add_wake_on_uart(void) { } +static inline void ux500_suspend_dbg_remove_wake_on_uart(void) { } +#endif + +#ifdef CONFIG_UX500_SUSPEND_DBG +bool ux500_suspend_enabled(void); +bool ux500_suspend_sleep_enabled(void); +bool ux500_suspend_deepsleep_enabled(void); +void ux500_suspend_dbg_sleep_status(bool is_deepsleep); +void ux500_suspend_dbg_init(void); +int ux500_suspend_dbg_begin(suspend_state_t state); + +#else +static inline bool ux500_suspend_enabled(void) +{ + return true; +} +static inline bool ux500_suspend_sleep_enabled(void) +{ +#ifdef CONFIG_UX500_SUSPEND_STANDBY + return true; +#else + return false; +#endif +} +static inline bool ux500_suspend_deepsleep_enabled(void) +{ +#ifdef CONFIG_UX500_SUSPEND_MEM + return true; +#else + return false; +#endif +} +static inline void ux500_suspend_dbg_sleep_status(bool is_deepsleep) { } +static inline void ux500_suspend_dbg_init(void) { } + +static inline int ux500_suspend_dbg_begin(suspend_state_t state) +{ + return 0; +} + +#endif + +#endif diff --git a/arch/arm/mach-ux500/pm/timer.c b/arch/arm/mach-ux500/pm/timer.c new file mode 100644 index 00000000000..fc81c2c15ad --- /dev/null +++ b/arch/arm/mach-ux500/pm/timer.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) ST-Ericsson SA 2010-2011 + * + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + * License Terms: GNU General Public License v2 + * + * The RTC timer block is a ST Microelectronics variant of ARM PL031. + * Clockwatch part is the same as PL031, while the timer part is only + * present on the ST Microelectronics variant. + * Here only the timer part is used. + * + * The timer part is quite troublesome to program correctly. Lots + * of long delays must be there in order to secure that you actually get what + * you wrote. + * + * In other words, this timer is and should only used from cpuidle during + * special conditions when the surroundings are know in order to be able + * to remove the number of delays. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ktime.h> +#include <linux/delay.h> + +#include <asm/errno.h> + +#include <mach/hardware.h> + +#define RTC_IMSC 0x10 +#define RTC_MIS 0x18 +#define RTC_ICR 0x1C +#define RTC_TDR 0x20 +#define RTC_TLR1 0x24 +#define RTC_TCR 0x28 + +#define RTC_TLR2 0x2C +#define RTC_TPR1 0x3C + +#define RTC_TCR_RTTOS (1 << 0) +#define RTC_TCR_RTTEN (1 << 1) +#define RTC_TCR_RTTSS (1 << 2) + +#define RTC_IMSC_TIMSC (1 << 1) +#define RTC_ICR_TIC (1 << 1) +#define RTC_MIS_RTCTMIS (1 << 1) + +#define RTC_TCR_RTTPS_2 (1 << 4) +#define RTC_TCR_RTTPS_3 (2 << 4) +#define RTC_TCR_RTTPS_4 (3 << 4) +#define RTC_TCR_RTTPS_5 (4 << 4) +#define RTC_TCR_RTTPS_6 (5 << 4) +#define RTC_TCR_RTTPS_7 (6 << 4) +#define RTC_TCR_RTTPS_8 (7 << 4) + +#define WRITE_DELAY 130 /* 4 cycles plus margin */ + +/* + * Count down measure point. It just have to be high to differ + * from scheduled values. + */ +#define MEASURE_VAL 0xffffffff + +/* Just a value bigger than any reason able scheduled timeout. */ +#define MEASURE_VAL_LIMIT 0xf0000000 + +#define TICKS_TO_NS(x) ((s64)x * 30518) +#define US_TO_TICKS(x) ((u32)((1000 * x) / 30518)) + +static void __iomem *rtc_base; +static bool measure_latency; + +#ifdef CONFIG_UX500_CPUIDLE_DEBUG + +/* + * The plan here is to be able to measure the ApSleep/ApDeepSleep exit latency + * by having a know timer pattern. + * The first entry in the pattern, LR1, is the value that the scheduler + * wants us to sleep. The second pattern in a high value, too large to be + * scheduled, so we can differ between a running scheduled value and a + * time measure value. + * When a RTT interrupt has occured, the block will automatically start + * to execute the measure value in LR2 and when the ARM is awake, it reads + * how far the RTT has decreased the value loaded from LR2 and from that + * calculate how long time it took to wake up. + */ +ktime_t u8500_rtc_exit_latency_get(void) +{ + u32 ticks; + + if (measure_latency) { + ticks = MEASURE_VAL - readl(rtc_base + RTC_TDR); + + /* + * Check if we are actually counting on a LR2 value. + * If not we have woken on another interrupt. + */ + if (ticks < MEASURE_VAL_LIMIT) { + /* convert 32 kHz ticks to ns */ + return ktime_set(0, TICKS_TO_NS(ticks)); + } + } + return ktime_set(0, 0); +} + +static void measure_latency_start(void) +{ + udelay(WRITE_DELAY); + /* + * Disable RTT and clean self-start due to we want to restart, + * not continue from current pattern. (See below) + */ + writel(0, rtc_base + RTC_TCR); + udelay(WRITE_DELAY); + + /* + * Program LR2 (load register two) to maximum value to ease + * identification of timer interrupt vs other. + */ + writel(MEASURE_VAL, rtc_base + RTC_TLR2); + /* + * Set Load Register execution pattern, bit clear + * means pick LR1, bit set means LR2 + * 0xfe, binary 11111110 means first do LR1 then do + * LR2 seven times + */ + writel(0xfe, rtc_base + RTC_TPR1); + + udelay(WRITE_DELAY); + + /* + * Enable self-start, plus a pattern of eight. + */ + writel(RTC_TCR_RTTSS | RTC_TCR_RTTPS_8, + rtc_base + RTC_TCR); + udelay(WRITE_DELAY); +} + +void ux500_rtcrtt_measure_latency(bool enable) +{ + if (enable) { + measure_latency_start(); + } else { + writel(RTC_TCR_RTTSS | RTC_TCR_RTTOS, rtc_base + RTC_TCR); + writel(RTC_ICR_TIC, rtc_base + RTC_ICR); + writel(RTC_IMSC_TIMSC, rtc_base + RTC_IMSC); + } + measure_latency = enable; +} +#else +static inline void measure_latency_start(void) { } +static inline void ux500_rtcrtt_measure_latency(bool enable) +{ + writel(RTC_TCR_RTTSS | RTC_TCR_RTTOS, rtc_base + RTC_TCR); + writel(RTC_ICR_TIC, rtc_base + RTC_ICR); + writel(RTC_IMSC_TIMSC, rtc_base + RTC_IMSC); +} +#endif + +void ux500_rtcrtt_off(void) +{ + if (measure_latency) { + measure_latency_start(); + } else { + /* Disable, self start and oneshot mode */ + writel(RTC_TCR_RTTSS | RTC_TCR_RTTOS, rtc_base + RTC_TCR); + + /* Clear eventual interrupts */ + if (readl(rtc_base + RTC_MIS) & RTC_MIS_RTCTMIS) + writel(RTC_ICR_TIC, rtc_base + RTC_ICR); + } +} + +void ux500_rtcrtt_next(u32 time_us) +{ + writel(US_TO_TICKS(time_us), rtc_base + RTC_TLR1); +} + +static int __init ux500_rtcrtt_init(void) +{ + if (cpu_is_u8500() || cpu_is_u9540()) { + rtc_base = __io_address(U8500_RTC_BASE); + } else if (cpu_is_u5500()) { + rtc_base = __io_address(U5500_RTC_BASE); + } else { + pr_err("timer-rtt: Unknown DB Asic!\n"); + return -EINVAL; + } + ux500_rtcrtt_measure_latency(false); + return 0; +} +subsys_initcall(ux500_rtcrtt_init); diff --git a/arch/arm/mach-ux500/pm/usecase_gov.c b/arch/arm/mach-ux500/pm/usecase_gov.c new file mode 100644 index 00000000000..1fd4fbb9830 --- /dev/null +++ b/arch/arm/mach-ux500/pm/usecase_gov.c @@ -0,0 +1,962 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Alexandre Torgue <alexandre.torgue@stericsson.com> for ST-Ericsson + * Author: Vincent Guittot <vincent.guittot@stericsson.com> for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/io.h> +#include <linux/earlysuspend.h> +#include <linux/cpu.h> +#include <linux/sched.h> +#include <linux/tick.h> +#include <linux/workqueue.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> +#include <linux/kernel_stat.h> +#include <linux/ktime.h> +#include <linux/cpufreq.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/cpufreq-dbx500.h> + +#include "../../../../drivers/cpuidle/cpuidle-dbx500.h" + + +#define CPULOAD_MEAS_DELAY 3000 /* 3 secondes of delta */ + +/* debug */ +static unsigned long debug; + +#define hp_printk \ + if (debug) \ + printk \ + +enum ux500_uc { + UX500_UC_NORMAL = 0, + UX500_UC_AUTO, /* Add use case below this. */ + UX500_UC_VC, + UX500_UC_LPA, + UX500_UC_USER, /* Add use case above this. */ + UX500_UC_MAX, +}; + +/* cpu load monitor struct */ +#define LOAD_MONITOR 4 +struct hotplug_cpu_info { + cputime64_t prev_cpu_wall; + cputime64_t prev_cpu_idle; + cputime64_t prev_cpu_io; + unsigned int load[LOAD_MONITOR]; + unsigned int idx; +}; + +static DEFINE_PER_CPU(struct hotplug_cpu_info, hotplug_info); + +/* Auto trigger criteria */ +/* loadavg threshold */ +static unsigned long lower_threshold = 175; +static unsigned long upper_threshold = 450; +/* load balancing */ +static unsigned long max_unbalance = 210; +/* trend load */ +static unsigned long trend_unbalance = 40; +static unsigned long min_trend = 5; +/* instant load */ +static unsigned long max_instant = 85; + +/* Number of interrupts per second before exiting auto mode */ +static u32 exit_irq_per_s = 1000; +static u64 old_num_irqs; + +static DEFINE_MUTEX(usecase_mutex); +static DEFINE_MUTEX(state_mutex); +static bool user_config_updated; +static enum ux500_uc current_uc = UX500_UC_MAX; +static bool is_work_scheduled; +static bool is_early_suspend; +static bool uc_master_enable = true; + +static unsigned int cpuidle_deepest_state; + +struct usecase_config { + char *name; + /* Minimum required ARM OPP. if no requirement set 25 */ + unsigned int min_arm_opp; + unsigned int max_arm_opp; + unsigned long cpuidle_multiplier; + bool second_cpu_online; + bool l2_prefetch_en; + bool enable; + unsigned int forced_state; /* Forced cpu idle state. */ + bool vc_override; /* QOS override for voice-call. */ +}; + +static struct usecase_config usecase_conf[UX500_UC_MAX] = { + [UX500_UC_NORMAL] = { + .name = "normal", + .min_arm_opp = 25, + .cpuidle_multiplier = 1024, + .second_cpu_online = true, + .l2_prefetch_en = true, + .enable = true, + .forced_state = 0, + .vc_override = false, + }, + [UX500_UC_AUTO] = { + .name = "auto", + .min_arm_opp = 25, + .cpuidle_multiplier = 0, + .second_cpu_online = false, + .l2_prefetch_en = true, + .enable = false, + .forced_state = 0, + .vc_override = false, + }, + [UX500_UC_VC] = { + .name = "voice-call", + .min_arm_opp = 50, + .cpuidle_multiplier = 0, + .second_cpu_online = true, + .l2_prefetch_en = false, + .enable = false, + .forced_state = 0, + .vc_override = true, + }, + [UX500_UC_LPA] = { + .name = "low-power-audio", + .min_arm_opp = 50, + .cpuidle_multiplier = 0, + .second_cpu_online = false, + .l2_prefetch_en = false, + .enable = false, + .forced_state = 0, /* Updated dynamically */ + .vc_override = false, + }, +}; + +/* daemon */ +static struct delayed_work work_usecase; +static struct early_suspend usecase_early_suspend; + +/* calculate loadavg */ +#define LOAD_INT(x) ((x) >> FSHIFT) +#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) + +extern int cpufreq_update_freq(int cpu, unsigned int min, unsigned int max); +extern int cpuidle_set_multiplier(unsigned int value); +extern int cpuidle_force_state(unsigned int state); + +static unsigned long determine_loadavg(void) +{ + unsigned long avg = 0; + unsigned long avnrun[3]; + + get_avenrun(avnrun, FIXED_1 / 200, 0); + avg += (LOAD_INT(avnrun[0]) * 100) + (LOAD_FRAC(avnrun[0]) % 100); + + return avg; +} + +static unsigned long determine_cpu_load(void) +{ + int i; + unsigned long total_load = 0; + + /* get cpu load of each cpu */ + for_each_online_cpu(i) { + unsigned int load; + unsigned int idle_time, wall_time; + cputime64_t cur_wall_time, cur_idle_time; + struct hotplug_cpu_info *info; + + info = &per_cpu(hotplug_info, i); + + /* update both cur_idle_time and cur_wall_time */ + cur_idle_time = get_cpu_idle_time_us(i, &cur_wall_time); + + /* how much wall time has passed since last iteration? */ + wall_time = (unsigned int) cputime64_sub(cur_wall_time, + info->prev_cpu_wall); + info->prev_cpu_wall = cur_wall_time; + + /* how much idle time has passed since last iteration? */ + idle_time = (unsigned int) cputime64_sub(cur_idle_time, + info->prev_cpu_idle); + info->prev_cpu_idle = cur_idle_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + continue; + + /* load is the percentage of time not spent in idle */ + load = 100 * (wall_time - idle_time) / wall_time; + info->load[info->idx++] = load; + if (info->idx >= LOAD_MONITOR) + info->idx = 0; + + hp_printk("cpu %d load %u ", i, load); + + total_load += load; + } + + return total_load; +} + +static unsigned long determine_cpu_load_trend(void) +{ + int i, k; + unsigned long total_load = 0; + + /* Get cpu load of each cpu */ + for_each_online_cpu(i) { + unsigned int load = 0; + struct hotplug_cpu_info *info; + + info = &per_cpu(hotplug_info, i); + + for (k = 0; k < LOAD_MONITOR; k++) + load += info->load[k]; + + load /= LOAD_MONITOR; + + hp_printk("cpu %d load trend %u\n", i, load); + + total_load += load; + } + + return total_load; +} + +static unsigned long determine_cpu_balance_trend(void) +{ + int i, k; + unsigned long total_load = 0; + unsigned long min_load = (unsigned long) (-1); + + /* Get cpu load of each cpu */ + for_each_online_cpu(i) { + unsigned int load = 0; + struct hotplug_cpu_info *info; + info = &per_cpu(hotplug_info, i); + + for (k = 0; k < LOAD_MONITOR; k++) + load += info->load[k]; + + load /= LOAD_MONITOR; + + if (min_load > load) + min_load = load; + total_load += load; + } + + if (min_load > min_trend) + total_load = (100 * total_load) / min_load; + else + total_load = 50 << num_online_cpus(); + + return total_load; +} + +static void init_cpu_load_trend(void) +{ + int i; + + for_each_possible_cpu(i) { + struct hotplug_cpu_info *info; + int j; + + info = &per_cpu(hotplug_info, i); + + info->prev_cpu_idle = get_cpu_idle_time_us(i, + &(info->prev_cpu_wall)); + info->prev_cpu_io = get_cpu_iowait_time_us(i, + &(info->prev_cpu_wall)); + + for (j = 0; j < LOAD_MONITOR; j++) { + info->load[j] = 100; + } + info->idx = 0; + } +} + +static u32 get_num_interrupts_per_s(void) +{ + int cpu; + int i; + u64 num_irqs = 0; + ktime_t now; + static ktime_t last; + unsigned int delta; + u32 irqs = 0; + + now = ktime_get(); + + for_each_possible_cpu(cpu) { + for (i = 0; i < NR_IRQS; i++) + num_irqs += kstat_irqs_cpu(i, cpu); + } + pr_debug("%s: total num irqs: %lld, previous %lld\n", + __func__, num_irqs, old_num_irqs); + + if (old_num_irqs > 0) { + delta = (u32)ktime_to_ms(ktime_sub(now, last)) / 1000; + irqs = ((u32)(num_irqs - old_num_irqs)) / delta; + } + + old_num_irqs = num_irqs; + last = now; + + pr_debug("delta irqs per sec:%d\n", irqs); + + return irqs; +} + +static int set_cpufreq(int cpu, int min_freq, int max_freq) +{ + int ret; + struct cpufreq_policy policy; + + pr_debug("set cpu freq: min %d max: %d\n", min_freq, max_freq); + + ret = cpufreq_get_policy(&policy, cpu); + if (ret < 0) { + pr_err("usecase-gov: failed to read policy\n"); + return ret; + } + + if (policy.min > max_freq) { + ret = cpufreq_update_freq(cpu, min_freq, policy.max); + if (ret) + pr_err("usecase-gov: update min cpufreq failed (1)\n"); + } + if (policy.max < min_freq) { + ret = cpufreq_update_freq(cpu, policy.min, max_freq); + if (ret) + pr_err("usecase-gov: update max cpufreq failed (2)\n"); + } + + ret = cpufreq_update_freq(cpu, min_freq, max_freq); + if (ret) + pr_err("usecase-gov: update min-max cpufreq failed\n"); + + return ret; +} + +static void set_cpu_config(enum ux500_uc new_uc) +{ + bool update = false; + int cpu; + int max_freq, min_freq; + + if (new_uc != current_uc) + update = true; + else if ((user_config_updated) && (new_uc == UX500_UC_USER)) + update = true; + + pr_debug("%s: new_usecase=%d, current_usecase=%d, update=%d\n", + __func__, new_uc, current_uc, update); + + if (!update) + goto exit; + + /* Cpu hotplug */ + if (!(usecase_conf[new_uc].second_cpu_online) && + (num_online_cpus() > 1)) + cpu_down(1); + else if ((usecase_conf[new_uc].second_cpu_online) && + (num_online_cpus() < 2)) + cpu_up(1); + + if(usecase_conf[new_uc].max_arm_opp) + max_freq = dbx500_cpufreq_percent2freq(usecase_conf[new_uc].max_arm_opp); + else + /* Maximum OPP is 125% */ + max_freq = dbx500_cpufreq_percent2freq(125); + + min_freq = dbx500_cpufreq_percent2freq(usecase_conf[new_uc].min_arm_opp); + + for_each_online_cpu(cpu) { + set_cpufreq(cpu, + min_freq, + max_freq); + } + + /* Kinda doing the job twice, but this is needed for reference keeping */ + prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, + "usecase", usecase_conf[new_uc].min_arm_opp); + + /* Cpu idle */ + cpuidle_set_multiplier(usecase_conf[new_uc].cpuidle_multiplier); + + /* L2 prefetch */ + if (usecase_conf[new_uc].l2_prefetch_en) + outer_prefetch_enable(); + else + outer_prefetch_disable(); + + /* Force cpuidle state */ + cpuidle_force_state(usecase_conf[new_uc].forced_state); + + /* QOS override */ + prcmu_qos_voice_call_override(usecase_conf[new_uc].vc_override); + + current_uc = new_uc; + +exit: + /* Its ok to clear even if new_uc != UX500_UC_USER */ + user_config_updated = false; +} + +void usecase_update_governor_state(void) +{ + bool cancel_work = false; + + /* + * usecase_mutex will have to be unlocked to ensure safe exit of + * delayed_usecase_work(). Protect this function with its own mutex + * from being executed by multiple threads at that point. + */ + mutex_lock(&state_mutex); + mutex_lock(&usecase_mutex); + + if (uc_master_enable && (usecase_conf[UX500_UC_AUTO].enable || + usecase_conf[UX500_UC_USER].enable)) { + /* + * Usecases are enabled. If we are in early suspend put + * governor to work. + */ + if (is_early_suspend && !is_work_scheduled) { + schedule_delayed_work_on(0, &work_usecase, + msecs_to_jiffies(CPULOAD_MEAS_DELAY)); + is_work_scheduled = true; + } else if (!is_early_suspend && is_work_scheduled) { + /* Exiting from early suspend. */ + cancel_work = true; + } + + } else if (is_work_scheduled) { + /* No usecase enabled or governor is not enabled. */ + cancel_work = true; + } + + if (cancel_work) { + /* + * usecase_mutex is used by delayed_usecase_work() so it must + * be unlocked before we call to cacnel the work. + */ + mutex_unlock(&usecase_mutex); + cancel_delayed_work_sync(&work_usecase); + mutex_lock(&usecase_mutex); + + is_work_scheduled = false; + + /* Set the default settings before exiting. */ + set_cpu_config(UX500_UC_NORMAL); + } + + mutex_unlock(&usecase_mutex); + mutex_unlock(&state_mutex); +} + +/* + * Start load measurment every 6 s in order detrmine if can unplug one CPU. + * In order to not corrupt measurment, the first load average is not done + * here call in early suspend. + */ +static void usecase_earlysuspend_callback(struct early_suspend *h) +{ + init_cpu_load_trend(); + + is_early_suspend = true; + + usecase_update_governor_state(); +} + +/* Stop measurement, call LCD early resume */ +static void usecase_lateresume_callback(struct early_suspend *h) +{ + is_early_suspend = false; + + usecase_update_governor_state(); +} + +static void delayed_usecase_work(struct work_struct *work) +{ + unsigned long avg, load, trend, balance; + bool inc_perf = false; + bool dec_perf = false; + u32 irqs_per_s; + + /* determine loadavg */ + avg = determine_loadavg(); + hp_printk("loadavg = %lu lower th %lu upper th %lu\n", + avg, lower_threshold, upper_threshold); + + /* determine instant load */ + load = determine_cpu_load(); + hp_printk("cpu instant load = %lu max %lu\n", load, max_instant); + + /* determine load trend */ + trend = determine_cpu_load_trend(); + hp_printk("cpu load trend = %lu min %lu unbal %lu\n", + trend, min_trend, trend_unbalance); + + /* determine load balancing */ + balance = determine_cpu_balance_trend(); + hp_printk("load balancing trend = %lu min %lu\n", + balance, max_unbalance); + + irqs_per_s = get_num_interrupts_per_s(); + + /* Dont let configuration change in the middle of our calculations. */ + mutex_lock(&usecase_mutex); + + /* detect "instant" load increase */ + if (load > max_instant || irqs_per_s > exit_irq_per_s) { + inc_perf = true; + } else if (!usecase_conf[UX500_UC_USER].enable && + usecase_conf[UX500_UC_AUTO].enable) { + /* detect high loadavg use case */ + if (avg > upper_threshold) + inc_perf = true; + /* detect idle use case */ + else if (trend < min_trend) + dec_perf = true; + /* detect unbalanced low cpu load use case */ + else if ((balance > max_unbalance) && (trend < trend_unbalance)) + dec_perf = true; + /* detect low loadavg use case */ + else if (avg < lower_threshold) + dec_perf = true; + /* All user use cases disabled, current load not triggering + * any change. + */ + else if (user_config_updated) + dec_perf = true; + } else { + dec_perf = true; + } + + /* + * set_cpu_config() will not update the config unless it has been + * changed. + */ + if (dec_perf) { + if (usecase_conf[UX500_UC_USER].enable) + set_cpu_config(UX500_UC_USER); + else if (usecase_conf[UX500_UC_AUTO].enable) + set_cpu_config(UX500_UC_AUTO); + } else if (inc_perf) { + set_cpu_config(UX500_UC_NORMAL); + } + + mutex_unlock(&usecase_mutex); + + /* reprogramm scheduled work */ + schedule_delayed_work_on(0, &work_usecase, + msecs_to_jiffies(CPULOAD_MEAS_DELAY)); + +} + +static struct dentry *usecase_dir; + +#ifdef CONFIG_DEBUG_FS +#define define_set(_name) \ +static ssize_t set_##_name(struct file *file, \ + const char __user *user_buf, \ + size_t count, loff_t *ppos) \ +{ \ + int err; \ + long unsigned i; \ + \ + err = kstrtoul_from_user(user_buf, count, 0, &i); \ + \ + if (err) \ + return err; \ + \ + _name = i; \ + hp_printk("New value : %lu\n", _name); \ + \ + return count; \ +} + +define_set(upper_threshold); +define_set(lower_threshold); +define_set(max_unbalance); +define_set(trend_unbalance); +define_set(min_trend); +define_set(max_instant); +define_set(debug); + +#define define_print(_name) \ +static ssize_t print_##_name(struct seq_file *s, void *p) \ +{ \ + return seq_printf(s, "%lu\n", _name); \ +} + +define_print(upper_threshold); +define_print(lower_threshold); +define_print(max_unbalance); +define_print(trend_unbalance); +define_print(min_trend); +define_print(max_instant); +define_print(debug); + +#define define_open(_name) \ +static ssize_t open_##_name(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, print_##_name, inode->i_private); \ +} + +define_open(upper_threshold); +define_open(lower_threshold); +define_open(max_unbalance); +define_open(trend_unbalance); +define_open(min_trend); +define_open(max_instant); +define_open(debug); + +#define define_dbg_file(_name) \ +static const struct file_operations fops_##_name = { \ + .open = open_##_name, \ + .write = set_##_name, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .owner = THIS_MODULE, \ +}; \ +static struct dentry *file_##_name; + +define_dbg_file(upper_threshold); +define_dbg_file(lower_threshold); +define_dbg_file(max_unbalance); +define_dbg_file(trend_unbalance); +define_dbg_file(min_trend); +define_dbg_file(max_instant); +define_dbg_file(debug); + +struct dbg_file { + struct dentry **file; + const struct file_operations *fops; + const char *name; +}; + +#define define_dbg_entry(_name) \ +{ \ + .file = &file_##_name, \ + .fops = &fops_##_name, \ + .name = #_name \ +} + +static struct dbg_file debug_entry[] = { + define_dbg_entry(upper_threshold), + define_dbg_entry(lower_threshold), + define_dbg_entry(max_unbalance), + define_dbg_entry(trend_unbalance), + define_dbg_entry(min_trend), + define_dbg_entry(max_instant), + define_dbg_entry(debug), +}; + +static int setup_debugfs(void) +{ + int i; + usecase_dir = debugfs_create_dir("usecase", NULL); + + if (IS_ERR_OR_NULL(usecase_dir)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(debug_entry); i++) { + if (IS_ERR_OR_NULL(debugfs_create_file(debug_entry[i].name, + S_IWUGO | S_IRUGO, + usecase_dir, + NULL, + debug_entry[i].fops))) + goto fail; + } + + if (IS_ERR_OR_NULL(debugfs_create_u32("exit_irq_per_s", + S_IWUGO | S_IRUGO, usecase_dir, + &exit_irq_per_s))) + goto fail; + return 0; +fail: + debugfs_remove_recursive(usecase_dir); + return -EINVAL; +} +#else +static int setup_debugfs(void) +{ + return 0; +} +#endif + +static void usecase_update_user_config(void) +{ + int i; + bool config_enable = false; + struct usecase_config *user_conf = &usecase_conf[UX500_UC_USER]; + + mutex_lock(&usecase_mutex); + + user_conf->min_arm_opp = 25; + user_conf->max_arm_opp = 0; + user_conf->cpuidle_multiplier = 0; + user_conf->second_cpu_online = false; + user_conf->l2_prefetch_en = false; + user_conf->forced_state = cpuidle_deepest_state; + user_conf->vc_override = true; /* A single false will clear it. */ + + /* Dont include Auto and Normal modes in this */ + for (i = (UX500_UC_AUTO + 1); i < UX500_UC_USER; i++) { + if (!usecase_conf[i].enable) + continue; + + config_enable = true; + + /* It's the highest arm opp requirement that should be used */ + if (usecase_conf[i].min_arm_opp > user_conf->min_arm_opp) + user_conf->min_arm_opp = usecase_conf[i].min_arm_opp; + + if (usecase_conf[i].max_arm_opp > user_conf->max_arm_opp) + user_conf->max_arm_opp = usecase_conf[i].max_arm_opp; + + if (usecase_conf[i].cpuidle_multiplier > + user_conf->cpuidle_multiplier) + user_conf->cpuidle_multiplier = + usecase_conf[i].cpuidle_multiplier; + + user_conf->second_cpu_online |= + usecase_conf[i].second_cpu_online; + + user_conf->l2_prefetch_en |= + usecase_conf[i].l2_prefetch_en; + + /* Take the shallowest state. */ + if (usecase_conf[i].forced_state < user_conf->forced_state) + user_conf->forced_state = usecase_conf[i].forced_state; + + /* Only override QOS if all enabled configurations are + * requesting it. + */ + if (!usecase_conf[i].vc_override) + user_conf->vc_override = false; + } + + user_conf->enable = config_enable; + user_config_updated = true; + + mutex_unlock(&usecase_mutex); +} + +struct usecase_devclass_attr { + struct sysdev_class_attribute class_attr; + u32 index; +}; + +/* One for each usecase except "user" + current + enable */ +#define UX500_NUM_SYSFS_NODES (UX500_UC_USER + 2) +#define UX500_CURRENT_NODE_INDEX (UX500_NUM_SYSFS_NODES - 1) +#define UX500_ENABLE_NODE_INDEX (UX500_NUM_SYSFS_NODES - 2) + +static struct usecase_devclass_attr usecase_dc_attr[UX500_NUM_SYSFS_NODES]; + +static struct attribute *dbs_attributes[UX500_NUM_SYSFS_NODES + 1] = {NULL}; + +static struct attribute_group dbs_attr_group = { + .attrs = dbs_attributes, + .name = "usecase", +}; + +static ssize_t show_current(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) +{ + enum ux500_uc display_uc = (current_uc == UX500_UC_MAX) ? + UX500_UC_NORMAL : current_uc; + + return sprintf(buf, "min_arm_opp: %d\n" + "max_arm_opp: %d\n" + "cpuidle_multiplier: %ld\n" + "second_cpu_online: %s\n" + "l2_prefetch_en: %s\n" + "forced_state: %d\n" + "vc_override: %s\n", + usecase_conf[display_uc].min_arm_opp, + usecase_conf[display_uc].max_arm_opp, + usecase_conf[display_uc].cpuidle_multiplier, + usecase_conf[display_uc].second_cpu_online ? "true" : "false", + usecase_conf[display_uc].l2_prefetch_en ? "true" : "false", + usecase_conf[display_uc].forced_state, + usecase_conf[display_uc].vc_override ? "true" : "false"); +} + +static ssize_t show_enable(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", uc_master_enable); +} + +static ssize_t store_enable(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + uc_master_enable = (bool) input; + + usecase_update_governor_state(); + + return count; +} + +static ssize_t show_dc_attr(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) +{ + struct usecase_devclass_attr *uattr = + container_of(attr, struct usecase_devclass_attr, class_attr); + + return sprintf(buf, "%u\n", + usecase_conf[uattr->index].enable); +} + +static ssize_t store_dc_attr(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + struct usecase_devclass_attr *uattr = + container_of(attr, struct usecase_devclass_attr, class_attr); + + ret = sscanf(buf, "%u", &input); + + /* Normal mode cant be changed. */ + if ((ret != 1) || (uattr->index == 0)) + return -EINVAL; + + usecase_conf[uattr->index].enable = (bool)input; + + if (uattr->index == UX500_UC_VC) + prcmu_vc(usecase_conf[UX500_UC_VC].enable); + + usecase_update_user_config(); + + usecase_update_governor_state(); + + return count; +} + +static int usecase_sysfs_init(void) +{ + int err; + int i; + + /* Last two nodes are not based on usecase configurations */ + for (i = 0; i < (UX500_NUM_SYSFS_NODES - 2); i++) { + usecase_dc_attr[i].class_attr.attr.name = usecase_conf[i].name; + usecase_dc_attr[i].class_attr.attr.mode = 0644; + usecase_dc_attr[i].class_attr.show = show_dc_attr; + usecase_dc_attr[i].class_attr.store = store_dc_attr; + usecase_dc_attr[i].index = i; + + dbs_attributes[i] = &(usecase_dc_attr[i].class_attr.attr); + } + + /* sysfs current */ + usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.attr.name = + "current"; + usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.attr.mode = + 0644; + usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.show = + show_current; + usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.store = + NULL; + usecase_dc_attr[UX500_CURRENT_NODE_INDEX].index = + 0; + dbs_attributes[UX500_CURRENT_NODE_INDEX] = + &(usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.attr); + + /* sysfs enable */ + usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.attr.name = + "enable"; + usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.attr.mode = + 0644; + usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.show = + show_enable; + usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.store = + store_enable; + usecase_dc_attr[UX500_ENABLE_NODE_INDEX].index = + 0; + dbs_attributes[UX500_ENABLE_NODE_INDEX] = + &(usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.attr); + + err = sysfs_create_group(&(cpu_sysdev_class.kset.kobj), + &dbs_attr_group); + if (err) + pr_err("usecase-gov: sysfs_create_group" + " failed with error = %d\n", err); + + return err; +} + +static void usecase_cpuidle_init(void) +{ + int max_states; + int i; + struct cstate *state = ux500_ci_get_cstates(&max_states); + + for (i = 0; i < max_states; i++) + if ((state[i].APE == APE_OFF) && (state[i].ARM == ARM_RET)) + break; + + usecase_conf[UX500_UC_LPA].forced_state = i; + + cpuidle_deepest_state = max_states - 1; +} + +/* initialize devices */ +static int __init init_usecase_devices(void) +{ + int err; + + pr_info("Use-case governor initialized\n"); + + /* add early_suspend callback */ + usecase_early_suspend.level = 200; + usecase_early_suspend.suspend = usecase_earlysuspend_callback; + usecase_early_suspend.resume = usecase_lateresume_callback; + register_early_suspend(&usecase_early_suspend); + + /* register delayed queuework */ + INIT_DELAYED_WORK_DEFERRABLE(&work_usecase, + delayed_usecase_work); + + init_cpu_load_trend(); + + err = setup_debugfs(); + if (err) + goto error; + err = usecase_sysfs_init(); + if (err) + goto error2; + + usecase_cpuidle_init(); + + prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "usecase", 25); + + return 0; +error2: + debugfs_remove_recursive(usecase_dir); +error: + unregister_early_suspend(&usecase_early_suspend); + return err; +} + +device_initcall(init_usecase_devices); diff --git a/arch/arm/mach-ux500/prcc.h b/arch/arm/mach-ux500/prcc.h new file mode 100644 index 00000000000..4224e478348 --- /dev/null +++ b/arch/arm/mach-ux500/prcc.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2009-2011 ST-Ericsson SA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MACH_UX500_PRCC_H__ + +#define PRCC_PCKEN 0x000 +#define PRCC_PCKDIS 0x004 +#define PRCC_KCKEN 0x008 +#define PRCC_KCKDIS 0x00C +#define PRCC_PCKSR 0x010 +#define PRCC_KCKSR 0x014 +#define PRCC_K_SOFTRST_SET 0x018 +#define PRCC_K_SOFTRST_CLR 0x01C +#define PRCC_K_RST_STATUS 0x020 + +#endif diff --git a/arch/arm/mach-ux500/prcmu-debug.c b/arch/arm/mach-ux500/prcmu-debug.c new file mode 100644 index 00000000000..6842e4b68fe --- /dev/null +++ b/arch/arm/mach-ux500/prcmu-debug.c @@ -0,0 +1,1041 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * + * Author: Martin Persson for ST-Ericsson + * Etienne Carriere <etienne.carriere@stericsson.com> for ST-Ericsson + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/mfd/dbx500-prcmu.h> + +#include <mach/hardware.h> + +#define MAX_STATES 5 +#define MAX_NAMELEN 16 +#define U8500_PRCMU_TCDM_SIZE 4096 + +struct state_history { + ktime_t start; + u32 state; + u32 counter[MAX_STATES]; + u8 opps[MAX_STATES]; + int max_states; + int req; + bool reqs[MAX_STATES]; + ktime_t time[MAX_STATES]; + int state_names[MAX_STATES]; + char prefix[MAX_NAMELEN]; + spinlock_t lock; +}; + +static struct state_history ape_sh = { + .prefix = "APE", + .req = PRCMU_QOS_APE_OPP, + .opps = {APE_50_OPP, APE_100_OPP}, + .state_names = {50, 100}, + .max_states = 2, +}; + +static struct state_history ddr_sh = { + .prefix = "DDR", + .req = PRCMU_QOS_DDR_OPP, + .opps = {DDR_25_OPP, DDR_50_OPP, DDR_100_OPP}, + .state_names = {25, 50, 100}, + .max_states = 3, +}; + +static struct state_history arm_sh = { + .prefix = "ARM", + .req = PRCMU_QOS_ARM_OPP, + .opps = {ARM_EXTCLK, ARM_50_OPP, ARM_100_OPP, ARM_MAX_OPP}, + .state_names = {25, 50, 100, 125}, + .max_states = 4, +}; + +static const u16 u8500_prcmu_dump_regs[] = { + /*ARMCLKFIX_MGT*/ 0x0, /*ACLK_MGT*/ 0x4, + /*SVAMMDSPCLK_MGT*/ 0x8, /*SIAMMDSPCLK_MGT*/ 0xc, + /*SGACLK_MGT*/ 0x14, /*UARTCLK_MGT*/ 0x18, + /*MSP02CLK_MGT*/ 0x1c, /*I2CCLK_MGT*/ 0x20, + /*SDMMCCLK_MGT*/ 0x24, /*SLIMCLK_MGT*/ 0x28, + /*PER1CLK_MGT*/ 0x2c, /*PER2CLK_MGT*/ 0x30, + /*PER3CLK_MGT*/ 0x34, /*PER5CLK_MGT*/ 0x38, + /*PER6CLK_MGT*/ 0x3c, /*PER7CLK_MGT*/ 0x40, + /*LCDCLK_MGT*/ 0x44, /*SPARE1CLK_MGT*/ 0x48, + /*BMLCLK_MGT*/ 0x4c, /*HSITXCLK_MGT*/ 0x50, + /*HSIRXCLK_MGT*/ 0x54, /*HDMICLK_MGT*/ 0x58, + /*APEATCLK_MGT*/ 0x5c, /*APETRACECLK_MGT*/ 0x60, + /*MCDECLK_MGT*/ 0x64, /*IPI2CCLK_MGT*/ 0x68, + /*DSIALTCLK_MGT*/ 0x6c, /*SPARE2CLK_MGT*/ 0x70, + /*DMACLK_MGT*/ 0x74, /*B2R2CLK_MGT*/ 0x78, + /*TVCLK_MGT*/ 0x7c, /*PLLSOC0_FREQ*/ 0x80, + /*PLLSOC1_FREQ*/ 0x84, /*PLLARM_FREQ*/ 0x88, + /*PLLDDR_FREQ*/ 0x8c, /*PLLSOC0_ENABLE*/ 0x90, + /*PLLSOC1_ENABLE*/ 0x94, /*PLLARM_ENABLE*/ 0x98, + /*PLLDDR_ENABLE*/ 0x9c, /*PLLSOC0_LOCKP*/ 0xa0, + /*PLLSOC1_LOCKP*/ 0xa4, /*PLLARM_LOCKP*/ 0xa8, + /*PLLDDR_LOCKP*/ 0xac, /*XP70CLK_MGT*/ 0xb0, + /*TIMER_0_REF*/ 0xb4, /*TIMER_0_DOWNCOUNT*/ 0xb8, + /*TIMER_0_MODE*/ 0xbc, /*TIMER_1_REF*/ 0xc0, + /*TIMER_1_DOWNCOUNT*/ 0xc4, /*TIMER_1_MODE*/ 0xc8, + /*TIMER_2_REF*/ 0xcc, /*TIMER_2_DOWNCOUNT*/ 0xd0, + /*TIMER_2_MODE*/ 0xd4, /*CLK009_MGT*/ 0xe4, + /*MODECLK*/ 0xe8, /*4500_CLK_REQ*/ 0xf8, + /*MBOX_CPU_VAL*/ 0xfc, /*PLL32K_ENABLE*/ 0x10c, + /*PLL32K_LOCKP*/ 0x110, /*ARM_CHGCLKREQ*/ 0x114, + /*ARM_PLLDIVPS*/ 0x118, /*ARMITMSK31TO0*/ 0x11c, + /*ARMITMSK63TO32*/ 0x120, /*ARMITMSK95TO64*/ 0x124, + /*ARMITMSK127TO96*/ 0x128, /*ARMSTANDBY_STATUS*/ 0x130, + /*CGATING_BYPASS*/ 0x134, /*GPIOCR*/ 0x138, + /*LEMI*/ 0x13c, /*COMPCR*/ 0x140, + /*COMPSTA*/ 0x144, /*ITSTATUS0*/ 0x148, + /*ITSTATUS1*/ 0x150, /*ITSTATUS2*/ 0x158, + /*ITSTATUS3*/ 0x160, /*ITSTATUS4*/ 0x168, + /*LINE_VALUE*/ 0x170, /*HOLD_EVT*/ 0x174, + /*EDGE_SENS_L*/ 0x178, /*EDGE_SENS_H*/ 0x17c, + /*DEBUG_CTRL_VAL*/ 0x190, /*DEBUG_NOPWRDOWN_VAL*/ 0x194, + /*DEBUG_CTRL_ACK*/ 0x198, /*A9PL_FORCE_CLKEN*/ 0x19c, + /*TPIU_FLUSHIN_REQ*/ 0x1a0, /*TPIU_FLUSHIN_ACK*/ 0x1a4, + /*STP_FLUSHIN_REQ*/ 0x1a8, /*STP_FLUSHIN_ACK*/ 0x1ac, + /*HWI2C_DIV*/ 0x1b0, /*HWI2C_CMD*/ 0x1b8, + /*HWI2C_DATA123*/ 0x1bc, /*HWI2C_SR*/ 0x1c0, + /*REMAPCR*/ 0x1c4, /*TCR*/ 0x1c8, + /*CLKOCR*/ 0x1cc, /*ITSTATUS_DBG*/ 0x1d0, + /*LINE_VALUE_DBG*/ 0x1d8, /*DBG_HOLD*/ 0x1dc, + /*EDGE_SENS_DBG*/ 0x1e0, /*APE_RESETN_VAL*/ 0x1ec, + /*A9_RESETN_SET*/ 0x1f0, /*A9_RESETN_VAL*/ 0x1f8, + /*MOD_RESETN_VAL*/ 0x204, /*GPIO_RESETN_VAL*/ 0x210, + /*4500_RESETN_VAL*/ 0x21c, /*SWD_RST_TEMPO*/ 0x238, + /*RST_4500_TEMPO*/ 0x23c, /*SVAMMDSP_IT*/ 0x240, + /*SIAMMDSP_IT*/ 0x248, /*POWER_STATE_VAL*/ 0x25c, + /*ARMITVALUE31TO0*/ 0x260, /*ARMITVALUE63TO32*/ 0x264, + /*ARMITVALUE95TO64*/ 0x268, /*ARMITVALUE127TO96*/ 0x26c, + /*REDUN_LOAD*/ 0x270, /*REDUN_STATUS*/ 0x274, + /*UNIPROCLK_MGT*/ 0x278, /*UICCCLK_MGT*/ 0x27c, + /*SSPCLK_MGT*/ 0x280, /*RNGCLK_MGT*/ 0x284, + /*MSP1CLK_MGT*/ 0x288, /*DAP_RESETN_SET*/ 0x2a0, + /*DAP_RESETN_VAL*/ 0x2a8, /*SRAM_DEDCSTOV*/ 0x300, + /*SRAM_LS_SLEEP*/ 0x304, /*SRAM_A9*/ 0x308, + /*ARM_LS_CLAMP*/ 0x30c, /*IOCR*/ 0x310, + /*MODEM_SYSCLKOK*/ 0x314, /*SYSCLKOK_DELAY*/ 0x318, + /*SYSCLKSTATUS*/ 0x31c, /*DSI_SW_RESET*/ 0x324, + /*A9_MASK_REQ*/ 0x328, /*A9_MASK_ACK*/ 0x32c, + /*HOSTACCESS_REQ*/ 0x334, /*TIMER_3_REF*/ 0x338, + /*TIMER_3_DOWNCOUNT*/ 0x33c, /*TIMER_3_MODE*/ 0x340, + /*PMB_SENS_CTRL*/ 0x344, /*PMB_REF_COUNTER*/ 0x348, + /*PMB_SENSOR_STATUS*/ 0x34c, /*APE_EPOD_CFG*/ 0x404, + /*DDR_EPOD_CFG*/ 0x408, /*EPOD_C_VAL*/ 0x418, + /*EPOD_VOK*/ 0x41c, /*MMIP_LS_CLAMP_VAL*/ 0x428, + /*VSAFE_LS_CLAMP_VAL*/ 0x434, /*DDRSUBSYS_APE_MINBW*/ 0x438, + /*DDRSUBSYS_STATUS*/ 0x43c, /*DDRSUBSYS_CONTROL*/ 0x440, + /*DDRSUBSYS_HIGH_LEAK_COND*/ 0x444, /*DDRSUBSYS_CONFIG*/ 0x448, + /*TIMER_4_REF*/ 0x450, /*TIMER_4_DOWNCOUNT*/ 0x454, + /*TIMER_4_MODE*/ 0x458, /*TIMER_5_REF*/ 0x45c, + /*TIMER_5_DOWNCOUNT*/ 0x460, /*TIMER_5_MODE*/ 0x464, + /*APE_MEM_REQ*/ 0x470, /*DBG_FRCS_APE_MEM_REQ*/ 0x474, + /*APE_MEM_WFX_EN*/ 0x478, /*APE_MEM_LATENCY*/ 0x47c, + /*APE_MEM_ACK*/ 0x480, /*ITSTATUS5*/ 0x484, + /*ARM_IT1_VAL*/ 0x494, /*MOD_PWR_OK*/ 0x498, + /*MOD_AUXCLKOK*/ 0x49c, /*MOD_AWAKE_STATUS*/ 0x4a0, + /*MOD_SWRESET_IRQ_ACK*/ 0x4a4, /*MOD_SWRESET_ACK*/ 0x4a8, + /*DBG_PWRCTL*/ 0x4ac, /*HWOBS_H*/ 0x4b0, + /*HWOBS_L*/ 0x4b4, /*PLLDSI_FREQ*/ 0x500, + /*PLLDSI_ENABLE*/ 0x504, /*PLLDSI_LOCKP*/ 0x508, + /*RNG_ENABLE*/ 0x50c, /*YYCLKEN0_MGT_SET*/ 0x510, + /*YYCLKEN0_MGT_VAL*/ 0x520, /*YYCLKEN1_MGT_VAL*/ 0x524, + /*XP70CLK_MGT2*/ 0x528, /*DSITVCLK_DIV*/ 0x52c, + /*DSI_PLLOUT_SEL*/ 0x530, /*DSI_GLITCHFREE_EN*/ 0x534, + /*CLKACTIV*/ 0x538, /*SIA_MMDSP_MEM_MGT*/ 0x53c, + /*SVA_MMDSP_MEM_MGT*/ 0x540, /*SXAMMDSP_FORCE_CLKEN*/ 0x544, + /*UICC_NANDTREE*/ 0x570, /*GPIOCR2*/ 0x574, + /*MDM_ACWAKE*/ 0x578, /*MOD_MEM_REQ*/ 0x5a4, + /*MOD_MEM_ACK*/ 0x5a8, /*ARM_PLLDIVPS_REQ*/ 0x5b0, + /*ARM_PLLDIVPS_ACK*/ 0x5b4, /*SRPTIMER_VAL*/ 0x5d0, +}; + +/* Offsets from secure base which is U8500_PRCMU_BASE + SZ_4K */ +static const u16 u8500_prcmu_dump_secure_regs[] = { + /*SECNONSEWM*/ 0x00, /*ESRAM0_INITN*/ 0x04, + /*ARMITMSKSEC_31TO0*/ 0x08, /*ARMITMSKSEC_63TO32*/ 0x0C, + /*ARMITMSKSEC_95TO64*/ 0x10, /*ARMITMSKSEC_127TO96*/ 0x14, + /*ARMIT_MASKXP70_IT*/ 0x18, /*ESRAM0_EPOD_CFG*/ 0x1C, + /*ESRAM0_EPOD_C_VAL*/ 0x20, /*ESRAM0_EPOD_VOK*/ 0x2C, + /*ESRAM0_LS_SLEEP*/ 0x30, /*SECURE_ONGOING*/ 0x34, + /*I2C_SECURE*/ 0x38, /*RESET_STATUS*/ 0x3C, + /*PERIPH4_RESETN_VAL*/ 0x48, /*SPAREOUT_SEC*/ 0x4C, + /*PIPELINEDCR*/ 0xD8, +}; + +static int ape_voltage_count; + +static void log_set(struct state_history *sh, u8 opp) +{ + ktime_t now; + ktime_t dtime; + unsigned long flags; + int state; + + now = ktime_get(); + spin_lock_irqsave(&sh->lock, flags); + + for (state = 0 ; sh->opps[state] != opp; state++) + ; + BUG_ON(state >= sh->max_states); + + dtime = ktime_sub(now, sh->start); + sh->time[sh->state] = ktime_add(sh->time[sh->state], dtime); + sh->start = now; + sh->counter[sh->state]++; + sh->state = state; + + spin_unlock_irqrestore(&sh->lock, flags); +} + +void prcmu_debug_ape_opp_log(u8 opp) +{ + if (opp == APE_50_PARTLY_25_OPP) + opp = APE_50_OPP; + + log_set(&ape_sh, opp); +} + +void prcmu_debug_ddr_opp_log(u8 opp) +{ + log_set(&ddr_sh, opp); +} + +void prcmu_debug_arm_opp_log(u8 opp) +{ + log_set(&arm_sh, opp); +} + +static void log_reset(struct state_history *sh) +{ + unsigned long flags; + int i; + + pr_info("reset\n"); + + spin_lock_irqsave(&sh->lock, flags); + for (i = 0; i < sh->max_states; i++) { + sh->counter[i] = 0; + sh->time[i] = ktime_set(0, 0); + } + + sh->start = ktime_get(); + spin_unlock_irqrestore(&sh->lock, flags); + +} + +static ssize_t ape_stats_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + log_reset(&ape_sh); + return count; +} + +static ssize_t ddr_stats_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + log_reset(&ddr_sh); + return count; +} + +static ssize_t arm_stats_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + log_reset(&arm_sh); + return count; +} + +static int log_print(struct seq_file *s, struct state_history *sh) +{ + int i; + unsigned long flags; + ktime_t total; + ktime_t dtime; + s64 t_ms; + s64 perc; + s64 total_ms; + + spin_lock_irqsave(&sh->lock, flags); + + dtime = ktime_sub(ktime_get(), sh->start); + + total = dtime; + + for (i = 0; i < sh->max_states; i++) + total = ktime_add(total, sh->time[i]); + total_ms = ktime_to_ms(total); + + for (i = 0; i < sh->max_states; i++) { + ktime_t t = sh->time[i]; + if (sh->state == i) + t = ktime_add(t, dtime); + + t_ms = ktime_to_ms(t); + perc = 100 * t_ms; + do_div(perc, total_ms); + + seq_printf(s, "%s OPP %d: # %u in %lld ms %d%%\n", + sh->prefix, sh->state_names[i], + sh->counter[i] + (int)(sh->state == i), + t_ms, (u32)perc); + + } + spin_unlock_irqrestore(&sh->lock, flags); + return 0; +} + +static int ape_stats_print(struct seq_file *s, void *p) +{ + log_print(s, &ape_sh); + return 0; +} + +static int ddr_stats_print(struct seq_file *s, void *p) +{ + log_print(s, &ddr_sh); + return 0; +} + +static int arm_stats_print(struct seq_file *s, void *p) +{ + log_print(s, &arm_sh); + return 0; +} + +static int opp_read(struct seq_file *s, void *p) +{ + int opp; + + struct state_history *sh = (struct state_history *)s->private; + + switch (sh->req) { + case PRCMU_QOS_DDR_OPP: + opp = prcmu_get_ddr_opp(); + seq_printf(s, "%s (%d)\n", + (opp == DDR_100_OPP) ? "100%" : + (opp == DDR_50_OPP) ? "50%" : + (opp == DDR_25_OPP) ? "25%" : + "unknown", opp); + break; + case PRCMU_QOS_APE_OPP: + opp = prcmu_get_ape_opp(); + seq_printf(s, "%s (%d)\n", + (opp == APE_100_OPP) ? "100%" : + (opp == APE_50_OPP) ? "50%" : + "unknown", opp); + break; + case PRCMU_QOS_ARM_OPP: + opp = prcmu_get_arm_opp(); + seq_printf(s, "%s (%d)\n", + (opp == ARM_MAX_OPP) ? "max" : + (opp == ARM_MAX_FREQ100OPP) ? "max-freq100" : + (opp == ARM_100_OPP) ? "100%" : + (opp == ARM_50_OPP) ? "50%" : + (opp == ARM_EXTCLK) ? "25% (extclk)" : + "unknown", opp); + break; + default: + break; + } + return 0; + +} + +static ssize_t opp_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + long unsigned i; + int err; + struct state_history *sh = (struct state_history *) + ((struct seq_file *)file->private_data)->private; + + err = kstrtoul_from_user(user_buf, count, 0, &i); + + if (err) + return err; + + prcmu_qos_force_opp(sh->req, i); + + pr_info("prcmu debug: forced OPP for %s to %d\n", sh->prefix, (int)i); + + return count; +} + +static int cpufreq_delay_read(struct seq_file *s, void *p) +{ + return seq_printf(s, "%lu\n", prcmu_qos_get_cpufreq_opp_delay()); +} + +static int ape_voltage_read(struct seq_file *s, void *p) +{ + return seq_printf(s, "This reference count only includes " + "requests via debugfs.\nCount: %d\n", + ape_voltage_count); +} + +static ssize_t ape_voltage_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + long unsigned i; + int err; + + err = kstrtoul_from_user(user_buf, count, 0, &i); + + if (err) + return err; + + switch (i) { + case 0: + if (ape_voltage_count == 0) + pr_info("prcmu debug: reference count is already 0\n"); + else { + err = prcmu_request_ape_opp_100_voltage(false); + if (err) + pr_err("prcmu debug: drop request failed\n"); + else + ape_voltage_count--; + } + break; + case 1: + err = prcmu_request_ape_opp_100_voltage(true); + if (err) + pr_err("prcmu debug: request failed\n"); + else + ape_voltage_count++; + break; + default: + pr_info("prcmu debug: value not equal to 0 or 1\n"); + } + return count; +} + +static ssize_t cpufreq_delay_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + int err; + long unsigned i; + + err = kstrtoul_from_user(user_buf, count, 0, &i); + + if (err) + return err; + + prcmu_qos_set_cpufreq_opp_delay(i); + + pr_info("prcmu debug: changed delay between cpufreq change and QoS " + "requirement to %lu.\n", i); + + return count; +} + +/* These are only for u8500 */ +#define PRCM_AVS_BASE 0x2FC +#define AVS_VBB_RET 0x0 +#define AVS_VBB_MAX_OPP 0x1 +#define AVS_VBB_100_OPP 0x2 +#define AVS_VBB_50_OPP 0x3 +#define AVS_VARM_MAX_OPP 0x4 +#define AVS_VARM_100_OPP 0x5 +#define AVS_VARM_50_OPP 0x6 +#define AVS_VARM_RET 0x7 +#define AVS_VAPE_100_OPP 0x8 +#define AVS_VAPE_50_OPP 0x9 +#define AVS_VMOD_100_OPP 0xA +#define AVS_VMOD_50_OPP 0xB +#define AVS_VSAFE 0xC +#define AVS_VSAFE_RET 0xD +#define AVS_SIZE 14 + +static int avs_read(struct seq_file *s, void *p) +{ + + u8 avs[AVS_SIZE]; + void __iomem *tcdm_base; + + if (cpu_is_u8500()) { + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); + + memcpy_fromio(avs, tcdm_base + PRCM_AVS_BASE, AVS_SIZE); + + seq_printf(s, "VBB_RET : 0x%02x\n", avs[AVS_VBB_RET]); + seq_printf(s, "VBB_MAX_OPP : 0x%02x\n", avs[AVS_VBB_MAX_OPP]); + seq_printf(s, "VBB_100_OPP : 0x%02x\n", avs[AVS_VBB_100_OPP]); + seq_printf(s, "VBB_50_OPP : 0x%02x\n", avs[AVS_VBB_50_OPP]); + seq_printf(s, "VARM_MAX_OPP : 0x%02x\n", avs[AVS_VARM_MAX_OPP]); + seq_printf(s, "VARM_100_OPP : 0x%02x\n", avs[AVS_VARM_100_OPP]); + seq_printf(s, "VARM_50_OPP : 0x%02x\n", avs[AVS_VARM_50_OPP]); + seq_printf(s, "VARM_RET : 0x%02x\n", avs[AVS_VARM_RET]); + seq_printf(s, "VAPE_100_OPP : 0x%02x\n", avs[AVS_VAPE_100_OPP]); + seq_printf(s, "VAPE_50_OPP : 0x%02x\n", avs[AVS_VAPE_50_OPP]); + seq_printf(s, "VMOD_100_OPP : 0x%02x\n", avs[AVS_VMOD_100_OPP]); + seq_printf(s, "VMOD_50_OPP : 0x%02x\n", avs[AVS_VMOD_50_OPP]); + seq_printf(s, "VSAFE : 0x%02x\n", avs[AVS_VSAFE]); + seq_printf(s, "VSAFE_RET : 0x%02x\n", avs[AVS_VSAFE_RET]); + } else { + seq_printf(s, "Only u8500 supported.\n"); + } + + return 0; +} + +static void prcmu_data_mem_print(struct seq_file *s) +{ + int i; + int err; + void __iomem *tcdm_base; + u32 dmem[4]; + + if (cpu_is_u8500()) { + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); + + for (i = 0; i < U8500_PRCMU_TCDM_SIZE; i += 16) { + dmem[0] = readl(tcdm_base + i + 0); + dmem[1] = readl(tcdm_base + i + 4); + dmem[2] = readl(tcdm_base + i + 8); + dmem[3] = readl(tcdm_base + i + 12); + + if (s) { + err = seq_printf(s, + "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + ((int)tcdm_base) + i, dmem[0], + dmem[1], dmem[2], dmem[3]); + if (err < 0) { + pr_err("%s: seq_printf overflow, addr=%x\n", + __func__, ((int)tcdm_base) + i); + /* Can't do much here */ + return; + } + } else { + printk(KERN_INFO + "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + ((int)tcdm_base) + i, dmem[0], + dmem[1], dmem[2], dmem[3]); + } + } + } +} + +void prcmu_debug_dump_data_mem(void) +{ + printk(KERN_INFO "PRCMU data memory dump:\n"); + prcmu_data_mem_print(NULL); +} + +static int prcmu_debugfs_data_mem_read(struct seq_file *s, void *p) +{ + seq_printf(s, "PRCMU data memory:\n"); + prcmu_data_mem_print(s); + + return 0; +} + +static void prcmu_regs_print(struct seq_file *s) +{ + int i; + int err; + void __iomem *prcmu_base; + u32 reg_val; + + if (cpu_is_u8500()) { + prcmu_base = __io_address(U8500_PRCMU_BASE); + + for (i = 0; i < ARRAY_SIZE(u8500_prcmu_dump_regs); i++) { + reg_val = readl(prcmu_base + + u8500_prcmu_dump_regs[i]); + + if (s) { + err = seq_printf(s, "0x%04x: 0x%08x\n", + u8500_prcmu_dump_regs[i], reg_val); + if (err < 0) { + pr_err("%s: seq_printf overflow," + "offset=%x\n", __func__, + u8500_prcmu_dump_regs[i]); + /* Can't do much here */ + return; + } + } else { + printk(KERN_INFO + "0x%04x: 0x%08x\n", + u8500_prcmu_dump_regs[i], reg_val); + } + } + } +} + +static void prcmu_secure_regs_print(struct seq_file *s) +{ + int i; + int err; + void __iomem *prcmu_sec_base; + u32 reg_val; + + if (cpu_is_u8500()) { + /* PRCMU secure base starts after SZ_4K */ + prcmu_sec_base = ioremap(U8500_PRCMU_BASE + SZ_4K, SZ_4K); + if (!prcmu_sec_base) { + pr_err("%s: ioremap faild\n", __func__); + return; + } + + for (i = 0; i < ARRAY_SIZE(u8500_prcmu_dump_secure_regs); i++) { + reg_val = readl(prcmu_sec_base + + u8500_prcmu_dump_secure_regs[i]); + + if (s) { + err = seq_printf(s, "0x%04x: 0x%08x\n", + u8500_prcmu_dump_secure_regs[i] + + SZ_4K, + reg_val); + if (err < 0) { + pr_err("%s: seq_printf overflow," + "offset=%x\n", __func__, + u8500_prcmu_dump_secure_regs[i] + + SZ_4K); + /* Can't do much here */ + break; + } + } else { + printk(KERN_INFO + "0x%04x: 0x%08x\n", + u8500_prcmu_dump_secure_regs[i] + + SZ_4K, + reg_val); + } + } + + iounmap(prcmu_sec_base); + } +} + +void prcmu_debug_dump_regs(void) +{ + printk(KERN_INFO "PRCMU registers dump:\n"); + prcmu_regs_print(NULL); + prcmu_secure_regs_print(NULL); +} + +static int prcmu_debugfs_regs_read(struct seq_file *s, void *p) +{ + seq_printf(s, "PRCMU registers:\n"); + prcmu_regs_print(s); + prcmu_secure_regs_print(s); + return 0; +} + +/* Interrupt debugging */ + +/* There are eight mailboxes */ +#define NUM_MAILBOXES 8 +#define NUM_MAILBOX0_EVENTS 32 +static u32 num_mailbox_interrupts[NUM_MAILBOXES]; +static u32 num_mailbox0_events[NUM_MAILBOX0_EVENTS]; +static u32 num_mailbox0_events_garbage[NUM_MAILBOX0_EVENTS]; + +void prcmu_debug_register_interrupt(u32 mailbox) +{ + if (mailbox < NUM_MAILBOXES) + num_mailbox_interrupts[mailbox]++; +} + +void prcmu_debug_register_mbox0_event(u32 ev, u32 mask) +{ + int i; + + for (i = 0 ; i < NUM_MAILBOX0_EVENTS; i++) + if (ev & (1 << i)) { + if (mask & (1 << i)) + num_mailbox0_events[i]++; + else + num_mailbox0_events_garbage[i]++; + } +} + +static int interrupt_read(struct seq_file *s, void *p) +{ + int i; + char **mbox0names; + + static char *mbox0names_u8500[] = { + "RTC", + "RTT0", + "RTT1", + "HSI0", + "HSI1", + "CA_WAKE", + "USB", + "ABB", + "ABB_FIFO", + "SYSCLK_OK", + "CA_SLEE", + "AC_WAKE_ACK", + "SIDE_TONE_OK", + "ANC_OK", + "SW_ERROR", + "AC_SLEEP_ACK", + NULL, + "ARM", + "HOTMON_LOW", + "HOTMON_HIGH", + "MODEM_SW_RESET_REQ", + NULL, + NULL, + "GPIO0", + "GPIO1", + "GPIO2", + "GPIO3", + "GPIO4", + "GPIO5", + "GPIO6", + "GPIO7", + "GPIO8"}; + static char *mbox0names_u5500[] = { + "RTC", + "RTT0", + "RTT1", + "CD_IRQ", + "SRP_TIM", + "APE_REQ", + "USB", + "ABB", + "LOW_POWER_AUDIO", + "TEMP_SENSOR_LOW", + "ARM", + "AC_WAKE_ACK", + NULL, + "TEMP_SENSOR_HIGH", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "MODEM_SW_RESET_REQ", + NULL, + NULL, + "GPIO0", + "GPIO1", + "GPIO2", + "GPIO3", + "GPIO4", + "GPIO5", + "GPIO6", + "GPIO7", + "AC_REL_ACK"}; + + if (cpu_is_u8500()) { + mbox0names = mbox0names_u8500; + } else if (cpu_is_u5500()) { + mbox0names = mbox0names_u5500; + } else { + seq_printf(s, "Unknown ASIC!\n"); + return 0; + } + + seq_printf(s, "mailbox0: %d\n", num_mailbox_interrupts[0]); + + for (i = 0; i < NUM_MAILBOX0_EVENTS; i++) + if (mbox0names[i]) { + seq_printf(s, " %20s %d ", mbox0names[i], + num_mailbox0_events[i] + ); + if (num_mailbox0_events_garbage[i]) + seq_printf(s, "unwanted: %d", + num_mailbox0_events_garbage[i]); + seq_printf(s, "\n"); + } else if (num_mailbox0_events[i]) { + seq_printf(s, " unknown (%d) %d\n", + i, num_mailbox0_events[i]); + } + + for (i = 1 ; i < NUM_MAILBOXES; i++) + seq_printf(s, "mailbox%d: %d\n", i, num_mailbox_interrupts[i]); + return 0; +} + +static int opp_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, opp_read, inode->i_private); +} + +static int ape_stats_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, ape_stats_print, inode->i_private); +} + +static int ddr_stats_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, ddr_stats_print, inode->i_private); +} + +static int arm_stats_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, arm_stats_print, inode->i_private); +} + +static int cpufreq_delay_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, cpufreq_delay_read, inode->i_private); +} + +static int ape_voltage_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, ape_voltage_read, inode->i_private); +} + +static int avs_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, avs_read, inode->i_private); +} + +static int prcmu_data_mem_open_file(struct inode *inode, struct file *file) +{ + int err; + struct seq_file *s; + + err = single_open(file, prcmu_debugfs_data_mem_read, inode->i_private); + if (!err) { + /* Default buf size in seq_read is not enough */ + s = (struct seq_file *)file->private_data; + s->size = (PAGE_SIZE * 4); + s->buf = kmalloc(s->size, GFP_KERNEL); + if (!s->buf) { + single_release(inode, file); + err = -ENOMEM; + } + } + return err; +} + +static int prcmu_regs_open_file(struct inode *inode, struct file *file) +{ + int err; + struct seq_file *s; + + err = single_open(file, prcmu_debugfs_regs_read, inode->i_private); + if (!err) { + /* Default buf size in seq_read is not enough */ + s = (struct seq_file *)file->private_data; + s->size = (PAGE_SIZE * 2); + s->buf = kmalloc(s->size, GFP_KERNEL); + if (!s->buf) { + single_release(inode, file); + err = -ENOMEM; + } + } + return err; +} + +static int interrupt_open_file(struct inode *inode, struct file *file) +{ + return single_open(file, interrupt_read, inode->i_private); +} + +static const struct file_operations opp_fops = { + .open = opp_open_file, + .write = opp_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations ape_stats_fops = { + .open = ape_stats_open_file, + .write = ape_stats_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations ddr_stats_fops = { + .open = ddr_stats_open_file, + .write = ddr_stats_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations arm_stats_fops = { + .open = arm_stats_open_file, + .write = arm_stats_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations cpufreq_delay_fops = { + .open = cpufreq_delay_open_file, + .write = cpufreq_delay_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations ape_voltage_fops = { + .open = ape_voltage_open_file, + .write = ape_voltage_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations avs_fops = { + .open = avs_open_file, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations prcmu_data_mem_fops = { + .open = prcmu_data_mem_open_file, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations prcmu_regs_fops = { + .open = prcmu_regs_open_file, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct file_operations interrupts_fops = { + .open = interrupt_open_file, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int setup_debugfs(void) +{ + struct dentry *dir; + struct dentry *file; + + dir = debugfs_create_dir("prcmu", NULL); + if (IS_ERR_OR_NULL(dir)) + goto fail; + + file = debugfs_create_file("ape_stats", (S_IRUGO | S_IWUGO), + dir, NULL, &ape_stats_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("ddr_stats", (S_IRUGO | S_IWUGO), + dir, NULL, &ddr_stats_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("arm_stats", (S_IRUGO | S_IWUGO), + dir, NULL, &arm_stats_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("ape_opp", (S_IRUGO), + dir, (void *)&ape_sh, + &opp_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("ddr_opp", (S_IRUGO), + dir, (void *)&ddr_sh, + &opp_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("arm_opp", (S_IRUGO), + dir, (void *)&arm_sh, + &opp_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("opp_cpufreq_delay", (S_IRUGO), + dir, NULL, &cpufreq_delay_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("ape_voltage", (S_IRUGO), + dir, NULL, &ape_voltage_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("avs", + (S_IRUGO), + dir, NULL, &avs_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("data_mem", (S_IRUGO), + dir, NULL, + &prcmu_data_mem_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("regs", (S_IRUGO), + dir, NULL, + &prcmu_regs_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + file = debugfs_create_file("interrupts", + (S_IRUGO), + dir, NULL, &interrupts_fops); + if (IS_ERR_OR_NULL(file)) + goto fail; + + return 0; +fail: + if (!IS_ERR_OR_NULL(dir)) + debugfs_remove_recursive(dir); + + pr_err("prcmu debug: debugfs entry failed\n"); + return -ENOMEM; +} + +static __init int prcmu_debug_init(void) +{ + spin_lock_init(&ape_sh.lock); + spin_lock_init(&ddr_sh.lock); + spin_lock_init(&arm_sh.lock); + ape_sh.start = ktime_get(); + ddr_sh.start = ktime_get(); + arm_sh.start = ktime_get(); + return 0; +} +arch_initcall(prcmu_debug_init); + +static __init int prcmu_debug_debugfs_init(void) +{ + setup_debugfs(); + return 0; +} +late_initcall(prcmu_debug_debugfs_init); diff --git a/arch/arm/mach-ux500/product.c b/arch/arm/mach-ux500/product.c new file mode 100644 index 00000000000..f4647b3ab29 --- /dev/null +++ b/arch/arm/mach-ux500/product.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Jens Wiklander <jens.wiklander@stericsson.com> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> + * + * License terms: GNU General Public License (GPL) version 2 + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/tee.h> +#include <linux/module.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> + +#define STATIC_TEE_TA_START_LOW 0xBC765EDE +#define STATIC_TEE_TA_START_MID 0x6724 +#define STATIC_TEE_TA_START_HIGH 0x11DF +#define STATIC_TEE_TA_START_CLOCKSEQ \ + {0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85} + +#define U5500_PRCMU_DBG_PWRCTRL (U5500_PRCMU_BASE + 0x4AC) +#define PRCMU_DBG_PWRCTRL_A9DBGCLKEN (1 << 4) + +static struct tee_product_config product_config; + +bool ux500_jtag_enabled(void) +{ +#ifdef CONFIG_UX500_DEBUG_NO_LAUTERBACH + return false; +#else + if (machine_is_snowball()) + return true; + if (cpu_is_u5500()) + return readl_relaxed(__io_address(U5500_PRCMU_DBG_PWRCTRL)) + & PRCMU_DBG_PWRCTRL_A9DBGCLKEN; + + if (cpu_is_u8500() || cpu_is_u9540()) + return (product_config.rt_flags & TEE_RT_FLAGS_JTAG_ENABLED) == + TEE_RT_FLAGS_JTAG_ENABLED; + + return true; +#endif +} + +static int __init product_detect(void) +{ + int err; + int origin_err; + struct tee_operation operation = { { { 0 } } }; + struct tee_context context; + struct tee_session session; + + /* Selects trustzone application needed for the job. */ + struct tee_uuid static_uuid = { + STATIC_TEE_TA_START_LOW, + STATIC_TEE_TA_START_MID, + STATIC_TEE_TA_START_HIGH, + STATIC_TEE_TA_START_CLOCKSEQ, + }; + + if (cpu_is_u5500()) + return -ENODEV; + + err = teec_initialize_context(NULL, &context); + if (err) { + pr_err("ux500-product: unable to initialize tee context," + " err = %d\n", err); + err = -EINVAL; + goto error0; + } + + err = teec_open_session(&context, &session, &static_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &origin_err); + if (err) { + pr_err("ux500-product: unable to open tee session," + " tee error = %d, origin error = %d\n", + err, origin_err); + err = -EINVAL; + goto error1; + } + + operation.shm[0].buffer = &product_config; + operation.shm[0].size = sizeof(product_config); + operation.shm[0].flags = TEEC_MEM_OUTPUT; + operation.flags = TEEC_MEMREF_0_USED; + + err = teec_invoke_command(&session, + TEE_STA_GET_PRODUCT_CONFIG, + &operation, &origin_err); + if (err) { + pr_err("ux500-product: fetching product settings failed, err=%d", + err); + err = -EINVAL; + goto error1; + } + + switch (product_config.product_id) { + case TEE_PRODUCT_ID_8400: + pr_info("ux500-product: u8400 detected\n"); + break; + case TEE_PRODUCT_ID_8500: + pr_info("ux500-product: u8500 detected\n"); + break; + case TEE_PRODUCT_ID_9500: + pr_info("ux500-product: u9500 detected\n"); + break; + case TEE_PRODUCT_ID_5500: + pr_info("ux500-product: u5500 detected\n"); + break; + case TEE_PRODUCT_ID_7400: + pr_info("ux500-product: u7400 detected\n"); + break; + case TEE_PRODUCT_ID_8500C: + pr_info("ux500-product: u8500C detected\n"); + break; + case TEE_PRODUCT_ID_UNKNOWN: + default: + pr_info("ux500-product: UNKNOWN! (0x%x) detected\n", + product_config.product_id); + break; + } + pr_info("ux500-product: JTAG is %s\n", + ux500_jtag_enabled() ? "enabled" : "disabled"); +error1: + (void) teec_finalize_context(&context); +error0: + return err; +} +device_initcall(product_detect); diff --git a/arch/arm/mach-ux500/product.h b/arch/arm/mach-ux500/product.h new file mode 100644 index 00000000000..502eff4df14 --- /dev/null +++ b/arch/arm/mach-ux500/product.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Jens Wiklander <jens.wiklander@stericsson.com> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * + * License terms: GNU General Public License (GPL) version 2 + * + */ + +#ifndef UX500_PRODUCT_H +#define UX500_PRODUCT_H + +#ifdef CONFIG_TEE_UX500 + +bool ux500_jtag_enabled(void); + +#else + +static inline bool ux500_jtag_enabled(void) +{ + return true; +} + +#endif +#endif diff --git a/arch/arm/mach-ux500/reboot_reasons.c b/arch/arm/mach-ux500/reboot_reasons.c new file mode 100644 index 00000000000..7b25ef8b4ff --- /dev/null +++ b/arch/arm/mach-ux500/reboot_reasons.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Rickard Evertsson <rickard.evertsson@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL) version 2 + * + * Use this file to customize your reboot / sw reset reasons. Add, remove or + * modify reasons in reboot_reasons[]. + */ + +#include <linux/bug.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <mach/reboot_reasons.h> + +struct reboot_reason reboot_reasons[] = { + {"crash", SW_RESET_CRASH}, + {"factory-reset", SW_RESET_FACTORY_RESET}, + {"recovery", SW_RESET_RECOVERY}, + {"charging", SW_RESET_CHARGING}, + {"coldstart", SW_RESET_COLDSTART}, + {"none", SW_RESET_NO_ARGUMENT}, /* Normal Boot */ + {"chgonly-exit", SW_RESET_CHGONLY_EXIT}, /* Exit Charge Only Mode */ +}; + +unsigned int reboot_reasons_size = ARRAY_SIZE(reboot_reasons); + +/* + * The reboot reason string can be 255 characters long and the memory + * in which we save the sw reset reason is 2 bytes. Therefore we need to + * convert the string into a 16 bit pattern. + * + * See file reboot_reasons.h for conversion. + */ +u16 reboot_reason_code(const char *cmd) +{ + int i; + + if (cmd == NULL) { + if (oops_in_progress) { + /* if we're in an oops assume it's a crash */ + return SW_RESET_CRASH; + } else { + /* normal reboot w/o argument */ + return SW_RESET_NO_ARGUMENT; + } + } + + /* Search through reboot reason list */ + for (i = 0; i < reboot_reasons_size; i++) { + if (!strcmp(reboot_reasons[i].reason, cmd)) + return reboot_reasons[i].code; + } + + /* No valid reboot reason found */ + return SW_RESET_NO_ARGUMENT; +} + +/* + * The saved sw reset reason is a 2 byte code that is translated into + * a reboot reason string which is up to 255 characters long by this + * function. + * + * See file reboot_reasons.h for conversion. + */ +const char *reboot_reason_string(u16 code) +{ + int i; + + /* Search through reboot reason list */ + for (i = 0; i < reboot_reasons_size; i++) { + if (reboot_reasons[i].code == code) + return reboot_reasons[i].reason; + } + + /* No valid reboot reason code found */ + return "unknown"; +} diff --git a/arch/arm/mach-ux500/regulator-u5500.h b/arch/arm/mach-ux500/regulator-u5500.h new file mode 100644 index 00000000000..cf3eeed9366 --- /dev/null +++ b/arch/arm/mach-ux500/regulator-u5500.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + */ + +#ifndef __REGULATOR_U5500_H +#define __REGULATOR_U5500_H + +enum u5500_regulator_id { + U5500_REGULATOR_VAPE, + U5500_REGULATOR_SWITCH_SGA, + U5500_REGULATOR_SWITCH_HVA, + U5500_REGULATOR_SWITCH_SIA, + U5500_REGULATOR_SWITCH_DISP, + U5500_REGULATOR_SWITCH_ESRAM12, + U5500_NUM_REGULATORS +}; + +#endif diff --git a/arch/arm/mach-ux500/tee_service_svp.c b/arch/arm/mach-ux500/tee_service_svp.c new file mode 100644 index 00000000000..aa65dd961a0 --- /dev/null +++ b/arch/arm/mach-ux500/tee_service_svp.c @@ -0,0 +1,66 @@ +/* + * TEE service to handle the calls to trusted applications in SVP. + * + * Copyright (C) ST-Ericsson SA 2010 + * Author: Shujuan Chen <shujuan.chen@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/tee.h> +#include <linux/err.h> +#include "mach/tee_ta_start_modem.h" + +static int cmp_uuid_start_modem(struct tee_uuid *uuid) +{ + int ret = -EINVAL; + + if (uuid == NULL) + return -EINVAL; + + /* This handles the calls to TA for start the modem */ + if ((uuid->timeLow == UUID_TEE_TA_START_MODEM_LOW) && + (uuid->timeMid == UUID_TEE_TA_START_MODEM_MID) && + (uuid->timeHiAndVersion == UUID_TEE_TA_START_MODEM_HIGH)) { + + u8 clockSeqAndNode[TEE_UUID_CLOCK_SIZE] = + UUID_TEE_TA_START_MODEM_CLOCKSEQ; + + ret = memcmp(uuid->clockSeqAndNode, clockSeqAndNode, + TEE_UUID_CLOCK_SIZE); + } + + return ret; +} + +int call_sec_world(struct tee_session *ts, int sec_cmd) +{ + int ret = 0; + + if (ts == NULL) + return -EINVAL; + + if (cmp_uuid_start_modem(ts->uuid)) + return -EINVAL; + + switch (ts->cmd) { + case COMMAND_ID_START_MODEM: + ret = tee_ta_start_modem((struct tee_ta_start_modem *) + ts->op); + if (ret) { + ts->err = TEED_ERROR_GENERIC; + ts->origin = TEED_ORIGIN_TEE_APPLICATION; + pr_err("tee_ta_start_modem() failed!\n"); + return ret; + } + break; + + default: + break; + } + + /* TODO: to handle more trusted applications. */ + + return ret; +} diff --git a/arch/arm/mach-ux500/tee_ta_start_modem_svp.c b/arch/arm/mach-ux500/tee_ta_start_modem_svp.c new file mode 100644 index 00000000000..12337b93154 --- /dev/null +++ b/arch/arm/mach-ux500/tee_ta_start_modem_svp.c @@ -0,0 +1,56 @@ +/* + * Trusted application for starting the modem. + * + * Copyright (C) ST-Ericsson SA 2010 + * Author: Shujuan Chen <shujuan.chen@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/elf.h> +#include <mach/hardware.h> + +#include "mach/tee_ta_start_modem.h" + +static int reset_modem(unsigned long modem_start_addr) +{ + void __iomem *base = ioremap(U5500_ACCCON_BASE_SEC, 0x2FF); + if (!base) + return -ENOMEM; + + pr_info("[%s] Setting modem start address!\n", __func__); + writel(base + (U5500_ACCCON_CPUVEC_RESET_ADDR_OFFSET/sizeof(uint32_t)), + modem_start_addr); + + pr_info("[%s] resetting the modem!\n", __func__); + writel(base + (U5500_ACCCON_ACC_CPU_CTRL_OFFSET/sizeof(uint32_t)), 1); + + iounmap(base); + + return 0; +} + +int tee_ta_start_modem(struct tee_ta_start_modem *data) +{ + int ret = 0; + struct elfhdr *elfhdr; + void __iomem *vaddr; + + vaddr = ioremap((unsigned long)data->access_image_descr.elf_hdr, + sizeof(struct elfhdr)); + if (!vaddr) + return -ENOMEM; + + elfhdr = (struct elfhdr *)readl(vaddr); + pr_info("Reading in kernel:elfhdr 0x%x:elfhdr->entry=0x%x\n", + (uint32_t)elfhdr, (uint32_t)elfhdr->e_entry); + + pr_info("[%s] reset modem()...\n", __func__); + ret = reset_modem(elfhdr->e_entry); + + iounmap(vaddr); + + return ret; +} diff --git a/arch/arm/mach-ux500/tee_ux500.c b/arch/arm/mach-ux500/tee_ux500.c new file mode 100644 index 00000000000..9fa985a48c8 --- /dev/null +++ b/arch/arm/mach-ux500/tee_ux500.c @@ -0,0 +1,99 @@ +/* + * TEE service to handle the calls to trusted applications. + * + * Copyright (C) ST-Ericsson SA 2010 + * Author: Joakim Bech <joakim.xx.bech@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ +#include <linux/kernel.h> +#include <linux/tee.h> +#include <linux/io.h> +#include <linux/errno.h> + +#include <mach/hardware.h> + +#define ISSWAPI_EXECUTE_TA 0x11000001 +#define ISSWAPI_CLOSE_TA 0x11000002 + +#define SEC_ROM_NO_FLAG_MASK 0x0000 + +static u32 call_sec_rom_bridge(u32 service_id, u32 cfg, ...) +{ + typedef u32 (*bridge_func)(u32, u32, va_list); + bridge_func hw_sec_rom_pub_bridge; + va_list ap; + u32 ret; + + if (cpu_is_u9540()) + hw_sec_rom_pub_bridge = (bridge_func) + ((u32)IO_ADDRESS_DB9540_ROM + (U9540_BOOT_ROM_BASE + 0x17300)); + else if (cpu_is_u8500()) + hw_sec_rom_pub_bridge = (bridge_func) + ((u32)IO_ADDRESS(U8500_BOOT_ROM_BASE + 0x17300)); + else if (cpu_is_u5500()) + hw_sec_rom_pub_bridge = (bridge_func) + ((u32)IO_ADDRESS(U5500_BOOT_ROM_BASE + 0x18300)); + else + ux500_unknown_soc(); + + va_start(ap, cfg); + ret = hw_sec_rom_pub_bridge(service_id, cfg, ap); + va_end(ap); + + return ret; +} + +int call_sec_world(struct tee_session *ts, int sec_cmd) +{ + /* + * ts->ta and ts->uuid is set to NULL when opening the device, + * hence it should be safe to just do the call here. + */ + + switch (sec_cmd) { + case TEED_INVOKE: + if (!ts->uuid) { + call_sec_rom_bridge(ISSWAPI_EXECUTE_TA, + SEC_ROM_NO_FLAG_MASK, + virt_to_phys(&ts->id), + NULL, + virt_to_phys(ts->ta), + ts->cmd, + virt_to_phys((void *)(ts->op)), + virt_to_phys((void *)(&ts->err)), + virt_to_phys((void *)(&ts->origin))); + } else { + call_sec_rom_bridge(ISSWAPI_EXECUTE_TA, + SEC_ROM_NO_FLAG_MASK, + virt_to_phys(&ts->id), + virt_to_phys(ts->uuid), + virt_to_phys(ts->ta), + ts->cmd, + virt_to_phys((void *)(ts->op)), + virt_to_phys((void *)(&ts->err)), + virt_to_phys((void *)(&ts->origin))); + } + break; + + case TEED_CLOSE_SESSION: + call_sec_rom_bridge(ISSWAPI_CLOSE_TA, + SEC_ROM_NO_FLAG_MASK, + ts->id, + NULL, + virt_to_phys(ts->ta), + virt_to_phys((void *)(&ts->err))); + + /* Since the TEE Client API does NOT take care of + * the return value, we print a warning here if + * something went wrong in secure world. + */ + if (ts->err != TEED_SUCCESS) + pr_warning("[%s] failed in secure world\n", + __func__); + + break; + } + + return 0; +} diff --git a/arch/arm/mach-ux500/test/Kconfig b/arch/arm/mach-ux500/test/Kconfig new file mode 100644 index 00000000000..a071166d092 --- /dev/null +++ b/arch/arm/mach-ux500/test/Kconfig @@ -0,0 +1,6 @@ + +config DB8500_PWR_TEST + bool "Power usage module test" + depends on (UX500_SOC_DB8500 && DEBUG_FS && REGULATOR_AB8500_DEBUG) + help + Add power module tests for idle diff --git a/arch/arm/mach-ux500/test/Makefile b/arch/arm/mach-ux500/test/Makefile new file mode 100644 index 00000000000..58f1f2f3be6 --- /dev/null +++ b/arch/arm/mach-ux500/test/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_DB8500_PWR_TEST) += pwr.o diff --git a/arch/arm/mach-ux500/test/pwr.c b/arch/arm/mach-ux500/test/pwr.c new file mode 100644 index 00000000000..5d5d24a38ab --- /dev/null +++ b/arch/arm/mach-ux500/test/pwr.c @@ -0,0 +1,828 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + * License terms: GNU General Public License (GPL) version 2 + * + * This is a module test for clocks and regulators. + */ + +#include <linux/module.h> +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/io.h> +#include <linux/bitops.h> +#include <linux/mfd/abx500/ab8500-sysctrl.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/db8500-prcmu.h> + +#include <mach/hardware.h> +#include <mach/pm.h> + +#include "../../../drivers/regulator/dbx500-prcmu.h" +#include "../../../drivers/regulator/ab8500-debug.h" + +#define PRCC_PCKSR 0x010 +#define PRCC_KCKSR 0x014 + +#define PRCM_PLLSOC0_ENABLE 0x090 +#define PRCM_PLLSOC1_ENABLE 0x094 +#define PRCM_PLL32K_ENABLE 0x10C +#define PRCM_PLLARM_ENABLE 0x098 +#define PRCM_PLLDDR_ENABLE 0x09C +#define PRCM_RNG_ENABLE 0x50C +#define PRCM_PLLDSI_ENABLE 0x504 + +#define PRCM_CLKOCR 0x1CC + +#define PRCM_ARMCLKFIX_MGT 0x000 +#define PRCM_ACLK_MGT 0x004 +#define PRCM_SGACLK_MGT 0x014 +#define PRCM_UARTCLK_MGT 0x018 +#define PRCM_MSP02CLK_MGT 0x01C +#define PRCM_MSP1CLK_MGT 0x288 +#define PRCM_I2CCLK_MGT 0x020 +#define PRCM_SDMMCCLK_MGT 0x024 +#define PRCM_SLIMCLK_MGT 0x028 +#define PRCM_PER1CLK_MGT 0x02C +#define PRCM_PER2CLK_MGT 0x030 +#define PRCM_PER3CLK_MGT 0x034 +#define PRCM_PER5CLK_MGT 0x038 +#define PRCM_PER6CLK_MGT 0x03C +#define PRCM_PER7CLK_MGT 0x040 +#define PRCM_LCDCLK_MGT 0x044 +#define PRCM_BMLCLK_MGT 0x04C +#define PRCM_HSITXCLK_MGT 0x050 +#define PRCM_HSIRXCLK_MGT 0x054 +#define PRCM_HDMICLK_MGT 0x058 +#define PRCM_APEATCLK_MGT 0x05C +#define PRCM_APETRACECLK_MGT 0x060 +#define PRCM_MCDECLK_MGT 0x064 +#define PRCM_IPI2CCLK_MGT 0x068 +#define PRCM_DSIALTCLK_MGT 0x06C +#define PRCM_SPARE2CLK_MGT 0x070 +#define PRCM_SPARE1CLK_MGT 0x048 +#define PRCM_DMACLK_MGT 0x074 +#define PRCM_B2R2CLK_MGT 0x078 +#define PRCM_TVCLK_MGT 0x07C +#define PRCM_SSPCLK_MGT 0x280 +#define PRCM_RNGCLK_MGT 0x284 +#define PRCM_UICCCLK_MGT 0x27C + +#define PRCM_DSITVCLK_DIV 0x52C +#define PRCM_DSI_PLLOUT_SEL 0x530 + +#define PRCM_YYCLKEN0_MGT_VAL 0x520 + +enum acc_type { + RAW = 0, + CLK_PRCMU, + CLK_PAR_PRCMU, + CLK_ABB_SYS, + REG_DB8500, + REG_AB8500, +}; + +struct pwr_test { + enum acc_type type; + u32 base; + u32 off; + u32 mask; + u32 val; + + u32 par_off; + u32 par_mask; + u32 par_val; + + char *txt; + char *txt2; + + /* For AB8500 */ + enum ab8500_regulator_mode mode; + enum ab8500_regulator_hwmode hwmode; + enum hwmode_auto hwmode_auto[4]; + int volt_selected; + int alt_volt_selected; + int volt_len; + int volt[4]; + int alt_volt[4]; +}; + +#define RAW_TEST(_base, _off, _mask, _val) \ + { \ + .type = RAW, \ + .base = _base, \ + .off = _off, \ + .mask = _mask, \ + .val = _val, \ + .txt = #_base, \ + .txt2 = #_off \ + } + +#define CLK_TEST_PAR_PRCMU(_base, _off, _mask, _val, _par_off, \ + _par_mask, _par_val) \ + { \ + .type = CLK_PAR_PRCMU, \ + .base = _base, \ + .off = _off, \ + .mask = _mask, \ + .val = _val, \ + .par_off = _par_off, \ + .par_mask = _par_mask, \ + .par_val = _par_val, \ + .txt = #_base, \ + .txt2 = #_off \ + } + +#define CLK_TEST_PRCMU(_off, _mask, _val) \ + { \ + .type = CLK_PRCMU, \ + .off = _off, \ + .mask = _mask, \ + .val = _val, \ + .txt = #_off, \ + } + +#define CLK_TEST_ABB_SYS(_off, _mask, _val) \ + { \ + .type = CLK_ABB_SYS, \ + .off = _off, \ + .mask = _mask, \ + .val = _val, \ + .txt = #_off, \ + } +#define REG_TEST_DB8500(_reg, _val) \ + { \ + .type = REG_DB8500, \ + .off = _reg, \ + .val = _val, \ + } + + +static struct u8500_regulators +{ + struct dbx500_regulator_info *db8500_reg; + int db8500_num; +} u8500_reg; + +/* + * Idle - Note: this is not suspend. + * This test shall pass when the screen is black, before + * suspend is executed. + */ + +static struct pwr_test idle_test[] = { + + /* Test all periph kernel and bus clocks */ + /* bus: gpioctrl */ + CLK_TEST_PAR_PRCMU(U8500_CLKRST1_BASE, PRCC_PCKSR, 0x07ff, BIT(9), + PRCM_PER1CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PAR_PRCMU(U8500_CLKRST1_BASE, PRCC_KCKSR, 0x037f, 0x0000, + PRCM_PER1CLK_MGT, BIT(8), BIT(8)), + /* bus: gpioctrl */ + CLK_TEST_PAR_PRCMU(U8500_CLKRST2_BASE, PRCC_PCKSR, 0x0fff, BIT(11), + PRCM_PER2CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PAR_PRCMU(U8500_CLKRST2_BASE, PRCC_KCKSR, 0x00ff, 0x0000, + PRCM_PER2CLK_MGT, BIT(8), BIT(8)), + /* bus: uart2, gpioctrl - users??, kernel: uart2 */ + CLK_TEST_PAR_PRCMU(U8500_CLKRST3_BASE, PRCC_PCKSR, 0x01ff, BIT(8) | BIT(6), + PRCM_PER3CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PAR_PRCMU(U8500_CLKRST3_BASE, PRCC_KCKSR, 0x00fe, BIT(6), + PRCM_PER3CLK_MGT, BIT(8), BIT(8)), + /* No user on periph5 */ + CLK_TEST_PAR_PRCMU(U8500_CLKRST5_BASE, PRCC_PCKSR, 0x0003, 0x0000, + PRCM_PER5CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PAR_PRCMU(U8500_CLKRST5_BASE, PRCC_KCKSR, 0x0000, 0x0000, + PRCM_PER5CLK_MGT, BIT(8), BIT(8)), + /* bus: MTU0 used for scheduling ApIdle */ + CLK_TEST_PAR_PRCMU(U8500_CLKRST6_BASE, PRCC_PCKSR, 0x00ff, BIT(6), + PRCM_PER6CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PAR_PRCMU(U8500_CLKRST6_BASE, PRCC_KCKSR, 0x0001, 0x0000, + PRCM_PER6CLK_MGT, BIT(8), BIT(8)), + + /* Test that clkout 1/2 is off */ + CLK_TEST_PRCMU(PRCM_CLKOCR, 0x3f003f, 0x0000), + + /* Test that ulp clock is off */ + CLK_TEST_ABB_SYS(AB8500_SYSULPCLKCTRL1, 0xfc, 0x00), + + /* Test that prcm clks are in proper state */ + CLK_TEST_PRCMU(PRCM_ARMCLKFIX_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_ACLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_SGACLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_UARTCLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_MSP02CLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_MSP1CLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_I2CCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_SDMMCCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_SLIMCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_PER1CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_PER2CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_PER3CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_PER5CLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_PER6CLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_PER7CLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_LCDCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_BMLCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_HSITXCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_HSIRXCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_HDMICLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_APEATCLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_APETRACECLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_MCDECLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_IPI2CCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_DSIALTCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_DMACLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_B2R2CLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_TVCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_SSPCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_RNGCLK_MGT, BIT(8), BIT(8)), + CLK_TEST_PRCMU(PRCM_UICCCLK_MGT, BIT(8), 0x000), + CLK_TEST_PRCMU(PRCM_DSITVCLK_DIV, BIT(24) | BIT(25) | BIT(26), + 0x000), + CLK_TEST_PRCMU(PRCM_DSI_PLLOUT_SEL, (BIT(0) | BIT(1) | BIT(2) | + BIT(8) | BIT(9) | BIT(10)), + 0x200), /* Will change */ + CLK_TEST_PRCMU(PRCM_YYCLKEN0_MGT_VAL, 0xBFFFFFFF, + (BIT(27) | BIT(23) | BIT(22) | BIT(15) | + BIT(13) | BIT(12) | BIT(11) | BIT(5) | + BIT(1) | BIT(0))), + + /* Check db8500 regulator settings - enable */ + REG_TEST_DB8500(DB8500_REGULATOR_VAPE, 0), + REG_TEST_DB8500(DB8500_REGULATOR_VARM, 0), + REG_TEST_DB8500(DB8500_REGULATOR_VMODEM, 0), + REG_TEST_DB8500(DB8500_REGULATOR_VPLL, 0), + REG_TEST_DB8500(DB8500_REGULATOR_VSMPS1, 0), + REG_TEST_DB8500(DB8500_REGULATOR_VSMPS2, 1), + REG_TEST_DB8500(DB8500_REGULATOR_VSMPS3, 0), + REG_TEST_DB8500(DB8500_REGULATOR_VRF1, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SVAMMDSP, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SVAMMDSPRET, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SVAPIPE, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SIAMMDSP, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SIAMMDSPRET, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SIAPIPE, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_SGA, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_B2R2_MCDE, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_ESRAM12, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_ESRAM12RET, 0), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_ESRAM34, 1), + REG_TEST_DB8500(DB8500_REGULATOR_SWITCH_ESRAM34RET, 0), + + /* ab8500 regulators */ + { + .type = REG_AB8500, + .off = AB8500_VARM, + .mode = AB8500_MODE_ON, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_INVAL, HWM_INVAL, HWM_OFF}, + .volt_selected = 2, + /* Voltage and voltage selection depends on ARM_OPP */ + .alt_volt_selected = 1, + .volt_len = 3, + .volt = {1350000, 1025000, 750000}, + .alt_volt = {1250000, 1025000, 750000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VBBP, + .mode = AB8500_MODE_ON, + .hwmode_auto = {HWM_OFF, HWM_INVAL, HWM_INVAL, HWM_INVAL}, + .volt_selected = 1, + .volt_len = 2, + .volt = {-300000, 0}, + }, + { + .type = REG_AB8500, + .off = AB8500_VBBN, + .mode = AB8500_MODE_ON, + .hwmode_auto = {HWM_OFF, HWM_INVAL, HWM_INVAL, HWM_INVAL}, + .volt_selected = 1, + .volt_len = 2, + .volt = {300000, 0}, + }, + { + .type = REG_AB8500, + .off = AB8500_VAPE, + .mode = AB8500_MODE_ON, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_INVAL, HWM_INVAL, HWM_OFF}, + .volt_selected = 2, + /* APE_OPP can get changes by cpufreq */ + .alt_volt_selected = 1, + .volt_len = 3, + .volt = {1225000, 1000000, 1200000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VSMPS1, + .mode = AB8500_MODE_HW, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_ON, HWM_OFF, HWM_OFF, HWM_OFF}, + .volt_selected = 2, + .volt_len = 3, + .volt = {1200000, 1200000, 1200000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VSMPS2, + .mode = AB8500_MODE_HW, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_ON, HWM_ON, HWM_ON, HWM_OFF}, + .volt_selected = 2, + .volt_len = 3, + .volt = {1800000, 1800000, 1800000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VSMPS3, + .mode = AB8500_MODE_HW, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_ON, HWM_OFF, HWM_OFF, HWM_OFF}, + .volt_selected = 2, + .volt_len = 3, + .volt = {925000, 1212500, 1200000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VPLL, + .mode = AB8500_MODE_HW, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_ON, HWM_OFF, HWM_OFF, HWM_OFF}, + }, + { + .type = REG_AB8500, + .off = AB8500_VREFDDR, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VMOD, + .mode = AB8500_MODE_OFF, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + .volt_selected = 2, + .volt_len = 2, + .volt = {1125000, 1025000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VEXTSUPPLY1, + .mode = AB8500_MODE_LP, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + }, + { + .type = REG_AB8500, + .off = AB8500_VEXTSUPPLY2, + .mode = AB8500_MODE_OFF, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + }, + { + .type = REG_AB8500, + .off = AB8500_VEXTSUPPLY3, + .mode = AB8500_MODE_ON, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_ON, HWM_OFF, HWM_ON, HWM_OFF}, + }, + { + .type = REG_AB8500, + .off = AB8500_VRF1, + .mode = AB8500_MODE_HW, + .volt_len = 1, + .volt = {2150000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VANA, + .mode = AB8500_MODE_OFF, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + }, + { + .type = REG_AB8500, + .off = AB8500_VAUX1, + .mode = AB8500_MODE_ON, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + .volt_len = 1, + .volt = {2800000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VAUX2, + .mode = AB8500_MODE_ON, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + .volt_len = 1, + .volt = {3300000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VAUX3, + .mode = AB8500_MODE_OFF, + .hwmode = AB8500_HWMODE_HPLP, + .hwmode_auto = {HWM_OFF, HWM_OFF, HWM_OFF, HWM_OFF}, + .volt_len = 1, + .volt = {2910000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VINTCORE, + .mode = AB8500_MODE_OFF, + .volt_len = 1, + .volt = {1250000}, + }, + { + .type = REG_AB8500, + .off = AB8500_VTVOUT, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VAUDIO, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VANAMIC1, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VANAMIC2, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VDMIC, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VUSB, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VOTG, + .mode = AB8500_MODE_OFF, + }, + { + .type = REG_AB8500, + .off = AB8500_VBUSBIS, + .mode = AB8500_MODE_OFF, + }, +}; + +static int read_raw(struct pwr_test *t) +{ + u32 res; + int i; + + for (i = 0 ; i < 50; i++) { + res = readl(__io_address(t->base) + t->off); + if ((res & t->mask) == t->val) + return 0; + msleep(10); + } + + pr_err("pwr_test: ERROR: %s %s 0x%x, 0x%x reads 0x%x (masked: 0x%x), " + "expected 0x%x (mask: 0x%x)\n", + t->txt, t->txt2, t->base, t->off, res, + res & t->mask, t->val, t->mask); + return -EINVAL; +} + +static int clk_read_par_prcmu(struct pwr_test *t) + { + u32 res; + int i; + bool parent_enabled = false; + + /* check if parent clock is in expected configuration (usually PRCC) */ + for (i = 0 ; i < 50; i++) { + res = prcmu_read(t->par_off); + if ((res & t->par_mask) == t->par_val) { + parent_enabled = true; + break; + } + msleep(10); + } + + /* If parent clock is off, but clock is expected to be on --> fail */ + if (!parent_enabled && t->val != 0) { + pr_err("pwr_test: ERROR: PRCMU parent clk of %s, " + "0x%x reads 0x%x (masked: 0x%x), " + "expected to be on 0x%x (mask: 0x%x)\n", + t->txt, t->par_off, res, res & t->par_mask, + t->par_val, t->par_mask); + return -EINVAL; + } + + /* It's ok if parent clock is off and clock is off as well */ + if (!parent_enabled && t->val == 0) + return 0; + + return read_raw(t); +} + +static int clk_read_prcmu(struct pwr_test *t) +{ + u32 res; + int i; + + for (i = 0 ; i < 50; i++) { + res = prcmu_read(t->off); + if ((res & t->mask) == t->val) + return 0; + msleep(10); + } + + pr_err("pwr_test: ERROR: %s PRCMU, 0x%x reads 0x%x (masked: 0x%x), " + "expected 0x%x (mask: 0x%x)\n", + t->txt, t->off, res, res & t->mask, t->val, t->mask); + return -EINVAL; +} + +static int clk_read_abb_sys(struct pwr_test *t) +{ + int ret; + u8 val = 0; + int i; + + for (i = 0; i < 50; i++) { + ret = ab8500_sysctrl_read(t->off, &val); + if (ret < 0) { + pr_err("pwr_test: AB8500 access error: %d of " + "reg: 0x%x\n", ret, t->off); + return ret; + } + if ((val & (u8)t->mask) == t->val) + return 0; + msleep(10); + } + + pr_err("pwr_test: ERROR: AB8500 register 0x%x %s, reads 0x%x," + " (masked 0x%x) expected 0x%x (mask: 0x%x)\n", + t->base, t->txt, val, val & (u8)t->mask, t->val, t->mask); + + return -EINVAL; +} + +static int reg_read_db8500(struct pwr_test *t) +{ + int i, j; + + for (j = 0 ; j < u8500_reg.db8500_num ; j++) + if (u8500_reg.db8500_reg[j].desc.id == t->off) + break; + + if (j == u8500_reg.db8500_num) { + pr_err("pwr_test: Invalid db8500 regulator\n"); + return -EINVAL; + } + + for (i = 0; i < 50; i++) { + + /* powerstate is a special case */ + if (t->off == DB8500_REGULATOR_VAPE) { + if ((u8500_reg.db8500_reg[j].is_enabled || + power_state_active_is_enabled()) == t->val) + return 0; + } else { + if (u8500_reg.db8500_reg[j].is_enabled == t->val) + return 0; + } + msleep(10); + } + + pr_err("pwr_test: ERROR: DB8500 regulator %s is 0x%x expected 0x%x\n", + u8500_reg.db8500_reg[j].desc.name, + t->off != DB8500_REGULATOR_VAPE ? + u8500_reg.db8500_reg[j].is_enabled : + u8500_reg.db8500_reg[j].is_enabled || + power_state_active_is_enabled(), + t->val); + + return -EINVAL; +} + +static int reg_read_ab8500(struct pwr_test *t) +{ + int i, j; + int ret; + struct ab8500_debug_regulator_status s; + + for (i = 0; i < 50; i++) { + ret = ab8500_regulator_debug_read(t->off, &s); + + if (ret) { + pr_err("pwr_test: Fail to read ab8500 regulator\n"); + return -EINVAL; + } + + if (t->mode != s.mode) + goto repeat; + + if (t->hwmode != s.hwmode) + goto repeat; + + if (t->volt_selected != s.volt_selected && + t->alt_volt_selected != s.volt_selected) + goto repeat; + + if (t->volt_len != s.volt_len) + goto repeat; + + for (j = 0; j < 4 && s.hwmode != AB8500_HWMODE_NONE; j++) + if (s.hwmode_auto[j] != t->hwmode_auto[j]) + goto repeat; + + for (j = 0; j < s.volt_len; j++) + if (s.volt[j] != t->volt[j] && + s.volt[j] != t->alt_volt[j]) + goto repeat; + return 0; + +repeat: + msleep(10); + } + + pr_err("pwr test: ERROR: AB8500 regulator %s ", s.name); + + if (t->mode != s.mode) + printk("mode is: %d expected: %d ", + s.mode, t->mode); + + if (t->hwmode != s.hwmode) + printk("hwmode is: %d expected: %d ", + s.hwmode, t->hwmode); + + if (t->volt_selected != s.volt_selected && + t->alt_volt_selected != s.volt_selected) { + printk("volt selected is: %d expected: %d ", + s.volt_selected, t->volt_selected); + if (t->alt_volt_selected) + printk("(alt volt: %d) ", t->alt_volt_selected); + } + + if (t->volt_len != s.volt_len) + printk("volt len is: %d expected: %d ", + s.volt_len, t->volt_len); + + for (j = 0; j < 4; j++) + if (s.hwmode_auto[j] != t->hwmode_auto[j]) + break; + if (j != 4 && s.hwmode != AB8500_HWMODE_NONE) { + + printk("hwmode auto:: {"); + for (j = 0; j < 4; j++) { + switch(s.hwmode_auto[j]) { + case HWM_OFF: { printk("OFF "); break; } + case HWM_ON: { printk("ON "); break; } + case HWM_INVAL: { printk("INVAL "); break; } + } + } + printk("}, expected: {"); + for (j = 0; j < 4; j++) { + switch(t->hwmode_auto[j]) { + case HWM_OFF: { printk("OFF "); break; } + case HWM_ON: { printk("ON "); break; } + case HWM_INVAL: { printk("INVAL "); break; } + } + } + printk("} "); + } + + if (s.volt_len == t->volt_len) { + for (j = 0; j < s.volt_len; j++) + if (s.volt[j] != t->volt[j] && + t->alt_volt[j] != s.volt[j]) + break; + + } else { + j = 0; + } + + if (j != s.volt_len) { + printk("voltage: {"); + for (j = 0; j < s.volt_len; j++) + printk("%d ", s.volt[j]); + + if (t->alt_volt) { + printk("} alt voltage: {"); + for (j = 0; j < s.volt_len; j++) + printk("%d ", t->alt_volt[j]); + } + printk("} expected: {"); + for (j = 0; j < t->volt_len; j++) + printk("%d ", t->volt[j]); + printk("} "); + } + + printk("\n"); + + return -EINVAL; +} + + +static int test_execute(struct pwr_test *t, int len) +{ + int err = 0; + int i; + + for (i = 0 ; i < len ; i++) { + switch (t[i].type) { + case CLK_ABB_SYS: + err |= clk_read_abb_sys(&t[i]); + break; + case CLK_PRCMU: + err |= clk_read_prcmu(&t[i]); + break; + case CLK_PAR_PRCMU: + err |= clk_read_par_prcmu(&t[i]); + break; + case RAW: + err |= read_raw(&t[i]); + break; + case REG_DB8500: + err |= reg_read_db8500(&t[i]); + break; + case REG_AB8500: + err |= reg_read_ab8500(&t[i]); + break; + default: + break; + } + + } + return err; +} + +static int pwr_test_idle(struct seq_file *s, void *data) +{ + int err; + + err = test_execute(idle_test, ARRAY_SIZE(idle_test)); + + seq_printf(s, "%s\n", err == 0 ? "PASS" : "FAIL"); + + return 0; +} + + +int dbx500_regulator_testcase(struct dbx500_regulator_info *regulator_info, + int num_regulators) +{ + u8500_reg.db8500_reg = regulator_info; + u8500_reg.db8500_num = num_regulators; + return 0; +} + +static int pwr_test_debugfs_open(struct inode *inode, + struct file *file) +{ + return single_open(file, + inode->i_private, + NULL); +} + +static const struct file_operations pwr_test_debugfs_ops = { + .open = pwr_test_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *debugfs_dir; + +static int __init pwr_test_init(void) +{ + int err = 0; + void *err_ptr; + + debugfs_dir = debugfs_create_dir("pwr_test", NULL); + if (IS_ERR(debugfs_dir)) + return PTR_ERR(debugfs_dir); + + err_ptr = debugfs_create_file("idle", + S_IFREG | S_IRUGO, + debugfs_dir, (void *)pwr_test_idle, + &pwr_test_debugfs_ops); + if (IS_ERR(err_ptr)) { + err = PTR_ERR(err_ptr); + goto out; + } + return 0; +out: + debugfs_remove_recursive(debugfs_dir); + return err; +} +late_initcall(pwr_test_init); diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index d37df98b5c3..438c9715aab 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c @@ -7,6 +7,7 @@ #include <linux/io.h> #include <linux/errno.h> #include <linux/clksrc-dbx500-prcmu.h> +#include <linux/clksrc-db5500-mtimer.h> #include <linux/of.h> #include <asm/smp_twd.h> @@ -16,6 +17,21 @@ #include <mach/setup.h> #include <mach/hardware.h> #include <mach/irqs.h> +#include <mach/context.h> + +#ifdef CONFIG_UX500_CONTEXT +static int mtu_context_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + if (event == CONTEXT_APE_RESTORE) + nmdk_clksrc_reset(); + return NOTIFY_OK; +} + +static struct notifier_block mtu_context_notifier = { + .notifier_call = mtu_context_notifier_call, +}; +#endif #ifdef CONFIG_HAVE_ARM_TWD static DEFINE_TWD_LOCAL_TIMER(u5500_twd_local_timer, @@ -51,7 +67,7 @@ static void __init ux500_timer_init(void) if (cpu_is_u5500()) { mtu_timer_base = __io_address(U5500_MTU0_BASE); prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE); - } else if (cpu_is_u8500()) { + } else if (cpu_is_u8500() || cpu_is_u9540()) { mtu_timer_base = __io_address(U8500_MTU0_BASE); prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); } else { @@ -70,14 +86,24 @@ static void __init ux500_timer_init(void) * depending on delay which is not yet calibrated. RTC-RTT is in the * always-on powerdomain and is used as clockevent instead of twd when * sleeping. - * The PRCMU timer 4(3 for DB5500) register a clocksource and - * sched_clock with higher rating then MTU since is always-on. * + * The PRCMU timer 4 (3 for DB5500) registers a clocksource and + * sched_clock with higher rating than the MTU since it is + * always-on. + * + * On DB5500, the MTIMER is the best clocksource since, unlike the + * PRCMU timer, it doesn't occasionally go backwards. */ nmdk_timer_init(mtu_timer_base); + if (cpu_is_u5500()) + db5500_mtimer_init(__io_address(U5500_MTIMER_BASE)); clksrc_dbx500_prcmu_init(prcmu_timer_base); ux500_twd_init(); + +#ifdef CONFIG_UX500_CONTEXT + WARN_ON(context_ape_notifier_register(&mtu_context_notifier)); +#endif } static void ux500_timer_reset(void) diff --git a/arch/arm/mach-ux500/uart-db8500.c b/arch/arm/mach-ux500/uart-db8500.c new file mode 100644 index 00000000000..fad9b9a13df --- /dev/null +++ b/arch/arm/mach-ux500/uart-db8500.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Arun R Murthy <arun.murthy@stericsson.com>, + * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/amba/serial.h> +#include <mach/setup.h> +#include <mach/hardware.h> +#include <mach/context.h> + +#ifdef CONFIG_UX500_CONTEXT + +static struct { + struct clk *uart_clk; + void __iomem *base; + /* dr */ + /* rsr_err */ + u32 dma_wm; + u32 timeout; + /* fr */ + u32 lcrh_rx; + u32 ilpr; + u32 ibrd; + u32 fbrd; + u32 lcrh_tx; + u32 cr; + u32 ifls; + u32 imsc; + /* ris */ + /* mis */ + /* icr */ + u32 dmacr; + u32 xfcr; + u32 xon1; + u32 xon2; + u32 xoff1; + u32 xoff2; + /* itcr */ + /* itip */ + /* itop */ + /* tdr */ + u32 abcr; + /* absr */ + /* abfmt */ + /* abdr */ + /* abdfr */ + /* abmr */ + u32 abimsc; + /* abris */ + /* abmis */ + /* abicr */ + /* id_product_h_xy */ + /* id_provider */ + /* periphid0 */ + /* periphid1 */ + /* periphid2 */ + /* periphid3 */ + /* pcellid0 */ + /* pcellid1 */ + /* pcellid2 */ + /* pcellid3 */ +} context_uart; + +static void save_uart(void) +{ + void __iomem *membase; + + membase = context_uart.base; + + clk_enable(context_uart.uart_clk); + + context_uart.dma_wm = readl_relaxed(membase + ST_UART011_DMAWM); + context_uart.timeout = readl_relaxed(membase + ST_UART011_TIMEOUT); + context_uart.lcrh_rx = readl_relaxed(membase + ST_UART011_LCRH_RX); + context_uart.ilpr = readl_relaxed(membase + UART01x_ILPR); + context_uart.ibrd = readl_relaxed(membase + UART011_IBRD); + context_uart.fbrd = readl_relaxed(membase + UART011_FBRD); + context_uart.lcrh_tx = readl_relaxed(membase + ST_UART011_LCRH_TX); + context_uart.cr = readl_relaxed(membase + UART011_CR); + context_uart.ifls = readl_relaxed(membase + UART011_IFLS); + context_uart.imsc = readl_relaxed(membase + UART011_IMSC); + context_uart.dmacr = readl_relaxed(membase + UART011_DMACR); + context_uart.xfcr = readl_relaxed(membase + ST_UART011_XFCR); + context_uart.xon1 = readl_relaxed(membase + ST_UART011_XON1); + context_uart.xon2 = readl_relaxed(membase + ST_UART011_XON2); + context_uart.xoff1 = readl_relaxed(membase + ST_UART011_XOFF1); + context_uart.xoff2 = readl_relaxed(membase + ST_UART011_XOFF2); + context_uart.abcr = readl_relaxed(membase + ST_UART011_ABCR); + context_uart.abimsc = readl_relaxed(membase + ST_UART011_ABIMSC); + + clk_disable(context_uart.uart_clk); +} + +static void restore_uart(void) +{ + int cnt; + int retries = 100; + unsigned int cr; + void __iomem *membase; + u16 dummy; + bool show_warn = false; + + membase = context_uart.base; + clk_enable(context_uart.uart_clk); + + writew_relaxed(context_uart.ifls, membase + UART011_IFLS); + cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; + + writew_relaxed(cr, membase + UART011_CR); + writew_relaxed(0, membase + UART011_FBRD); + writew_relaxed(1, membase + UART011_IBRD); + writew_relaxed(0, membase + ST_UART011_LCRH_RX); + if (context_uart.lcrh_tx != ST_UART011_LCRH_RX) { + int i; + /* + * Wait 10 PCLKs before writing LCRH_TX register, + * to get this delay write read only register 10 times + */ + for (i = 0; i < 10; ++i) + dummy = readw(membase + ST_UART011_LCRH_RX); + writew_relaxed(0, membase + ST_UART011_LCRH_TX); + } + writew(0, membase + UART01x_DR); + do { + if (!(readw(membase + UART01x_FR) & UART01x_FR_BUSY)) + break; + cpu_relax(); + } while (retries-- > 0); + if (retries < 0) + /* + * We can't print out a warning here since the uart is + * not fully restored. Do it later. + */ + show_warn = true; + + writel_relaxed(context_uart.dma_wm, membase + ST_UART011_DMAWM); + writel_relaxed(context_uart.timeout, membase + ST_UART011_TIMEOUT); + writel_relaxed(context_uart.lcrh_rx, membase + ST_UART011_LCRH_RX); + writel_relaxed(context_uart.ilpr, membase + UART01x_ILPR); + writel_relaxed(context_uart.ibrd, membase + UART011_IBRD); + writel_relaxed(context_uart.fbrd, membase + UART011_FBRD); + /* + * Wait 10 PCLKs before writing LCRH_TX register, + * to get this delay write read only register 10-3 + * times, as already there are 3 writes after + * ST_UART011_LCRH_RX + */ + for (cnt = 0; cnt < 7; cnt++) + dummy = readw(membase + ST_UART011_LCRH_RX); + + writel_relaxed(context_uart.lcrh_tx, membase + ST_UART011_LCRH_TX); + writel_relaxed(context_uart.ifls, membase + UART011_IFLS); + writel_relaxed(context_uart.dmacr, membase + UART011_DMACR); + writel_relaxed(context_uart.xfcr, membase + ST_UART011_XFCR); + writel_relaxed(context_uart.xon1, membase + ST_UART011_XON1); + writel_relaxed(context_uart.xon2, membase + ST_UART011_XON2); + writel_relaxed(context_uart.xoff1, membase + ST_UART011_XOFF1); + writel_relaxed(context_uart.xoff2, membase + ST_UART011_XOFF2); + writel_relaxed(context_uart.abcr, membase + ST_UART011_ABCR); + writel_relaxed(context_uart.abimsc, membase + ST_UART011_ABIMSC); + writel_relaxed(context_uart.cr, membase + UART011_CR); + writel(context_uart.imsc, membase + UART011_IMSC); + + clk_disable(context_uart.uart_clk); + + if (show_warn) + pr_warning("%s:uart tx busy\n", __func__); +} + +static int uart_context_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + switch (event) { + case CONTEXT_APE_SAVE: + save_uart(); + break; + + case CONTEXT_APE_RESTORE: + restore_uart(); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block uart_context_notifier = { + .notifier_call = uart_context_notifier_call, +}; + +#define __UART_BASE(soc, x) soc##_UART##x##_BASE +#define UART_BASE(soc, x) __UART_BASE(soc, x) + +static int __init uart_context_notifier_init(void) +{ + unsigned long base; + static const char clkname[] __initconst + = "uart" __stringify(CONFIG_UX500_DEBUG_UART); + + if (cpu_is_u8500()) + base = UART_BASE(U8500, CONFIG_UX500_DEBUG_UART); + else if (cpu_is_u5500()) + base = UART_BASE(U5500, CONFIG_UX500_DEBUG_UART); + else + ux500_unknown_soc(); + + context_uart.base = ioremap(base, SZ_4K); + context_uart.uart_clk = clk_get_sys(clkname, NULL); + + if (IS_ERR(context_uart.uart_clk)) { + pr_err("%s:unable to get clk-uart%d\n", __func__, + CONFIG_UX500_DEBUG_UART); + return -EINVAL; + } + + return WARN_ON(context_ape_notifier_register(&uart_context_notifier)); +} +arch_initcall(uart_context_notifier_init); +#endif diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index a74af389bc6..fb1f6775154 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -11,6 +11,10 @@ #include <plat/ste_dma40.h> #include <mach/hardware.h> #include <mach/usb.h> +#include <mach/pm.h> +#include <plat/pincfg.h> +#include "pins.h" +#include "board-ux500-usb.h" #define MUSB_DMA40_RX_CH { \ .mode = STEDMA40_MODE_LOGICAL, \ @@ -32,6 +36,8 @@ .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ } +#define USB_OTG_GPIO_CS 76 + static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS] = { MUSB_DMA40_RX_CH, @@ -86,9 +92,54 @@ static struct ux500_musb_board_data musb_board_data = { .dma_filter = stedma40_filter, }; +#ifdef CONFIG_USB_UX500_DMA static u64 ux500_musb_dmamask = DMA_BIT_MASK(32); +#else +static u64 ux500_musb_dmamask = DMA_BIT_MASK(0); +#endif +static struct ux500_pins *usb_gpio_pins; + +/** + * Fifo mode + * Sum of maxpacket <= 12 KB + * As ux500 provides 12 KB buffer size only + * + * Enable Double buffer for Mass Storage Class + * endpoint. + */ +static struct musb_fifo_cfg ux500_mode_cfg[] = { +{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, +{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, +{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, }, +{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, +{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, +}; static struct musb_hdrc_config musb_hdrc_config = { + .fifo_cfg = ux500_mode_cfg, /* Fifo configuration */ + .fifo_cfg_size = ARRAY_SIZE(ux500_mode_cfg), .multipoint = true, .dyn_fifo = true, .num_eps = 16, @@ -120,11 +171,46 @@ struct platform_device ux500_musb_device = { .platform_data = &musb_platform_data, .dma_mask = &ux500_musb_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), +#ifdef CONFIG_UX500_SOC_DB8500 + .pm_domain = &ux500_dev_power_domain, +#endif }, .num_resources = ARRAY_SIZE(usb_resources), .resource = usb_resources, }; +static void enable_gpio(void) +{ + ux500_pins_enable(usb_gpio_pins); +} +static void disable_gpio(void) +{ + ux500_pins_disable(usb_gpio_pins); +} +static int get_gpio(struct device *device) +{ + usb_gpio_pins = ux500_pins_get(dev_name(device)); + + if (usb_gpio_pins == NULL) { + dev_err(device, "Could not get %s:usb_gpio_pins structure\n", + dev_name(device)); + + return PTR_ERR(usb_gpio_pins); + } + return 0; +} +static void put_gpio(void) +{ + ux500_pins_put(usb_gpio_pins); +} +struct abx500_usbgpio_platform_data abx500_usbgpio_plat_data = { + .get = &get_gpio, + .enable = &enable_gpio, + .disable = &disable_gpio, + .put = &put_gpio, + .usb_cs = USB_OTG_GPIO_CS, +}; + static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type) { u32 idx; diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 07201637109..226f8736152 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S @@ -240,6 +240,24 @@ ENTRY(fa_dma_unmap_area) mov pc, lr ENDPROC(fa_dma_unmap_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(fa_clean_dcache_all) + mov pc, lr +ENDPROC(fa_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(fa_flush_dcache_all) + mov pc, lr +ENDPROC(fa_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 2a8e380501e..1768e4038fc 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -319,9 +319,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); - aux &= aux_mask; - aux |= aux_val; - /* Determine the number of ways */ switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: @@ -335,6 +332,13 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) sync_reg_offset = L2X0_DUMMY_REG; #endif outer_cache.set_debug = pl310_set_debug; + + /* + * Set bit 22 in the auxiliary control register. If this bit + * is cleared, PL310 treats Normal Shared Non-cacheable + * accesses as Cacheable no-allocate. + */ + aux_val |= 1 << 22; break; case L2X0_CACHE_ID_PART_L210: ways = (aux >> 13) & 0xf; @@ -362,6 +366,9 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) * accessing the below registers will fault. */ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + aux &= aux_mask; + aux |= aux_val; + /* Make sure that I&D is not locked down when starting */ l2x0_unlock(cache_id); diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index c2301f22610..ab5bf508a2a 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -127,6 +127,24 @@ ENTRY(v3_dma_map_area) ENDPROC(v3_dma_unmap_area) ENDPROC(v3_dma_map_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v3_clean_dcache_all) + mov pc, lr +ENDPROC(v3_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v3_flush_dcache_all) + mov pc, lr +ENDPROC(v3_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index fd9bb7addc8..9d3a055127e 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -139,6 +139,24 @@ ENTRY(v4_dma_map_area) ENDPROC(v4_dma_unmap_area) ENDPROC(v4_dma_map_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v4_clean_dcache_all) + mov pc, lr +ENDPROC(v4_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v4_flush_dcache_all) + mov pc, lr +ENDPROC(v4_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 4f2c14151cc..54d3cda4a89 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -251,6 +251,24 @@ ENTRY(v4wb_dma_unmap_area) mov pc, lr ENDPROC(v4wb_dma_unmap_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v4wb_clean_dcache_all) + mov pc, lr +ENDPROC(v4wb_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v4wb_flush_dcache_all) + mov pc, lr +ENDPROC(v4wb_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 4d7b467631c..40f7dba11f5 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -195,6 +195,24 @@ ENTRY(v4wt_dma_map_area) ENDPROC(v4wt_dma_unmap_area) ENDPROC(v4wt_dma_map_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v4wt_clean_dcache_all) + mov pc, lr +ENDPROC(v4wt_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v4wt_flush_dcache_all) + mov pc, lr +ENDPROC(v4wt_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 74c2e5a33a4..b88dd4ab038 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -328,6 +328,24 @@ ENTRY(v6_dma_unmap_area) mov pc, lr ENDPROC(v6_dma_unmap_area) +/* + * clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v6_clean_dcache_all) + mov pc, lr +ENDPROC(v6_clean_dcache_all) + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v6_flush_dcache_all) + mov pc, lr +ENDPROC(v6_flush_dcache_all) + __INITDATA @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index a655d3da386..70744d6a066 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -33,7 +33,7 @@ ENTRY(v7_flush_icache_all) ENDPROC(v7_flush_icache_all) /* - * v7_flush_dcache_all() + * __v7_flush_dcache_all() * * Flush the whole D-cache. * @@ -41,7 +41,7 @@ ENDPROC(v7_flush_icache_all) * * - mm - mm_struct describing address space */ -ENTRY(v7_flush_dcache_all) +ENTRY(__v7_flush_dcache_all) dmb @ ensure ordering with previous memory accesses mrc p15, 1, r0, c0, c0, 1 @ read clidr ands r3, r0, #0x7000000 @ extract loc from clidr @@ -94,9 +94,93 @@ finished: dsb isb mov pc, lr +ENDPROC(__v7_flush_dcache_all) + +/* + * __v7_clean_dcache_all() + * + * Clean the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + */ +ENTRY(__v7_clean_dcache_all) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished1 @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +loop21: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip1 @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop22: + mov r9, r4 @ create working copy of max way size +loop23: + ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r9, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r7, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 + mcr p15, 0, r11, c7, c10, 2 @ clean by set/way + subs r9, r9, #1 @ decrement the way + bge loop23 + subs r7, r7, #1 @ decrement the index + bge loop22 +skip1: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt loop21 +finished1: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb + isb + mov pc, lr +ENDPROC(__v7_clean_dcache_all) + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + */ +ENTRY(v7_flush_dcache_all) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl __v7_flush_dcache_all + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + mov pc, lr ENDPROC(v7_flush_dcache_all) /* + * v7_clean_dcache_all() + * + * Clean the whole D-cache. + */ +ENTRY(v7_clean_dcache_all) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl __v7_clean_dcache_all + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + mov pc, lr +ENDPROC(v7_clean_dcache_all) + +/* * v7_flush_cache_all() * * Flush the entire cache system. @@ -108,14 +192,12 @@ ENDPROC(v7_flush_dcache_all) * */ ENTRY(v7_flush_kern_cache_all) - ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) - THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + stmfd sp!, {lr} bl v7_flush_dcache_all mov r0, #0 ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate - ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) - THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + ldmfd sp!, {lr} mov pc, lr ENDPROC(v7_flush_kern_cache_all) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index aa78de8bfdd..4ecd1f8bbb5 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -288,6 +288,20 @@ static struct mem_type mem_types[] = { PMD_SECT_UNCACHED | PMD_SECT_XN, .domain = DOMAIN_KERNEL, }, + /* NOTE : this is only a temporary hack!!! + * The U8500 ED/V1.0 cuts require such a + * memory type for deep sleep resume. + * This is expected to be solved in cut v2.0 + * and we clean this up then. for more details + * look @ the commit message please + */ + [MT_BACKUP_RAM] = { + .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | + L_PTE_SHARED, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, + .domain = DOMAIN_IO, + }, }; const struct mem_type *get_mem_type(unsigned int type) diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 2d8ff3ad86d..518ab10fea5 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -304,6 +304,8 @@ ENTRY(\name\()_cache_fns) .long \name\()_coherent_kern_range .long \name\()_coherent_user_range .long \name\()_flush_kern_dcache_area + .long \name\()_clean_dcache_all + .long \name\()_flush_dcache_all .long \name\()_dma_map_area .long \name\()_dma_unmap_area .long \name\()_dma_flush_range diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index c2e2b66f72b..d1c42ead765 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -172,7 +172,7 @@ __v7_ca15mp_setup: __v7_setup: adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} - bl v7_flush_dcache_all + bl __v7_flush_dcache_all ldmia r12, {r0-r5, r7, r9, r11, lr} mrc p15, 0, r0, c0, c0, 0 @ read main ID register diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h deleted file mode 100644 index 9605bf227df..00000000000 --- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Structures and registers for GPIO access in the Nomadik SoC - * - * Copyright (C) 2008 STMicroelectronics - * Author: Prafulla WADASKAR <prafulla.wadaskar@st.com> - * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __PLAT_NOMADIK_GPIO -#define __PLAT_NOMADIK_GPIO - -/* - * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving - * the "gpio" namespace for generic and cross-machine functions - */ - -/* Register in the logic block */ -#define NMK_GPIO_DAT 0x00 -#define NMK_GPIO_DATS 0x04 -#define NMK_GPIO_DATC 0x08 -#define NMK_GPIO_PDIS 0x0c -#define NMK_GPIO_DIR 0x10 -#define NMK_GPIO_DIRS 0x14 -#define NMK_GPIO_DIRC 0x18 -#define NMK_GPIO_SLPC 0x1c -#define NMK_GPIO_AFSLA 0x20 -#define NMK_GPIO_AFSLB 0x24 - -#define NMK_GPIO_RIMSC 0x40 -#define NMK_GPIO_FIMSC 0x44 -#define NMK_GPIO_IS 0x48 -#define NMK_GPIO_IC 0x4c -#define NMK_GPIO_RWIMSC 0x50 -#define NMK_GPIO_FWIMSC 0x54 -#define NMK_GPIO_WKS 0x58 - -/* Alternate functions: function C is set in hw by setting both A and B */ -#define NMK_GPIO_ALT_GPIO 0 -#define NMK_GPIO_ALT_A 1 -#define NMK_GPIO_ALT_B 2 -#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) - -/* Pull up/down values */ -enum nmk_gpio_pull { - NMK_GPIO_PULL_NONE, - NMK_GPIO_PULL_UP, - NMK_GPIO_PULL_DOWN, -}; - -/* Sleep mode */ -enum nmk_gpio_slpm { - NMK_GPIO_SLPM_INPUT, - NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, - NMK_GPIO_SLPM_NOCHANGE, - NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, -}; - -extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); -extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); -extern int nmk_gpio_set_mode(int gpio, int gpio_mode); -extern int nmk_gpio_get_mode(int gpio); - -extern void nmk_gpio_wakeups_suspend(void); -extern void nmk_gpio_wakeups_resume(void); - -extern void nmk_gpio_clocks_enable(void); -extern void nmk_gpio_clocks_disable(void); - -extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); - -/* - * Platform data to register a block: only the initial gpio/irq number. - */ -struct nmk_gpio_platform_data { - char *name; - int first_gpio; - int first_irq; - int num_gpio; - u32 (*get_secondary_status)(unsigned int bank); - void (*set_ioforce)(bool enable); - bool supports_sleepmode; -}; - -#endif /* __PLAT_NOMADIK_GPIO */ diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h index 582641f3dc0..489e92723b4 100644 --- a/arch/arm/plat-nomadik/include/plat/mtu.h +++ b/arch/arm/plat-nomadik/include/plat/mtu.h @@ -5,5 +5,7 @@ void nmdk_timer_init(void __iomem *base); void nmdk_clkevt_reset(void); void nmdk_clksrc_reset(void); +struct clock_event_device *nmdk_clkevt_get(void); + #endif /* __PLAT_MTU_H */ diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 22cb97d2d8a..c015133a7ad 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -24,6 +24,7 @@ * bit 16..18 - SLPM pull up/down state * bit 19..20 - SLPM direction * bit 21..22 - SLPM Value (if output) + * bit 23..25 - PDIS value (if input) * * to facilitate the definition, the following macros are provided * @@ -67,6 +68,10 @@ typedef unsigned long pin_cfg_t; /* These two replace the above in DB8500v2+ */ #define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) #define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE + +#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ +#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ #define PIN_DIR_SHIFT 14 #define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) @@ -105,6 +110,20 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) #define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_PDIS_SHIFT 23 +#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS(x) \ + (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) + +#define PIN_LOWEMI_SHIFT 25 +#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) + /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h index 31382fbc07d..834c015c935 100644 --- a/arch/arm/plat-nomadik/include/plat/ske.h +++ b/arch/arm/plat-nomadik/include/plat/ske.h @@ -22,6 +22,9 @@ #define SKE_MIS 0x18 #define SKE_ICR 0x1C +#define SKE_KPD_MAX_ROWS 8 +#define SKE_KPD_MAX_COLS 8 + /* * Keypad module */ @@ -30,21 +33,31 @@ * struct keypad_platform_data - structure for platform specific data * @init: pointer to keypad init function * @exit: pointer to keypad deinitialisation function + * @gpio_input_pins: pointer to gpio input pins + * @gpio_output_pins: pointer to gpio output pins * @keymap_data: matrix scan code table for keycodes * @krow: maximum number of rows * @kcol: maximum number of columns + * @kconnected_rows: number of rows actually connected + * @kconnected_cols: number of columns actually connected * @debounce_ms: platform specific debounce time * @no_autorepeat: flag for auto repetition * @wakeup_enable: allow waking up the system + * @switch_delay: gpio switch_delay */ struct ske_keypad_platform_data { int (*init)(void); int (*exit)(void); + int *gpio_input_pins; + int *gpio_output_pins; const struct matrix_keymap_data *keymap_data; u8 krow; u8 kcol; + u8 kconnected_rows; + u8 kconnected_cols; u8 debounce_ms; bool no_autorepeat; bool wakeup_enable; + int switch_delay; }; #endif /*__SKE_KPD_H*/ diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 9ff93b06568..08cc3bf8f6d 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -146,6 +146,7 @@ struct stedma40_chan_cfg { * @memcpy_conf_phy: default configuration of physical channel memcpy * @memcpy_conf_log: default configuration of logical channel memcpy * @disabled_channels: A vector, ending with -1, that marks physical channels + * @use_esram_lcla: flag for mapping the lcla into esram region * that are for different reasons not available for the driver. */ struct stedma40_platform_data { @@ -162,6 +163,24 @@ struct stedma40_platform_data { #ifdef CONFIG_STE_DMA40 +/* + * stedma40_get_src_addr - get current source address + * @chan: the DMA channel + * + * Returns the physical address of the current source element to be read by the + * DMA. + */ +dma_addr_t stedma40_get_src_addr(struct dma_chan *chan); + +/* + * stedma40_get_dst_addr - get current destination address + * @chan: the DMA channel + * + * Returns the physical address of the current destination element to be + * written by the DMA. + */ +dma_addr_t stedma40_get_dst_addr(struct dma_chan *chan); + /** * stedma40_filter() - Provides stedma40_chan_cfg to the * ste_dma40 dma driver via the dmaengine framework. @@ -204,6 +223,16 @@ dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, } #else +dma_addr_t stedma40_get_src_addr(struct dma_chan *chan) +{ + return NULL; +} + +dma_addr_t stedma40_get_dst_addr(struct dma_chan *chan) +{ + return NULL; +} + static inline bool stedma40_filter(struct dma_chan *chan, void *data) { return false; diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 9222e5522a4..f26ce2fb0d1 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -17,6 +17,7 @@ #include <linux/clk.h> #include <linux/jiffies.h> #include <linux/err.h> +#include <linux/delay.h> #include <asm/mach/time.h> #include <asm/sched_clock.h> @@ -142,6 +143,28 @@ static struct clock_event_device nmdk_clkevt = { .set_next_event = nmdk_clkevt_next, }; +#ifdef ARCH_HAS_READ_CURRENT_TIMER +static void nmdk_timer_delay_loop(unsigned long loops) +{ + unsigned long bclock, now; + + bclock = ~readl(mtu_base + MTU_VAL(0)); + do { + now = ~readl(mtu_base + MTU_VAL(0)); + /* If timer have been cleared (suspend) or wrapped we exit */ + if (unlikely(now < bclock)) + return; + } while ((now - bclock) < loops); +} + +/* Used to calibrate the delay */ +int read_current_timer(unsigned long *timer_val) +{ + *timer_val = ~readl(mtu_base + MTU_VAL(0)); + return 0; +} +#endif + /* * IRQ Handler for timer 1 of the MTU block. */ @@ -174,6 +197,11 @@ void nmdk_clksrc_reset(void) mtu_base + MTU_CR(0)); } +struct clock_event_device *nmdk_clkevt_get(void) +{ + return &nmdk_clkevt; +} + void __init nmdk_timer_init(void __iomem *base) { unsigned long rate; @@ -220,4 +248,8 @@ void __init nmdk_timer_init(void __iomem *base) setup_irq(IRQ_MTU0, &nmdk_timer_irq); nmdk_clkevt.cpumask = cpumask_of(0); clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); +#ifdef ARCH_HAS_READ_CURRENT_TIMER + set_delay_fn(nmdk_timer_delay_loop); +#endif + } diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index f9c9f33f8cb..bb2f9e9d6d2 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,531 +12,3179 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# This is a cut-down version of the file; it contains only machines that -# are merged into mainline or have been edited in the machine database -# within the last 12 months. References to machine_is_NAME() do not count! -# -# Last update: Tue Dec 6 11:07:38 2011 +# Last update: Thu Feb 2 12:49:17 2012 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # ebsa110 ARCH_EBSA110 EBSA110 0 riscpc ARCH_RPC RISCPC 1 +nexuspci ARCH_NEXUSPCI NEXUSPCI 3 ebsa285 ARCH_EBSA285 EBSA285 4 netwinder ARCH_NETWINDER NETWINDER 5 cats ARCH_CATS CATS 6 +tbox ARCH_TBOX TBOX 7 +co285 ARCH_CO285 CO285 8 +clps7110 ARCH_CLPS7110 CLPS7110 9 +archimedes ARCH_ARC ARCHIMEDES 10 +a5k ARCH_A5K A5K 11 +etoile ARCH_ETOILE ETOILE 12 +lacie_nas ARCH_LACIE_NAS LACIE_NAS 13 +clps7500 ARCH_CLPS7500 CLPS7500 14 shark ARCH_SHARK SHARK 15 brutus SA1100_BRUTUS BRUTUS 16 personal_server ARCH_PERSONAL_SERVER PERSONAL_SERVER 17 +itsy SA1100_ITSY ITSY 18 l7200 ARCH_L7200 L7200 19 pleb SA1100_PLEB PLEB 20 integrator ARCH_INTEGRATOR INTEGRATOR 21 h3600 SA1100_H3600 H3600 22 +ixp1200 ARCH_IXP1200 IXP1200 23 p720t ARCH_P720T P720T 24 assabet SA1100_ASSABET ASSABET 25 +victor SA1100_VICTOR VICTOR 26 lart SA1100_LART LART 27 +ranger SA1100_RANGER RANGER 28 graphicsclient SA1100_GRAPHICSCLIENT GRAPHICSCLIENT 29 xp860 SA1100_XP860 XP860 30 cerf SA1100_CERF CERF 31 nanoengine SA1100_NANOENGINE NANOENGINE 32 +fpic SA1100_FPIC FPIC 33 +extenex1 SA1100_EXTENEX1 EXTENEX1 34 +sherman SA1100_SHERMAN SHERMAN 35 +accelent_sa SA1100_ACCELENT ACCELENT_SA 36 +accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37 +netport SA1100_NETPORT NETPORT 38 +pangolin SA1100_PANGOLIN PANGOLIN 39 +yopy SA1100_YOPY YOPY 40 +coolidge SA1100_COOLIDGE COOLIDGE 41 +huw_webpanel SA1100_HUW_WEBPANEL HUW_WEBPANEL 42 +spotme ARCH_SPOTME SPOTME 43 +freebird ARCH_FREEBIRD FREEBIRD 44 +ti925 ARCH_TI925 TI925 45 +riscstation ARCH_RISCSTATION RISCSTATION 46 +cavy SA1100_CAVY CAVY 47 jornada720 SA1100_JORNADA720 JORNADA720 48 +omnimeter SA1100_OMNIMETER OMNIMETER 49 edb7211 ARCH_EDB7211 EDB7211 50 +citygo SA1100_CITYGO CITYGO 51 pfs168 SA1100_PFS168 PFS168 52 +spot SA1100_SPOT SPOT 53 flexanet SA1100_FLEXANET FLEXANET 54 +webpal ARCH_WEBPAL WEBPAL 55 +linpda SA1100_LINPDA LINPDA 56 +anakin ARCH_ANAKIN ANAKIN 57 +mvi SA1100_MVI MVI 58 +jupiter SA1100_JUPITER JUPITER 59 +psionw ARCH_PSIONW PSIONW 60 +aln SA1100_ALN ALN 61 +epxa ARCH_CAMELOT CAMELOT 62 +gds2200 SA1100_GDS2200 GDS2200 63 +netbook SA1100_PSION_SERIES7 PSION_SERIES7 64 +xfile SA1100_XFILE XFILE 65 +accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66 +ic200 ARCH_IC200 IC200 67 +creditlart SA1100_CREDITLART CREDITLART 68 +htm SA1100_HTM HTM 69 +iq80310 ARCH_IQ80310 IQ80310 70 +freebot SA1100_FREEBOT FREEBOT 71 +entel ARCH_ENTEL ENTEL 72 +enp3510 ARCH_ENP3510 ENP3510 73 +trizeps SA1100_TRIZEPS TRIZEPS 74 +nesa SA1100_NESA NESA 75 +venus ARCH_VENUS VENUS 76 +tardis ARCH_TARDIS TARDIS 77 +mercury ARCH_MERCURY MERCURY 78 +empeg SA1100_EMPEG EMPEG 79 +adi_evb ARCH_I80200FCC I80200FCC 80 +itt_cpb SA1100_ITT_CPB ITT_CPB 81 +svc SA1100_SVC SVC 82 +alpha2 SA1100_ALPHA2 ALPHA2 84 +alpha1 SA1100_ALPHA1 ALPHA1 85 +netarm ARCH_NETARM NETARM 86 simpad SA1100_SIMPAD SIMPAD 87 +pda1 ARCH_PDA1 PDA1 88 lubbock ARCH_LUBBOCK LUBBOCK 89 +aniko ARCH_ANIKO ANIKO 90 clep7212 ARCH_CLEP7212 CLEP7212 91 +cs89712 ARCH_CS89712 CS89712 92 +weararm SA1100_WEARARM WEARARM 93 +possio_px SA1100_POSSIO_PX POSSIO_PX 94 +sidearm SA1100_SIDEARM SIDEARM 95 +stork SA1100_STORK STORK 96 shannon SA1100_SHANNON SHANNON 97 +ace ARCH_ACE ACE 98 +ballyarm SA1100_BALLYARM BALLYARM 99 +simputer SA1100_SIMPUTER SIMPUTER 100 +nexterm SA1100_NEXTERM NEXTERM 101 +sa1100_elf SA1100_SA1100_ELF SA1100_ELF 102 +gator SA1100_GATOR GATOR 103 +granite ARCH_GRANITE GRANITE 104 consus SA1100_CONSUS CONSUS 105 aaed2000 ARCH_AAED2000 AAED2000 106 cdb89712 ARCH_CDB89712 CDB89712 107 graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108 adsbitsy SA1100_ADSBITSY ADSBITSY 109 pxa_idp ARCH_PXA_IDP PXA_IDP 110 +plce ARCH_PLCE PLCE 111 pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112 +murphy ARCH_MEDALB MEDALB 113 +eagle ARCH_EAGLE EAGLE 114 +dsc21 ARCH_DSC21 DSC21 115 +dsc24 ARCH_DSC24 DSC24 116 +ti5472 ARCH_TI5472 TI5472 117 autcpu12 ARCH_AUTCPU12 AUTCPU12 118 +uengine ARCH_UENGINE UENGINE 119 +bluestem SA1100_BLUESTEM BLUESTEM 120 +xingu8 ARCH_XINGU8 XINGU8 121 +bushstb ARCH_BUSHSTB BUSHSTB 122 +epsilon1 SA1100_EPSILON1 EPSILON1 123 +balloon SA1100_BALLOON BALLOON 124 +puppy ARCH_PUPPY PUPPY 125 +elroy SA1100_ELROY ELROY 126 +gms720 ARCH_GMS720 GMS720 127 +s24x ARCH_S24X S24X 128 +jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129 +cx821xx ARCH_CX821XX CX821XX 130 +edb7312 ARCH_EDB7312 EDB7312 131 +bsa1110 SA1100_BSA1110 BSA1110 132 +powerpin ARCH_POWERPIN POWERPIN 133 +openarm ARCH_OPENARM OPENARM 134 +whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135 h3100 SA1100_H3100 H3100 136 +h3800 SA1100_H3800 H3800 137 +blue_v1 ARCH_BLUE_V1 BLUE_V1 138 +pxa_cerf ARCH_PXA_CERF PXA_CERF 139 +arm7tevb ARCH_ARM7TEVB ARM7TEVB 140 +d7400 SA1100_D7400 D7400 141 +piranha ARCH_PIRANHA PIRANHA 142 +sbcamelot SA1100_SBCAMELOT SBCAMELOT 143 +kings SA1100_KINGS KINGS 144 +smdk2400 ARCH_SMDK2400 SMDK2400 145 collie SA1100_COLLIE COLLIE 146 +idr ARCH_IDR IDR 147 badge4 SA1100_BADGE4 BADGE4 148 +webnet ARCH_WEBNET WEBNET 149 +d7300 SA1100_D7300 D7300 150 +cep SA1100_CEP CEP 151 fortunet ARCH_FORTUNET FORTUNET 152 +vc547x ARCH_VC547X VC547X 153 +filewalker SA1100_FILEWALKER FILEWALKER 154 +netgateway SA1100_NETGATEWAY NETGATEWAY 155 +symbol2800 SA1100_SYMBOL2800 SYMBOL2800 156 +suns SA1100_SUNS SUNS 157 +frodo SA1100_FRODO FRODO 158 +ms301 SA1100_MACH_TYTE_MS301 MACH_TYTE_MS301 159 mx1ads ARCH_MX1ADS MX1ADS 160 h7201 ARCH_H7201 H7201 161 h7202 ARCH_H7202 H7202 162 +amico ARCH_AMICO AMICO 163 +iam SA1100_IAM IAM 164 +tt530 SA1100_TT530 TT530 165 +sam2400 ARCH_SAM2400 SAM2400 166 +jornada56x SA1100_JORNADA56X JORNADA56X 167 +active SA1100_ACTIVE ACTIVE 168 iq80321 ARCH_IQ80321 IQ80321 169 +wid SA1100_WID WID 170 +sabinal ARCH_SABINAL SABINAL 171 +ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172 +miniprint SA1100_MINIPRINT MINIPRINT 173 +adm510x ARCH_ADM510X ADM510X 174 +svs200 SA1100_SVS200 SVS200 175 +atg_tcu ARCH_ATG_TCU ATG_TCU 176 +jornada820 SA1100_JORNADA820 JORNADA820 177 +s3c44b0 ARCH_S3C44B0 S3C44B0 178 +margis2 ARCH_MARGIS2 MARGIS2 179 ks8695 ARCH_KS8695 KS8695 180 +brh ARCH_BRH BRH 181 +s3c2410 ARCH_S3C2410 S3C2410 182 +possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183 +s3c2800 ARCH_S3C2800 S3C2800 184 +fleetwood SA1100_FLEETWOOD FLEETWOOD 185 +omaha ARCH_OMAHA OMAHA 186 +ta7 ARCH_TA7 TA7 187 +nova SA1100_NOVA NOVA 188 +hmk ARCH_HMK HMK 189 karo ARCH_KARO KARO 190 +fester SA1100_FESTER FESTER 191 +gpi ARCH_GPI GPI 192 smdk2410 ARCH_SMDK2410 SMDK2410 193 +i519 ARCH_I519 I519 194 +nexio SA1100_NEXIO NEXIO 195 +bitbox SA1100_BITBOX BITBOX 196 +g200 SA1100_G200 G200 197 +gill SA1100_GILL GILL 198 +pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199 ceiva ARCH_CEIVA CEIVA 200 +fret SA1100_FRET FRET 201 +emailphone SA1100_EMAILPHONE EMAILPHONE 202 +h3900 ARCH_H3900 H3900 203 +pxa1 ARCH_PXA1 PXA1 204 +koan369 SA1100_KOAN369 KOAN369 205 +cogent ARCH_COGENT COGENT 206 +esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207 +esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208 +esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209 +hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210 +he500 ARCH_HE500 HE500 211 +inhandelf2 SA1100_INHANDELF2 INHANDELF2 212 +inhandftip SA1100_INHANDFTIP INHANDFTIP 213 +dnp1110 SA1100_DNP1110 DNP1110 214 +pnp1110 SA1100_PNP1110 PNP1110 215 +csb226 ARCH_CSB226 CSB226 216 +arnold SA1100_ARNOLD ARNOLD 217 voiceblue MACH_VOICEBLUE VOICEBLUE 218 +jz8028 ARCH_JZ8028 JZ8028 219 h5400 ARCH_H5400 H5400 220 +forte SA1100_FORTE FORTE 221 +acam SA1100_ACAM ACAM 222 +abox SA1100_ABOX ABOX 223 +atmel ARCH_ATMEL ATMEL 224 +sitsang ARCH_SITSANG SITSANG 225 +cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226 +mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227 +opus_a1 ARCH_OPUS_A1 OPUS_A1 228 +daytona ARCH_DAYTONA DAYTONA 229 +killbear SA1100_KILLBEAR KILLBEAR 230 +yoho ARCH_YOHO YOHO 231 +jasper ARCH_JASPER JASPER 232 +dsc25 ARCH_DSC25 DSC25 233 omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234 +mnci ARCH_RAMSES RAMSES 235 +s28x ARCH_S28X S28X 236 +mport3 ARCH_MPORT3 MPORT3 237 +pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 +pdb ARCH_PDB PDB 239 +blue_2g SA1100_BLUE_2G BLUE_2G 240 +bluearch SA1100_BLUEARCH BLUEARCH 241 ixdp2400 ARCH_IXDP2400 IXDP2400 242 ixdp2800 ARCH_IXDP2800 IXDP2800 243 +explorer SA1100_EXPLORER EXPLORER 244 ixdp425 ARCH_IXDP425 IXDP425 245 +chimp ARCH_CHIMP CHIMP 246 +stork_nest ARCH_STORK_NEST STORK_NEST 247 +stork_egg ARCH_STORK_EGG STORK_EGG 248 +wismo SA1100_WISMO WISMO 249 +ezlinx ARCH_EZLINX EZLINX 250 +at91rm9200 ARCH_AT91RM9200 AT91RM9200 251 +adtech_orion ARCH_ADTECH_ORION ADTECH_ORION 252 +neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 +pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255 +lavinna SA1100_LAVINNA LAVINNA 256 +pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257 +innokom ARCH_INNOKOM INNOKOM 258 +bms ARCH_BMS BMS 259 ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260 +prpmc1100 ARCH_PRPMC1100 PRPMC1100 261 at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262 +armstick ARCH_ARMSTICK ARMSTICK 263 +armonie ARCH_ARMONIE ARMONIE 264 +mport1 ARCH_MPORT1 MPORT1 265 +s3c5410 ARCH_S3C5410 S3C5410 266 +zcp320a ARCH_ZCP320A ZCP320A 267 +i_box ARCH_I_BOX I_BOX 268 +stlc1502 ARCH_STLC1502 STLC1502 269 +siren ARCH_SIREN SIREN 270 +greenlake ARCH_GREENLAKE GREENLAKE 271 +argus ARCH_ARGUS ARGUS 272 +combadge SA1100_COMBADGE COMBADGE 273 +rokepxa ARCH_ROKEPXA ROKEPXA 274 cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275 +guidea07 ARCH_GUIDEA07 GUIDEA07 276 +tat257 ARCH_TAT257 TAT257 277 +igp2425 ARCH_IGP2425 IGP2425 278 +bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279 +ipod ARCH_IPOD IPOD 280 +adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281 +trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282 viper ARCH_VIPER VIPER 283 +adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 +adsagc SA1100_ADSAGC ADSAGC 285 +stp7312 ARCH_STP7312 STP7312 286 +nx_phnx MACH_NX_PHNX NX_PHNX 287 +wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 +inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 +iyonix ARCH_IYONIX IYONIX 291 +damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 +meg03 ARCH_MEG03 MEG03 293 +pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 +nwsc ARCH_NWSC NWSC 295 +nwlarm ARCH_NWLARM NWLARM 296 +ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297 +pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298 ixdp2401 ARCH_IXDP2401 IXDP2401 299 ixdp2801 ARCH_IXDP2801 IXDP2801 300 +zodiac ARCH_ZODIAC ZODIAC 301 +armmodul ARCH_ARMMODUL ARMMODUL 302 +ketop SA1100_KETOP KETOP 303 +av7200 ARCH_AV7200 AV7200 304 +arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305 +acq200 ARCH_ACQ200 ACQ200 306 +pt_dafit SA1100_PT_DAFIT PT_DAFIT 307 +ihba ARCH_IHBA IHBA 308 +quinque ARCH_QUINQUE QUINQUE 309 +nimbraone ARCH_NIMBRAONE NIMBRAONE 310 +nimbra29x ARCH_NIMBRA29X NIMBRA29X 311 +nimbra210 ARCH_NIMBRA210 NIMBRA210 312 +hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 +labarm ARCH_LABARM LABARM 314 +m825xx ARCH_M825XX M825XX 315 +m7100 SA1100_M7100 M7100 316 +nipc2 ARCH_NIPC2 NIPC2 317 +fu7202 ARCH_FU7202 FU7202 318 +adsagx ARCH_ADSAGX ADSAGX 319 +pxa_pooh ARCH_PXA_POOH PXA_POOH 320 +bandon ARCH_BANDON BANDON 321 +pcm7210 ARCH_PCM7210 PCM7210 322 +nms9200 ARCH_NMS9200 NMS9200 323 +logodl ARCH_LOGODL LOGODL 324 +m7140 SA1100_M7140 M7140 325 +korebot ARCH_KOREBOT KOREBOT 326 iq31244 ARCH_IQ31244 IQ31244 327 +koan393 SA1100_KOAN393 KOAN393 328 +inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329 +gonzo ARCH_GONZO GONZO 330 bast ARCH_BAST BAST 331 +scanpass ARCH_SCANPASS SCANPASS 332 +ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333 +ta7s ARCH_TA7S TA7S 334 +ta7v ARCH_TA7V TA7V 335 +icarus SA1100_ICARUS ICARUS 336 +h1900 ARCH_H1900 H1900 337 +gemini SA1100_GEMINI GEMINI 338 +axim ARCH_AXIM AXIM 339 +audiotron ARCH_AUDIOTRON AUDIOTRON 340 +h2200 ARCH_H2200 H2200 341 +loox600 ARCH_LOOX600 LOOX600 342 +niop ARCH_NIOP NIOP 343 +dm310 ARCH_DM310 DM310 344 +seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345 +ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346 h1940 ARCH_H1940 H1940 347 +scorpio ARCH_SCORPIO SCORPIO 348 +viva ARCH_VIVA VIVA 349 +pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350 +csb335 ARCH_CSB335 CSB335 351 +ixrd425 ARCH_IXRD425 IXRD425 352 +iq80315 ARCH_IQ80315 IQ80315 353 +nmp7312 ARCH_NMP7312 NMP7312 354 +cx861xx ARCH_CX861XX CX861XX 355 enp2611 ARCH_ENP2611 ENP2611 356 +xda SA1100_XDA XDA 357 +csir_ims ARCH_CSIR_IMS CSIR_IMS 358 +ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359 +pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360 +toto ARCH_TOTO TOTO 361 s3c2440 ARCH_S3C2440 S3C2440 362 +ks8695p ARCH_KS8695P KS8695P 363 +se4000 ARCH_SE4000 SE4000 364 +quadriceps ARCH_QUADRICEPS QUADRICEPS 365 +bronco ARCH_BRONCO BRONCO 366 +esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367 +esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368 +s5c7375 ARCH_S5C7375 S5C7375 369 +spearhead ARCH_SPEARHEAD SPEARHEAD 370 +pantera ARCH_PANTERA PANTERA 371 +prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372 gumstix ARCH_GUMSTIX GUMSTIX 373 +rcube ARCH_RCUBE RCUBE 374 +rea_olv ARCH_REA_OLV REA_OLV 375 +pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376 +s3c3410 ARCH_S3C3410 S3C3410 377 +espd_4510b ARCH_ESPD_4510B ESPD_4510B 378 +mp1x ARCH_MP1X MP1X 379 +at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380 +adsvgx ARCH_ADSVGX ADSVGX 381 omap_h2 MACH_OMAP_H2 OMAP_H2 382 +pelee ARCH_PELEE PELEE 383 e740 MACH_E740 E740 384 iq80331 ARCH_IQ80331 IQ80331 385 versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387 kev7a400 MACH_KEV7A400 KEV7A400 388 lpd7a400 MACH_LPD7A400 LPD7A400 389 lpd7a404 MACH_LPD7A404 LPD7A404 390 +fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391 +janus2m ARCH_JANUS2M JANUS2M 392 +embtf MACH_EMBTF EMBTF 393 +hpm MACH_HPM HPM 394 +smdk2410tk MACH_SMDK2410TK SMDK2410TK 395 +smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396 +streetracer MACH_STREETRACER STREETRACER 397 +eframe MACH_EFRAME EFRAME 398 csb337 MACH_CSB337 CSB337 399 +pxa_lark MACH_PXA_LARK PXA_LARK 400 +pxa_pnp2110 MACH_PNP2110 PNP2110 401 +tcc72x MACH_TCC72X TCC72X 402 +altair MACH_ALTAIR ALTAIR 403 +kc3 MACH_KC3 KC3 404 +sinteftd MACH_SINTEFTD SINTEFTD 405 mainstone MACH_MAINSTONE MAINSTONE 406 +aday4x MACH_ADAY4X ADAY4X 407 +lite300 MACH_LITE300 LITE300 408 +s5c7376 MACH_S5C7376 S5C7376 409 +mt02 MACH_MT02 MT02 410 +mport3s MACH_MPORT3S MPORT3S 411 +ra_alpha MACH_RA_ALPHA RA_ALPHA 412 xcep MACH_XCEP XCEP 413 arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414 +stargate MACH_STARGATE STARGATE 415 +armadilloj MACH_ARMADILLOJ ARMADILLOJ 416 +elroy_jack MACH_ELROY_JACK ELROY_JACK 417 +backend MACH_BACKEND BACKEND 418 +s5linbox MACH_S5LINBOX S5LINBOX 419 nomadik MACH_NOMADIK NOMADIK 420 +ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421 +at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422 corgi MACH_CORGI CORGI 423 poodle MACH_POODLE POODLE 424 +ten MACH_TEN TEN 425 +roverp5p MACH_ROVERP5P ROVERP5P 426 +sc2700 MACH_SC2700 SC2700 427 +ex_eagle MACH_EX_EAGLE EX_EAGLE 428 +nx_pxa12 MACH_NX_PXA12 NX_PXA12 429 +nx_pxa5 MACH_NX_PXA5 NX_PXA5 430 +blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431 +i819 MACH_I819 I819 432 +ixmb995e MACH_IXMB995E IXMB995E 433 +skyrider MACH_SKYRIDER SKYRIDER 434 +skyhawk MACH_SKYHAWK SKYHAWK 435 +enterprise MACH_ENTERPRISE ENTERPRISE 436 +dep2410 MACH_DEP2410 DEP2410 437 armcore MACH_ARMCORE ARMCORE 438 +hobbit MACH_HOBBIT HOBBIT 439 +h7210 MACH_H7210 H7210 440 +pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441 +acc MACH_ACC ACC 442 +esl_sarva MACH_ESL_SARVA ESL_SARVA 443 +xm250 MACH_XM250 XM250 444 +t6tc1xb MACH_T6TC1XB T6TC1XB 445 +ess710 MACH_ESS710 ESS710 446 mx31ads MACH_MX31ADS MX31ADS 447 himalaya MACH_HIMALAYA HIMALAYA 448 +bolfenk MACH_BOLFENK BOLFENK 449 +at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450 edb9312 MACH_EDB9312 EDB9312 451 omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452 +aximx3 MACH_AXIMX3 AXIMX3 453 +eb67xdip MACH_EB67XDIP EB67XDIP 454 +webtxs MACH_WEBTXS WEBTXS 455 +hawk MACH_HAWK HAWK 456 +ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457 +expresso MACH_EXPRESSO EXPRESSO 458 +h4000 MACH_H4000 H4000 459 +dino MACH_DINO DINO 460 +ml675k MACH_ML675K ML675K 461 edb9301 MACH_EDB9301 EDB9301 462 edb9315 MACH_EDB9315 EDB9315 463 +reciva_tt MACH_RECIVA_TT RECIVA_TT 464 +cstcb01 MACH_CSTCB01 CSTCB01 465 +cstcb1 MACH_CSTCB1 CSTCB1 466 +shadwell MACH_SHADWELL SHADWELL 467 +goepel263 MACH_GOEPEL263 GOEPEL263 468 +acq100 MACH_ACQ100 ACQ100 469 +mx1fs2 MACH_MX1FS2 MX1FS2 470 +hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471 +sparky MACH_SPARKY SPARKY 472 +ns9750 MACH_NS9750 NS9750 473 +phoenix MACH_PHOENIX PHOENIX 474 vr1000 MACH_VR1000 VR1000 475 +deisterpxa MACH_DEISTERPXA DEISTERPXA 476 +bcm1160 MACH_BCM1160 BCM1160 477 +pcm022 MACH_PCM022 PCM022 478 +adsgcx MACH_ADSGCX ADSGCX 479 +dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480 +dm320 MACH_DM320 DM320 481 +markov MACH_MARKOV MARKOV 482 +cos7a400 MACH_COS7A400 COS7A400 483 +milano MACH_MILANO MILANO 484 +ue9328 MACH_UE9328 UE9328 485 +uex255 MACH_UEX255 UEX255 486 +ue2410 MACH_UE2410 UE2410 487 +a620 MACH_A620 A620 488 +ocelot MACH_OCELOT OCELOT 489 +cheetah MACH_CHEETAH CHEETAH 490 omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491 +zvue MACH_ZVUE ZVUE 492 +roverp1 MACH_ROVERP1 ROVERP1 493 +asidial2 MACH_ASIDIAL2 ASIDIAL2 494 +s3c24a0 MACH_S3C24A0 S3C24A0 495 e800 MACH_E800 E800 496 e750 MACH_E750 E750 497 +s3c5500 MACH_S3C5500 S3C5500 498 +smdk5500 MACH_SMDK5500 SMDK5500 499 +signalsync MACH_SIGNALSYNC SIGNALSYNC 500 +nbc MACH_NBC NBC 501 +kodiak MACH_KODIAK KODIAK 502 +netbookpro MACH_NETBOOKPRO NETBOOKPRO 503 +hw90200 MACH_HW90200 HW90200 504 +condor MACH_CONDOR CONDOR 505 +cup MACH_CUP CUP 506 +kite MACH_KITE KITE 507 scb9328 MACH_SCB9328 SCB9328 508 omap_h3 MACH_OMAP_H3 OMAP_H3 509 omap_h4 MACH_OMAP_H4 OMAP_H4 510 +n10 MACH_N10 N10 511 +montejade MACH_MONTAJADE MONTAJADE 512 +sg560 MACH_SG560 SG560 513 +dp1000 MACH_DP1000 DP1000 514 omap_osk MACH_OMAP_OSK OMAP_OSK 515 +rg100v3 MACH_RG100V3 RG100V3 516 +mx2ads MACH_MX2ADS MX2ADS 517 +pxa_kilo MACH_PXA_KILO PXA_KILO 518 +ixp4xx_eagle MACH_IXP4XX_EAGLE IXP4XX_EAGLE 519 tosa MACH_TOSA TOSA 520 +mb2520f MACH_MB2520F MB2520F 521 +emc1000 MACH_EMC1000 EMC1000 522 +tidsc25 MACH_TIDSC25 TIDSC25 523 +akcpmxl MACH_AKCPMXL AKCPMXL 524 +av3xx MACH_AV3XX AV3XX 525 avila MACH_AVILA AVILA 526 +pxa_mpm10 MACH_PXA_MPM10 PXA_MPM10 527 +pxa_kyanite MACH_PXA_KYANITE PXA_KYANITE 528 +sgold MACH_SGOLD SGOLD 529 +oscar MACH_OSCAR OSCAR 530 +epxa4usb2 MACH_EPXA4USB2 EPXA4USB2 531 +xsengine MACH_XSENGINE XSENGINE 532 +ip600 MACH_IP600 IP600 533 +mcan2 MACH_MCAN2 MCAN2 534 +ddi_blueridge MACH_DDI_BLUERIDGE DDI_BLUERIDGE 535 +skyminder MACH_SKYMINDER SKYMINDER 536 +lpd79520 MACH_LPD79520 LPD79520 537 edb9302 MACH_EDB9302 EDB9302 538 +hw90340 MACH_HW90340 HW90340 539 +cip_box MACH_CIP_BOX CIP_BOX 540 +ivpn MACH_IVPN IVPN 541 +rsoc2 MACH_RSOC2 RSOC2 542 husky MACH_HUSKY HUSKY 543 +boxer MACH_BOXER BOXER 544 shepherd MACH_SHEPHERD SHEPHERD 545 +aml42800aa MACH_AML42800AA AML42800AA 546 +lpc2294 MACH_LPC2294 LPC2294 548 +switchgrass MACH_SWITCHGRASS SWITCHGRASS 549 +ens_cmu MACH_ENS_CMU ENS_CMU 550 +mm6_sdb MACH_MM6_SDB MM6_SDB 551 +saturn MACH_SATURN SATURN 552 +i30030evb MACH_I30030EVB I30030EVB 553 +mxc27530evb MACH_MXC27530EVB MXC27530EVB 554 +smdk2800 MACH_SMDK2800 SMDK2800 555 +mtwilson MACH_MTWILSON MTWILSON 556 +ziti MACH_ZITI ZITI 557 +grandfather MACH_GRANDFATHER GRANDFATHER 558 +tengine MACH_TENGINE TENGINE 559 +s3c2460 MACH_S3C2460 S3C2460 560 +pdm MACH_PDM PDM 561 h4700 MACH_H4700 H4700 562 +h6300 MACH_H6300 H6300 563 +rz1700 MACH_RZ1700 RZ1700 564 +a716 MACH_A716 A716 565 +estk2440a MACH_ESTK2440A ESTK2440A 566 +atwixp425 MACH_ATWIXP425 ATWIXP425 567 +csb336 MACH_CSB336 CSB336 568 +rirm2 MACH_RIRM2 RIRM2 569 +cx23518 MACH_CX23518 CX23518 570 +cx2351x MACH_CX2351X CX2351X 571 +computime MACH_COMPUTIME COMPUTIME 572 +izarus MACH_IZARUS IZARUS 573 +pxa_rts MACH_RTS RTS 574 +se5100 MACH_SE5100 SE5100 575 +s3c2510 MACH_S3C2510 S3C2510 576 +csb437tl MACH_CSB437TL CSB437TL 577 +slauson MACH_SLAUSON SLAUSON 578 +pearlriver MACH_PEARLRIVER PEARLRIVER 579 +tdc_p210 MACH_TDC_P210 TDC_P210 580 +sg580 MACH_SG580 SG580 581 +wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582 +ipd MACH_IPD IPD 583 +pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584 +xaeniax MACH_XAENIAX XAENIAX 585 +somn4250 MACH_SOMN4250 SOMN4250 586 +pleb2 MACH_PLEB2 PLEB2 587 +cornwallis MACH_CORNWALLIS CORNWALLIS 588 +gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589 +chaffee MACH_CHAFFEE CHAFFEE 590 +rms101 MACH_RMS101 RMS101 591 rx3715 MACH_RX3715 RX3715 592 +swift MACH_SWIFT SWIFT 593 +roverp7 MACH_ROVERP7 ROVERP7 594 +pr818s MACH_PR818S PR818S 595 +trxpro MACH_TRXPRO TRXPRO 596 nslu2 MACH_NSLU2 NSLU2 597 e400 MACH_E400 E400 598 +trab MACH_TRAB TRAB 599 +cmc_pu2 MACH_CMC_PU2 CMC_PU2 600 +fulcrum MACH_FULCRUM FULCRUM 601 +netgate42x MACH_NETGATE42X NETGATE42X 602 +str710 MACH_STR710 STR710 603 ixdpg425 MACH_IXDPG425 IXDPG425 604 +tomtomgo MACH_TOMTOMGO TOMTOMGO 605 versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606 edb9307 MACH_EDB9307 EDB9307 607 +sg565 MACH_SG565 SG565 608 +lpd79524 MACH_LPD79524 LPD79524 609 +lpd79525 MACH_LPD79525 LPD79525 610 +rms100 MACH_RMS100 RMS100 611 kb9200 MACH_KB9200 KB9200 612 sx1 MACH_SX1 SX1 613 +hms39c7092 MACH_HMS39C7092 HMS39C7092 614 +armadillo MACH_ARMADILLO ARMADILLO 615 +ipcu MACH_IPCU IPCU 616 +loox720 MACH_LOOX720 LOOX720 617 ixdp465 MACH_IXDP465 IXDP465 618 ixdp2351 MACH_IXDP2351 IXDP2351 619 +adsvix MACH_ADSVIX ADSVIX 620 +dm270 MACH_DM270 DM270 621 +socltplus MACH_SOCLTPLUS SOCLTPLUS 622 +ecia MACH_ECIA ECIA 623 +cm4008 MACH_CM4008 CM4008 624 +p2001 MACH_P2001 P2001 625 +twister MACH_TWISTER TWISTER 626 +mudshark MACH_MUDSHARK MUDSHARK 627 +hb2 MACH_HB2 HB2 628 iq80332 MACH_IQ80332 IQ80332 629 +sendt MACH_SENDT SENDT 630 +mx2jazz MACH_MX2JAZZ MX2JAZZ 631 +multiio MACH_MULTIIO MULTIIO 632 +hrdisplay MACH_HRDISPLAY HRDISPLAY 633 +mxc27530ads MACH_MXC27530ADS MXC27530ADS 634 +trizeps3 MACH_TRIZEPS3 TRIZEPS3 635 +zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636 +zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637 +zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638 +zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639 +zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640 gtwx5715 MACH_GTWX5715 GTWX5715 641 +astro_jack MACH_ASTRO_JACK ASTRO_JACK 643 +tip03 MACH_TIP03 TIP03 644 +a9200ec MACH_A9200EC A9200EC 645 +pnx0105 MACH_PNX0105 PNX0105 646 +adcpoecpu MACH_ADCPOECPU ADCPOECPU 647 csb637 MACH_CSB637 CSB637 648 +mb9200 MACH_MB9200 MB9200 650 +kulun MACH_KULUN KULUN 651 +snapper MACH_SNAPPER SNAPPER 652 +optima MACH_OPTIMA OPTIMA 653 +dlhsbc MACH_DLHSBC DLHSBC 654 +x30 MACH_X30 X30 655 n30 MACH_N30 N30 656 +manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657 +ajax MACH_AJAX AJAX 658 nec_mp900 MACH_NEC_MP900 NEC_MP900 659 +vvtk1000 MACH_VVTK1000 VVTK1000 661 kafa MACH_KAFA KAFA 662 +vvtk3000 MACH_VVTK3000 VVTK3000 663 +pimx1 MACH_PIMX1 PIMX1 664 +ollie MACH_OLLIE OLLIE 665 +skymax MACH_SKYMAX SKYMAX 666 +jazz MACH_JAZZ JAZZ 667 +tel_t3 MACH_TEL_T3 TEL_T3 668 +aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669 +btweb MACH_BTWEB BTWEB 670 +dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671 +cm41xx MACH_CM41XX CM41XX 672 ts72xx MACH_TS72XX TS72XX 673 +nggpxa MACH_NGGPXA NGGPXA 674 +csb535 MACH_CSB535 CSB535 675 +csb536 MACH_CSB536 CSB536 676 +pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677 +praxis MACH_PRAXIS PRAXIS 678 +lh75411 MACH_LH75411 LH75411 679 otom MACH_OTOM OTOM 680 nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681 +loox410 MACH_LOOX410 LOOX410 682 +westlake MACH_WESTLAKE WESTLAKE 683 +nsb MACH_NSB NSB 684 +esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685 +esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686 +esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687 +esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688 +typhoon MACH_TYPHOON TYPHOON 689 +cnav MACH_CNAV CNAV 690 +a730 MACH_A730 A730 691 +netstar MACH_NETSTAR NETSTAR 692 +supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693 +shiva1100 MACH_SHIVA1100 SHIVA1100 694 +etexsc MACH_ETEXSC ETEXSC 695 +ixdpg465 MACH_IXDPG465 IXDPG465 696 +a9m2410 MACH_A9M2410 A9M2410 697 +a9m2440 MACH_A9M2440 A9M2440 698 +a9m9750 MACH_A9M9750 A9M9750 699 +a9m9360 MACH_A9M9360 A9M9360 700 +unc90 MACH_UNC90 UNC90 701 eco920 MACH_ECO920 ECO920 702 +satview MACH_SATVIEW SATVIEW 703 roadrunner MACH_ROADRUNNER ROADRUNNER 704 at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705 +gp32 MACH_GP32 GP32 706 +gem MACH_GEM GEM 707 +i858 MACH_I858 I858 708 +hx2750 MACH_HX2750 HX2750 709 +mxc91131evb MACH_MXC91131EVB MXC91131EVB 710 +p700 MACH_P700 P700 711 +cpe MACH_CPE CPE 712 spitz MACH_SPITZ SPITZ 713 +nimbra340 MACH_NIMBRA340 NIMBRA340 714 +lpc22xx MACH_LPC22XX LPC22XX 715 +omap_comet3 MACH_COMET3 COMET3 716 +omap_comet4 MACH_COMET4 COMET4 717 +csb625 MACH_CSB625 CSB625 718 +fortunet2 MACH_FORTUNET2 FORTUNET2 719 +s5h2200 MACH_S5H2200 S5H2200 720 +optorm920 MACH_OPTORM920 OPTORM920 721 +adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722 adssphere MACH_ADSSPHERE ADSSPHERE 723 +adsportal MACH_ADSPORTAL ADSPORTAL 724 +ln2410sbc MACH_LN2410SBC LN2410SBC 725 +cb3rufc MACH_CB3RUFC CB3RUFC 726 +mp2usb MACH_MP2USB MP2USB 727 +ntnp425c MACH_NTNP425C NTNP425C 728 colibri MACH_COLIBRI COLIBRI 729 +pcm7220 MACH_PCM7220 PCM7220 730 gateway7001 MACH_GATEWAY7001 GATEWAY7001 731 pcm027 MACH_PCM027 PCM027 732 +cmpxa MACH_CMPXA CMPXA 733 anubis MACH_ANUBIS ANUBIS 734 +ite8152 MACH_ITE8152 ITE8152 735 +lpc3xxx MACH_LPC3XXX LPC3XXX 736 +puppeteer MACH_PUPPETEER PUPPETEER 737 +e570 MACH_E570 E570 739 +x50 MACH_X50 X50 740 +recon MACH_RECON RECON 741 +xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742 +fpic2 MACH_FPIC2 FPIC2 743 akita MACH_AKITA AKITA 744 +a81 MACH_A81 A81 745 +svm_sc25x MACH_SVM_SC25X SVM_SC25X 746 +vt020 MACH_VADATECH020 VADATECH020 747 +tli MACH_TLI TLI 748 +edb9315lc MACH_EDB9315LC EDB9315LC 749 +passec MACH_PASSEC PASSEC 750 +ds_tiger MACH_DS_TIGER DS_TIGER 751 +e310 MACH_E310 E310 752 e330 MACH_E330 E330 753 +rt3000 MACH_RT3000 RT3000 754 nokia770 MACH_NOKIA770 NOKIA770 755 +pnx0106 MACH_PNX0106 PNX0106 756 +hx21xx MACH_HX21XX HX21XX 757 +faraday MACH_FARADAY FARADAY 758 +sbc9312 MACH_SBC9312 SBC9312 759 +batman MACH_BATMAN BATMAN 760 +jpd201 MACH_JPD201 JPD201 761 +mipsa MACH_MIPSA MIPSA 762 +kacom MACH_KACOM KACOM 763 +swarcocpu MACH_SWARCOCPU SWARCOCPU 764 +swarcodsl MACH_SWARCODSL SWARCODSL 765 +blueangel MACH_BLUEANGEL BLUEANGEL 766 +hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767 +banff MACH_BANFF BANFF 768 carmeva MACH_CARMEVA CARMEVA 769 +sam255 MACH_SAM255 SAM255 770 +ppm10 MACH_PPM10 PPM10 771 edb9315a MACH_EDB9315A EDB9315A 772 +sunset MACH_SUNSET SUNSET 773 stargate2 MACH_STARGATE2 STARGATE2 774 intelmote2 MACH_INTELMOTE2 INTELMOTE2 775 trizeps4 MACH_TRIZEPS4 TRIZEPS4 776 +mainstone2 MACH_MAINSTONE2 MAINSTONE2 777 +ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778 +tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779 +universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780 +hicoarm9 MACH_HICOARM9 HICOARM9 781 pnx4008 MACH_PNX4008 PNX4008 782 +kws6000 MACH_KWS6000 KWS6000 783 +portux920t MACH_PORTUX920T PORTUX920T 784 +ez_x5 MACH_EZ_X5 EZ_X5 785 +omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786 cpuat91 MACH_CPUAT91 CPUAT91 787 +rea9200 MACH_REA9200 REA9200 788 +acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789 +ixp425 MACH_IXP425 IXP425 790 +i30030ads MACH_I30030ADS I30030ADS 791 +perch MACH_PERCH PERCH 792 +eis05r1 MACH_EIS05R1 EIS05R1 793 +pepperpad MACH_PEPPERPAD PEPPERPAD 794 +sb3010 MACH_SB3010 SB3010 795 +rm9200 MACH_RM9200 RM9200 796 +dma03 MACH_DMA03 DMA03 797 +road_s101 MACH_ROAD_S101 ROAD_S101 798 iq81340sc MACH_IQ81340SC IQ81340SC 799 +iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800 iq81340mc MACH_IQ81340MC IQ81340MC 801 +iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802 +iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803 +mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804 +cybertracker_i MACH_CYBERTRACKER_I CYBERTRACKER_I 805 +gesbc931x MACH_GESBC931X GESBC931X 806 +centipad MACH_CENTIPAD CENTIPAD 807 +armsoc MACH_ARMSOC ARMSOC 808 +se4200 MACH_SE4200 SE4200 809 +ems197a MACH_EMS197A EMS197A 810 micro9 MACH_MICRO9 MICRO9 811 micro9l MACH_MICRO9L MICRO9L 812 +uc5471dsp MACH_UC5471DSP UC5471DSP 813 +sj5471eng MACH_SJ5471ENG SJ5471ENG 814 +none MACH_CMPXA26X CMPXA26X 815 +nc1 MACH_NC NC 816 omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817 +ajax52x MACH_AJAX52X AJAX52X 818 +siriustar MACH_SIRIUSTAR SIRIUSTAR 819 +iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820 +at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821 +biosafe MACH_BIOSAFE BIOSAFE 822 +mp1000 MACH_MP1000 MP1000 823 +parsy MACH_PARSY PARSY 824 +ccxp270 MACH_CCXP CCXP 825 +omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826 realview_eb MACH_REALVIEW_EB REALVIEW_EB 827 +samoa MACH_SAMOA SAMOA 828 +palmt3 MACH_PALMT3 PALMT3 829 +i878 MACH_I878 I878 830 borzoi MACH_BORZOI BORZOI 831 +gecko MACH_GECKO GECKO 832 +ds101 MACH_DS101 DS101 833 +omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834 palmld MACH_PALMLD PALMLD 835 +cc9c MACH_CC9C CC9C 836 +sbc1670 MACH_SBC1670 SBC1670 837 ixdp28x5 MACH_IXDP28X5 IXDP28X5 838 omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839 +ml696k MACH_ML696K ML696K 840 arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841 osiris MACH_OSIRIS OSIRIS 842 +maestro MACH_MAESTRO MAESTRO 843 palmte2 MACH_PALMTE2 PALMTE2 844 +ixbbm MACH_IXBBM IXBBM 845 mx27ads MACH_MX27ADS MX27ADS 846 +ax8004 MACH_AX8004 AX8004 847 at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848 loft MACH_LOFT LOFT 849 +magpie MACH_MAGPIE MAGPIE 850 mx21ads MACH_MX21ADS MX21ADS 851 +mb87m3400 MACH_MB87M3400 MB87M3400 852 +mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853 +davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854 +htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855 +tpad MACH_TPAD TPAD 856 +roverp3 MACH_ROVERP3 ROVERP3 857 +jornada928 MACH_JORNADA928 JORNADA928 858 +mv88fxx81 MACH_MV88FXX81 MV88FXX81 859 +stmp36xx MACH_STMP36XX STMP36XX 860 +sxni79524 MACH_SXNI79524 SXNI79524 861 ams_delta MACH_AMS_DELTA AMS_DELTA 862 +uranium MACH_URANIUM URANIUM 863 +ucon MACH_UCON UCON 864 nas100d MACH_NAS100D NAS100D 865 +l083 MACH_L083_1000 L083_1000 866 +ezx MACH_EZX EZX 867 +pnx5220 MACH_PNX5220 PNX5220 868 +butte MACH_BUTTE BUTTE 869 +srm2 MACH_SRM2 SRM2 870 +dsbr MACH_DSBR DSBR 871 +crystalball MACH_CRYSTALBALL CRYSTALBALL 872 +tinypxa27x MACH_TINYPXA27X TINYPXA27X 873 +herbie MACH_HERBIE HERBIE 874 magician MACH_MAGICIAN MAGICIAN 875 +cm4002 MACH_CM4002 CM4002 876 +b4 MACH_B4 B4 877 +maui MACH_MAUI MAUI 878 +cybertracker_g MACH_CYBERTRACKER_G CYBERTRACKER_G 879 nxdkn MACH_NXDKN NXDKN 880 +mio8390 MACH_MIO8390 MIO8390 881 +omi_board MACH_OMI_BOARD OMI_BOARD 882 +mx21civ MACH_MX21CIV MX21CIV 883 +mahi_cdac MACH_MAHI_CDAC MAHI_CDAC 884 palmtx MACH_PALMTX PALMTX 885 s3c2413 MACH_S3C2413 S3C2413 887 +samsys_ep0 MACH_SAMSYS_EP0 SAMSYS_EP0 888 +wg302v1 MACH_WG302V1 WG302V1 889 wg302v2 MACH_WG302V2 WG302V2 890 +eb42x MACH_EB42X EB42X 891 +iq331es MACH_IQ331ES IQ331ES 892 +cosydsp MACH_COSYDSP COSYDSP 893 +uplat7d_proto MACH_UPLAT7D UPLAT7D 894 +ptdavinci MACH_PTDAVINCI PTDAVINCI 895 +mbus MACH_MBUS MBUS 896 +nadia2vb MACH_NADIA2VB NADIA2VB 897 +r1000 MACH_R1000 R1000 898 +hw90250 MACH_HW90250 HW90250 899 omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900 davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901 +omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902 +olocreek MACH_OLOCREEK OLOCREEK 903 palmz72 MACH_PALMZ72 PALMZ72 904 nxdb500 MACH_NXDB500 NXDB500 905 apf9328 MACH_APF9328 APF9328 906 +omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907 +omap_twip MACH_OMAP_TWIP OMAP_TWIP 908 +treo650 MACH_TREO650 TREO650 909 +acumen MACH_ACUMEN ACUMEN 910 +xp100 MACH_XP100 XP100 911 +fs2410 MACH_FS2410 FS2410 912 +pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913 +sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914 +bsemserver MACH_BSEMSERVER BSEMSERVER 915 +netclient MACH_NETCLIENT NETCLIENT 916 palmt5 MACH_PALMT5 PALMT5 917 palmtc MACH_PALMTC PALMTC 918 omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 +mxc30030evb MACH_MXC30030EVB MXC30030EVB 920 +rea_cpu2 MACH_REA_2D REA_2D 921 +eti3e524 MACH_TI3E524 TI3E524 922 ateb9200 MACH_ATEB9200 ATEB9200 923 +auckland MACH_AUCKLAND AUCKLAND 924 +ak3220m MACH_AK3320M AK3320M 925 +duramax MACH_DURAMAX DURAMAX 926 n35 MACH_N35 N35 927 +pronghorn MACH_PRONGHORN PRONGHORN 928 +fundy MACH_FUNDY FUNDY 929 logicpd_pxa270 MACH_LOGICPD_PXA270 LOGICPD_PXA270 930 +cpu777 MACH_CPU777 CPU777 931 +simicon9201 MACH_SIMICON9201 SIMICON9201 932 +leap2_hpm MACH_LEAP2_HPM LEAP2_HPM 933 +cm922txa10 MACH_CM922TXA10 CM922TXA10 934 +sandgate MACH_PXA PXA 935 +sandgate2 MACH_SANDGATE2 SANDGATE2 936 +sandgate2g MACH_SANDGATE2G SANDGATE2G 937 +sandgate2p MACH_SANDGATE2P SANDGATE2P 938 +fred_jack MACH_FRED_JACK FRED_JACK 939 +ttg_color1 MACH_TTG_COLOR1 TTG_COLOR1 940 nxeb500hmi MACH_NXEB500HMI NXEB500HMI 941 +netdcu8 MACH_NETDCU8 NETDCU8 942 +ng_fvx538 MACH_NG_FVX538 NG_FVX538 944 +ng_fvs338 MACH_NG_FVS338 NG_FVS338 945 +pnx4103 MACH_PNX4103 PNX4103 946 +hesdb MACH_HESDB HESDB 947 +xsilo MACH_XSILO XSILO 948 espresso MACH_ESPRESSO ESPRESSO 949 +emlc MACH_EMLC EMLC 950 +sisteron MACH_SISTERON SISTERON 951 rx1950 MACH_RX1950 RX1950 952 +tsc_venus MACH_TSC_VENUS TSC_VENUS 953 +ds101j MACH_DS101J DS101J 954 +mxc30030ads MACH_MXC30030ADS MXC30030ADS 955 +fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956 +dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957 gesbc9312 MACH_GESBC9312 GESBC9312 958 +htcapache MACH_HTCAPACHE HTCAPACHE 959 +ixdp435 MACH_IXDP435 IXDP435 960 +catprovt100 MACH_CATPROVT100 CATPROVT100 961 +picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962 picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963 dsmg600 MACH_DSMG600 DSMG600 964 +empc2 MACH_EMPC2 EMPC2 965 +ventura MACH_VENTURA VENTURA 966 +phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967 +ij3k MACH_IJ3K IJ3K 968 +pisgah MACH_PISGAH PISGAH 969 omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970 +sg720 MACH_SG720 SG720 971 +redfox MACH_REDFOX REDFOX 972 +mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973 +tpf106 MACH_TPF106 TPF106 974 +at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975 +rcmt2 MACH_SLEDB SLEDB 976 +ontrack MACH_ONTRACK ONTRACK 977 +pm1200 MACH_PM1200 PM1200 978 +ess24562 MACH_ESS24XXX ESS24XXX 979 +coremp7 MACH_COREMP7 COREMP7 980 +nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981 +stvc8380 MACH_STVC8380 STVC8380 982 +teklynx MACH_TEKLYNX TEKLYNX 983 +carbonado MACH_CARBONADO CARBONADO 984 +sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985 snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986 +pgigim MACH_PGIGIM PGIGIM 987 +ptx9160p2 MACH_PTX9160P2 PTX9160P2 988 +dcore1 MACH_DCORE1 DCORE1 989 +victorpxa MACH_VICTORPXA VICTORPXA 990 +mx2dtb MACH_MX2DTB MX2DTB 991 +pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992 omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993 +bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994 +hw50251 MACH_HW50251 HW50251 995 +ibox MACH_IBOX IBOX 996 +atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997 +pt2026 MACH_PT2026 PT2026 998 +htcalpine MACH_HTCALPINE HTCALPINE 999 +bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000 +vcoreii MACH_VCOREII VCOREII 1001 +pdnb3 MACH_PDNB3 PDNB3 1002 +htcbeetles MACH_HTCBEETLES HTCBEETLES 1003 +s3c6400 MACH_S3C6400 S3C6400 1004 +s3c2443 MACH_S3C2443 S3C2443 1005 +omap_ldk MACH_OMAP_LDK OMAP_LDK 1006 +smdk2460 MACH_SMDK2460 SMDK2460 1007 +smdk2440 MACH_SMDK2440 SMDK2440 1008 smdk2412 MACH_SMDK2412 SMDK2412 1009 +webbox MACH_WEBBOX WEBBOX 1010 +cwwndp MACH_CWWNDP CWWNDP 1011 +i839 MACH_DRAGON DRAGON 1012 +opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013 +ccm2200 MACH_CCM2200 CCM2200 1014 +etwarm MACH_ETWARM ETWARM 1015 +m93030 MACH_M93030 M93030 1016 +cc7u MACH_CC7U CC7U 1017 +mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018 +nexus MACH_NEXUS NEXUS 1019 +desman MACH_DESMAN DESMAN 1020 +bkde303 MACH_BKDE303 BKDE303 1021 smdk2413 MACH_SMDK2413 SMDK2413 1022 +aml_m7200 MACH_AML_M7200 AML_M7200 1023 aml_m5900 MACH_AML_M5900 AML_M5900 1024 +sg640 MACH_SG640 SG640 1025 +edg79524 MACH_EDG79524 EDG79524 1026 +ai2410 MACH_AI2410 AI2410 1027 +ixp465 MACH_IXP465 IXP465 1028 balloon3 MACH_BALLOON3 BALLOON3 1029 +heins MACH_HEINS HEINS 1030 +mpluseva MACH_MPLUSEVA MPLUSEVA 1031 +rt042 MACH_RT042 RT042 1032 +cwiem MACH_CWIEM CWIEM 1033 +cm_x270 MACH_CM_X270 CM_X270 1034 +cm_x255 MACH_CM_X255 CM_X255 1035 +esh_at91 MACH_ESH_AT91 ESH_AT91 1036 +sandgate3 MACH_SANDGATE3 SANDGATE3 1037 +primo MACH_PRIMO PRIMO 1038 +gemstone MACH_GEMSTONE GEMSTONE 1039 +pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040 +sidewinder MACH_SIDEWINDER SIDEWINDER 1041 +picomod1 MACH_PICOMOD1 PICOMOD1 1042 +sg590 MACH_SG590 SG590 1043 +akai9307 MACH_AKAI9307 AKAI9307 1044 +fontaine MACH_FONTAINE FONTAINE 1045 +wombat MACH_WOMBAT WOMBAT 1046 +acq300 MACH_ACQ300 ACQ300 1047 +mod272 MACH_MOD_270 MOD_270 1048 +vmc_vc0820 MACH_VC0820 VC0820 1049 +ani_aim MACH_ANI_AIM ANI_AIM 1050 +jellyfish MACH_JELLYFISH JELLYFISH 1051 +amanita MACH_AMANITA AMANITA 1052 +vlink MACH_VLINK VLINK 1053 +dexflex MACH_DEXFLEX DEXFLEX 1054 +eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055 +arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056 +tabla MACH_TABLA TABLA 1057 +mdirac3 MACH_MDIRAC3 MDIRAC3 1058 +mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059 +at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060 +ani_apm MACH_ANI_APM ANI_APM 1061 +ella1 MACH_ELLA1 ELLA1 1062 +inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063 +inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064 +empos_xm MACH_EMPOS_XM EMPOS_XM 1065 +empos MACH_EMPOS EMPOS 1066 +empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067 +empos_sm MACH_EMPOS_SM EMPOS_SM 1068 +egret MACH_EGRET EGRET 1069 +ostrich MACH_OSTRICH OSTRICH 1070 +n50 MACH_N50 N50 1071 ecbat91 MACH_ECBAT91 ECBAT91 1072 +stareast MACH_STAREAST STAREAST 1073 +dspg_dw MACH_DSPG_DW DSPG_DW 1074 onearm MACH_ONEARM ONEARM 1075 +mrg110_6 MACH_MRG110_6 MRG110_6 1076 +wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077 +xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078 +msm6100 MACH_MSM6100 MSM6100 1079 +eti_b1 MACH_ETI_B1 ETI_B1 1080 +za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081 +bit2440 MACH_BIT2440 BIT2440 1082 +nbi MACH_NBI NBI 1083 smdk2443 MACH_SMDK2443 SMDK2443 1084 +vdavinci MACH_VDAVINCI VDAVINCI 1085 +atc6 MACH_ATC6 ATC6 1086 +multmdw MACH_MULTMDW MULTMDW 1087 +mba2440 MACH_MBA2440 MBA2440 1088 +ecsd MACH_ECSD ECSD 1089 +palmz31 MACH_PALMZ31 PALMZ31 1090 fsg MACH_FSG FSG 1091 +razor101 MACH_RAZOR101 RAZOR101 1092 +opera_tdm MACH_OPERA_TDM OPERA_TDM 1093 +comcerto MACH_COMCERTO COMCERTO 1094 +tb0319 MACH_TB0319 TB0319 1095 +kws8000 MACH_KWS8000 KWS8000 1096 +b2 MACH_B2 B2 1097 +lcl54 MACH_LCL54 LCL54 1098 at91sam9260ek MACH_AT91SAM9260EK AT91SAM9260EK 1099 glantank MACH_GLANTANK GLANTANK 1100 n2100 MACH_N2100 N2100 1101 +n4100 MACH_N4100 N4100 1102 +rsc4 MACH_VERTICAL_RSC4 VERTICAL_RSC4 1103 +sg8100 MACH_SG8100 SG8100 1104 +im42xx MACH_IM42XX IM42XX 1105 +ftxx MACH_FTXX FTXX 1106 +lwfusion MACH_LWFUSION LWFUSION 1107 qt2410 MACH_QT2410 QT2410 1108 kixrp435 MACH_KIXRP435 KIXRP435 1109 +ccw9c MACH_CCW9C CCW9C 1110 +dabhs MACH_DABHS DABHS 1111 +gzmx MACH_GZMX GZMX 1112 +ipnw100ap MACH_IPNW100AP IPNW100AP 1113 cc9p9360dev MACH_CC9P9360DEV CC9P9360DEV 1114 +cc9p9750dev MACH_CC9P9750DEV CC9P9750DEV 1115 +cc9p9360val MACH_CC9P9360VAL CC9P9360VAL 1116 +cc9p9750val MACH_CC9P9750VAL CC9P9750VAL 1117 +nx70v MACH_NX70V NX70V 1118 +at91rm9200df MACH_AT91RM9200DF AT91RM9200DF 1119 +se_pilot2 MACH_SE_PILOT2 SE_PILOT2 1120 +mtcn_t800 MACH_MTCN_T800 MTCN_T800 1121 +vcmx212 MACH_VCMX212 VCMX212 1122 +lynx MACH_LYNX LYNX 1123 +at91sam9260id MACH_AT91SAM9260ID AT91SAM9260ID 1124 +hw86052 MACH_HW86052 HW86052 1125 +pilz_pmi3 MACH_PILZ_PMI3 PILZ_PMI3 1126 edb9302a MACH_EDB9302A EDB9302A 1127 edb9307a MACH_EDB9307A EDB9307A 1128 +ct_dfs MACH_CT_DFS CT_DFS 1129 +pilz_pmi4 MACH_PILZ_PMI4 PILZ_PMI4 1130 +xceednp_ixp MACH_XCEEDNP_IXP XCEEDNP_IXP 1131 +smdk2442b MACH_SMDK2442B SMDK2442B 1132 +xnode MACH_XNODE XNODE 1133 +aidx270 MACH_AIDX270 AIDX270 1134 +rema MACH_REMA REMA 1135 +bps1000 MACH_BPS1000 BPS1000 1136 +hw90350 MACH_HW90350 HW90350 1137 omap_3430sdp MACH_OMAP_3430SDP OMAP_3430SDP 1138 +bluetouch MACH_BLUETOUCH BLUETOUCH 1139 vstms MACH_VSTMS VSTMS 1140 +xsbase270 MACH_XSBASE270 XSBASE270 1141 +at91sam9260ek_cn MACH_AT91SAM9260EK_CN AT91SAM9260EK_CN 1142 +adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143 +oti4110 MACH_OTI4110 OTI4110 1144 +hme_pxa MACH_HME_PXA HME_PXA 1145 +deisterdca MACH_DEISTERDCA DEISTERDCA 1146 +ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147 +ces_mtr MACH_CES_MTR CES_MTR 1148 +tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149 +everest MACH_EVEREST EVEREST 1150 +pnx4010 MACH_PNX4010 PNX4010 1151 +oxnas MACH_OXNAS OXNAS 1152 +fiori MACH_FIORI FIORI 1153 +ml1200 MACH_ML1200 ML1200 1154 +pecos MACH_PECOS PECOS 1155 +nb2xxx MACH_NB2XXX NB2XXX 1156 +hw6900 MACH_HW6900 HW6900 1157 +cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158 +quicksilver MACH_QUICKSILVER QUICKSILVER 1159 +uplat926 MACH_UPLAT926 UPLAT926 1160 +dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161 +dtk2410 MACH_DTK2410 DTK2410 1162 +chili MACH_CHILI CHILI 1163 +demeter MACH_DEMETER DEMETER 1164 +dionysus MACH_DIONYSUS DIONYSUS 1165 +as352x MACH_AS352X AS352X 1166 +service MACH_SERVICE SERVICE 1167 +cs_e9301 MACH_CS_E9301 CS_E9301 1168 micro9m MACH_MICRO9M MICRO9M 1169 +ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170 +ql201b MACH_QL201B QL201B 1171 +bbm MACH_BBM BBM 1174 +exxx MACH_EXXX EXXX 1175 +wma11b MACH_WMA11B WMA11B 1176 +pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177 +g500 MACH_G500 G500 1178 bug MACH_BUG BUG 1179 +mx33ads MACH_MX33ADS MX33ADS 1180 +chub MACH_CHUB CHUB 1181 +neo1973_gta01 MACH_NEO1973_GTA01 NEO1973_GTA01 1182 +w90n740 MACH_W90N740 W90N740 1183 +medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184 +ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185 +dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186 +pm9261 MACH_PM9261 PM9261 1187 +ml7304 MACH_ML7304 ML7304 1189 +ucp250 MACH_UCP250 UCP250 1190 +intboard MACH_INTBOARD INTBOARD 1191 +gulfstream MACH_GULFSTREAM GULFSTREAM 1192 +labquest MACH_LABQUEST LABQUEST 1193 +vcmx313 MACH_VCMX313 VCMX313 1194 +urg200 MACH_URG200 URG200 1195 +cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196 +netdcu9 MACH_NETDCU9 NETDCU9 1197 +netdcu10 MACH_NETDCU10 NETDCU10 1198 +dspg_dga MACH_DSPG_DGA DSPG_DGA 1199 +dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200 +solos MACH_SOLOS SOLOS 1201 at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202 +osstbox MACH_OSSTBOX OSSTBOX 1203 +kbat9261 MACH_KBAT9261 KBAT9261 1204 +ct1100 MACH_CT1100 CT1100 1205 +akcppxa MACH_AKCPPXA AKCPPXA 1206 +ochaya1020 MACH_OCHAYA1020 OCHAYA1020 1207 +hitrack MACH_HITRACK HITRACK 1208 +syme1 MACH_SYME1 SYME1 1209 +syhl1 MACH_SYHL1 SYHL1 1210 +empca400 MACH_EMPCA400 EMPCA400 1211 em7210 MACH_EM7210 EM7210 1212 +htchermes MACH_HTCHERMES HTCHERMES 1213 +eti_c1 MACH_ETI_C1 ETI_C1 1214 +ac100 MACH_AC100 AC100 1216 +sneetch MACH_SNEETCH SNEETCH 1217 +studentmate MACH_STUDENTMATE STUDENTMATE 1218 +zir2410 MACH_ZIR2410 ZIR2410 1219 +zir2413 MACH_ZIR2413 ZIR2413 1220 +dlonip3 MACH_DLONIP3 DLONIP3 1221 +instream MACH_INSTREAM INSTREAM 1222 +ambarella MACH_AMBARELLA AMBARELLA 1223 +nevis MACH_NEVIS NEVIS 1224 +htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225 +ql202b MACH_QL202B QL202B 1226 vpac270 MACH_VPAC270 VPAC270 1227 +rd129 MACH_RD129 RD129 1228 +htcwizard MACH_HTCWIZARD HTCWIZARD 1229 treo680 MACH_TREO680 TREO680 1230 +tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231 zylonite MACH_ZYLONITE ZYLONITE 1233 +gene1270 MACH_GENE1270 GENE1270 1234 +zir2412 MACH_ZIR2412 ZIR2412 1235 mx31lite MACH_MX31LITE MX31LITE 1236 +t700wx MACH_T700WX T700WX 1237 +vf100 MACH_VF100 VF100 1238 +nsb2 MACH_NSB2 NSB2 1239 +nxhmi_bb MACH_NXHMI_BB NXHMI_BB 1240 +nxhmi_re MACH_NXHMI_RE NXHMI_RE 1241 +n4100pro MACH_N4100PRO N4100PRO 1242 +sam9260 MACH_SAM9260 SAM9260 1243 +omap_treo600 MACH_OMAP_TREO600 OMAP_TREO600 1244 +indy2410 MACH_INDY2410 INDY2410 1245 +nelt_a MACH_NELT_A NELT_A 1246 +n311 MACH_N311 N311 1248 +at91sam9260vgk MACH_AT91SAM9260VGK AT91SAM9260VGK 1249 +at91leppe MACH_AT91LEPPE AT91LEPPE 1250 +at91lepccn MACH_AT91LEPCCN AT91LEPCCN 1251 +apc7100 MACH_APC7100 APC7100 1252 +stargazer MACH_STARGAZER STARGAZER 1253 +sonata MACH_SONATA SONATA 1254 +schmoogie MACH_SCHMOOGIE SCHMOOGIE 1255 +aztool MACH_AZTOOL AZTOOL 1256 mioa701 MACH_MIOA701 MIOA701 1257 +sxni9260 MACH_SXNI9260 SXNI9260 1258 +mxc27520evb MACH_MXC27520EVB MXC27520EVB 1259 armadillo5x0 MACH_ARMADILLO5X0 ARMADILLO5X0 1260 +mb9260 MACH_MB9260 MB9260 1261 +mb9263 MACH_MB9263 MB9263 1262 +ipac9302 MACH_IPAC9302 IPAC9302 1263 cc9p9360js MACH_CC9P9360JS CC9P9360JS 1264 +gallium MACH_GALLIUM GALLIUM 1265 +msc2410 MACH_MSC2410 MSC2410 1266 +ghi270 MACH_GHI270 GHI270 1267 +davinci_leonardo MACH_DAVINCI_LEONARDO DAVINCI_LEONARDO 1268 +oiab MACH_OIAB OIAB 1269 smdk6400 MACH_SMDK6400 SMDK6400 1270 nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271 +greenphone MACH_GREENPHONE GREENPHONE 1272 +compex42x MACH_COMPEXWP18 COMPEXWP18 1273 +xmate MACH_XMATE XMATE 1274 +energizer MACH_ENERGIZER ENERGIZER 1275 +ime1 MACH_IME1 IME1 1276 +sweda_tms MACH_SWEDATMS SWEDATMS 1277 +ntnp435c MACH_NTNP435C NTNP435C 1278 +spectro2 MACH_SPECTRO2 SPECTRO2 1279 +h6039 MACH_H6039 H6039 1280 ep80219 MACH_EP80219 EP80219 1281 +samoa_ii MACH_SAMOA_II SAMOA_II 1282 +cwmxl MACH_CWMXL CWMXL 1283 +as9200 MACH_AS9200 AS9200 1284 +sfx1149 MACH_SFX1149 SFX1149 1285 +navi010 MACH_NAVI010 NAVI010 1286 +multmdp MACH_MULTMDP MULTMDP 1287 +scb9520 MACH_SCB9520 SCB9520 1288 +htcathena MACH_HTCATHENA HTCATHENA 1289 +xp179 MACH_XP179 XP179 1290 +h4300 MACH_H4300 H4300 1291 goramo_mlr MACH_GORAMO_MLR GORAMO_MLR 1292 +mxc30020evb MACH_MXC30020EVB MXC30020EVB 1293 +adsbitsyg5 MACH_ADSBITSYG5 ADSBITSYG5 1294 +adsportalplus MACH_ADSPORTALPLUS ADSPORTALPLUS 1295 +mmsp2plus MACH_MMSP2PLUS MMSP2PLUS 1296 em_x270 MACH_EM_X270 EM_X270 1297 +tpp302 MACH_TPP302 TPP302 1298 +tpp104 MACH_TPM104 TPM104 1299 +tpm102 MACH_TPM102 TPM102 1300 +tpm109 MACH_TPM109 TPM109 1301 +fbxo1 MACH_FBXO1 FBXO1 1302 +hxd8 MACH_HXD8 HXD8 1303 neo1973_gta02 MACH_NEO1973_GTA02 NEO1973_GTA02 1304 +emtest MACH_EMTEST EMTEST 1305 +ad6900 MACH_AD6900 AD6900 1306 +europa MACH_EUROPA EUROPA 1307 +metroconnect MACH_METROCONNECT METROCONNECT 1308 +ez_s2410 MACH_EZ_S2410 EZ_S2410 1309 +ez_s2440 MACH_EZ_S2440 EZ_S2440 1310 +ez_ep9312 MACH_EZ_EP9312 EZ_EP9312 1311 +ez_ep9315 MACH_EZ_EP9315 EZ_EP9315 1312 +ez_x7 MACH_EZ_X7 EZ_X7 1313 +godotdb MACH_GODOTDB GODOTDB 1314 +mistral MACH_MISTRAL MISTRAL 1315 +msm MACH_MSM MSM 1316 +ct5910 MACH_CT5910 CT5910 1317 +ct5912 MACH_CT5912 CT5912 1318 +argonst_mp MACH_HYNET_INE HYNET_INE 1319 +hynet_app MACH_HYNET_APP HYNET_APP 1320 +msm7200 MACH_MSM7200 MSM7200 1321 +msm7600 MACH_MSM7600 MSM7600 1322 +ceb255 MACH_CEB255 CEB255 1323 +ciel MACH_CIEL CIEL 1324 +slm5650 MACH_SLM5650 SLM5650 1325 at91sam9rlek MACH_AT91SAM9RLEK AT91SAM9RLEK 1326 +comtech_router MACH_COMTECH_ROUTER COMTECH_ROUTER 1327 +sbc2410x MACH_SBC2410X SBC2410X 1328 +at4x0bd MACH_AT4X0BD AT4X0BD 1329 +cbifr MACH_CBIFR CBIFR 1330 +arcom_quantum MACH_ARCOM_QUANTUM ARCOM_QUANTUM 1331 +matrix520 MACH_MATRIX520 MATRIX520 1332 +matrix510 MACH_MATRIX510 MATRIX510 1333 +matrix500 MACH_MATRIX500 MATRIX500 1334 +m501 MACH_M501 M501 1335 +aaeon1270 MACH_AAEON1270 AAEON1270 1336 +matrix500ev MACH_MATRIX500EV MATRIX500EV 1337 +pac500 MACH_PAC500 PAC500 1338 +pnx8181 MACH_PNX8181 PNX8181 1339 colibri320 MACH_COLIBRI320 COLIBRI320 1340 +aztoolbb MACH_AZTOOLBB AZTOOLBB 1341 +aztoolg2 MACH_AZTOOLG2 AZTOOLG2 1342 +dvlhost MACH_DVLHOST DVLHOST 1343 +zir9200 MACH_ZIR9200 ZIR9200 1344 +zir9260 MACH_ZIR9260 ZIR9260 1345 +cocopah MACH_COCOPAH COCOPAH 1346 +nds MACH_NDS NDS 1347 +rosencrantz MACH_ROSENCRANTZ ROSENCRANTZ 1348 +fttx_odsc MACH_FTTX_ODSC FTTX_ODSC 1349 +classe_r6904 MACH_CLASSE_R6904 CLASSE_R6904 1350 cam60 MACH_CAM60 CAM60 1351 +mxc30031ads MACH_MXC30031ADS MXC30031ADS 1352 +datacall MACH_DATACALL DATACALL 1353 at91eb01 MACH_AT91EB01 AT91EB01 1354 +rty MACH_RTY RTY 1355 +dwl2100 MACH_DWL2100 DWL2100 1356 +vinsi MACH_VINSI VINSI 1357 db88f5281 MACH_DB88F5281 DB88F5281 1358 csb726 MACH_CSB726 CSB726 1359 +tik27 MACH_TIK27 TIK27 1360 +mx_uc7420 MACH_MX_UC7420 MX_UC7420 1361 +rirm3 MACH_RIRM3 RIRM3 1362 +pelco_odyssey MACH_PELCO_ODYSSEY PELCO_ODYSSEY 1363 +adx_abox MACH_ADX_ABOX ADX_ABOX 1365 +adx_tpid MACH_ADX_TPID ADX_TPID 1366 +minicheck MACH_MINICHECK MINICHECK 1367 +idam MACH_IDAM IDAM 1368 +mario_mx MACH_MARIO_MX MARIO_MX 1369 +vi1888 MACH_VI1888 VI1888 1370 +zr4230 MACH_ZR4230 ZR4230 1371 +t1_ix_blue MACH_T1_IX_BLUE T1_IX_BLUE 1372 +syhq2 MACH_SYHQ2 SYHQ2 1373 +computime_r3 MACH_COMPUTIME_R3 COMPUTIME_R3 1374 +oratis MACH_ORATIS ORATIS 1375 +mikko MACH_MIKKO MIKKO 1376 +holon MACH_HOLON HOLON 1377 +olip8 MACH_OLIP8 OLIP8 1378 +ghi270hg MACH_GHI270HG GHI270HG 1379 davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380 davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381 +blackriver MACH_BLACKRIVER BLACKRIVER 1383 +sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384 +cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385 +quark963 MACH_QUARK963 QUARK963 1386 +csb735 MACH_CSB735 CSB735 1387 littleton MACH_LITTLETON LITTLETON 1388 +mio_p550 MACH_MIO_P550 MIO_P550 1389 +motion2440 MACH_MOTION2440 MOTION2440 1390 +imm500 MACH_IMM500 IMM500 1391 +homematic MACH_HOMEMATIC HOMEMATIC 1392 +ermine MACH_ERMINE ERMINE 1393 +kb9202b MACH_KB9202B KB9202B 1394 +hs1xx MACH_HS1XX HS1XX 1395 +studentmate2440 MACH_STUDENTMATE2440 STUDENTMATE2440 1396 +arvoo_l1_z1 MACH_ARVOO_L1_Z1 ARVOO_L1_Z1 1397 +dep2410k MACH_DEP2410K DEP2410K 1398 +xxsvideo MACH_XXSVIDEO XXSVIDEO 1399 +im4004 MACH_IM4004 IM4004 1400 +ochaya1050 MACH_OCHAYA1050 OCHAYA1050 1401 +lep9261 MACH_LEP9261 LEP9261 1402 +svenmeb MACH_SVENMEB SVENMEB 1403 +fortunet2ne MACH_FORTUNET2NE FORTUNET2NE 1404 +nxhx MACH_NXHX NXHX 1406 realview_pb11mp MACH_REALVIEW_PB11MP REALVIEW_PB11MP 1407 +ids500 MACH_IDS500 IDS500 1408 +ors_n725 MACH_ORS_N725 ORS_N725 1409 +hsdarm MACH_HSDARM HSDARM 1410 +sha_pon003 MACH_SHA_PON003 SHA_PON003 1411 +sha_pon004 MACH_SHA_PON004 SHA_PON004 1412 +sha_pon007 MACH_SHA_PON007 SHA_PON007 1413 +sha_pon011 MACH_SHA_PON011 SHA_PON011 1414 +h6042 MACH_H6042 H6042 1415 +h6043 MACH_H6043 H6043 1416 +looxc550 MACH_LOOXC550 LOOXC550 1417 +cnty_titan MACH_CNTY_TITAN CNTY_TITAN 1418 +app3xx MACH_APP3XX APP3XX 1419 +sideoatsgrama MACH_SIDEOATSGRAMA SIDEOATSGRAMA 1420 +treo700p MACH_TREO700P TREO700P 1421 +treo700w MACH_TREO700W TREO700W 1422 +treo750 MACH_TREO750 TREO750 1423 +treo755p MACH_TREO755P TREO755P 1424 +ezreganut9200 MACH_EZREGANUT9200 EZREGANUT9200 1425 +sarge MACH_SARGE SARGE 1426 +a696 MACH_A696 A696 1427 +turtle1916 MACH_TURTLE TURTLE 1428 mx27_3ds MACH_MX27_3DS MX27_3DS 1430 +bishop MACH_BISHOP BISHOP 1431 +pxx MACH_PXX PXX 1432 +redwood MACH_REDWOOD REDWOOD 1433 +omap_2430dlp MACH_OMAP_2430DLP OMAP_2430DLP 1436 +omap_2430osk MACH_OMAP_2430OSK OMAP_2430OSK 1437 +sardine MACH_SARDINE SARDINE 1438 halibut MACH_HALIBUT HALIBUT 1439 trout MACH_TROUT TROUT 1440 +goldfish MACH_GOLDFISH GOLDFISH 1441 +gesbc2440 MACH_GESBC2440 GESBC2440 1442 +nomad MACH_NOMAD NOMAD 1443 +rosalind MACH_ROSALIND ROSALIND 1444 +cc9p9215 MACH_CC9P9215 CC9P9215 1445 +cc9p9210 MACH_CC9P9210 CC9P9210 1446 +cc9p9215js MACH_CC9P9215JS CC9P9215JS 1447 +cc9p9210js MACH_CC9P9210JS CC9P9210JS 1448 +nasffe MACH_NASFFE NASFFE 1449 +tn2x0bd MACH_TN2X0BD TN2X0BD 1450 +gwmpxa MACH_GWMPXA GWMPXA 1451 +exyplus MACH_EXYPLUS EXYPLUS 1452 +jadoo21 MACH_JADOO21 JADOO21 1453 +looxn560 MACH_LOOXN560 LOOXN560 1454 +bonsai MACH_BONSAI BONSAI 1455 +adsmilgato MACH_ADSMILGATO ADSMILGATO 1456 +gba MACH_GBA GBA 1457 +h6044 MACH_H6044 H6044 1458 +app MACH_APP APP 1459 tct_hammer MACH_TCT_HAMMER TCT_HAMMER 1460 herald MACH_HERALD HERALD 1461 +artemis MACH_ARTEMIS ARTEMIS 1462 +htctitan MACH_HTCTITAN HTCTITAN 1463 +qranium MACH_QRANIUM QRANIUM 1464 +adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465 +adx_medcom MACH_ADX_MEDCOM ADX_MEDCOM 1466 +bboard MACH_BBOARD BBOARD 1467 +cambria MACH_CAMBRIA CAMBRIA 1468 +mt7xxx MACH_MT7XXX MT7XXX 1469 +matrix512 MACH_MATRIX512 MATRIX512 1470 +matrix522 MACH_MATRIX522 MATRIX522 1471 +ipac5010 MACH_IPAC5010 IPAC5010 1472 +sakura MACH_SAKURA SAKURA 1473 +grocx MACH_GROCX GROCX 1474 +pm9263 MACH_PM9263 PM9263 1475 sim_one MACH_SIM_ONE SIM_ONE 1476 +acq132 MACH_ACQ132 ACQ132 1477 +datr MACH_DATR DATR 1478 +actux1 MACH_ACTUX1 ACTUX1 1479 +actux2 MACH_ACTUX2 ACTUX2 1480 +actux3 MACH_ACTUX3 ACTUX3 1481 +flexit MACH_FLEXIT FLEXIT 1482 +bh2x0bd MACH_BH2X0BD BH2X0BD 1483 +atb2002 MACH_ATB2002 ATB2002 1484 +xenon MACH_XENON XENON 1485 +fm607 MACH_FM607 FM607 1486 +matrix514 MACH_MATRIX514 MATRIX514 1487 +matrix524 MACH_MATRIX524 MATRIX524 1488 +inpod MACH_INPOD INPOD 1489 jive MACH_JIVE JIVE 1490 +tll_mx21 MACH_TLL_MX21 TLL_MX21 1491 +sbc2800 MACH_SBC2800 SBC2800 1492 +cc7ucamry MACH_CC7UCAMRY CC7UCAMRY 1493 +ubisys_p9_sc15 MACH_UBISYS_P9_SC15 UBISYS_P9_SC15 1494 +ubisys_p9_ssc2d10 MACH_UBISYS_P9_SSC2D10 UBISYS_P9_SSC2D10 1495 +ubisys_p9_rcu3 MACH_UBISYS_P9_RCU3 UBISYS_P9_RCU3 1496 +aml_m8000 MACH_AML_M8000 AML_M8000 1497 +snapper_270 MACH_SNAPPER_270 SNAPPER_270 1498 +omap_bbx MACH_OMAP_BBX OMAP_BBX 1499 +ucn2410 MACH_UCN2410 UCN2410 1500 sam9_l9260 MACH_SAM9_L9260 SAM9_L9260 1501 +eti_c2 MACH_ETI_C2 ETI_C2 1502 +avalanche MACH_AVALANCHE AVALANCHE 1503 realview_pb1176 MACH_REALVIEW_PB1176 REALVIEW_PB1176 1504 +dp1500 MACH_DP1500 DP1500 1505 +apple_iphone MACH_APPLE_IPHONE APPLE_IPHONE 1506 yl9200 MACH_YL9200 YL9200 1507 rd88f5182 MACH_RD88F5182 RD88F5182 1508 kurobox_pro MACH_KUROBOX_PRO KUROBOX_PRO 1509 +se_poet MACH_SE_POET SE_POET 1510 mx31_3ds MACH_MX31_3DS MX31_3DS 1511 +r270 MACH_R270 R270 1512 +armour21 MACH_ARMOUR21 ARMOUR21 1513 +dt2 MACH_DT2 DT2 1514 +vt4 MACH_VT4 VT4 1515 +tyco320 MACH_TYCO320 TYCO320 1516 +adma MACH_ADMA ADMA 1517 +wp188 MACH_WP188 WP188 1518 +corsica MACH_CORSICA CORSICA 1519 +bigeye MACH_BIGEYE BIGEYE 1520 +tll5000 MACH_TLL5000 TLL5000 1522 +bebot MACH_BEBOT BEBOT 1523 qong MACH_QONG QONG 1524 +tcompact MACH_TCOMPACT TCOMPACT 1525 +puma5 MACH_PUMA5 PUMA5 1526 +elara MACH_ELARA ELARA 1527 +ellington MACH_ELLINGTON ELLINGTON 1528 +xda_atom MACH_XDA_ATOM XDA_ATOM 1529 +energizer2 MACH_ENERGIZER2 ENERGIZER2 1530 +odin MACH_ODIN ODIN 1531 +actux4 MACH_ACTUX4 ACTUX4 1532 +esl_omap MACH_ESL_OMAP ESL_OMAP 1533 omap2evm MACH_OMAP2EVM OMAP2EVM 1534 omap3evm MACH_OMAP3EVM OMAP3EVM 1535 +adx_pcu57 MACH_ADX_PCU57 ADX_PCU57 1536 +monaco MACH_MONACO MONACO 1537 +levante MACH_LEVANTE LEVANTE 1538 +tmxipx425 MACH_TMXIPX425 TMXIPX425 1539 +leep MACH_LEEP LEEP 1540 +raad MACH_RAAD RAAD 1541 dns323 MACH_DNS323 DNS323 1542 +ap1000 MACH_AP1000 AP1000 1543 +a9sam6432 MACH_A9SAM6432 A9SAM6432 1544 +shiny MACH_SHINY SHINY 1545 omap3_beagle MACH_OMAP3_BEAGLE OMAP3_BEAGLE 1546 +csr_bdb2 MACH_CSR_BDB2 CSR_BDB2 1547 nokia_n810 MACH_NOKIA_N810 NOKIA_N810 1548 +c270 MACH_C270 C270 1549 +sentry MACH_SENTRY SENTRY 1550 pcm038 MACH_PCM038 PCM038 1551 +anc300 MACH_ANC300 ANC300 1552 +htckaiser MACH_HTCKAISER HTCKAISER 1553 +sbat100 MACH_SBAT100 SBAT100 1554 +modunorm MACH_MODUNORM MODUNORM 1555 +pelos_twarm MACH_PELOS_TWARM PELOS_TWARM 1556 +flank MACH_FLANK FLANK 1557 +sirloin MACH_SIRLOIN SIRLOIN 1558 +brisket MACH_BRISKET BRISKET 1559 +chuck MACH_CHUCK CHUCK 1560 +otter MACH_OTTER OTTER 1561 +davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562 +phreedom MACH_PHREEDOM PHREEDOM 1563 +sg310 MACH_SG310 SG310 1564 ts209 MACH_TS209 TS209 1565 at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566 +tion9315 MACH_TION9315 TION9315 1567 +mast MACH_MAST MAST 1568 +pfw MACH_PFW PFW 1569 +yl_p2440 MACH_YL_P2440 YL_P2440 1570 +zsbc32 MACH_ZSBC32 ZSBC32 1571 +omap_pace2 MACH_OMAP_PACE2 OMAP_PACE2 1572 +imx_pace2 MACH_IMX_PACE2 IMX_PACE2 1573 mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574 +mx37_3ds MACH_MX37_3DS MX37_3DS 1575 +rcc MACH_RCC RCC 1576 +dmp MACH_ARM9 ARM9 1577 vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578 +scly1000 MACH_SCLY1000 SCLY1000 1579 +fontel_ep MACH_FONTEL_EP FONTEL_EP 1580 +voiceblue3g MACH_VOICEBLUE3G VOICEBLUE3G 1581 +tt9200 MACH_TT9200 TT9200 1582 +digi2410 MACH_DIGI2410 DIGI2410 1583 terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584 linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585 +motorola_a780 MACH_MOTOROLA_A780 MOTOROLA_A780 1587 +motorola_e6 MACH_MOTOROLA_E6 MOTOROLA_E6 1588 +motorola_e2 MACH_MOTOROLA_E2 MOTOROLA_E2 1589 +motorola_e680 MACH_MOTOROLA_E680 MOTOROLA_E680 1590 +ur2410 MACH_UR2410 UR2410 1591 +tas9261 MACH_TAS9261 TAS9261 1592 +davinci_hermes_hd MACH_HERMES_HD HERMES_HD 1593 +davinci_perseo_hd MACH_PERSEO_HD PERSEO_HD 1594 +stargazer2 MACH_STARGAZER2 STARGAZER2 1595 e350 MACH_E350 E350 1596 +wpcm450 MACH_WPCM450 WPCM450 1597 +cartesio MACH_CARTESIO CARTESIO 1598 +toybox MACH_TOYBOX TOYBOX 1599 +tx27 MACH_TX27 TX27 1600 ts409 MACH_TS409 TS409 1601 +p300 MACH_P300 P300 1602 +xdacomet MACH_XDACOMET XDACOMET 1603 +dexflex2 MACH_DEXFLEX2 DEXFLEX2 1604 +ow MACH_OW OW 1605 +armebs3 MACH_ARMEBS3 ARMEBS3 1606 +u3 MACH_U3 U3 1607 +smdk2450 MACH_SMDK2450 SMDK2450 1608 rsi_ews MACH_RSI_EWS RSI_EWS 1609 +tnb MACH_TNB TNB 1610 +toepath MACH_TOEPATH TOEPATH 1611 +kb9263 MACH_KB9263 KB9263 1612 +mt7108 MACH_MT7108 MT7108 1613 +smtr2440 MACH_SMTR2440 SMTR2440 1614 +manao MACH_MANAO MANAO 1615 cm_x300 MACH_CM_X300 CM_X300 1616 +gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617 +lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618 +arma37 MACH_ARMA37 ARMA37 1619 +mendel MACH_MENDEL MENDEL 1620 +pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621 +unit2p MACH_UNIT2P UNIT2P 1622 +inc20otter MACH_INC20OTTER INC20OTTER 1623 at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624 +sc_ge2 MACH_STORCENTER STORCENTER 1625 smdk6410 MACH_SMDK6410 SMDK6410 1626 u300 MACH_U300 U300 1627 +u500 MACH_U500 U500 1628 +ds9260 MACH_DS9260 DS9260 1629 +riverrock MACH_RIVERROCK RIVERROCK 1630 +scibath MACH_SCIBATH SCIBATH 1631 +at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632 wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633 +multimedia MACH_MULTIMEDIA MULTIMEDIA 1634 +marvin MACH_MARVIN MARVIN 1635 +x500 MACH_X500 X500 1636 +awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637 +palermoc MACH_PALERMOC PALERMOC 1638 omap_ldp MACH_OMAP_LDP OMAP_LDP 1639 +ip500 MACH_IP500 IP500 1640 +ase2 MACH_ASE2 ASE2 1642 +mx35evb MACH_MX35EVB MX35EVB 1643 +aml_m8050 MACH_AML_M8050 AML_M8050 1644 mx35_3ds MACH_MX35_3DS MX35_3DS 1645 +mars MACH_MARS MARS 1646 neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647 +badger MACH_BADGER BADGER 1648 trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649 +trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650 +marlin MACH_MARLIN MARLIN 1651 ts78xx MACH_TS78XX TS78XX 1652 +hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653 +at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654 +ne1board MACH_NE1BOARD NE1BOARD 1655 +zante MACH_ZANTE ZANTE 1656 sffsdr MACH_SFFSDR SFFSDR 1657 +tw2662 MACH_TW2662 TW2662 1658 +vf10xx MACH_VF10XX VF10XX 1659 +zoran43xx MACH_ZORAN43XX ZORAN43XX 1660 +sonix926 MACH_SONIX926 SONIX926 1661 +celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662 +cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663 +tw5334 MACH_TW5334 TW5334 1664 +omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665 +nal_hlite MACH_NAL_HLITE NAL_HLITE 1666 +htcvogue MACH_HTCVOGUE HTCVOGUE 1667 +smartweb MACH_SMARTWEB SMARTWEB 1668 +mv86xx MACH_MV86XX MV86XX 1669 +mv87xx MACH_MV87XX MV87XX 1670 +songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671 +younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672 pcm037 MACH_PCM037 PCM037 1673 +mmvp MACH_MMVP MMVP 1674 +mmap MACH_MMAP MMAP 1675 +ptid2410 MACH_PTID2410 PTID2410 1676 +james_926 MACH_JAMES_926 JAMES_926 1677 +fm6000 MACH_FM6000 FM6000 1678 db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680 rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681 rd88f6281 MACH_RD88F6281 RD88F6281 1682 db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683 smdk2416 MACH_SMDK2416 SMDK2416 1685 +oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686 +oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687 +rovern6 MACH_ROVERN6 ROVERN6 1688 +pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689 wbd111 MACH_WBD111 WBD111 1690 +elaracpe MACH_ELARACPE ELARACPE 1691 +mabv3 MACH_MABV3 MABV3 1692 mv2120 MACH_MV2120 MV2120 1693 +csb737 MACH_CSB737 CSB737 1695 mx51_3ds MACH_MX51_3DS MX51_3DS 1696 +g900 MACH_G900 G900 1697 +apf27 MACH_APF27 APF27 1698 +ggus2000 MACH_GGUS2000 GGUS2000 1699 +omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700 imx27lite MACH_IMX27LITE IMX27LITE 1701 +almex MACH_ALMEX ALMEX 1702 +control MACH_CONTROL CONTROL 1703 +mba2410 MACH_MBA2410 MBA2410 1704 +volcano MACH_VOLCANO VOLCANO 1705 +zenith MACH_ZENITH ZENITH 1706 +muchip MACH_MUCHIP MUCHIP 1707 +magellan MACH_MAGELLAN MAGELLAN 1708 usb_a9260 MACH_USB_A9260 USB_A9260 1709 usb_a9263 MACH_USB_A9263 USB_A9263 1710 qil_a9260 MACH_QIL_A9260 QIL_A9260 1711 +cme9210 MACH_CME9210 CME9210 1712 +hczh4 MACH_HCZH4 HCZH4 1713 +spearbasic MACH_SPEARBASIC SPEARBASIC 1714 +dep2440 MACH_DEP2440 DEP2440 1715 +hdl_gxr MACH_HDL_GXR HDL_GXR 1716 +hdl_gt MACH_HDL_GT HDL_GT 1717 +hdl_4g MACH_HDL_4G HDL_4G 1718 +s3c6000 MACH_S3C6000 S3C6000 1719 +mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720 +mpx220 MACH_MPX220 MPX220 1721 kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722 +htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723 +htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724 +lg_ks20 MACH_LG_KS20 LG_KS20 1725 +hhgps MACH_HHGPS HHGPS 1726 nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727 +insight MACH_INSIGHT INSIGHT 1728 sapphire MACH_SAPPHIRE SAPPHIRE 1729 +csb637xo MACH_CSB637XO CSB637XO 1730 +evisiong MACH_EVISIONG EVISIONG 1731 stmp37xx MACH_STMP37XX STMP37XX 1732 stmp378x MACH_STMP378X STMP378X 1733 +tnt MACH_TNT TNT 1734 +tbxt MACH_TBXT TBXT 1735 +playmate MACH_PLAYMATE PLAYMATE 1736 +pns10 MACH_PNS10 PNS10 1737 +eznavi MACH_EZNAVI EZNAVI 1738 +ps4000 MACH_PS4000 PS4000 1739 ezx_a780 MACH_EZX_A780 EZX_A780 1740 ezx_e680 MACH_EZX_E680 EZX_E680 1741 ezx_a1200 MACH_EZX_A1200 EZX_A1200 1742 ezx_e6 MACH_EZX_E6 EZX_E6 1743 ezx_e2 MACH_EZX_E2 EZX_E2 1744 ezx_a910 MACH_EZX_A910 EZX_A910 1745 +cwmx31 MACH_CWMX31 CWMX31 1746 +sl2312 MACH_SL2312 SL2312 1747 +blenny MACH_BLENNY BLENNY 1748 +ds107 MACH_DS107 DS107 1749 +dsx07 MACH_DSX07 DSX07 1750 +picocom1 MACH_PICOCOM1 PICOCOM1 1751 +lynx_wolverine MACH_LYNX_WOLVERINE LYNX_WOLVERINE 1752 +ubisys_p9_sc19 MACH_UBISYS_P9_SC19 UBISYS_P9_SC19 1753 +kratos_low MACH_KRATOS_LOW KRATOS_LOW 1754 +m700 MACH_M700 M700 1755 edmini_v2 MACH_EDMINI_V2 EDMINI_V2 1756 zipit2 MACH_ZIPIT2 ZIPIT2 1757 +hslfemtocell MACH_HSLFEMTOCELL HSLFEMTOCELL 1758 +daintree_at91 MACH_DAINTREE_AT91 DAINTREE_AT91 1759 +sg560usb MACH_SG560USB SG560USB 1760 omap3_pandora MACH_OMAP3_PANDORA OMAP3_PANDORA 1761 +usr8200 MACH_USR8200 USR8200 1762 +s1s65k MACH_S1S65K S1S65K 1763 +s2s65a MACH_S2S65A S2S65A 1764 +icore MACH_ICORE ICORE 1765 mss2 MACH_MSS2 MSS2 1766 +belmont MACH_BELMONT BELMONT 1767 +asusp525 MACH_ASUSP525 ASUSP525 1768 lb88rc8480 MACH_LB88RC8480 LB88RC8480 1769 +hipxa MACH_HIPXA HIPXA 1770 mx25_3ds MACH_MX25_3DS MX25_3DS 1771 +m800 MACH_M800 M800 1772 omap3530_lv_som MACH_OMAP3530_LV_SOM OMAP3530_LV_SOM 1773 +prima_evb MACH_PRIMA_EVB PRIMA_EVB 1774 +mx31bt1 MACH_MX31BT1 MX31BT1 1775 +atlas4_evb MACH_ATLAS4_EVB ATLAS4_EVB 1776 +mx31cicada MACH_MX31CICADA MX31CICADA 1777 +mi424wr MACH_MI424WR MI424WR 1778 +axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779 +at572d940deb MACH_AT572D940DEB AT572D940DEB 1780 davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781 +ep9302 MACH_EP9302 EP9302 1782 +at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783 +cybook3 MACH_CYBOOK3 CYBOOK3 1784 +wdg002 MACH_WDG002 WDG002 1785 +sg560adsl MACH_SG560ADSL SG560ADSL 1786 +nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787 dove_db MACH_DOVE_DB DOVE_DB 1788 +vandihud MACH_VANDIHUD VANDIHUD 1790 +magx_e8 MACH_MAGX_E8 MAGX_E8 1791 +magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792 +magx_v8 MACH_MAGX_V8 MAGX_V8 1793 +magx_u9 MACH_MAGX_U9 MAGX_U9 1794 +toughcf08 MACH_TOUGHCF08 TOUGHCF08 1795 +zw4400 MACH_ZW4400 ZW4400 1796 +marat91 MACH_MARAT91 MARAT91 1797 overo MACH_OVERO OVERO 1798 at2440evb MACH_AT2440EVB AT2440EVB 1799 neocore926 MACH_NEOCORE926 NEOCORE926 1800 wnr854t MACH_WNR854T WNR854T 1801 +imx27 MACH_IMX27 IMX27 1802 +moose_db MACH_MOOSE_DB MOOSE_DB 1803 +fab4 MACH_FAB4 FAB4 1804 +htcdiamond MACH_HTCDIAMOND HTCDIAMOND 1805 +fiona MACH_FIONA FIONA 1806 +mxc30030_x MACH_MXC30030_X MXC30030_X 1807 +bmp1000 MACH_BMP1000 BMP1000 1808 +logi9200 MACH_LOGI9200 LOGI9200 1809 +tqma31 MACH_TQMA31 TQMA31 1810 +ccw9p9215js MACH_CCW9P9215JS CCW9P9215JS 1811 rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812 +sifmain MACH_SIFMAIN SIFMAIN 1813 +sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814 +cc9m2443 MACH_CC9M2443 CC9M2443 1815 +xaria300 MACH_XARIA300 XARIA300 1816 +it9200 MACH_IT9200 IT9200 1817 rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818 +kriss_sensor MACH_KRISS_SENSOR KRISS_SENSOR 1819 +pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820 +jade MACH_JADE JADE 1821 +ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822 +gprisc3 MACH_GPRISC3 GPRISC3 1823 stamp9g20 MACH_STAMP9G20 STAMP9G20 1824 +smdk6430 MACH_SMDK6430 SMDK6430 1825 smdkc100 MACH_SMDKC100 SMDKC100 1826 tavorevb MACH_TAVOREVB TAVOREVB 1827 saar MACH_SAAR SAAR 1828 +deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829 at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830 +linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831 +hit_b0 MACH_HIT_B0 HIT_B0 1832 +adx_rmu MACH_ADX_RMU ADX_RMU 1833 +xg_cpe_main MACH_XG_CPE_MAIN XG_CPE_MAIN 1834 +edb9407a MACH_EDB9407A EDB9407A 1835 +dtb9608 MACH_DTB9608 DTB9608 1836 +em104v1 MACH_EM104V1 EM104V1 1837 +demo MACH_DEMO DEMO 1838 +logi9260 MACH_LOGI9260 LOGI9260 1839 +mx31_exm32 MACH_MX31_EXM32 MX31_EXM32 1840 usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841 +picproje2008 MACH_PICPROJE2008 PICPROJE2008 1842 +cs_e9315 MACH_CS_E9315 CS_E9315 1843 +qil_a9g20 MACH_QIL_A9G20 QIL_A9G20 1844 +sha_pon020 MACH_SHA_PON020 SHA_PON020 1845 +nad MACH_NAD NAD 1846 +sbc35_a9260 MACH_SBC35_A9260 SBC35_A9260 1847 +sbc35_a9g20 MACH_SBC35_A9G20 SBC35_A9G20 1848 +davinci_beginning MACH_DAVINCI_BEGINNING DAVINCI_BEGINNING 1849 +uwc MACH_UWC UWC 1850 mxlads MACH_MXLADS MXLADS 1851 +htcnike MACH_HTCNIKE HTCNIKE 1852 +deister_pxa270 MACH_DEISTER_PXA270 DEISTER_PXA270 1853 +cme9210js MACH_CME9210JS CME9210JS 1854 +cc9p9360 MACH_CC9P9360 CC9P9360 1855 +mocha MACH_MOCHA MOCHA 1856 +wapd170ag MACH_WAPD170AG WAPD170AG 1857 linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858 afeb9260 MACH_AFEB9260 AFEB9260 1859 +w90x900 MACH_W90X900 W90X900 1860 +w90x700 MACH_W90X700 W90X700 1861 +kt300ip MACH_KT300IP KT300IP 1862 +kt300ip_g20 MACH_KT300IP_G20 KT300IP_G20 1863 +srcm MACH_SRCM SRCM 1864 +wlnx_9260 MACH_WLNX_9260 WLNX_9260 1865 +openmoko_gta03 MACH_OPENMOKO_GTA03 OPENMOKO_GTA03 1866 +osprey2 MACH_OSPREY2 OSPREY2 1867 +kbio9260 MACH_KBIO9260 KBIO9260 1868 +ginza MACH_GINZA GINZA 1869 +a636n MACH_A636N A636N 1870 imx27ipcam MACH_IMX27IPCAM IMX27IPCAM 1871 +nemoc MACH_NEMOC NEMOC 1872 +geneva MACH_GENEVA GENEVA 1873 +htcpharos MACH_HTCPHAROS HTCPHAROS 1874 +neonc MACH_NEONC NEONC 1875 +nas7100 MACH_NAS7100 NAS7100 1876 +teuphone MACH_TEUPHONE TEUPHONE 1877 +annax_eth2 MACH_ANNAX_ETH2 ANNAX_ETH2 1878 +csb733 MACH_CSB733 CSB733 1879 +bk3 MACH_BK3 BK3 1880 +omap_em32 MACH_OMAP_EM32 OMAP_EM32 1881 +et9261cp MACH_ET9261CP ET9261CP 1882 +jasperc MACH_JASPERC JASPERC 1883 +issi_arm9 MACH_ISSI_ARM9 ISSI_ARM9 1884 +ued MACH_UED UED 1885 +esiblade MACH_ESIBLADE ESIBLADE 1886 +eye02 MACH_EYE02 EYE02 1887 +imx27kbd MACH_IMX27KBD IMX27KBD 1888 +kixvp435 MACH_KIXVP435 KIXVP435 1890 +kixnp435 MACH_KIXNP435 KIXNP435 1891 +africa MACH_AFRICA AFRICA 1892 +nh233 MACH_NH233 NH233 1893 rd88f6183ap_ge MACH_RD88F6183AP_GE RD88F6183AP_GE 1894 +bcm4760 MACH_BCM4760 BCM4760 1895 +eddy_v2 MACH_EDDY_V2 EDDY_V2 1896 realview_pba8 MACH_REALVIEW_PBA8 REALVIEW_PBA8 1897 +hid_a7 MACH_HID_A7 HID_A7 1898 +hero MACH_HERO HERO 1899 +omap_poseidon MACH_OMAP_POSEIDON OMAP_POSEIDON 1900 realview_pbx MACH_REALVIEW_PBX REALVIEW_PBX 1901 micro9s MACH_MICRO9S MICRO9S 1902 +mako MACH_MAKO MAKO 1903 +xdaflame MACH_XDAFLAME XDAFLAME 1904 +phidget_sbc2 MACH_PHIDGET_SBC2 PHIDGET_SBC2 1905 +limestone MACH_LIMESTONE LIMESTONE 1906 +iprobe_c32 MACH_IPROBE_C32 IPROBE_C32 1907 rut100 MACH_RUT100 RUT100 1908 +asusp535 MACH_ASUSP535 ASUSP535 1909 +htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910 +sygdg1 MACH_SYGDG1 SYGDG1 1911 +sygdg2 MACH_SYGDG2 SYGDG2 1912 +seoul MACH_SEOUL SEOUL 1913 +salerno MACH_SALERNO SALERNO 1914 +ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915 +msm7201a MACH_MSM7201A MSM7201A 1916 +lpr1 MACH_LPR1 LPR1 1917 +armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918 g3evm MACH_G3EVM G3EVM 1919 +z3_dm355 MACH_Z3_DM355 Z3_DM355 1920 w90p910evb MACH_W90P910EVB W90P910EVB 1921 +w90p920evb MACH_W90P920EVB W90P920EVB 1922 w90p950evb MACH_W90P950EVB W90P950EVB 1923 w90n960evb MACH_W90N960EVB W90N960EVB 1924 +camhd MACH_CAMHD CAMHD 1925 +mvc100 MACH_MVC100 MVC100 1926 +electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927 +htcjade MACH_HTCJADE HTCJADE 1928 +memphis MACH_MEMPHIS MEMPHIS 1929 +imx27sbc MACH_IMX27SBC IMX27SBC 1930 +lextar MACH_LEXTAR LEXTAR 1931 mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932 ncp MACH_NCP NCP 1933 +z32an_series MACH_Z32AN Z32AN 1934 +tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935 +omap3_wl MACH_OMAP3_WL OMAP3_WL 1936 +chumby MACH_CHUMBY CHUMBY 1937 +atsarm9 MACH_ATSARM9 ATSARM9 1938 davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939 +bahamas MACH_BAHAMAS BAHAMAS 1940 +das MACH_DAS DAS 1941 +minidas MACH_MINIDAS MINIDAS 1942 +vk1000 MACH_VK1000 VK1000 1943 centro MACH_CENTRO CENTRO 1944 +ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945 +edgeconnect MACH_EDGECONNECT EDGECONNECT 1946 +nd27000 MACH_ND27000 ND27000 1947 +cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948 +ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949 +pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950 +blackstone MACH_BLACKSTONE BLACKSTONE 1951 +topaz MACH_TOPAZ TOPAZ 1952 +aixle MACH_AIXLE AIXLE 1953 +mw998 MACH_MW998 MW998 1954 nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955 +vsc5605ev MACH_VSC5605EV VSC5605EV 1956 +nt98700dk MACH_NT98700DK NT98700DK 1957 +icontact MACH_ICONTACT ICONTACT 1958 +swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959 +swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960 +bbox_p16 MACH_BBOX_P16 BBOX_P16 1961 +bstd MACH_BSTD BSTD 1962 +sbc2440ii MACH_SBC2440II SBC2440II 1963 +pcm034 MACH_PCM034 PCM034 1964 +neso MACH_NESO NESO 1965 +wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966 omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967 +totemnova MACH_TOTEMNOVA TOTEMNOVA 1968 +c5000 MACH_C5000 C5000 1969 +unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970 +ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971 +arm11 MACH_ARM11 ARM11 1972 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 +cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 eukrea_cpuimx27 MACH_EUKREA_CPUIMX27 EUKREA_CPUIMX27 1975 +cheflux MACH_CHEFLUX CHEFLUX 1976 +eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 +opcotec MACH_OPCOTEC OPCOTEC 1978 +yt MACH_YT YT 1979 +motoq MACH_MOTOQ MOTOQ 1980 +bsb1 MACH_BSB1 BSB1 1981 acs5k MACH_ACS5K ACS5K 1982 +milan MACH_MILAN MILAN 1983 +quartzv2 MACH_QUARTZV2 QUARTZV2 1984 +rsvp MACH_RSVP RSVP 1985 +rmp200 MACH_RMP200 RMP200 1986 snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987 dsm320 MACH_DSM320 DSM320 1988 +adsgcm MACH_ADSGCM ADSGCM 1989 +ase2_400 MACH_ASE2_400 ASE2_400 1990 +pizza MACH_PIZZA PIZZA 1991 +spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992 +armata MACH_ARMATA ARMATA 1993 exeda MACH_EXEDA EXEDA 1994 +mx31sf005 MACH_MX31SF005 MX31SF005 1995 +f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996 +q2440 MACH_Q2440 Q2440 1997 +qq2440 MACH_QQ2440 QQ2440 1998 mini2440 MACH_MINI2440 MINI2440 1999 colibri300 MACH_COLIBRI300 COLIBRI300 2000 +jades MACH_JADES JADES 2001 +spark MACH_SPARK SPARK 2002 +benzina MACH_BENZINA BENZINA 2003 +blaze MACH_BLAZE BLAZE 2004 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005 +htckovsky MACH_HTCKOVSKY HTCKOVSKY 2006 +sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007 +hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008 +sapphira MACH_SAPPHIRA SAPPHIRA 2009 +dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010 +armbox MACH_ARMBOX ARMBOX 2011 +harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012 +ribaldo MACH_RIBALDO RIBALDO 2013 +agora MACH_AGORA AGORA 2014 +omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015 +a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016 +usg2410 MACH_USG2410 USG2410 2017 +pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018 +mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019 +topas910 MACH_TOPAS910 TOPAS910 2020 +hyena MACH_HYENA HYENA 2021 +pospax MACH_POSPAX POSPAX 2022 +hdl_gx MACH_HDL_GX HDL_GX 2023 +ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024 +ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025 +crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026 +egauge2 MACH_EGAUGE2 EGAUGE2 2027 +didj MACH_DIDJ DIDJ 2028 +m_s3c2443 MACH_MEISTER MEISTER 2029 +htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030 cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031 smdk6440 MACH_SMDK6440 SMDK6440 2032 +omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033 +ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034 +pvg610_100 MACH_PVG610 PVG610 2035 +hprw6815 MACH_HPRW6815 HPRW6815 2036 +omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037 nas4220b MACH_NAS4220B NAS4220B 2038 +htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039 +htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040 +scaler MACH_SCALER SCALER 2041 zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042 aspenite MACH_ASPENITE ASPENITE 2043 +teton MACH_TETON TETON 2044 ttc_dkb MACH_TTC_DKB TTC_DKB 2045 +bishop2 MACH_BISHOP2 BISHOP2 2046 +ippv5 MACH_IPPV5 IPPV5 2047 +farm926 MACH_FARM926 FARM926 2048 +mmccpu MACH_MMCCPU MMCCPU 2049 +sgmsfl MACH_SGMSFL SGMSFL 2050 +tt8000 MACH_TT8000 TT8000 2051 +zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052 +mptc MACH_MPTC MPTC 2053 +h6051 MACH_H6051 H6051 2054 +pvg610_101 MACH_PVG610_101 PVG610_101 2055 +stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056 +pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057 +tny_a9260 MACH_TNY_A9260 TNY_A9260 2058 +tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059 +aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060 +dx900 MACH_DX900 DX900 2061 +cpodc2 MACH_CPODC2 CPODC2 2062 +tilt_8925 MACH_TILT_8925 TILT_8925 2063 +davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064 +swordfish MACH_SWORDFISH SWORDFISH 2065 +corvus MACH_CORVUS CORVUS 2066 +taurus MACH_TAURUS TAURUS 2067 +axm MACH_AXM AXM 2068 +axc MACH_AXC AXC 2069 +baby MACH_BABY BABY 2070 +mp200 MACH_MP200 MP200 2071 pcm043 MACH_PCM043 PCM043 2072 +hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073 +kbk9g20 MACH_KBK9G20 KBK9G20 2074 +adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075 +avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076 +suc82x MACH_SUC SUC 2077 +at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078 +mendoza MACH_MENDOZA MENDOZA 2079 +kira MACH_KIRA KIRA 2080 +mx1hbm MACH_MX1HBM MX1HBM 2081 +quatro43xx MACH_QUATRO43XX QUATRO43XX 2082 +quatro4230 MACH_QUATRO4230 QUATRO4230 2083 +nsb400 MACH_NSB400 NSB400 2084 +drp255 MACH_DRP255 DRP255 2085 +thoth MACH_THOTH THOTH 2086 +firestone MACH_FIRESTONE FIRESTONE 2087 +asusp750 MACH_ASUSP750 ASUSP750 2088 +ctera_dl MACH_CTERA_DL CTERA_DL 2089 +socr MACH_SOCR SOCR 2090 +htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091 +heroc MACH_HEROC HEROC 2092 +zeno6800 MACH_ZENO6800 ZENO6800 2093 +sc2mcs MACH_SC2MCS SC2MCS 2094 +gene100 MACH_GENE100 GENE100 2095 +as353x MACH_AS353X AS353X 2096 sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097 +at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098 +mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099 +cc9200 MACH_CC9200 CC9200 2100 +sm9200 MACH_SM9200 SM9200 2101 +tp9200 MACH_TP9200 TP9200 2102 +snapperdv MACH_SNAPPERDV SNAPPERDV 2103 avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104 +avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105 +omap3axon MACH_OMAP3AXON OMAP3AXON 2106 +ma8xx MACH_MA8XX MA8XX 2107 +mp201ek MACH_MP201EK MP201EK 2108 +davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109 +mpa1600 MACH_MPA1600 MPA1600 2110 +pelco_troy MACH_PELCO_TROY PELCO_TROY 2111 +nsb667 MACH_NSB667 NSB667 2112 +rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113 +twocom MACH_TWOCOM TWOCOM 2114 +ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115 +hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116 +afeusb MACH_AFEUSB AFEUSB 2117 +t830 MACH_T830 T830 2118 +spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119 +om_3d7k MACH_OM_3D7K OM_3D7K 2120 +picocom2 MACH_PICOCOM2 PICOCOM2 2121 +uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122 +uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123 +cherry MACH_CHERRY CHERRY 2124 mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125 +s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126 tx37 MACH_TX37 TX37 2127 +sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128 +benzglb MACH_BENZGLB BENZGLB 2129 +benztd MACH_BENZTD BENZTD 2130 +cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131 +solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132 +mx27wallace MACH_MX27WALLACE MX27WALLACE 2133 +fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134 rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 +smallogger MACH_SMALLOGGER SMALLOGGER 2136 +ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137 dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138 ts219 MACH_TS219 TS219 2139 +tny_a9263 MACH_TNY_A9263 TNY_A9263 2140 +apollo MACH_APOLLO APOLLO 2141 +at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142 +spc300 MACH_SPC300 SPC300 2143 +eko MACH_EKO EKO 2144 +ccw9m2443 MACH_CCW9M2443 CCW9M2443 2145 +ccw9m2443js MACH_CCW9M2443JS CCW9M2443JS 2146 +m2m_router_device MACH_M2M_ROUTER_DEVICE M2M_ROUTER_DEVICE 2147 +str9104nas MACH_STAR9104NAS STAR9104NAS 2148 pca100 MACH_PCA100 PCA100 2149 +z3_dm365_mod_01 MACH_Z3_DM365_MOD_01 Z3_DM365_MOD_01 2150 +hipox MACH_HIPOX HIPOX 2151 +omap3_piteds MACH_OMAP3_PITEDS OMAP3_PITEDS 2152 +bm150r MACH_BM150R BM150R 2153 +tbone MACH_TBONE TBONE 2154 +merlin MACH_MERLIN MERLIN 2155 +falcon MACH_FALCON FALCON 2156 davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157 +s5p6440 MACH_S5P6440 S5P6440 2158 at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159 omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160 +lpc313x MACH_LPC313X LPC313X 2161 magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162 +magx_em30 MACH_MAGX_EM30 MAGX_EM30 2163 +magx_ve66 MACH_MAGX_VE66 MAGX_VE66 2164 +meesc MACH_MEESC MEESC 2165 +otc570 MACH_OTC570 OTC570 2166 +bcu2412 MACH_BCU2412 BCU2412 2167 +beacon MACH_BEACON BEACON 2168 +actia_tgw MACH_ACTIA_TGW ACTIA_TGW 2169 +e4430 MACH_E4430 E4430 2170 +ql300 MACH_QL300 QL300 2171 btmavb101 MACH_BTMAVB101 BTMAVB101 2172 btmawb101 MACH_BTMAWB101 BTMAWB101 2173 +sq201 MACH_SQ201 SQ201 2174 +quatro45xx MACH_QUATRO45XX QUATRO45XX 2175 +openpad MACH_OPENPAD OPENPAD 2176 tx25 MACH_TX25 TX25 2177 omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178 +htcraphael_k MACH_HTCRAPHAEL_K HTCRAPHAEL_K 2179 +lal43 MACH_LAL43 LAL43 2181 +htcraphael_cdma500 MACH_HTCRAPHAEL_CDMA500 HTCRAPHAEL_CDMA500 2182 anw6410 MACH_ANW6410 ANW6410 2183 +htcprophet MACH_HTCPROPHET HTCPROPHET 2185 +cfa_10022 MACH_CFA_10022 CFA_10022 2186 imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187 +px2imx27 MACH_PX2IMX27 PX2IMX27 2188 +stm3210e_eval MACH_STM3210E_EVAL STM3210E_EVAL 2189 +dvs10 MACH_DVS10 DVS10 2190 portuxg20 MACH_PORTUXG20 PORTUXG20 2191 +arm_spv MACH_ARM_SPV ARM_SPV 2192 smdkc110 MACH_SMDKC110 SMDKC110 2193 +cabespresso MACH_CABESPRESSO CABESPRESSO 2194 +hmc800 MACH_HMC800 HMC800 2195 +sholes MACH_SHOLES SHOLES 2196 +btmxc31 MACH_BTMXC31 BTMXC31 2197 +dt501 MACH_DT501 DT501 2198 +ktx MACH_KTX KTX 2199 omap3517evm MACH_OMAP3517EVM OMAP3517EVM 2200 netspace_v2 MACH_NETSPACE_V2 NETSPACE_V2 2201 netspace_max_v2 MACH_NETSPACE_MAX_V2 NETSPACE_MAX_V2 2202 d2net_v2 MACH_D2NET_V2 D2NET_V2 2203 net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204 +net4big_v2 MACH_NET4BIG_V2 NET4BIG_V2 2205 net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206 +endb2443 MACH_ENDB2443 ENDB2443 2207 inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208 +tros MACH_TROS TROS 2209 +pelco_homer MACH_PELCO_HOMER PELCO_HOMER 2210 +ofsp8 MACH_OFSP8 OFSP8 2211 at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212 +guf_cupid MACH_GUF_CUPID GUF_CUPID 2213 +eab1r MACH_EAB1R EAB1R 2214 +desirec MACH_DESIREC DESIREC 2215 +cordoba MACH_CORDOBA CORDOBA 2216 +irvine MACH_IRVINE IRVINE 2217 +sff772 MACH_SFF772 SFF772 2218 +pelco_milano MACH_PELCO_MILANO PELCO_MILANO 2219 pc7302 MACH_PC7302 PC7302 2220 +bip6000 MACH_BIP6000 BIP6000 2221 +silvermoon MACH_SILVERMOON SILVERMOON 2222 +vc0830 MACH_VC0830 VC0830 2223 +dt430 MACH_DT430 DT430 2224 +ji42pf MACH_JI42PF JI42PF 2225 +gnet_ksm MACH_GNET_KSM GNET_KSM 2226 +gnet_sgm MACH_GNET_SGM GNET_SGM 2227 +gnet_sgr MACH_GNET_SGR GNET_SGR 2228 +omap3_icetekevm MACH_OMAP3_ICETEKEVM OMAP3_ICETEKEVM 2229 +pnp MACH_PNP PNP 2230 +ctera_2bay_k MACH_CTERA_2BAY_K CTERA_2BAY_K 2231 +ctera_2bay_u MACH_CTERA_2BAY_U CTERA_2BAY_U 2232 +sas_c MACH_SAS_C SAS_C 2233 +vma2315 MACH_VMA2315 VMA2315 2234 +vcs MACH_VCS VCS 2235 spear600 MACH_SPEAR600 SPEAR600 2236 spear300 MACH_SPEAR300 SPEAR300 2237 +spear1300 MACH_SPEAR1300 SPEAR1300 2238 lilly1131 MACH_LILLY1131 LILLY1131 2239 +arvoo_ax301 MACH_ARVOO_AX301 ARVOO_AX301 2240 +mapphone MACH_MAPPHONE MAPPHONE 2241 +legend MACH_LEGEND LEGEND 2242 +salsa MACH_SALSA SALSA 2243 +lounge MACH_LOUNGE LOUNGE 2244 +vision MACH_VISION VISION 2245 +vmb20 MACH_VMB20 VMB20 2246 +hy2410 MACH_HY2410 HY2410 2247 +hy9315 MACH_HY9315 HY9315 2248 +bullwinkle MACH_BULLWINKLE BULLWINKLE 2249 +arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250 +vs_v210 MACH_VS_V210 VS_V210 2252 +vs_v212 MACH_VS_V212 VS_V212 2253 hmt MACH_HMT HMT 2254 +km_kirkwood MACH_KM_KIRKWOOD KM_KIRKWOOD 2255 +vesper MACH_VESPER VESPER 2256 +str9 MACH_STR9 STR9 2257 +omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258 +simcom MACH_SIMCOM SIMCOM 2259 +mcwebio MACH_MCWEBIO MCWEBIO 2260 +omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261 +darwin MACH_DARWIN DARWIN 2262 +oratiscomu MACH_ORATISCOMU ORATISCOMU 2263 +rtsbc20 MACH_RTSBC20 RTSBC20 2264 +sgh_i780 MACH_I780 I780 2265 +gemini324 MACH_GEMINI324 GEMINI324 2266 +oratislan MACH_ORATISLAN ORATISLAN 2267 +oratisalog MACH_ORATISALOG ORATISALOG 2268 +oratismadi MACH_ORATISMADI ORATISMADI 2269 +oratisot16 MACH_ORATISOT16 ORATISOT16 2270 +oratisdesk MACH_ORATISDESK ORATISDESK 2271 vexpress MACH_VEXPRESS VEXPRESS 2272 +sintexo MACH_SINTEXO SINTEXO 2273 +cm3389 MACH_CM3389 CM3389 2274 +omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275 +sgh_i900 MACH_SGH_I900 SGH_I900 2276 +bst100 MACH_BST100 BST100 2277 +passion MACH_PASSION PASSION 2278 +indesign_at91sam MACH_INDESIGN_AT91SAM INDESIGN_AT91SAM 2279 +c4_badger MACH_C4_BADGER C4_BADGER 2280 +c4_viper MACH_C4_VIPER C4_VIPER 2281 d2net MACH_D2NET D2NET 2282 bigdisk MACH_BIGDISK BIGDISK 2283 +notalvision MACH_NOTALVISION NOTALVISION 2284 +omap3_kboc MACH_OMAP3_KBOC OMAP3_KBOC 2285 +cyclone MACH_CYCLONE CYCLONE 2286 +ninja MACH_NINJA NINJA 2287 at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288 bcmring MACH_BCMRING BCMRING 2289 +resol_dl2 MACH_RESOL_DL2 RESOL_DL2 2290 +ifosw MACH_IFOSW IFOSW 2291 +htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292 +htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293 +matrix504 MACH_MATRIX504 MATRIX504 2294 +mrfsa MACH_MRFSA MRFSA 2295 +sc_p270 MACH_SC_P270 SC_P270 2296 +atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297 +pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298 +dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299 +leonardo MACH_LEONARDO LEONARDO 2300 +zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301 dp6xx MACH_DP6XX DP6XX 2302 +bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303 mahimahi MACH_MAHIMAHI MAHIMAHI 2304 +clickc MACH_CLICKC CLICKC 2305 +zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306 +tazcard MACH_TAZCARD TAZCARD 2307 +tazdev MACH_TAZDEV TAZDEV 2308 +annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309 +annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310 +cerebric MACH_CEREBRIC CEREBRIC 2311 +orca MACH_ORCA ORCA 2312 +pc9260 MACH_PC9260 PC9260 2313 +ems285a MACH_EMS285A EMS285A 2314 +gec2410 MACH_GEC2410 GEC2410 2315 +gec2440 MACH_GEC2440 GEC2440 2316 +mw903 MACH_ARCH_MW903 ARCH_MW903 2317 +mw2440 MACH_MW2440 MW2440 2318 +ecac2378 MACH_ECAC2378 ECAC2378 2319 +tazkiosk MACH_TAZKIOSK TAZKIOSK 2320 +whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321 +sbox9263 MACH_SBOX9263 SBOX9263 2322 smdk6442 MACH_SMDK6442 SMDK6442 2324 openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 +incredible MACH_INCREDIBLE INCREDIBLE 2326 +incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327 +heroct MACH_HEROCT HEROCT 2328 +mmnet1000 MACH_MMNET1000 MMNET1000 2329 devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330 +devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331 +mx31txtr MACH_MX31TXTR MX31TXTR 2332 +u380 MACH_U380 U380 2333 +oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334 +npcmx50 MACH_NPCMX50 NPCMX50 2335 mx51_efikamx MACH_MX51_EFIKAMX MX51_EFIKAMX 2336 +mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337 +riom MACH_RIOM RIOM 2338 +comcas MACH_COMCAS COMCAS 2339 +wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340 cm_t35 MACH_CM_T35 CM_T35 2341 net2big MACH_NET2BIG NET2BIG 2342 +motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343 igep0020 MACH_IGEP0020 IGEP0020 2344 +igep0010 MACH_IGEP0010 IGEP0010 2345 +mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346 +scat100 MACH_SCAT100 SCAT100 2347 +sanmina MACH_SANMINA SANMINA 2348 +momento MACH_MOMENTO MOMENTO 2349 +nuc9xx MACH_NUC9XX NUC9XX 2350 +nuc910evb MACH_NUC910EVB NUC910EVB 2351 +nuc920evb MACH_NUC920EVB NUC920EVB 2352 +nuc950evb MACH_NUC950EVB NUC950EVB 2353 +nuc945evb MACH_NUC945EVB NUC945EVB 2354 +nuc960evb MACH_NUC960EVB NUC960EVB 2355 nuc932evb MACH_NUC932EVB NUC932EVB 2356 +nuc900 MACH_NUC900 NUC900 2357 +sd1soc MACH_SD1SOC SD1SOC 2358 +ln2440bc MACH_LN2440BC LN2440BC 2359 +rsbc MACH_RSBC RSBC 2360 openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361 +hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362 +wayland MACH_WAYLAND WAYLAND 2363 +acnbsx102 MACH_ACNBSX102 ACNBSX102 2364 +hwat91 MACH_HWAT91 HWAT91 2365 +at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366 +csb732 MACH_CSB732 CSB732 2367 u8500 MACH_U8500 U8500 2368 +huqiu MACH_HUQIU HUQIU 2369 mx51_efikasb MACH_MX51_EFIKASB MX51_EFIKASB 2370 +pmt1g MACH_PMT1G PMT1G 2371 +htcelf MACH_HTCELF HTCELF 2372 +armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373 +armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374 +u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375 +csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376 +dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377 +hy9307 MACH_HY9307 HY9307 2378 +aspire_easystore MACH_A_ES A_ES 2379 +davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380 +agama9263 MACH_AGAMA9263 AGAMA9263 2381 marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382 flint MACH_FLINT FLINT 2383 tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384 +sch_m490 MACH_SCH_M490 SCH_M490 2386 +rbl01 MACH_RBL01 RBL01 2387 +omnifi MACH_OMNIFI OMNIFI 2388 +otavalo MACH_OTAVALO OTAVALO 2389 +htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391 +htc_opal MACH_HTC_OPAL HTC_OPAL 2392 touchbook MACH_TOUCHBOOK TOUCHBOOK 2393 +latte MACH_LATTE LATTE 2394 +xa200 MACH_XA200 XA200 2395 +nimrod MACH_NIMROD NIMROD 2396 +cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397 +cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398 +tk71 MACH_TK71 TK71 2399 +comham3525 MACH_COMHAM3525 COMHAM3525 2400 +mx31erebus MACH_MX31EREBUS MX31EREBUS 2401 +mcardmx27 MACH_MCARDMX27 MCARDMX27 2402 +paradise MACH_PARADISE PARADISE 2403 +tide MACH_TIDE TIDE 2404 +wzl2440 MACH_WZL2440 WZL2440 2405 +sdrdemo MACH_SDRDEMO SDRDEMO 2406 +ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407 +ecmimg20 MACH_ECMIMG20 ECMIMG20 2408 +omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409 +halo MACH_HALO HALO 2410 +huangshan MACH_HUANGSHAN HUANGSHAN 2411 +vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412 raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413 raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414 raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415 +multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416 +multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417 tnetv107x MACH_TNETV107X TNETV107X 2418 +snake MACH_SNAKE SNAKE 2419 +cwmx27 MACH_CWMX27 CWMX27 2420 +sch_m480 MACH_SCH_M480 SCH_M480 2421 +platypus MACH_PLATYPUS PLATYPUS 2422 +pss2 MACH_PSS2 PSS2 2423 +davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424 +str9100 MACH_STR9100 STR9100 2425 +net5big MACH_NET5BIG NET5BIG 2426 +seabed9263 MACH_SEABED9263 SEABED9263 2427 mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428 +octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429 +klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430 +klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431 +klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432 +supersonic MACH_SUPERSONIC SUPERSONIC 2433 +liberty MACH_LIBERTY LIBERTY 2434 +mh355 MACH_MH355 MH355 2435 +pc7802 MACH_PC7802 PC7802 2436 +gnet_sgc MACH_GNET_SGC GNET_SGC 2437 +einstein15 MACH_EINSTEIN15 EINSTEIN15 2438 +cmpd MACH_CMPD CMPD 2439 +davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440 +lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441 +ea313x MACH_EA313X EA313X 2442 +fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443 +fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444 +pelco_moe MACH_PELCO_MOE PELCO_MOE 2445 +minimix27 MACH_MINIMIX27 MINIMIX27 2446 +omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447 +passionc MACH_PASSIONC PASSIONC 2448 +mx27amata MACH_MX27AMATA MX27AMATA 2449 +bgat1 MACH_BGAT1 BGAT1 2450 +buzz MACH_BUZZ BUZZ 2451 +mb9g20 MACH_MB9G20 MB9G20 2452 +yushan MACH_YUSHAN YUSHAN 2453 +lizard MACH_LIZARD LIZARD 2454 +omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455 smdkv210 MACH_SMDKV210 SMDKV210 2456 +bravo MACH_BRAVO BRAVO 2457 +siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458 +siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459 +sm3k MACH_SM3K SM3K 2460 +acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461 +glittertind MACH_GLITTERTIND GLITTERTIND 2463 omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464 omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465 +cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466 +torino_s MACH_TORINO_S TORINO_S 2467 +havana MACH_HAVANA HAVANA 2468 +beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469 +vanguard MACH_VANGUARD VANGUARD 2470 +s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471 +cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472 +aster MACH_ASTER ASTER 2473 +voguesv210 MACH_VOGUESV210 VOGUESV210 2474 +acm500x MACH_ACM500X ACM500X 2475 +km9260 MACH_KM9260 KM9260 2476 +nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477 +ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478 smartq7 MACH_SMARTQ7 SMARTQ7 2479 +at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480 +asusp527 MACH_ASUSP527 ASUSP527 2481 +at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482 +topasa900 MACH_TOPASA900 TOPASA900 2483 +electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484 +mx51grb MACH_MX51GRB MX51GRB 2485 +xea300 MACH_XEA300 XEA300 2486 +htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487 +lima MACH_LIMA LIMA 2488 +csb740 MACH_CSB740 CSB740 2489 +usb_s8815 MACH_USB_S8815 USB_S8815 2490 watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491 +milkyway MACH_MILKYWAY MILKYWAY 2492 g4evm MACH_G4EVM G4EVM 2493 +picomod6 MACH_PICOMOD6 PICOMOD6 2494 omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495 +ip6000 MACH_IP6000 IP6000 2496 +ip6010 MACH_IP6010 IP6010 2497 +utm400 MACH_UTM400 UTM400 2498 +omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499 +wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500 +sx560 MACH_SX560 SX560 2501 ts41x MACH_TS41X TS41X 2502 +elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503 +rhobot MACH_RHOBOT RHOBOT 2504 +mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505 +ls9260 MACH_LS9260 LS9260 2506 +shank MACH_SHANK SHANK 2507 +qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508 +at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509 +hiram MACH_HIRAM HIRAM 2510 phy3250 MACH_PHY3250 PHY3250 2511 +ea3250 MACH_EA3250 EA3250 2512 +fdi3250 MACH_FDI3250 FDI3250 2513 +at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515 +ccmx51 MACH_CCMX51 CCMX51 2516 +ccmx51js MACH_CCMX51JS CCMX51JS 2517 +ccwmx51 MACH_CCWMX51 CCWMX51 2518 +ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519 mini6410 MACH_MINI6410 MINI6410 2520 +tiny6410 MACH_TINY6410 TINY6410 2521 +nano6410 MACH_NANO6410 NANO6410 2522 +at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523 +htcleo MACH_HTCLEO HTCLEO 2524 +avp13 MACH_AVP13 AVP13 2525 +xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526 +vpnext MACH_VPNEXT VPNEXT 2527 +swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528 tx51 MACH_TX51 TX51 2529 +dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530 mx28evk MACH_MX28EVK MX28EVK 2531 +phoenix260 MACH_PHOENIX260 PHOENIX260 2532 +uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533 smartq5 MACH_SMARTQ5 SMARTQ5 2534 +all3078 MACH_ALL3078 ALL3078 2535 +ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536 +siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537 +epb5000 MACH_EPB5000 EPB5000 2538 +hy9263 MACH_HY9263 HY9263 2539 +acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540 +acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541 +acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542 +acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543 +acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544 +bonnell MACH_BONNELL BONNELL 2545 +oht_mx27 MACH_OHT_MX27 OHT_MX27 2546 +htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547 davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548 +c3ax03 MACH_C3AX03 C3AX03 2549 mxt_td60 MACH_MXT_TD60 MXT_TD60 2550 +esyx MACH_ESYX ESYX 2551 +dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552 +bulldog MACH_BULLDOG BULLDOG 2553 +derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554 +bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555 +bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556 +bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557 +bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558 +bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559 +bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560 +bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561 +bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562 +bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563 +bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564 +bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565 +acer_s200 MACH_ACER_S200 ACER_S200 2566 +bt270 MACH_BT270 BT270 2567 +iseo MACH_ISEO ISEO 2568 +cezanne MACH_CEZANNE CEZANNE 2569 +lucca MACH_LUCCA LUCCA 2570 +supersmart MACH_SUPERSMART SUPERSMART 2571 +arm11_board MACH_CS_MISANO CS_MISANO 2572 +magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573 +emxx MACH_EMXX EMXX 2574 +outlaw MACH_OUTLAW OUTLAW 2575 riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 +riot_gx2 MACH_RIOT_VOX RIOT_VOX 2577 riot_x37 MACH_RIOT_X37 RIOT_X37 2578 +mega25mx MACH_MEGA25MX MEGA25MX 2579 +benzina2 MACH_BENZINA2 BENZINA2 2580 +ignite MACH_IGNITE IGNITE 2581 +foggia MACH_FOGGIA FOGGIA 2582 +arezzo MACH_AREZZO AREZZO 2583 +leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584 +jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585 +gts_nova MACH_GTS_NOVA GTS_NOVA 2586 +p3600 MACH_P3600 P3600 2587 +dlt2 MACH_DLT2 DLT2 2588 +df3120 MACH_DF3120 DF3120 2589 +ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590 +nautel_am35xx MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591 +glacier MACH_GLACIER GLACIER 2592 +phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593 +omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594 pca101 MACH_PCA101 PCA101 2595 +buzzc MACH_BUZZC BUZZC 2596 +sasie2 MACH_SASIE2 SASIE2 2597 +smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599 +wzl6410 MACH_WZL6410 WZL6410 2600 +wzl6410m MACH_WZL6410M WZL6410M 2601 +wzl6410f MACH_WZL6410F WZL6410F 2602 +wzl6410i MACH_WZL6410I WZL6410I 2603 +spacecom1 MACH_SPACECOM1 SPACECOM1 2604 +pingu920 MACH_PINGU920 PINGU920 2605 +bravoc MACH_BRAVOC BRAVOC 2606 +vdssw MACH_VDSSW VDSSW 2608 +romulus MACH_ROMULUS ROMULUS 2609 +omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610 +eltd100 MACH_ELTD100 ELTD100 2611 capc7117 MACH_CAPC7117 CAPC7117 2612 +swan MACH_SWAN SWAN 2613 +veu MACH_VEU VEU 2614 +rm2 MACH_RM2 RM2 2615 +tt2100 MACH_TT2100 TT2100 2616 +venice MACH_VENICE VENICE 2617 +pc7323 MACH_PC7323 PC7323 2618 +masp MACH_MASP MASP 2619 +fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620 +fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621 +lexikon MACH_LEXIKON LEXIKON 2622 +mini2440v2 MACH_MINI2440V2 MINI2440V2 2623 icontrol MACH_ICONTROL ICONTROL 2624 gplugd MACH_GPLUGD GPLUGD 2625 +qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626 qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627 +bee MACH_BEE BEE 2628 mx23evk MACH_MX23EVK MX23EVK 2629 ap4evb MACH_AP4EVB AP4EVB 2630 +stockholm MACH_STOCKHOLM STOCKHOLM 2631 +lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632 +stingray MACH_STINGRAY STINGRAY 2633 +kraken MACH_KRAKEN KRAKEN 2634 +gw2388 MACH_GW2388 GW2388 2635 +jadecpu MACH_JADECPU JADECPU 2636 +carlisle MACH_CARLISLE CARLISLE 2637 +lux_sf9 MACH_LUX_SF9 LUX_SF9 2638 +nemid_tb MACH_NEMID_TB NEMID_TB 2639 +terrier MACH_TERRIER TERRIER 2640 +turbot MACH_TURBOT TURBOT 2641 +sanddab MACH_SANDDAB SANDDAB 2642 +mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643 +ghi2703d MACH_GHI2703D GHI2703D 2644 +lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645 +lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646 +lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647 +hw90240 MACH_HW90240 HW90240 2648 +dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649 mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650 +scat110 MACH_SCAT110 SCAT110 2651 +acer_a1 MACH_ACER_A1 ACER_A1 2652 +cmcontrol MACH_CMCONTROL CMCONTROL 2653 +pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654 +rfp43 MACH_RFP43 RFP43 2655 +sk86r0301 MACH_SK86R0301 SK86R0301 2656 +ctpxa MACH_CTPXA CTPXA 2657 +epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658 guruplug MACH_GURUPLUG GURUPLUG 2659 spear310 MACH_SPEAR310 SPEAR310 2660 spear320 MACH_SPEAR320 SPEAR320 2661 +robotx MACH_ROBOTX ROBOTX 2662 +lsxhl MACH_LSXHL LSXHL 2663 +smartlite MACH_SMARTLITE SMARTLITE 2664 +cws2 MACH_CWS2 CWS2 2665 +m619 MACH_M619 M619 2666 +smartview MACH_SMARTVIEW SMARTVIEW 2667 +lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668 +kizbox MACH_KIZBOX KIZBOX 2669 +htccharmer MACH_HTCCHARMER HTCCHARMER 2670 +guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671 +pm9g45 MACH_PM9G45 PM9G45 2672 +htcpanther MACH_HTCPANTHER HTCPANTHER 2673 +htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674 +reb01 MACH_REB01 REB01 2675 aquila MACH_AQUILA AQUILA 2676 +spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677 esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679 +micro2440 MACH_MICRO2440 MICRO2440 2680 +am2440 MACH_AM2440 AM2440 2681 +tq2440 MACH_TQ2440 TQ2440 2682 ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683 +ak880x MACH_AK880X AK880X 2684 +cobra3530 MACH_COBRA3530 COBRA3530 2685 +pmppb MACH_PMPPB PMPPB 2686 +u6715 MACH_U6715 U6715 2687 +axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688 +g30_dvb MACH_G30_DVB G30_DVB 2689 +vc088x MACH_VC088X VC088X 2690 +mioa702 MACH_MIOA702 MIOA702 2691 +hpmin MACH_HPMIN HPMIN 2692 +ak880xak MACH_AK880XAK AK880XAK 2693 +arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694 +lkevm MACH_LKEVM LKEVM 2695 +mw6410 MACH_MW6410 MW6410 2696 terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697 +cpu8000e MACH_CPU8000E CPU8000E 2698 +tokyo MACH_TOKYO TOKYO 2700 +msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701 +msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702 msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703 msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704 msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705 msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706 msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707 qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708 +qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709 +qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710 +qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711 +qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712 +adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713 +mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714 +mobikt MACH_MOBIKT MOBIKT 2715 mx53_evk MACH_MX53_EVK MX53_EVK 2716 igep0030 MACH_IGEP0030 IGEP0030 2717 +axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718 +dtcommod MACH_DTCOMMOD DTCOMMOD 2719 +gould MACH_GOULD GOULD 2720 +siberia MACH_SIBERIA SIBERIA 2721 sbc3530 MACH_SBC3530 SBC3530 2722 +qarm MACH_QARM QARM 2723 +mips MACH_MIPS MIPS 2724 +mx27grb MACH_MX27GRB MX27GRB 2725 +sbc8100 MACH_SBC8100 SBC8100 2726 saarb MACH_SAARB SAARB 2727 +omap3mini MACH_OMAP3MINI OMAP3MINI 2728 +cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729 +catan MACH_CATAN CATAN 2730 harmony MACH_HARMONY HARMONY 2731 +tonga MACH_TONGA TONGA 2732 +cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733 +htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734 +epc_g45 MACH_EPC_G45 EPC_G45 2735 +epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736 +mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737 +rtw1000 MACH_RTW1000 RTW1000 2738 +bobcat MACH_BOBCAT BOBCAT 2739 +trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740 msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741 +nedap9263 MACH_NEDAP9263 NEDAP9263 2742 +netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743 +bmx MACH_BMX BMX 2744 +netstream MACH_NETSTREAM NETSTREAM 2745 +vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746 +vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747 +bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748 +sgarm10 MACH_SGARM10 SGARM10 2749 cm_t3517 MACH_CM_T3517 CM_T3517 2750 +dig297 MACH_OMAP3_CPS OMAP3_CPS 2751 +axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752 wbd222 MACH_WBD222 WBD222 2753 +mt65xx MACH_MT65XX MT65XX 2754 msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755 msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756 tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758 nanos MACH_NANOS NANOS 2759 +stamp9g10 MACH_STAMP9G10 STAMP9G10 2760 stamp9g45 MACH_STAMP9G45 STAMP9G45 2761 +h6053 MACH_H6053 H6053 2762 +smint01 MACH_SMINT01 SMINT01 2763 +prtlvt2 MACH_PRTLVT2 PRTLVT2 2764 +ap420 MACH_AP420 AP420 2765 +davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767 +msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768 +msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769 +esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770 +sbc35 MACH_SBC35 SBC35 2771 +mpx6446 MACH_MPX6446 MPX6446 2772 +oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773 +kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774 +ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775 cns3420vb MACH_CNS3420VB CNS3420VB 2776 +lpc_evo MACH_LPC2 LPC2 2777 +olympus MACH_OLYMPUS OLYMPUS 2778 +vortex MACH_VORTEX VORTEX 2779 +s5pc200 MACH_S5PC200 S5PC200 2780 +ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781 +smdkc200 MACH_SMDKC200 SMDKC200 2782 +emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783 +apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784 +songshan MACH_SONGSHAN SONGSHAN 2785 +tianshan MACH_TIANSHAN TIANSHAN 2786 +vpx500 MACH_VPX500 VPX500 2787 +am3517sam MACH_AM3517SAM AM3517SAM 2788 +skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789 +skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790 omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791 +df7220 MACH_DF7220 DF7220 2792 +nemini MACH_NEMINI NEMINI 2793 +t8200 MACH_T8200 T8200 2794 +apf51 MACH_APF51 APF51 2795 +dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796 +bordeaux MACH_BORDEAUX BORDEAUX 2797 +catania_b MACH_CATANIA_B CATANIA_B 2798 +mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799 ti8168evm MACH_TI8168EVM TI8168EVM 2800 +neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801 +withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802 +dbps MACH_DBPS DBPS 2803 +pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805 +speedy MACH_SPEEDY SPEEDY 2806 +chrysaor MACH_CHRYSAOR CHRYSAOR 2807 +tango MACH_TANGO TANGO 2808 +synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809 +hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810 +hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811 +hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812 +iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813 +irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814 +irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815 teton_bga MACH_TETON_BGA TETON_BGA 2816 +snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817 +tam3517 MACH_TAM3517 TAM3517 2818 +pdc100 MACH_PDC100 PDC100 2819 eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25SD EUKREA_CPUIMX25SD 2820 eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821 eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822 eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823 +p565 MACH_P565 P565 2824 +acer_a4 MACH_ACER_A4 ACER_A4 2825 +davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826 +eshare MACH_ESHARE ESHARE 2827 +wlbargn MACH_WLBARGN WLBARGN 2829 +bm170 MACH_BM170 BM170 2830 +netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831 +netspace_plug_v2 MACH_NETSPACE_PLUG_V2 NETSPACE_PLUG_V2 2832 +siemens_l1 MACH_SIEMENS_L1 SIEMENS_L1 2833 +elv_lcu1 MACH_ELV_LCU1 ELV_LCU1 2834 +mcu1 MACH_MCU1 MCU1 2835 +omap3_tao3530 MACH_OMAP3_TAO3530 OMAP3_TAO3530 2836 +omap3_pcutouch MACH_OMAP3_PCUTOUCH OMAP3_PCUTOUCH 2837 smdkc210 MACH_SMDKC210 SMDKC210 2838 -pca102 MACH_PCA102 PCA102 2843 +omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839 +spyplug MACH_SPYPLUG SPYPLUG 2840 +ginger MACH_GINGER GINGER 2841 +tny_t3530 MACH_TNY_T3530 TNY_T3530 2842 +pcaal1 MACH_PCAAL1 PCAAL1 2843 +spade MACH_SPADE SPADE 2844 +mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845 t5325 MACH_T5325 T5325 2846 +gw2361 MACH_GW2361 GW2361 2847 +elog MACH_ELOG ELOG 2848 income MACH_INCOME INCOME 2849 +bcm589x MACH_BCM589X BCM589X 2850 +etna MACH_ETNA ETNA 2851 +hawks MACH_HAWKS HAWKS 2852 +meson MACH_MESON MESON 2853 +xsbase255 MACH_XSBASE255 XSBASE255 2854 +pvm2030 MACH_PVM2030 PVM2030 2855 +mioa502 MACH_MIOA502 MIOA502 2856 vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857 vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858 vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859 +htc_spv_m700 MACH_HTC_SPV_M700 HTC_SPV_M700 2860 mx257sx MACH_MX257SX MX257SX 2861 goni MACH_GONI GONI 2862 +msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863 +msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864 +quickstep MACH_QUICKSTEP QUICKSTEP 2865 +dmw96 MACH_DMW96 DMW96 2866 +hammerhead MACH_HAMMERHEAD HAMMERHEAD 2867 +trident MACH_TRIDENT TRIDENT 2868 +lightning MACH_LIGHTNING LIGHTNING 2869 +iconnect MACH_ICONNECT ICONNECT 2870 +autobot MACH_AUTOBOT AUTOBOT 2871 +coconut MACH_COCONUT COCONUT 2872 +durian MACH_DURIAN DURIAN 2873 +cayenne MACH_CAYENNE CAYENNE 2874 +fuji MACH_FUJI FUJI 2875 +synology_6282 MACH_SYNOLOGY_6282 SYNOLOGY_6282 2876 +em1sy MACH_EM1SY EM1SY 2877 +m502 MACH_M502 M502 2878 +matrix518 MACH_MATRIX518 MATRIX518 2879 +tiny_gurnard MACH_TINY_GURNARD TINY_GURNARD 2880 +spear1310 MACH_SPEAR1310 SPEAR1310 2881 bv07 MACH_BV07 BV07 2882 +mxt_td61 MACH_MXT_TD61 MXT_TD61 2883 openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884 devixp MACH_DEVIXP DEVIXP 2885 miccpt MACH_MICCPT MICCPT 2886 mic256 MACH_MIC256 MIC256 2887 +as1167 MACH_AS1167 AS1167 2888 +omap3_ibiza MACH_OMAP3_IBIZA OMAP3_IBIZA 2889 u5500 MACH_U5500 U5500 2890 +davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891 +mecha MACH_MECHA MECHA 2892 +bubba3 MACH_BUBBA3 BUBBA3 2893 +pupitre MACH_PUPITRE PUPITRE 2894 +tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896 +tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897 +simplenet MACH_SIMPLENET SIMPLENET 2898 +ec4350tbm MACH_EC4350TBM EC4350TBM 2899 +pec_tc MACH_PEC_TC PEC_TC 2900 +pec_hc2 MACH_PEC_HC2 PEC_HC2 2901 +esl_mobilis_a MACH_ESL_MOBILIS_A ESL_MOBILIS_A 2902 +esl_mobilis_b MACH_ESL_MOBILIS_B ESL_MOBILIS_B 2903 +esl_wave_a MACH_ESL_WAVE_A ESL_WAVE_A 2904 +esl_wave_b MACH_ESL_WAVE_B ESL_WAVE_B 2905 +unisense_mmm MACH_UNISENSE_MMM UNISENSE_MMM 2906 +blueshark MACH_BLUESHARK BLUESHARK 2907 +e10 MACH_E10 E10 2908 +app3k_robin MACH_APP3K_ROBIN APP3K_ROBIN 2909 +pov15hd MACH_POV15HD POV15HD 2910 +stella MACH_STELLA STELLA 2911 linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913 +netwalker MACH_NETWALKER NETWALKER 2914 +acsx106 MACH_ACSX106 ACSX106 2915 +atlas5_c1 MACH_ATLAS5_C1 ATLAS5_C1 2916 +nsb3ast MACH_NSB3AST NSB3AST 2917 +gnet_slc MACH_GNET_SLC GNET_SLC 2918 +af4000 MACH_AF4000 AF4000 2919 +ark9431 MACH_ARK9431 ARK9431 2920 +fs_s5pc100 MACH_FS_S5PC100 FS_S5PC100 2921 +omap3505nova8 MACH_OMAP3505NOVA8 OMAP3505NOVA8 2922 +omap3621_edp1 MACH_OMAP3621_EDP1 OMAP3621_EDP1 2923 +oratisaes MACH_ORATISAES ORATISAES 2924 smdkv310 MACH_SMDKV310 SMDKV310 2925 +siemens_l0 MACH_SIEMENS_L0 SIEMENS_L0 2926 +ventana MACH_VENTANA VENTANA 2927 wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928 +ec4350sdb MACH_EC4350SDB EC4350SDB 2929 +mimas MACH_MIMAS MIMAS 2930 +titan MACH_TITAN TITAN 2931 craneboard MACH_CRANEBOARD CRANEBOARD 2932 +es2440 MACH_ES2440 ES2440 2933 +najay_a9263 MACH_NAJAY_A9263 NAJAY_A9263 2934 +htctornado MACH_HTCTORNADO HTCTORNADO 2935 +dimm_mx257 MACH_DIMM_MX257 DIMM_MX257 2936 +jigen301 MACH_JIGEN JIGEN 2937 smdk6450 MACH_SMDK6450 SMDK6450 2938 +meno_qng MACH_MENO_QNG MENO_QNG 2939 +ns2416 MACH_NS2416 NS2416 2940 +rpc353 MACH_RPC353 RPC353 2941 +tq6410 MACH_TQ6410 TQ6410 2942 +sky6410 MACH_SKY6410 SKY6410 2943 +dynasty MACH_DYNASTY DYNASTY 2944 +vivo MACH_VIVO VIVO 2945 +bury_bl7582 MACH_BURY_BL7582 BURY_BL7582 2946 +bury_bps5270 MACH_BURY_BPS5270 BURY_BPS5270 2947 +basi MACH_BASI BASI 2948 +tn200 MACH_TN200 TN200 2949 +c2mmi MACH_C2MMI C2MMI 2950 +meson_6236m MACH_MESON_6236M MESON_6236M 2951 +meson_8626m MACH_MESON_8626M MESON_8626M 2952 +tube MACH_TUBE TUBE 2953 +messina MACH_MESSINA MESSINA 2954 +mx50_arm2 MACH_MX50_ARM2 MX50_ARM2 2955 +cetus9263 MACH_CETUS9263 CETUS9263 2956 brownstone MACH_BROWNSTONE BROWNSTONE 2957 +vmx25 MACH_VMX25 VMX25 2958 +vmx51 MACH_VMX51 VMX51 2959 +abacus MACH_ABACUS ABACUS 2960 +cm4745 MACH_CM4745 CM4745 2961 +oratislink MACH_ORATISLINK ORATISLINK 2962 +davinci_dm365_dvr MACH_DAVINCI_DM365_DVR DAVINCI_DM365_DVR 2963 +netviz MACH_NETVIZ NETVIZ 2964 flexibity MACH_FLEXIBITY FLEXIBITY 2965 +wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966 +lpc24xx MACH_LPC24XX LPC24XX 2967 +spica MACH_SPICA SPICA 2968 +gpsdisplay MACH_GPSDISPLAY GPSDISPLAY 2969 +bipnet MACH_BIPNET BIPNET 2970 +overo_ctu_inertial MACH_OVERO_CTU_INERTIAL OVERO_CTU_INERTIAL 2971 +davinci_dm355_mmm MACH_DAVINCI_DM355_MMM DAVINCI_DM355_MMM 2972 +pc9260_v2 MACH_PC9260_V2 PC9260_V2 2973 +ptx7545 MACH_PTX7545 PTX7545 2974 +tm_efdc MACH_TM_EFDC TM_EFDC 2975 +omap3_waldo1 MACH_OMAP3_WALDO1 OMAP3_WALDO1 2977 +flyer MACH_FLYER FLYER 2978 +tornado3240 MACH_TORNADO3240 TORNADO3240 2979 +soli_01 MACH_SOLI_01 SOLI_01 2980 +omapl138_europalc MACH_OMAPL138_EUROPALC OMAPL138_EUROPALC 2981 +helios_v1 MACH_HELIOS_V1 HELIOS_V1 2982 +netspace_lite_v2 MACH_NETSPACE_LITE_V2 NETSPACE_LITE_V2 2983 +ssc MACH_SSC SSC 2984 +premierwave_en MACH_PREMIERWAVE_EN PREMIERWAVE_EN 2985 +wasabi MACH_WASABI WASABI 2986 mx50_rdp MACH_MX50_RDP MX50_RDP 2988 universal_c210 MACH_UNIVERSAL_C210 UNIVERSAL_C210 2989 real6410 MACH_REAL6410 REAL6410 2990 +spx_sakura MACH_SPX_SAKURA SPX_SAKURA 2991 +ij3k_2440 MACH_IJ3K_2440 IJ3K_2440 2992 +omap3_bc10 MACH_OMAP3_BC10 OMAP3_BC10 2993 +thebe MACH_THEBE THEBE 2994 +rv082 MACH_RV082 RV082 2995 +armlguest MACH_ARMLGUEST ARMLGUEST 2996 +tjinc1000 MACH_TJINC1000 TJINC1000 2997 dockstar MACH_DOCKSTAR DOCKSTAR 2998 +ax8008 MACH_AX8008 AX8008 2999 +gnet_sgce MACH_GNET_SGCE GNET_SGCE 3000 +pxwnas_500_1000 MACH_PXWNAS_500_1000 PXWNAS_500_1000 3001 +ea20 MACH_EA20 EA20 3002 +awm2 MACH_AWM2 AWM2 3003 ti8148evm MACH_TI8148EVM TI8148EVM 3004 seaboard MACH_SEABOARD SEABOARD 3005 +linkstation_chlv2 MACH_LINKSTATION_CHLV2 LINKSTATION_CHLV2 3006 +tera_pro2_rack MACH_TERA_PRO2_RACK TERA_PRO2_RACK 3007 +rubys MACH_RUBYS RUBYS 3008 +aquarius MACH_AQUARIUS AQUARIUS 3009 mx53_ard MACH_MX53_ARD MX53_ARD 3010 mx53_smd MACH_MX53_SMD MX53_SMD 3011 +lswxl MACH_LSWXL LSWXL 3012 +dove_avng_v3 MACH_DOVE_AVNG_V3 DOVE_AVNG_V3 3013 +sdi_ess_9263 MACH_SDI_ESS_9263 SDI_ESS_9263 3014 +jocpu550 MACH_JOCPU550 JOCPU550 3015 msm8x60_rumi3 MACH_MSM8X60_RUMI3 MSM8X60_RUMI3 3016 msm8x60_ffa MACH_MSM8X60_FFA MSM8X60_FFA 3017 +yanomami MACH_YANOMAMI YANOMAMI 3018 +gta04 MACH_GTA04 GTA04 3019 cm_a510 MACH_CM_A510 CM_A510 3020 +omap3_rfs200 MACH_OMAP3_RFS200 OMAP3_RFS200 3021 +kx33xx MACH_KX33XX KX33XX 3022 +ptx7510 MACH_PTX7510 PTX7510 3023 +top9000 MACH_TOP9000 TOP9000 3024 +teenote MACH_TEENOTE TEENOTE 3025 +ts3 MACH_TS3 TS3 3026 +a0 MACH_A0 A0 3027 +fsm9xxx_surf MACH_FSM9XXX_SURF FSM9XXX_SURF 3028 +fsm9xxx_ffa MACH_FSM9XXX_FFA FSM9XXX_FFA 3029 +frrhwcdma60w MACH_FRRHWCDMA60W FRRHWCDMA60W 3030 +remus MACH_REMUS REMUS 3031 +at91cap7xdk MACH_AT91CAP7XDK AT91CAP7XDK 3032 +at91cap7stk MACH_AT91CAP7STK AT91CAP7STK 3033 +kt_sbc_sam9_1 MACH_KT_SBC_SAM9_1 KT_SBC_SAM9_1 3034 +armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036 +spdm MACH_SPDM SPDM 3037 +gtib MACH_GTIB GTIB 3038 +dgm3240 MACH_DGM3240 DGM3240 3039 +htcmega MACH_HTCMEGA HTCMEGA 3041 +tricorder MACH_TRICORDER TRICORDER 3042 tx28 MACH_TX28 TX28 3043 +bstbrd MACH_BSTBRD BSTBRD 3044 +pwb3090 MACH_PWB3090 PWB3090 3045 +idea6410 MACH_IDEA6410 IDEA6410 3046 +qbc9263 MACH_QBC9263 QBC9263 3047 +borabora MACH_BORABORA BORABORA 3048 +valdez MACH_VALDEZ VALDEZ 3049 +ls9g20 MACH_LS9G20 LS9G20 3050 +mios_v1 MACH_MIOS_V1 MIOS_V1 3051 +s5pc110_crespo MACH_S5PC110_CRESPO S5PC110_CRESPO 3052 +controltek9g20 MACH_CONTROLTEK9G20 CONTROLTEK9G20 3053 +tin307 MACH_TIN307 TIN307 3054 +tin510 MACH_TIN510 TIN510 3055 +ep3505 MACH_EP3517 EP3517 3056 +bluecheese MACH_BLUECHEESE BLUECHEESE 3057 +tem3x30 MACH_TEM3X30 TEM3X30 3058 +harvest_desoto MACH_HARVEST_DESOTO HARVEST_DESOTO 3059 +msm8x60_qrdc MACH_MSM8X60_QRDC MSM8X60_QRDC 3060 +spear900 MACH_SPEAR900 SPEAR900 3061 pcontrol_g20 MACH_PCONTROL_G20 PCONTROL_G20 3062 +rdstor MACH_RDSTOR RDSTOR 3063 +usdloader MACH_USDLOADER USDLOADER 3064 +tsoploader MACH_TSOPLOADER TSOPLOADER 3065 +kronos MACH_KRONOS KRONOS 3066 +ffcore MACH_FFCORE FFCORE 3067 +mone MACH_MONE MONE 3068 +unit2s MACH_UNIT2S UNIT2S 3069 +acer_a5 MACH_ACER_A5 ACER_A5 3070 +etherpro_isp MACH_ETHERPRO_ISP ETHERPRO_ISP 3071 +stretchs7000 MACH_STRETCHS7000 STRETCHS7000 3072 +p87_smartsim MACH_P87_SMARTSIM P87_SMARTSIM 3073 +tulip MACH_TULIP TULIP 3074 +sunflower MACH_SUNFLOWER SUNFLOWER 3075 +rib MACH_RIB RIB 3076 +clod MACH_CLOD CLOD 3077 +rump MACH_RUMP RUMP 3078 +tenderloin MACH_TENDERLOIN TENDERLOIN 3079 +shortloin MACH_SHORTLOIN SHORTLOIN 3080 +antares MACH_ANTARES ANTARES 3082 +wb40n MACH_WB40N WB40N 3083 +herring MACH_HERRING HERRING 3084 +naxy400 MACH_NAXY400 NAXY400 3085 +naxy1200 MACH_NAXY1200 NAXY1200 3086 vpr200 MACH_VPR200 VPR200 3087 +bug20 MACH_BUG20 BUG20 3088 +goflexnet MACH_GOFLEXNET GOFLEXNET 3089 torbreck MACH_TORBRECK TORBRECK 3090 +saarb_mg1 MACH_SAARB_MG1 SAARB_MG1 3091 +callisto MACH_CALLISTO CALLISTO 3092 +multhsu MACH_MULTHSU MULTHSU 3093 +saluda MACH_SALUDA SALUDA 3094 +pemp_omap3_apollo MACH_PEMP_OMAP3_APOLLO PEMP_OMAP3_APOLLO 3095 +vc0718 MACH_VC0718 VC0718 3096 +mvblx MACH_MVBLX MVBLX 3097 +inhand_apeiron MACH_INHAND_APEIRON INHAND_APEIRON 3098 +inhand_fury MACH_INHAND_FURY INHAND_FURY 3099 +inhand_siren MACH_INHAND_SIREN INHAND_SIREN 3100 +hdnvp MACH_HDNVP HDNVP 3101 +softwinner MACH_SOFTWINNER SOFTWINNER 3102 prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 +nas6210 MACH_NAS6210 NAS6210 3104 +unisdev MACH_UNISDEV UNISDEV 3105 +sbca11 MACH_SBCA11 SBCA11 3106 +saga MACH_SAGA SAGA 3107 +ns_k330 MACH_NS_K330 NS_K330 3108 +tanna MACH_TANNA TANNA 3109 +imate8502 MACH_IMATE8502 IMATE8502 3110 +aspen MACH_ASPEN ASPEN 3111 +daintree_cwac MACH_DAINTREE_CWAC DAINTREE_CWAC 3112 +zmx25 MACH_ZMX25 ZMX25 3113 +maple1 MACH_MAPLE1 MAPLE1 3114 +qsd8x72_surf MACH_QSD8X72_SURF QSD8X72_SURF 3115 +qsd8x72_ffa MACH_QSD8X72_FFA QSD8X72_FFA 3116 +abilene MACH_ABILENE ABILENE 3117 +eigen_ttr MACH_EIGEN_TTR EIGEN_TTR 3118 +iomega_ix2_200 MACH_IOMEGA_IX2_200 IOMEGA_IX2_200 3119 +coretec_vcx7400 MACH_CORETEC_VCX7400 CORETEC_VCX7400 3120 +santiago MACH_SANTIAGO SANTIAGO 3121 +mx257sol MACH_MX257SOL MX257SOL 3122 +strasbourg MACH_STRASBOURG STRASBOURG 3123 +msm8x60_fluid MACH_MSM8X60_FLUID MSM8X60_FLUID 3124 +smartqv5 MACH_SMARTQV5 SMARTQV5 3125 +smartqv3 MACH_SMARTQV3 SMARTQV3 3126 +smartqv7 MACH_SMARTQV7 SMARTQV7 3127 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 +fwbd_0404 MACH_FWBD_0404 FWBD_0404 3131 +hdgu MACH_HDGU HDGU 3132 +pyramid MACH_PYRAMID PYRAMID 3133 +epiphan MACH_EPIPHAN EPIPHAN 3134 +omap_bender MACH_OMAP_BENDER OMAP_BENDER 3135 +gurnard MACH_GURNARD GURNARD 3136 +gtl_it5100 MACH_GTL_IT5100 GTL_IT5100 3137 +bcm2708 MACH_BCM2708 BCM2708 3138 +mx51_ggc MACH_MX51_GGC MX51_GGC 3139 +sharespace MACH_SHARESPACE SHARESPACE 3140 +haba_knx_explorer MACH_HABA_KNX_EXPLORER HABA_KNX_EXPLORER 3141 +simtec_kirkmod MACH_SIMTEC_KIRKMOD SIMTEC_KIRKMOD 3142 +crux MACH_CRUX CRUX 3143 +mx51_bravo MACH_MX51_BRAVO MX51_BRAVO 3144 +charon MACH_CHARON CHARON 3145 +picocom3 MACH_PICOCOM3 PICOCOM3 3146 +picocom4 MACH_PICOCOM4 PICOCOM4 3147 +serrano MACH_SERRANO SERRANO 3148 +doubleshot MACH_DOUBLESHOT DOUBLESHOT 3149 +evsy MACH_EVSY EVSY 3150 +huashan MACH_HUASHAN HUASHAN 3151 +lausanne MACH_LAUSANNE LAUSANNE 3152 +emerald MACH_EMERALD EMERALD 3153 +tqma35 MACH_TQMA35 TQMA35 3154 +marvel MACH_MARVEL MARVEL 3155 +manuae MACH_MANUAE MANUAE 3156 +chacha MACH_CHACHA CHACHA 3157 +lemon MACH_LEMON LEMON 3158 +csc MACH_CSC CSC 3159 +gira_knxip_router MACH_GIRA_KNXIP_ROUTER GIRA_KNXIP_ROUTER 3160 +t20 MACH_T20 T20 3161 +hdmini MACH_HDMINI HDMINI 3162 +sciphone_g2 MACH_SCIPHONE_G2 SCIPHONE_G2 3163 +express MACH_EXPRESS EXPRESS 3164 +express_kt MACH_EXPRESS_KT EXPRESS_KT 3165 +maximasp MACH_MAXIMASP MAXIMASP 3166 +nitrogen_imx51 MACH_NITROGEN_IMX51 NITROGEN_IMX51 3167 +nitrogen_imx53 MACH_NITROGEN_IMX53 NITROGEN_IMX53 3168 +sunfire MACH_SUNFIRE SUNFIRE 3169 +arowana MACH_AROWANA AROWANA 3170 +tegra_daytona MACH_TEGRA_DAYTONA TEGRA_DAYTONA 3171 +tegra_swordfish MACH_TEGRA_SWORDFISH TEGRA_SWORDFISH 3172 +edison MACH_EDISON EDISON 3173 +svp8500v1 MACH_SVP8500V1 SVP8500V1 3174 +svp8500v2 MACH_SVP8500V2 SVP8500V2 3175 +svp5500 MACH_SVP5500 SVP5500 3176 +b5500 MACH_B5500 B5500 3177 +s5500 MACH_S5500 S5500 3178 +icon MACH_ICON ICON 3179 +elephant MACH_ELEPHANT ELEPHANT 3180 +shooter MACH_SHOOTER SHOOTER 3182 +spade_lte MACH_SPADE_LTE SPADE_LTE 3183 +philhwani MACH_PHILHWANI PHILHWANI 3184 +gsncomm MACH_GSNCOMM GSNCOMM 3185 +strasbourg_a2 MACH_STRASBOURG_A2 STRASBOURG_A2 3186 +mmm MACH_MMM MMM 3187 +davinci_dm365_bv MACH_DAVINCI_DM365_BV DAVINCI_DM365_BV 3188 ag5evm MACH_AG5EVM AG5EVM 3189 +sc575plc MACH_SC575PLC SC575PLC 3190 +sc575hmi MACH_SC575IPC SC575IPC 3191 +omap3_tdm3730 MACH_OMAP3_TDM3730 OMAP3_TDM3730 3192 +top9000_eval MACH_TOP9000_EVAL TOP9000_EVAL 3194 +top9000_su MACH_TOP9000_SU TOP9000_SU 3195 +utm300 MACH_UTM300 UTM300 3196 tsunagi MACH_TSUNAGI TSUNAGI 3197 +ts75xx MACH_TS75XX TS75XX 3198 +ts47xx MACH_TS47XX TS47XX 3200 +da850_k5 MACH_DA850_K5 DA850_K5 3201 +ax502 MACH_AX502 AX502 3202 +igep0032 MACH_IGEP0032 IGEP0032 3203 +antero MACH_ANTERO ANTERO 3204 +synergy MACH_SYNERGY SYNERGY 3205 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 +punica MACH_PUNICA PUNICA 3208 trimslice MACH_TRIMSLICE TRIMSLICE 3209 +mx27_wmultra MACH_MX27_WMULTRA MX27_WMULTRA 3210 mackerel MACH_MACKEREL MACKEREL 3211 +fa9x27 MACH_FA9X27 FA9X27 3213 +ns2816tb MACH_NS2816TB NS2816TB 3214 +ns2816_ntpad MACH_NS2816_NTPAD NS2816_NTPAD 3215 +ns2816_ntnb MACH_NS2816_NTNB NS2816_NTNB 3216 kaen MACH_KAEN KAEN 3217 +nv1000 MACH_NV1000 NV1000 3218 +nuc950ts MACH_NUC950TS NUC950TS 3219 nokia_rm680 MACH_NOKIA_RM680 NOKIA_RM680 3220 +ast2200 MACH_AST2200 AST2200 3221 +lead MACH_LEAD LEAD 3222 +unino1 MACH_UNINO1 UNINO1 3223 +greeco MACH_GREECO GREECO 3224 +verdi MACH_VERDI VERDI 3225 dm6446_adbox MACH_DM6446_ADBOX DM6446_ADBOX 3226 quad_salsa MACH_QUAD_SALSA QUAD_SALSA 3227 abb_gma_1_1 MACH_ABB_GMA_1_1 ABB_GMA_1_1 3228 @@ -603,7 +3251,9 @@ isc3 MACH_ISC3 ISC3 3291 rascal MACH_RASCAL RASCAL 3292 hrefv60 MACH_HREFV60 HREFV60 3293 tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294 +pydtd MACH_PYRAMID_TD PYRAMID_TD 3295 splendor MACH_SPLENDOR SPLENDOR 3296 +guf_vincell MACH_GUF_PLANET GUF_PLANET 3297 msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298 htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299 athene MACH_ATHENE ATHENE 3300 @@ -614,6 +3264,7 @@ rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304 nmh MACH_NMH NMH 3305 wn802t MACH_WN802T WN802T 3306 dragonet MACH_DRAGONET DRAGONET 3307 +geneva_b4 MACH_GENEVA_B GENEVA_B 3308 at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309 bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310 bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311 @@ -621,11 +3272,13 @@ koi MACH_KOI KOI 3312 ts4800 MACH_TS4800 TS4800 3313 tqma9263 MACH_TQMA9263 TQMA9263 3314 holiday MACH_HOLIDAY HOLIDAY 3315 +dma_6410 MACH_DMA6410 DMA6410 3316 pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317 hwgw6410 MACH_HWGW6410 HWGW6410 3318 shenzhou MACH_SHENZHOU SHENZHOU 3319 cwme9210 MACH_CWME9210 CWME9210 3320 cwme9210js MACH_CWME9210JS CWME9210JS 3321 +pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322 colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323 w21 MACH_W21 W21 3324 polysat1 MACH_POLYSAT1 POLYSAT1 3325 @@ -691,11 +3344,15 @@ viprinet MACH_VIPRINET VIPRINET 3385 bockw MACH_BOCKW BOCKW 3386 eva2000 MACH_EVA2000 EVA2000 3387 steelyard MACH_STEELYARD STEELYARD 3388 +ea2468devkit MACH_LPC2468OEM LPC2468OEM 3389 +sdh001 MACH_MACH_SDH001 MACH_SDH001 3390 +fe2478mblox MACH_LPC2478MICROBLOX LPC2478MICROBLOX 3391 nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392 geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393 spear1340 MACH_SPEAR1340 SPEAR1340 3394 rexmas MACH_REXMAS REXMAS 3395 msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396 +msm8960_mtp MACH_MSM8960_MDP MSM8960_MDP 3397 msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398 msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399 helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400 @@ -727,6 +3384,7 @@ gt_i5700 MACH_GT_I5700 GT_I5700 3425 ctera_plug_c2 MACH_CTERA_PLUG_C2 CTERA_PLUG_C2 3426 marvelct MACH_MARVELCT MARVELCT 3427 ag11005 MACH_AG11005 AG11005 3428 +omap_tabletblaze MACH_OMAP_BLAZE OMAP_BLAZE 3429 vangogh MACH_VANGOGH VANGOGH 3430 matrix505 MACH_MATRIX505 MATRIX505 3431 oce_nigma MACH_OCE_NIGMA OCE_NIGMA 3432 @@ -766,6 +3424,7 @@ h1600 MACH_H1600 H1600 3465 mini210 MACH_MINI210 MINI210 3466 mini8168 MACH_MINI8168 MINI8168 3467 pc7308 MACH_PC7308 PC7308 3468 +ge863pro3 MACH_GE863 GE863 3469 kmm2m01 MACH_KMM2M01 KMM2M01 3470 mx51erebus MACH_MX51EREBUS MX51EREBUS 3471 wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472 @@ -802,6 +3461,7 @@ shooter_k MACH_SHOOTER_K SHOOTER_K 3502 nspire MACH_NSPIRE NSPIRE 3503 mickxx MACH_MICKXX MICKXX 3504 lxmb MACH_LXMB LXMB 3505 +tmdxscbp6618x MACH_TMDXSCBP6616X TMDXSCBP6616X 3506 adam MACH_ADAM ADAM 3507 b1004 MACH_B1004 B1004 3508 oboea MACH_OBOEA OBOEA 3509 @@ -879,6 +3539,7 @@ bct MACH_BCT BCT 3582 tuscan MACH_TUSCAN TUSCAN 3583 xbt_sam9g45 MACH_XBT_SAM9G45 XBT_SAM9G45 3584 enbw_cmc MACH_ENBW_CMC ENBW_CMC 3585 +msm8x60_dragon MACH_APQ8060_DRAGON APQ8060_DRAGON 3586 ch104mx257 MACH_CH104MX257 CH104MX257 3587 openpri MACH_OPENPRI OPENPRI 3588 am335xevm MACH_AM335XEVM AM335XEVM 3589 @@ -900,6 +3561,7 @@ cinema MACH_CINEMA CINEMA 3604 cinema_tea MACH_CINEMA_TEA CINEMA_TEA 3605 cinema_coffee MACH_CINEMA_COFFEE CINEMA_COFFEE 3606 cinema_juice MACH_CINEMA_JUICE CINEMA_JUICE 3607 +linux_pad MACH_THEPAD THEPAD 3608 mx53_mirage2 MACH_MX53_MIRAGE2 MX53_MIRAGE2 3609 mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610 stm_b2000 MACH_STM_B2000 STM_B2000 3612 @@ -965,6 +3627,7 @@ pia_am35x MACH_PIA_AM35X PIA_AM35X 3671 cedar MACH_CEDAR CEDAR 3672 picasso_e MACH_PICASSO_E PICASSO_E 3673 samsung_e60 MACH_SAMSUNG_E60 SAMSUNG_E60 3674 +msm9615_cdp MACH_MDM9615 MDM9615 3675 sdvr_mini MACH_SDVR_MINI SDVR_MINI 3676 omap3_ij3k MACH_OMAP3_IJ3K OMAP3_IJ3K 3677 modasmc1 MACH_MODASMC1 MODASMC1 3678 @@ -992,6 +3655,8 @@ fmc_uic MACH_FMC_UIC FMC_UIC 3699 fmc_dcm MACH_FMC_DCM FMC_DCM 3700 batwm MACH_BATWM BATWM 3701 atlas6cb MACH_ATLAS6CB ATLAS6CB 3702 +quattro_f MACH_QUATTROF QUATTROF 3703 +quattro_u MACH_QUATTROU QUATTROU 3704 blue MACH_BLUE BLUE 3705 colorado MACH_COLORADO COLORADO 3706 popc MACH_POPC POPC 3707 @@ -999,15 +3664,19 @@ promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708 amp MACH_AMP AMP 3709 gnet_amp MACH_GNET_AMP GNET_AMP 3710 toques MACH_TOQUES TOQUES 3711 +apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712 dct_storm MACH_DCT_STORM DCT_STORM 3713 +dm8168z3 MACH_Z3 Z3 3714 owl MACH_OWL OWL 3715 cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716 +omap3_kiko MACH_OMAP3 OMAP3 3717 adillustra610 MACH_ADILLUSTRA610 ADILLUSTRA610 3718 ecafe_na04 MACH_ECAFE_NA04 ECAFE_NA04 3719 popct MACH_POPCT POPCT 3720 omap3_helena MACH_OMAP3_HELENA OMAP3_HELENA 3721 ach MACH_ACH ACH 3722 module_dtb MACH_MODULE_DTB MODULE_DTB 3723 +ratebox MACH_RACKBOX RACKBOX 3724 oslo_elisabeth MACH_OSLO_ELISABETH OSLO_ELISABETH 3725 tt01 MACH_TT01 TT01 3726 msm8930_cdp MACH_MSM8930_CDP MSM8930_CDP 3727 @@ -1038,6 +3707,7 @@ ptip_murnau MACH_PTIP_MURNAU PTIP_MURNAU 3752 ptip_classic MACH_PTIP_CLASSIC PTIP_CLASSIC 3753 mx53grb MACH_MX53GRB MX53GRB 3754 gagarin MACH_GAGARIN GAGARIN 3755 +msm7627a_qrd1 MACH_MSM7X27A_QRD1 MSM7X27A_QRD1 3756 nas2big MACH_NAS2BIG NAS2BIG 3757 superfemto MACH_SUPERFEMTO SUPERFEMTO 3758 teufel MACH_TEUFEL TEUFEL 3759 @@ -1087,6 +3757,7 @@ ubisys_g1 MACH_UBISYS_G1 UBISYS_G1 3802 mx53_pf1 MACH_MX53_PF1 MX53_PF1 3803 asanti MACH_ASANTI ASANTI 3804 volta MACH_VOLTA VOLTA 3805 +potenza MACH_S5P6450 S5P6450 3806 knight MACH_KNIGHT KNIGHT 3807 beaglebone MACH_BEAGLEBONE BEAGLEBONE 3808 becker MACH_BECKER BECKER 3809 @@ -1148,6 +3819,7 @@ primou MACH_PRIMOU PRIMOU 3864 primoc MACH_PRIMOC PRIMOC 3865 primoct MACH_PRIMOCT PRIMOCT 3866 a9500 MACH_A9500 A9500 3867 +pue_td MACH_PULSE_TD PULSE_TD 3868 pluto MACH_PLUTO PLUTO 3869 acfx100 MACH_ACFX100 ACFX100 3870 msm8625_rumi3 MACH_MSM8625_RUMI3 MSM8625_RUMI3 3871 @@ -1161,6 +3833,8 @@ valente_wx MACH_VALENTE_WX VALENTE_WX 3878 huangshans MACH_HUANGSHANS HUANGSHANS 3879 bosphorus1 MACH_BOSPHORUS1 BOSPHORUS1 3880 prima MACH_PRIMA PRIMA 3881 +meson3_skt MACH_M3_SKT M3_SKT 3882 +meson3_ref MACH_M3_REF M3_REF 3883 evita_ulk MACH_EVITA_ULK EVITA_ULK 3884 merisc600 MACH_MERISC600 MERISC600 3885 dolak MACH_DOLAK DOLAK 3886 @@ -1169,3 +3843,113 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888 pov2 MACH_POV2 POV2 3889 ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890 da850_pqab MACH_DA850_PQAB DA850_PQAB 3891 +fermi MACH_FERMI FERMI 3892 +ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893 +ccardmx28 MACH_CCARDMX28 CCARDMX28 3894 +fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895 +kinetis MACH_KINETIS KINETIS 3896 +kai MACH_KAI KAI 3897 +bcthb2 MACH_BCTHB2 BCTHB2 3898 +inels3_cu MACH_INELS3_CU INELS3_CU 3899 +da850_juniper MACH_JUNIPER JUNIPER 3900 +da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901 +tracnas MACH_TRACNAS TRACNAS 3902 +mityarm335x MACH_MITYARM335X MITYARM335X 3903 +xcgz7x MACH_XCGZ7X XCGZ7X 3904 +cubox MACH_CUBOX CUBOX 3905 +terminator MACH_TERMINATOR TERMINATOR 3906 +eye03 MACH_EYE03 EYE03 3907 +kota3 MACH_KOTA3 KOTA3 3908 +mx53_nitrogen_k MACH_MX5 MX5 3909 +pscpe MACH_PSCPE PSCPE 3910 +akt1100 MACH_AKT1100 AKT1100 3911 +pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912 +primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913 +nsbc MACH_NSBC NSBC 3914 +meson2_skt MACH_MESON2_SKT MESON2_SKT 3915 +meson2_ref MACH_MESON2_REF MESON2_REF 3916 +ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917 +ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918 +indico MACH_INDICO INDICO 3919 +msm8960dt MACH_MSM8960DT MSM8960DT 3920 +primods MACH_PRIMODS PRIMODS 3921 +beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922 +primotd MACH_PRIMOTD PRIMOTD 3923 +varan_master MACH_VARAN_MASTER VARAN_MASTER 3924 +primodd MACH_PRIMODD PRIMODD 3925 +jetduo MACH_JETDUO JETDUO 3926 +mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927 +trats MACH_TRATS TRATS 3928 +starcraft MACH_STARCRAFT STARCRAFT 3929 +qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930 +lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931 +movenow MACH_MOVENOW MOVENOW 3932 +golf_u MACH_GOLF_U GOLF_U 3933 +msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934 +rambo MACH_RAMBO RAMBO 3935 +golfu MACH_GOLFU GOLFU 3936 +mango310 MACH_MANGO310 MANGO310 3937 +dns343 MACH_DNS343 DNS343 3938 +var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939 +naon MACH_NAON NAON 3940 +vp4000 MACH_VP4000 VP4000 3941 +impcard MACH_IMPCARD IMPCARD 3942 +smoovcam MACH_SMOOVCAM SMOOVCAM 3943 +cobham3725 MACH_COBHAM3725 COBHAM3725 3944 +cobham3730 MACH_COBHAM3730 COBHAM3730 3945 +cobham3703 MACH_COBHAM3703 COBHAM3703 3946 +quetzal MACH_QUETZAL QUETZAL 3947 +apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948 +apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949 +apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950 +apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951 +mango210 MACH_MANGO210 MANGO210 3952 +mango100 MACH_MANGO100 MANGO100 3953 +mango24 MACH_MANGO24 MANGO24 3954 +mango64 MACH_MANGO64 MANGO64 3955 +nsa320 MACH_NSA320 NSA320 3956 +elv_ccu2 MACH_ELV_CCU2 ELV_CCU2 3957 +triton_x00 MACH_TRITON_X00 TRITON_X00 3958 +triton_1500_2000 MACH_TRITON_1500_2000 TRITON_1500_2000 3959 +pogoplugv4 MACH_POGOPLUGV4 POGOPLUGV4 3960 +venus_cl MACH_VENUS_CL VENUS_CL 3961 +vulcano_g20 MACH_VULCANO_G20 VULCANO_G20 3962 +sgs_i9100 MACH_SGS_I9100 SGS_I9100 3963 +stsv2 MACH_STSV2 STSV2 3964 +csb1724 MACH_CSB1724 CSB1724 3965 +omapl138_lcdk MACH_OMAPL138_LCDK OMAPL138_LCDK 3966 +jel_dd MACH_JEWEL_DD JEWEL_DD 3967 +pvd_mx25 MACH_PVD_MX25 PVD_MX25 3968 +meson6_skt MACH_MESON6_SKT MESON6_SKT 3969 +meson6_ref MACH_MESON6_REF MESON6_REF 3970 +pxm MACH_PXM PXM 3971 +stuttgart MACH_S3 S3 3972 +pogoplugv3 MACH_POGOPLUGV3 POGOPLUGV3 3973 +mlp89626 MACH_MLP89626 MLP89626 3974 +iomegahmndce MACH_IOMEGAHMNDCE IOMEGAHMNDCE 3975 +pogoplugv3pci MACH_POGOPLUGV3PCI POGOPLUGV3PCI 3976 +bntv250 MACH_BNTV250 BNTV250 3977 +mx53_qseven MACH_MX53_QSEVEN MX53_QSEVEN 3978 +gtl_it1100 MACH_GTL_IT1100 GTL_IT1100 3979 +mx6q_sabresd MACH_MX6Q_SABRESD MX6Q_SABRESD 3980 +mt4 MACH_MT4 MT4 3981 +jumbo_d MACH_JUMBO_D JUMBO_D 3982 +jumbo_i MACH_JUMBO_I JUMBO_I 3983 +fs20_dmp MACH_FS20_DMP FS20_DMP 3984 +dns320 MACH_DNS320 DNS320 3985 +mx28bacos MACH_MX28BACOS MX28BACOS 3986 +tl80 MACH_TL80 TL80 3987 +polatis_nic_1001 MACH_POLATIS_NIC_1001 POLATIS_NIC_1001 3988 +tely MACH_TELY TELY 3989 +u8520 MACH_U8520 U8520 3990 +manta MACH_MANTA MANTA 3991 +spear1340_lcad MACH_SPEAR_EM_S900 SPEAR_EM_S900 3992 +mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993 +mpq8064_stb MACH_MPQ8064_STB MPQ8064_STB 3994 +mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995 +dm368som MACH_DM368SOM DM368SOM 3996 +gprisb2 MACH_GPRISB2 GPRISB2 3997 +chammid MACH_CHAMMID CHAMMID 3998 +seoul2 MACH_SEOUL2 SEOUL2 3999 +omap4_nooktablet MACH_OMAP4_NOOKTABLET OMAP4_NOOKTABLET 4000 +aalto MACH_AALTO AALTO 4001 |