From ba0fcc3f6e59facde89de74fb3df270b7070dbe3 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:19:16 +0300 Subject: [PATCH 01/32] EfikaSB support. --- arch/arm/configs/mx53_efikasb_defconfig | 2597 +++++++++++++++++++++++ arch/arm/mach-mx5/Kconfig | 15 + arch/arm/mach-mx5/Makefile | 1 + arch/arm/mach-mx5/board-mx53_efikasb.c | 622 ++++++ arch/arm/tools/mach-types | 1 + 5 files changed, 3236 insertions(+) create mode 100644 arch/arm/configs/mx53_efikasb_defconfig create mode 100644 arch/arm/mach-mx5/board-mx53_efikasb.c diff --git a/arch/arm/configs/mx53_efikasb_defconfig b/arch/arm/configs/mx53_efikasb_defconfig new file mode 100644 index 00000000000..6b399a9dd03 --- /dev/null +++ b/arch/arm/configs/mx53_efikasb_defconfig @@ -0,0 +1,2597 @@ +# +# Automatically generated make config: don't edit +# Linux/arm 2.6.38 Kernel Configuration +# Thu Sep 15 16:09:13 2011 +# +CONFIG_ARM=y +CONFIG_HAVE_PWM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_SCHED_CLOCK=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_FIQ=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y +CONFIG_HAVE_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set +CONFIG_HAVE_SPARSE_IRQ=y +# CONFIG_GENERIC_PENDING_IRQ is not set +# CONFIG_AUTO_IRQ_AFFINITY is not set +# CONFIG_IRQ_PER_CPU is not set +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +# CONFIG_TINY_RCU is not set +# CONFIG_TINY_PREEMPT_RCU is not set +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +CONFIG_ARCH_MXC=y +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5P6442 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_S5PV310 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +CONFIG_IMX_HAVE_PLATFORM_FEC=y +CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SRTC=y +CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SSI=y +CONFIG_IMX_HAVE_PLATFORM_IMX_UART=y +CONFIG_IMX_HAVE_PLATFORM_MXC_NAND=y +CONFIG_IMX_HAVE_PLATFORM_MXC_PWM=y +CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX=y +CONFIG_IMX_HAVE_PLATFORM_IMX_IPUV3=y +CONFIG_IMX_HAVE_PLATFORM_IMX_TVE=y +CONFIG_IMX_HAVE_PLATFORM_IMX_VPU=y +CONFIG_IMX_HAVE_PLATFORM_IMX_DVFS=y +CONFIG_IMX_HAVE_PLATFORM_AHCI=y +CONFIG_IMX_HAVE_PLATFORM_IMX_IIM=y +CONFIG_IMX_HAVE_PLATFORM_MXC_GPU=y +CONFIG_IMX_HAVE_PLATFORM_LDB=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y + +# +# Freescale MXC Implementations +# +# CONFIG_ARCH_MX1 is not set +# CONFIG_ARCH_MX2 is not set +# CONFIG_ARCH_MX25 is not set +# CONFIG_ARCH_MX3 is not set +# CONFIG_ARCH_MXC91231 is not set +CONFIG_ARCH_MX5=y +# CONFIG_ARCH_MX6 is not set +CONFIG_ARCH_MX53=y +CONFIG_SOC_IMX53=y +CONFIG_FORCE_MAX_ZONEORDER=11 + +# +# MX5 platforms: +# +# CONFIG_MACH_MX51_BABBAGE is not set +# CONFIG_MACH_MX51_3DS is not set +# CONFIG_MACH_EUKREA_CPUIMX51 is not set +# CONFIG_MACH_EUKREA_CPUIMX51SD is not set +# CONFIG_MACH_MX51_EFIKAMX is not set +# CONFIG_MACH_MX51_EFIKASB is not set +# CONFIG_MACH_MX53_EVK is not set +# CONFIG_MACH_MX53_SMD is not set +# CONFIG_MACH_MX53_LOCO is not set +CONFIG_MACH_MX53_EFIKASB=y +# CONFIG_MACH_MX53_ARD is not set +# CONFIG_MACH_MX50_RDP is not set +# CONFIG_MACH_IMX_BLUETOOTH_RFKILL is not set +CONFIG_DMA_ZONE_SIZE=24 +CONFIG_ISP1504_MXC=y +CONFIG_UTMI_MXC=y +# CONFIG_MXC_IRQ_PRIOR is not set +CONFIG_MXC_TZIC=y +CONFIG_MXC_PWM=y +# CONFIG_MXC_DEBUG_BOARD is not set +CONFIG_ARCH_MXC_IOMUX_V3=y +CONFIG_ARCH_MXC_AUDMUX_V2=y +CONFIG_IRAM_ALLOC=y + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_SWP_EMULATE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_743622 is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_VMSPLIT_3G is not set +CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0x80000000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=223.223.223.11:/srv/arm2_new,v3 ip=dhcp" +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_IMX=y +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_APM_EMULATION=y +CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_CAN=y +CONFIG_CAN_RAW=y +CONFIG_CAN_BCM=y + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=y +# CONFIG_CAN_SLCAN is not set +# CONFIG_CAN_DEV is not set +CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=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 + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +# CONFIG_BT_HCIUART_H4 is not set +# CONFIG_BT_HCIUART_BCSP is not set +# CONFIG_BT_HCIUART_ATH3K is not set +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +CONFIG_BT_HCIVHCI=y +# CONFIG_BT_MRVL is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# + +# +# Some wireless drivers require a rate control algorithm +# +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_TESTS=m +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLKDEVS is not set +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_MXC=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=256 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_SATA_PMP is not set + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_SATA_MV is not set + +# +# PATA SFF controllers with BMDMA +# + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_PLATFORM is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_MII=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM63XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_FEC is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_USB_ZD1201 is not set +# CONFIG_HOSTAP is not set +# CONFIG_ATH6K_LEGACY is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=y +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_APMPOWER is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_IMX is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_MXC is not set +CONFIG_KEYBOARD_MPR121=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_QT602240 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_P1003 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +CONFIG_TOUCHSCREEN_MAX11801=y +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_ISL29023 is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +# CONFIG_MXC_IIM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +CONFIG_I2C_IMX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_IMX_VER_0_7=y +CONFIG_SPI_IMX_VER_2_3=y +CONFIG_SPI_IMX=y +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_APM_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_BQ20Z75 is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_GPIO is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX17135 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_IMX_AHCI is not set +# CONFIG_MXC_MMA8450 is not set +# CONFIG_MXC_MMA8451 is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_IMX2_WDT=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_PMIC_DIALOG is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_MAX17135 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_CUSTOMISE=y + +# +# Customize TV tuners +# +# CONFIG_MEDIA_TUNER_SIMPLE is not set +# CONFIG_MEDIA_TUNER_TDA8290 is not set +# CONFIG_MEDIA_TUNER_TDA827X is not set +# CONFIG_MEDIA_TUNER_TDA18271 is not set +# CONFIG_MEDIA_TUNER_TDA9887 is not set +# CONFIG_MEDIA_TUNER_TEA5761 is not set +# CONFIG_MEDIA_TUNER_TEA5767 is not set +# CONFIG_MEDIA_TUNER_MT20XX is not set +# CONFIG_MEDIA_TUNER_MT2060 is not set +# CONFIG_MEDIA_TUNER_MT2266 is not set +# CONFIG_MEDIA_TUNER_MT2131 is not set +# CONFIG_MEDIA_TUNER_QT1010 is not set +# CONFIG_MEDIA_TUNER_XC2028 is not set +# CONFIG_MEDIA_TUNER_XC5000 is not set +# CONFIG_MEDIA_TUNER_MXL5005S is not set +# CONFIG_MEDIA_TUNER_MXL5007T is not set +# CONFIG_MEDIA_TUNER_MC44S803 is not set +CONFIG_MEDIA_TUNER_MAX2165=m +# CONFIG_MEDIA_TUNER_TDA18218 is not set +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders/decoders and other helper chips +# + +# +# Audio decoders +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_AK881X is not set + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_MXC_CAMERA is not set +CONFIG_VIDEO_MXC_OUTPUT=y +CONFIG_VIDEO_MXC_IPU_OUTPUT=y +# CONFIG_VIDEO_MXC_IPUV1_WVGA_OUTPUT is not set +# CONFIG_VIDEO_MXC_PXP_V4L2 is not set +# CONFIG_VIDEO_MXC_OPL is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_TIMBERDALE is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_SOC_CAMERA is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_I2C_SI4713 is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_SI470X is not set +# CONFIG_USB_MR800 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_ADP8860 is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +CONFIG_FB_MXC=y +CONFIG_FB_MXC_SYNC_PANEL=y +# CONFIG_FB_MXC_EPSON_VGA_SYNC_PANEL is not set +# CONFIG_FB_MXC_TVOUT_TVE is not set +CONFIG_FB_MXC_LDB=y +# CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL is not set +# CONFIG_FB_MXC_SEIKO_WVGA_SYNC_PANEL is not set +# CONFIG_FB_MXC_SII902X is not set +# CONFIG_FB_MXC_CH7026 is not set +# CONFIG_FB_MXC_TVOUT_CH7024 is not set +# CONFIG_FB_MXC_ASYNC_PANEL is not set +# CONFIG_FB_MXC_EINK_PANEL is not set +# CONFIG_FB_MXC_ELCDIF_FB is not set +# CONFIG_FB_MXC_HDMI is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +CONFIG_SND_SOC=y +# CONFIG_SND_SOC_CACHE_LZO is not set +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_MXC_SOC_MX2=y +CONFIG_SND_SOC_IMX_CS42L52=y +# CONFIG_SND_SOC_IMX_SPDIF is not set +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_3M_PCT is not set +CONFIG_HID_A4TECH=m +# CONFIG_HID_ACRUX_FF is not set +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +# CONFIG_HID_CANDO is not set +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +# CONFIG_HID_PRODIKEYS is not set +CONFIG_HID_CYPRESS=m +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EGALAX is not set +# CONFIG_HID_ELECOM is not set +CONFIG_HID_EZKEY=m +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +CONFIG_HID_GYRATION=m +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +CONFIG_HID_LOGITECH=m +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIWII_FF is not set +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=m +# CONFIG_HID_MOSART is not set +CONFIG_HID_MONTEREY=m +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +CONFIG_HID_PANTHERLORD=m +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=m +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_QUANTA is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set +# CONFIG_HID_ROCCAT_PYRA is not set +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +# CONFIG_HID_STANTUM is not set +CONFIG_HID_SUNPLUS=m +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ARC=y +CONFIG_USB_EHCI_ARC_OTG=y +# CONFIG_USB_STATIC_IRAM is not set +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_EHCI_MXC is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +# CONFIG_USB_EZUSB is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SAMBA is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA_U2O is not set +# CONFIG_USB_GADGET_M66592 is not set +CONFIG_USB_GADGET_ARC=y +CONFIG_USB_ARC=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_MXC_OTG is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +# CONFIG_MMC_MXC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TRIGGERS is not set + +# +# LED Triggers +# + +# +# LED Triggers +# +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_MXC is not set +CONFIG_RTC_DRV_MXC_V2=y +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_MXC_PXP=y +CONFIG_MXC_PXP_CLIENT_DEVICE=y +# CONFIG_TIMB_DMA is not set +CONFIG_IMX_SDMA=y +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y + +# +# MXC support drivers +# +CONFIG_MXC_IPU=y +CONFIG_MXC_IPU_V3=y +CONFIG_MXC_IPU_V3EX=y + +# +# MXC SSI support +# +CONFIG_MXC_SSI=y + +# +# MXC Digital Audio Multiplexer support +# +CONFIG_MXC_DAM=y + +# +# MXC PMIC support +# +# CONFIG_MXC_PMIC_MC13783 is not set +# CONFIG_MXC_PMIC_MC13892 is not set +# CONFIG_MXC_PMIC_MC34704 is not set +# CONFIG_MXC_PMIC_MC9SDZ60 is not set +# CONFIG_MXC_PMIC_MC9S08DZ60 is not set + +# +# MXC Security Drivers +# +# CONFIG_MXC_SECURITY_SCC is not set +# CONFIG_MXC_SECURITY_SCC2 is not set +# CONFIG_MXC_SECURITY_RNG is not set + +# +# SAHARA2 Security Hardware Support +# +# CONFIG_MXC_SAHARA is not set + +# +# MXC MPEG4 Encoder Kernel module support +# +# CONFIG_MXC_HMP4E is not set + +# +# MXC HARDWARE EVENT +# +# CONFIG_MXC_HWEVENT is not set + +# +# MXC VPU(Video Processing Unit) support +# +CONFIG_MXC_VPU=y +# CONFIG_MXC_VPU_DEBUG is not set + +# +# MXC Asynchronous Sample Rate Converter support +# +CONFIG_MXC_ASRC=y + +# +# MXC Bluetooth support +# + +# +# Broadcom GPS ioctrl support +# + +# +# MXC Media Local Bus Driver +# +# CONFIG_MXC_MLB is not set + +# +# i.MX ADC support +# +# CONFIG_IMX_ADC is not set + +# +# MXC GPU support +# +CONFIG_MXC_AMD_GPU=y + +# +# ANATOP_THERMAL +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_FS_XIP=y +CONFIG_JBD=y +CONFIG_JBD2=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_XATTR=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +# CONFIG_LOGFS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +CONFIG_BKL=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE=y +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_TEST=m +# CONFIG_CRYPTO_CRYPTODEV is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig index ce2ad6c7240..482bf9be450 100644 --- a/arch/arm/mach-mx5/Kconfig +++ b/arch/arm/mach-mx5/Kconfig @@ -202,6 +202,21 @@ config MACH_MX53_LOCO Include support for MX53 LOCO platform. This includes specific configurations for the board and its peripherals. +config MACH_MX53_EFIKASB + bool "Support MX53 EFIKASB platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IMX_SRTC + select IMX_HAVE_PLATFORM_MXC_GPU + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_AHCI + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for MX53 EFIKASB platform. This includes specific + configurations for the board and its peripherals. + config MACH_MX53_ARD bool "Support MX53 ARD platform" select SOC_IMX53 diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile index 557a514a90a..7e0f41978c0 100644 --- a/arch/arm/mach-mx5/Makefile +++ b/arch/arm/mach-mx5/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o mx53_smd_pmic_da9053.o obj-$(CONFIG_MACH_IMX_BLUETOOTH_RFKILL) += imx_bt_rfkill.o obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o mx53_loco_pmic_da9053.o +obj-$(CONFIG_MACH_MX53_EFIKASB) += board-mx53_efikasb.o obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c new file mode 100644 index 00000000000..8096350970f --- /dev/null +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -0,0 +1,622 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "crm_regs.h" +#include "devices-imx53.h" +#include "devices.h" +#include "usb.h" + +/* MX53 Efika SB GPIO PIN configurations */ +#define USBDR_OC IMX_GPIO_NR(4, 14) /* GPIO_4_14 */ +#define USBDR_PWREN IMX_GPIO_NR(4, 15) /* GPIO_4_15 */ +#define USBH1_OC IMX_GPIO_NR(3, 30) /* GPIO_3_30 */ +#define USBH1_PWREN IMX_GPIO_NR(3, 31) /* GPIO_3_31 */ +#define CLKO IMX_GPIO_NR(1, 5) /* GPIO_1_5 */ +#define WIFISWITCH IMX_GPIO_NR(1, 0) /* GPIO_1_0 */ +#define SD1_WP IMX_GPIO_NR(1, 9) /* GPIO_1_9 */ + +#define PERIPH_RESET IMX_GPIO_NR(5, 28) /* GPIO_5_28 */ +#define PERIPH_PWR IMX_GPIO_NR(5, 29) /* GPIO_5_29 */ + +/* GPIO I2C */ +#define GPIO_SDA IMX_GPIO_NR(5, 27) /* GPIO_5_27 */ +#define GPIO_SCL IMX_GPIO_NR(5, 26) /* GPIO_5_26 */ + +extern void __iomem *imx_otg_base; + +static iomux_v3_cfg_t mx53_efikasb_pads[] = { + /* USB */ + MX53_PAD_KEY_COL4__GPIO4_14, /* overcurrent */ + MX53_PAD_KEY_ROW4__GPIO4_15, /* pwr_en */ + MX53_PAD_EIM_D30__GPIO3_30, /* overcurrent input */ + MX53_PAD_EIM_D31__GPIO3_31, /* power enable */ + /* AUDIO */ + MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, + MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD, + MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS, + MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD, + /* PERIPHERAL */ + MX53_PAD_GPIO_5__CCM_CLKO, /* CLKO master audio/camera clock */ + MX53_PAD_GPIO_0__GPIO1_0, /* WIFI switch */ + MX53_PAD_CSI0_DAT10__GPIO5_28, /* Periph Reset */ + MX53_PAD_CSI0_DAT11__GPIO5_29, /* Periph Power Down */ + /* SD1 */ + MX53_PAD_SD1_CMD__ESDHC1_CMD, + MX53_PAD_SD1_CLK__ESDHC1_CLK, + MX53_PAD_SD1_DATA0__ESDHC1_DAT0, + MX53_PAD_SD1_DATA1__ESDHC1_DAT1, + MX53_PAD_SD1_DATA2__ESDHC1_DAT2, + MX53_PAD_SD1_DATA3__ESDHC1_DAT3, + MX53_PAD_GPIO_9__GPIO1_9, /* SD1 write protect */ + /* SD2 */ + MX53_PAD_SD2_CMD__ESDHC2_CMD, + MX53_PAD_SD2_CLK__ESDHC2_CLK, + MX53_PAD_SD2_DATA0__ESDHC2_DAT0, + MX53_PAD_SD2_DATA1__ESDHC2_DAT1, + MX53_PAD_SD2_DATA2__ESDHC2_DAT2, + MX53_PAD_SD2_DATA3__ESDHC2_DAT3, + /* LVDS */ +/* MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3, */ /* Schematic says no */ + MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK, + MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2, + MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, + MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, + /* I2C1 */ +/* MX53_PAD_CSI0_DAT8__I2C1_SDA, */ +/* MX53_PAD_CSI0_DAT9__I2C1_SCL, */ + MX53_PAD_CSI0_DAT8__GPIO5_26, + MX53_PAD_CSI0_DAT9__GPIO5_27, + /* UART */ + MX53_PAD_PATA_DIOW__UART1_TXD_MUX, + MX53_PAD_PATA_DMACK__UART1_RXD_MUX, + MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, + MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, + /* CAMERA */ + MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12, + MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13, + MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14, + MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15, + MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16, + MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17, + MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18, + MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19, + MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC, + MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC, + MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK, +}; + +static iomux_v3_cfg_t mx53_efikasb_nand_pads[] = { + MX53_PAD_NANDF_CLE__EMI_NANDF_CLE, + MX53_PAD_NANDF_ALE__EMI_NANDF_ALE, + MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B, + MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B, + MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B, + MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0, + MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0, + MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1, + MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2, /* --> not connected */ + MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3, /* --> not connected */ + MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0, + MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1, + MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2, + MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3, + MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4, + MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5, + MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6, + MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7, +}; + +static struct fb_videomode video_modes[] = { + { + /* WSVGA 1024x600 @ 60 Hz */ + "WSVGA", 60, 1024, 600, 22800, + 80, 40, + 20, 21, + 4, 4, + FB_SYNC_OE_LOW_ACT, + FB_VMODE_NONINTERLACED, + 0,}, +}; + +static struct ipuv3_fb_platform_data efikasb_fb0_data = { + .interface_pix_fmt = IPU_PIX_FMT_BGR24, + .mode_str = "WSVGA", + .modes = video_modes, + .num_modes = ARRAY_SIZE(video_modes), +}; + +static struct ipuv3_fb_platform_data efikasb_fb1_data = { + .interface_pix_fmt = IPU_PIX_FMT_BGR24, + .mode_str = "WSVGA", + .modes = video_modes, + .num_modes = ARRAY_SIZE(video_modes), +}; + +static struct imx_ipuv3_platform_data ipu_data = { + .rev = 3, + .fb_head0_platform_data = &efikasb_fb0_data, + .fb_head1_platform_data = &efikasb_fb1_data, + .primary_di = MXC_PRI_DI0, +}; + +static struct fsl_mxc_ldb_platform_data ldb_data = { + .ext_ref = 1, +}; + +static struct mxc_dvfs_platform_data efikasb_dvfs_core_data = { + .reg_id = "DA9052_BUCK_CORE", + .clk1_id = "cpu_clk", + .clk2_id = "gpc_dvfs_clk", + .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, + .gpc_vcr_offset = MXC_GPC_VCR_OFFSET, + .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET, + .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET, + .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET, + .prediv_mask = 0x1F800, + .prediv_offset = 11, + .prediv_val = 3, + .div3ck_mask = 0xE0000000, + .div3ck_offset = 29, + .div3ck_val = 2, + .emac_val = 0x08, + .upthr_val = 25, + .dnthr_val = 9, + .pncthr_val = 33, + .upcnt_val = 10, + .dncnt_val = 10, + .delay_time = 30, +}; + + +static const struct esdhc_platform_data mx53_efikasb_sd1_data __initconst = { + .always_present = true, + .wp_gpio = SD1_WP, +}; + +static const struct esdhc_platform_data mx53_efikasb_sd2_data __initconst = { + .always_present = true, +}; + +static struct fsl_mxc_camera_platform_data camera_data = { + .mclk = 27000000, + .csi = 0, +}; + +static struct mxc_audio_platform_data cs42l52_data = { + .ssi_num = 1, + .src_port = 2, + .ext_port = 3, + .sysclk = 27000000, +}; + +static struct platform_device cs42l52_device = { + .name = "imx-cs42l52", +}; + + +static const struct imxi2c_platform_data mx53_efikasb_i2c_data __initconst = { + .bitrate = 100000, +}; + +static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { + { + .type = "cs42l52", + .addr = 0x4a, + }, + { + .type = "gc0308", + .addr = 0x42, + .platform_data = (void *)&camera_data, + }, +}; + +/* Temporary GPIO I2C solution */ +static struct i2c_gpio_platform_data i2c_gpio_data = { + .sda_pin = GPIO_SDA, + .scl_pin = GPIO_SCL, +}; + +static struct platform_device i2c_gpio_device = { + .name = "i2c-gpio", + .id = 0, +}; + +static int nand_init(void) +{ + u32 i, reg; + void __iomem *base; + +#define M4IF_GENP_WEIM_MM_MASK 0x00000001 +#define WEIM_GCR2_MUX16_BYP_GRANT_MASK 0x00001000 + + base = ioremap(MX53_M4IF_BASE_ADDR, SZ_4K); + reg = __raw_readl(base + 0xc); + reg &= ~M4IF_GENP_WEIM_MM_MASK; + __raw_writel(reg, base + 0xc); + + iounmap(base); + + base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K); + for (i = 0x4; i < 0x94; i += 0x18) { + reg = __raw_readl((u32)base + i); + reg &= ~WEIM_GCR2_MUX16_BYP_GRANT_MASK; + __raw_writel(reg, (u32)base + i); + } + iounmap(base); + + return 0; +} + + +/* NAND Flash Partitions */ +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition nand_flash_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 32 * 1024 * 1024}, + { + .name = "nand.kernel", + .offset = MTDPART_OFS_APPEND, + .size = 128 * 1024 * 1024}, + { + .name = "nand.rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL}, +}; +#endif + +static struct flash_platform_data efikasb_nand_data = { +#ifdef CONFIG_MTD_PARTITIONS + .parts = nand_flash_partitions, + .nr_parts = ARRAY_SIZE(nand_flash_partitions), +#endif + .width = 1, + .init = nand_init, +}; + +static struct resource mxc_nand_resources[] = { + { + .flags = IORESOURCE_MEM, + .name = "NFC_AXI_BASE", + .start = MX53_NFC_AXI_BASE_ADDR , + .end = MX53_NFC_AXI_BASE_ADDR + SZ_8K - 1, + }, + { + .flags = IORESOURCE_MEM, + .name = "NFC_IP_BASE", + .start = MX53_NFC_BASE_ADDR + 0x00, + .end = MX53_NFC_BASE_ADDR + 0x34 - 1, + }, + { + .flags = IORESOURCE_IRQ, + .start = MX53_INT_NFC, + .end = MX53_INT_NFC, + }, +}; + +struct platform_device mxc_nandv2_mtd_device = { + .name = "mxc_nandv2_flash", + .id = 0, + .resource = mxc_nand_resources, + .num_resources = ARRAY_SIZE(mxc_nand_resources), +}; + + +static void mx53_efikasb_usbh1_vbus(bool on) +{ + if (on) + gpio_set_value(USBH1_PWREN, 1); + else + gpio_set_value(USBH1_PWREN, 0); +} + +static void mx53_efikasb_usbdr_vbus(bool on) +{ + if (on) + gpio_set_value(USBDR_PWREN, 1); + else + gpio_set_value(USBDR_PWREN, 0); +} + +static void mx53_efikasb_wlan_power(bool on) +{ + if (on) + gpio_set_value(WIFISWITCH, 1); + else + gpio_set_value(WIFISWITCH, 0); +} + +static void mx53_efikasb_periph_power(bool on) +{ + if (on) + gpio_set_value(PERIPH_PWR, 1); + else + gpio_set_value(PERIPH_PWR, 0); +} + +static void mx53_efikasb_do_periph_reset(void) +{ + gpio_set_value(PERIPH_RESET, 0); + mdelay(10); /* Should be fine... */ + gpio_set_value(PERIPH_RESET, 1); +} + +static struct imx_ssi_platform_data efikasb_ssi_pdata = { + .flags = IMX_SSI_DMA | IMX_SSI_SYN | + IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE, +}; + + +static struct mxc_gpu_platform_data gpu_data __initdata; +/*! + * Board specific fixup function. It is called by \b setup_arch() in + * setup.c file very early on during kernel starts. It allows the user to + * statically fill in the proper values for the passed-in parameters. None of + * the parameters is used currently. + * + * @param desc pointer to \b struct \b machine_desc + * @param tags pointer to \b struct \b tag + * @param cmdline pointer to the command line + * @param mi pointer to \b struct \b meminfo + */ +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + struct tag *t; + struct tag *mem_tag = 0; + int total_mem = SZ_512M; + int left_mem = 0; + int gpu_mem = SZ_32M; + int fb_mem = SZ_16M; + char *str; + + for_each_tag(mem_tag, tags) { + if (mem_tag->hdr.tag == ATAG_MEM) { + total_mem = mem_tag->u.mem.size; + left_mem = total_mem - gpu_mem - fb_mem; + break; + } + } + + for_each_tag(t, tags) { + if (t->hdr.tag == ATAG_CMDLINE) { + str = t->u.cmdline.cmdline; + str = strstr(str, "mem="); + if (str != NULL) { + str += 4; + left_mem = memparse(str, &str); + if (left_mem == 0 || left_mem > total_mem) + left_mem = total_mem - gpu_mem - fb_mem; + } + + str = t->u.cmdline.cmdline; + str = strstr(str, "gpu_memory="); + if (str != NULL) { + str += 11; + gpu_mem = memparse(str, &str); + } + + break; + } + } + + if (mem_tag) { + fb_mem = total_mem - left_mem - gpu_mem; + if (fb_mem < 0) { + gpu_mem = total_mem - left_mem; + fb_mem = 0; + } + mem_tag->u.mem.size = left_mem; + + /* reserve memory for gpu */ + gpu_data.reserved_mem_base = + mem_tag->u.mem.start + left_mem; + gpu_data.reserved_mem_size = gpu_mem; + + /* reserve memory for fb */ + efikasb_fb0_data.res_base = gpu_data.reserved_mem_base + + gpu_data.reserved_mem_size; + efikasb_fb0_data.res_size = fb_mem; + efikasb_fb1_data.res_base = gpu_data.reserved_mem_base + + gpu_data.reserved_mem_size; + efikasb_fb1_data.res_size = fb_mem; + } +} + + +static void __init mx53_efikasb_io_init(void) +{ + + imx_otg_base = MX53_IO_ADDRESS(MX53_OTG_BASE_ADDR); + + mxc_iomux_v3_setup_multiple_pads(mx53_efikasb_pads, + ARRAY_SIZE(mx53_efikasb_pads)); + + mxc_iomux_v3_setup_multiple_pads(mx53_efikasb_nand_pads, + ARRAY_SIZE(mx53_efikasb_nand_pads)); + + /* SD1 Write Protect */ + gpio_request(SD1_WP, "sd1-wp"); + gpio_direction_input(SD1_WP); + gpio_free(SD1_WP); + + /* USB PWR enable */ + gpio_request(USBH1_PWREN, "usb-pwr1"); + gpio_direction_output(USBH1_PWREN, 0); + + gpio_request(USBDR_PWREN, "usb-pwr0"); + gpio_direction_output(USBDR_PWREN, 0); + + /* WIFI power */ + gpio_request(WIFISWITCH, "wifi-pwr"); + gpio_direction_output(WIFISWITCH, 0); + + /* Peripheral power */ + gpio_request(PERIPH_PWR, "periph-pwr"); + gpio_direction_output(PERIPH_PWR, 0); + + /* Peripheral reset */ + gpio_request(PERIPH_RESET, "periph-reset"); + gpio_direction_output(PERIPH_RESET, 0); + +} + +/* Sets up the MCLK for audio and camera */ +static void efikasb_mclk_init(void) +{ + + struct clk *oclk, *pclk; + int ret = 0; + + oclk = clk_get(NULL, "cko1"); + pclk = clk_get(NULL, "pll3"); + + ret = clk_set_parent(oclk, pclk); + if (ret) + printk(KERN_ERR "Can't set parent clock.\n"); + + clk_put(pclk); + + ret = clk_set_rate(oclk, 27000000); + if (ret) + printk(KERN_ERR "Can't set clock rate.\n"); + + ret = clk_enable(oclk); + if (ret) + printk(KERN_ERR "Can't enable Output Clock.\n"); +} + + +static void __init mx53_efikasb_board_init(void) +{ + mx53_efikasb_io_init(); + + imx53_add_imx_uart(0, NULL); + + imx53_add_ipuv3(&ipu_data); + + imx53_add_vpu(); + imx53_add_ldb(&ldb_data); + imx53_add_v4l2_output(0); + + imx53_add_imx2_wdt(0, NULL); + imx53_add_srtc(); + imx53_add_dvfs_core(&efikasb_dvfs_core_data); + + /* I2C */ + /* imx53_add_imx_i2c(0, &mx53_efikasb_i2c_data); */ + mxc_register_device(&i2c_gpio_device, &i2c_gpio_data); + + i2c_register_board_info(0, mxc_i2c0_board_info, + ARRAY_SIZE(mxc_i2c0_board_info)); + + /* SD Interfaces */ + imx53_add_sdhci_esdhc_imx(0, &mx53_efikasb_sd1_data); + imx53_add_sdhci_esdhc_imx(1, &mx53_efikasb_sd2_data); + + /* USB */ + mx5_set_otghost_vbus_func(mx53_efikasb_usbdr_vbus); + mx5_usb_dr_init(); + mx5_set_host1_vbus_func(mx53_efikasb_usbh1_vbus); + mx5_usbh1_init(); + + /* Audio */ + imx53_add_imx_ssi(1, &efikasb_ssi_pdata); + mxc_register_device(&cs42l52_device, &cs42l52_data); + + /* NAND */ + mxc_register_device(&mxc_nandv2_mtd_device, &efikasb_nand_data); + + /*GPU*/ + if (mx53_revision() >= IMX_CHIP_REVISION_2_0) + gpu_data.z160_revision = 1; + else + gpu_data.z160_revision = 0; + imx53_add_mxc_gpu(&gpu_data); + + /* this call required to release SCC RAM partition held by ROM + * during boot, even if SCC2 driver is not part of the image + */ + imx53_add_mxc_scc2(); + + /* MCLK for camera and audio */ + efikasb_mclk_init(); + + /* Power on peripherals */ + mx53_efikasb_periph_power(1); + + /* Power on WLan */ + mx53_efikasb_wlan_power(1); + /* And do reset... */ + mx53_efikasb_do_periph_reset(); +} + +static void __init mx53_efikasb_timer_init(void) +{ + mx53_clocks_init(32768, 24000000, 0, 0); +} + +static struct sys_timer mx53_efikasb_timer = { + .init = mx53_efikasb_timer_init, +}; + +MACHINE_START(MX53_EFIKASB, "Genesi MX53 Efika SB Board") + .fixup = fixup_mxc_board, + .map_io = mx53_map_io, + .init_early = imx53_init_early, + .init_irq = mx53_init_irq, + .timer = &mx53_efikasb_timer, + .init_machine = mx53_efikasb_board_init, +MACHINE_END diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 7ca41f0a09b..1c92901f318 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -1099,3 +1099,4 @@ ecuv5 MACH_ECUV5 ECUV5 3421 hsgx6d MACH_HSGX6D HSGX6D 3422 dawad7 MACH_DAWAD7 DAWAD7 3423 sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424 +mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610 From 08625c94a02f1dc0b59c02315c326bc783efd9a6 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:29:09 +0300 Subject: [PATCH 02/32] Fixed dam driver, but for MX53 only. TODO: more elegant solution. --- drivers/mxc/dam/dam.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mxc/dam/dam.c b/drivers/mxc/dam/dam.c index 9e57e1a260e..8f61350e844 100644 --- a/drivers/mxc/dam/dam.c +++ b/drivers/mxc/dam/dam.c @@ -32,9 +32,11 @@ */ #include +#define AUDMUX_BASE_ADDR MX53_AUDMUX_BASE_ADDR + #define ModifyRegister32(a, b, c) (c = (((c)&(~(a))) | (b))) -#define DAM_VIRT_BASE_ADDR IO_ADDRESS(AUDMUX_BASE_ADDR) +#define DAM_VIRT_BASE_ADDR MX53_IO_ADDRESS(AUDMUX_BASE_ADDR) #ifndef _reg_DAM_PTCR1 #define _reg_DAM_PTCR1 (*((volatile unsigned long *) \ From 26358b9a990bf8a8e830f660c118959319071c56 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:31:39 +0300 Subject: [PATCH 03/32] Fixed ssi driver, but for MX53 only. TODO: more elegant solution. --- drivers/mxc/ssi/ssi.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/mxc/ssi/ssi.c b/drivers/mxc/ssi/ssi.c index da09631283e..d26fd82840a 100644 --- a/drivers/mxc/ssi/ssi.c +++ b/drivers/mxc/ssi/ssi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -127,11 +128,11 @@ void *get_ssi_base_addr(unsigned int ssi) { if (ssi_platform_data->ssi_num == 2) { if (ssi == SSI1) - return IO_ADDRESS(base_addr_1); + return MX53_IO_ADDRESS(base_addr_1); else - return IO_ADDRESS(base_addr_2); + return MX53_IO_ADDRESS(base_addr_2); } - return IO_ADDRESS(base_addr_1); + return MX53_IO_ADDRESS(base_addr_1); } void set_register_bits(unsigned int mask, unsigned int data, @@ -565,11 +566,11 @@ unsigned char ssi_rx_fifo_counter(ssi_mod module, fifo_nb fifo) if (ssi_fifo_0 == fifo) { result = getreg_value(MXC_SSISFCSR, module); - result &= (0xF << SSI_RX_FIFO_0_COUNT_SHIFT); + result &= (unsigned char)(0xF << SSI_RX_FIFO_0_COUNT_SHIFT); result = result >> SSI_RX_FIFO_0_COUNT_SHIFT; } else { result = getreg_value(MXC_SSISFCSR, module); - result &= (0xF << SSI_RX_FIFO_1_COUNT_SHIFT); + result &= (unsigned char)(0xF << SSI_RX_FIFO_1_COUNT_SHIFT); result = result >> SSI_RX_FIFO_1_COUNT_SHIFT; } @@ -936,11 +937,11 @@ unsigned char ssi_tx_fifo_counter(ssi_mod module, fifo_nb fifo) if (ssi_fifo_0 == fifo) { result = getreg_value(MXC_SSISFCSR, module); - result &= (0xF << SSI_TX_FIFO_0_COUNT_SHIFT); + result &= (unsigned char)(0xF << SSI_TX_FIFO_0_COUNT_SHIFT); result >>= SSI_TX_FIFO_0_COUNT_SHIFT; } else { result = getreg_value(MXC_SSISFCSR, module); - result &= (0xF << SSI_TX_FIFO_1_COUNT_SHIFT); + result &= (unsigned char)(0xF << SSI_TX_FIFO_1_COUNT_SHIFT); result >>= SSI_TX_FIFO_1_COUNT_SHIFT; } From 376745d72505a4bf35961f2684cd41c642974789 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:37:05 +0300 Subject: [PATCH 04/32] CS42L52 codec. TODO: cleanup --- sound/soc/codecs/cs42l52.c | 1101 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs42l52.h | 298 ++++++++++ 2 files changed, 1399 insertions(+) create mode 100644 sound/soc/codecs/cs42l52.c create mode 100644 sound/soc/codecs/cs42l52.h diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c new file mode 100644 index 00000000000..e2df36fa35e --- /dev/null +++ b/sound/soc/codecs/cs42l52.c @@ -0,0 +1,1101 @@ +/* + * cs42l52.c -- CS42L52 ALSA SoC audio driver + * + * Copyright 2011 CirrusLogic, Inc. + * + * Author: Brian Austin + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs42l52.h" + +struct sp_config { + u8 spc, format, spfs; + u32 srate; +}; + +struct cs42l52_private { + enum snd_soc_control_type control_type; + void *control_data; + u8 reg_cache[CS42L52_CACHEREGNUM]; + u32 sysclk; /* external MCLK */ + u8 mclksel; /* MCLKx */ + u32 mclk; /* internal MCLK */ + u8 flags; + struct sp_config config; +}; + +/* + * CS42L52 register default value + */ + +static const u8 cs42l52_reg[] = { + 0x00, 0xE0, 0x01, 0x07, 0x05, /*4*/ + 0xa0, 0x00, 0x00, 0x81, /*8*/ + 0x81, 0xa5, 0x00, 0x00, /*12*/ + 0x60, 0x02, 0x00, 0x00, /*16*/ + 0x00, 0x00, 0x00, 0x00, /*20*/ + 0x00, 0x00, 0x00, 0x80, /*24*/ + 0x80, 0x00, 0x00, 0x00, /*28*/ + 0x00, 0x00, 0x88, 0x00, /*32*/ + 0x00, 0x00, 0x00, 0x00, /*36*/ + 0x00, 0x00, 0x00, 0x7f, /*40*/ + 0xc0, 0x00, 0x3f, 0x00, /*44*/ + 0x00, 0x00, 0x00, 0x00, /*48*/ + 0x00, 0x3b, 0x00, 0x5f, /*52*/ +}; + +static inline int cs42l52_read_reg_cache(struct snd_soc_codec *codec, + u_int reg) +{ + u8 *cache = codec->reg_cache; + + return reg > CS42L52_CACHEREGNUM ? -EINVAL : cache[reg]; +} + +static inline void cs42l52_write_reg_cache(struct snd_soc_codec *codec, + u_int reg, u_int val) +{ + u8 *cache = codec->reg_cache; + + if(reg > CS42L52_CACHEREGNUM) + return; + cache[reg] = val & 0xff; +} + +static inline int cs42l52_get_revison(struct snd_soc_codec *codec) +{ + u8 data; + u8 addr; + int ret; + + struct cs42l52_private *info = snd_soc_codec_get_drvdata(codec); + + + if(codec->hw_write(codec->control_data, &addr, 1) == 1) + { + if(codec->hw_read(codec->control_data, 1) == 1) + { + if((data & CHIP_ID_MASK) != CHIP_ID ) + { + ret = -ENODEV; + } + } + else + ret = -EIO; + } + else + ret = -EIO; + + return ret < 0 ? ret : data; +} + +/** + * snd_soc_get_volsw - single mixer get callback + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to get the value of a single mixer control. + * + * Returns 0 for success. + */ +int cs42l52_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int rshift = mc->rshift; + int max = mc->max; + int min = mc->min; + int mmax = (max > min) ? max:min; + unsigned int mask = (1 << fls(mmax)) - 1; + + ucontrol->value.integer.value[0] = + ((snd_soc_read(codec, reg) >> shift) - min) & mask; + if (shift != rshift) + ucontrol->value.integer.value[1] = + ((snd_soc_read(codec, reg) >> rshift) - min) & mask; + + return 0; +} + +/** + * snd_soc_put_volsw - single mixer put callback + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to set the value of a single mixer control. + * + * Returns 0 for success. + */ +int cs42l52_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int rshift = mc->rshift; + int max = mc->max; + int min = mc->min; + int mmax = (max > min) ? max:min; + unsigned int mask = (1 << fls(mmax)) - 1; + unsigned short val, val2, val_mask; + + val = ((ucontrol->value.integer.value[0] + min) & mask); + + val_mask = mask << shift; + val = val << shift; + if (shift != rshift) { + val2 = ((ucontrol->value.integer.value[1] + min) & mask); + val_mask |= mask << rshift; + val |= val2 << rshift; + } + return snd_soc_update_bits(codec, reg, val_mask, val); +} + +/** + * snd_soc_info_volsw_2r - double mixer info callback + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to provide information about a double mixer control that + * spans 2 codec registers. + * + * Returns 0 for success. + */ +int cs42l52_info_volsw_2r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + int max = mc->max; + + if (max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = max; + return 0; +} + +/** + * snd_soc_get_volsw_2r - double mixer get callback + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to get the value of a double mixer control that spans 2 registers. + * + * Returns 0 for success. + */ +int cs42l52_get_volsw_2r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + int max = mc->max; + int min = mc->min; + int mmax = (max > min) ? max:min; + unsigned int mask = (1 << fls(mmax)) - 1; + int val, val2; + + val = snd_soc_read(codec, reg); + val2 = snd_soc_read(codec, reg2); + ucontrol->value.integer.value[0] = (val - min) & mask; + ucontrol->value.integer.value[1] = (val2 - min) & mask; + return 0; +} + +/** + * snd_soc_put_volsw_2r - double mixer set callback + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to set the value of a double mixer control that spans 2 registers. + * + * Returns 0 for success. + */ +int cs42l52_put_volsw_2r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + unsigned int reg = mc->reg; + unsigned int reg2 = mc->rreg; + int max = mc->max; + int min = mc->min; + int mmax = (max > min) ? max:min; + unsigned int mask = (1 << fls(mmax)) - 1; + int err; + unsigned short val, val2; + + val = (ucontrol->value.integer.value[0] + min) & mask; + val2 = (ucontrol->value.integer.value[1] + min) & mask; + + if ((err = snd_soc_update_bits(codec, reg, mask, val)) < 0) + return err; + + return snd_soc_update_bits(codec, reg2, mask, val2); +} + +#define SOC_SINGLE_S8_C_TLV(xname, xreg, xshift, xmax, xmin, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = snd_soc_info_volsw, .get = cs42l52_get_volsw,\ + .put = cs42l52_put_volsw, .tlv.p = (tlv_array),\ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .shift = xshift, .rshift = xshift, \ + .max = xmax, .min = xmin} } + +#define SOC_DOUBLE_R_S8_C_TLV(xname, xreg, xrreg, xmax, xmin, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = cs42l52_info_volsw_2r, \ + .get = cs42l52_get_volsw_2r, .put = cs42l52_put_volsw_2r, \ + .tlv.p = (tlv_array), \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .rreg = xrreg, .max = xmax, .min = xmin} } + +/* Analog Input PGA Mux */ +static const char *cs42l52_pgaa_text[] = { "INPUT1A", "INPUT2A", "INPUT3A", "INPUT4A", "MICA" }; +static const char *cs42l52_pgab_text[] = { "INPUT1B", "INPUT2B", "INPUT3B", "INPUT4B", "MICB" }; + +static const struct soc_enum pgaa_enum = + SOC_ENUM_SINGLE(ADC_PGA_A, 0, + ARRAY_SIZE(cs42l52_pgaa_text), cs42l52_pgaa_text); + +static const struct soc_enum pgab_enum = + SOC_ENUM_SINGLE(ADC_PGA_B, 0, + ARRAY_SIZE (cs42l52_pgab_text), cs42l52_pgab_text); + +static const struct snd_kcontrol_new pgaa_mux = +SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); + +static const struct snd_kcontrol_new pgab_mux = +SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum); + +/* + HP,LO Analog Volume TLV + -76dB ... -50 dB in 2dB steps + -50dB ... 12dB in 1dB steps +*/ +static const unsigned int hpaloa_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0), + 14,75, TLV_DB_SCALE_ITEM(-4900, 100, 0), +}; + +/* -102dB ... 12 dB in 0.5 dB steps */ +static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0); + +/* -96dB ... 12 dB in 1 dB steps */ +static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0); + +/* -6dB ... 12 dB in 0.5 dB steps */ +static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0); + +/* + HL, ESL, SPK, Limiter Threshold/Cushion TLV + 0dB -12 dB in -3dB steps + -12dB -30dB in -6dB steps +*/ +static const unsigned int limiter_tlv[] = { + TLV_DB_RANGE_HEAD(2), + 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), + 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0), +}; + +/* + * Stereo Mixer Input Attenuation (regs 35h-54h) TLV + * Mono Mixer Input Attenuation (regs 56h-5Dh) + + -62dB ... 0dB in 1dB steps, < -62dB = mute +*/ +static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); + +/* NG */ +static const char *cs42l52_ng_delay_text[] = + { "50ms", "100ms", "150ms", "200ms" }; + +static const struct soc_enum ng_delay_enum = + SOC_ENUM_SINGLE(NOISE_GATE_CTL, 0, + ARRAY_SIZE (cs42l52_ng_delay_text), cs42l52_ng_delay_text); + +static const char *cs42l52_ng_type_text[] = + {"Apply Specific", "Apply All"}; + +static const struct soc_enum ng_type_enum = + SOC_ENUM_SINGLE(NOISE_GATE_CTL, 6, + ARRAY_SIZE (cs42l52_ng_type_text), cs42l52_ng_type_text); + + +static const struct snd_kcontrol_new cs42l52_snd_controls[] = { + +SOC_DOUBLE_R_S8_C_TLV("Master Playback Volume", MASTERA_VOL, + MASTERB_VOL, 0xe4, 0x34, hl_tlv), + +/* Headphone */ +SOC_DOUBLE_R_S8_C_TLV("HP Digital Playback Volume", HPA_VOL, + HPB_VOL, 0xff, 0x1, hl_tlv), + +SOC_SINGLE_S8_C_TLV("HP Analog Playback Volume", + PB_CTL1, 5, 7, 0, hpaloa_tlv), + +SOC_SINGLE_S8_C_TLV("HP Digital Playback Switch", + PB_CTL2, 6, 7, 1, 1), + +/* Speaker */ +SOC_DOUBLE_R_S8_C_TLV("Speaker Playback Volume", SPKA_VOL, + SPKB_VOL, 0xff, 0x1, hl_tlv), +SOC_SINGLE_S8_C_TLV("Speaker Playback Switch", + PB_CTL2, 4, 5, 1, 1), + +/* Passthrough */ +SOC_DOUBLE_R_S8_C_TLV("Passthru Playback Volume", PASSTHRUA_VOL, + PASSTHRUB_VOL, 0x90, 0x88, hl_tlv), +SOC_SINGLE("Passthru Playback Switch", MISC_CTL, 4, 5, 1), + +/* Mic LineIN */ +SOC_DOUBLE_R_S8_C_TLV("Mic Gain Capture Volume", MICA_CTL, + MICB_CTL, 0, 31, micpga_tlv), + +/* ADC */ +SOC_DOUBLE_R_S8_C_TLV("ADC Capture Volume", ADCA_VOL, + ADCB_VOL, 0x80, 0xA0, ipd_tlv), +SOC_DOUBLE_R_S8_C_TLV("ADC Mixer Capture Volume", + ADCA_MIXER_VOL, ADCB_MIXER_VOL, 0x7f, 0x19, ipd_tlv), + +SOC_DOUBLE("ADC Switch", ADC_MISC_CTL, 0, 1, 1, 1), + +SOC_DOUBLE_R("ADC Mixer Switch", + ADCA_MIXER_VOL, ADCB_MIXER_VOL, 7, 1, 1), + +SOC_DOUBLE_R_S8_C_TLV("PGA Volume", PGAA_CTL, PGAB_CTL, 0x30, 0x18, micpga_tlv), + + +SOC_DOUBLE_R("PCM Mixer Playback Switch", + PCMA_MIXER_VOL, PCMB_MIXER_VOL, 7, 1, 1), + + + +SOC_DOUBLE_R_S8_C_TLV("PCM Mixer Playback Volume", + PCMA_MIXER_VOL, PCMB_MIXER_VOL, 0x7f, 0x19, hl_tlv), + +SOC_SINGLE_S8_C_TLV("Beep Volume", BEEP_VOL, 0, 0x1f, 0x07, hl_tlv), + +SOC_SINGLE_S8_C_TLV("Treble Gain Playback Volume", + TONE_CTL, 4, 15, 1, hl_tlv), +SOC_SINGLE_S8_C_TLV("Bass Gain Playback Volume", + TONE_CTL, 0, 15, 1, hl_tlv), + + + + + +/* Limiter */ +SOC_SINGLE_TLV("Limiter Max Threshold Volume", + LIMITER_CTL1, 5, 7, 0, limiter_tlv), +SOC_SINGLE_TLV("Limiter Cushion Threshold Volume", + LIMITER_CTL1, 2, 7, 0, limiter_tlv), +SOC_SINGLE_TLV("Limiter Release Rate Volume", + LIMITER_CTL2, 0, 63, 0, limiter_tlv), +SOC_SINGLE_TLV("Limiter Attack Rate Volume", + LIMITER_AT_RATE, 0, 63, 0, limiter_tlv), + +SOC_SINGLE("Limiter SR Switch", + LIMITER_CTL1, 1, 1, 0), +SOC_SINGLE("Limiter ZC Switch", + LIMITER_CTL1, 0, 1, 0), +SOC_SINGLE("Limiter Switch", + LIMITER_CTL2, 7, 1, 0), + +/* ALC */ +SOC_SINGLE_TLV("ALC Attack Rate Volume", + ALC_CTL, 0, 63, 0, limiter_tlv), +SOC_SINGLE_TLV("ALC Release Rate Volume", + ALC_RATE, 0, 63, 0, limiter_tlv), +SOC_SINGLE_TLV("ALC Max Threshold Volume", + ALC_THRESHOLD, 5, 7, 0, limiter_tlv), +SOC_SINGLE_TLV("ALC Min Threshold Volume", + ALC_THRESHOLD, 2, 7, 0, limiter_tlv), + +SOC_DOUBLE_R("ALC SR Capture Switch", PGAA_CTL, + PGAB_CTL, 7, 1, 1), /*20*/ +SOC_DOUBLE_R("ALC ZC Capture Switch", PGAA_CTL, + PGAB_CTL, 6, 1, 1), +SOC_DOUBLE("ALC Capture Switch",ALC_CTL, + 6, 7, 1, 0), + +/* Noise gate */ +SOC_ENUM("NG Type Switch", ng_type_enum), +SOC_SINGLE("NG Enable Switch", NOISE_GATE_CTL, 6, 1, 0), +SOC_SINGLE("NG Boost Switch", NOISE_GATE_CTL, 5, 1, 1), +SOC_SINGLE("NG Threshold", NOISE_GATE_CTL, 2, 7, 0), +SOC_ENUM("NG Delay", ng_delay_enum), + + +SOC_DOUBLE("HPF Switch", ANALOG_HPF_CTL, 5, 7, 1, 0), + +SOC_DOUBLE("Analog SR Switch", ANALOG_HPF_CTL, 1, 3, 1, 1), +SOC_DOUBLE("Analog ZC Switch", ANALOG_HPF_CTL, 0, 2, 1, 1), + +SOC_SINGLE("Batt Compensation Switch", BATT_COMPEN, 7, 1, 0), +SOC_SINGLE("Batt VP Monitor Switch", BATT_COMPEN, 6, 1, 0), +SOC_SINGLE("Batt VP ref", BATT_COMPEN, 0, 0x0f, 0), +SOC_SINGLE("Playback Charge Pump Freq", CHARGE_PUMP, 4, 15, 0), + +}; + +static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { + + SND_SOC_DAPM_INPUT("INPUT1A"), + SND_SOC_DAPM_INPUT("INPUT2A"), + SND_SOC_DAPM_INPUT("INPUT3A"), + SND_SOC_DAPM_INPUT("INPUT4A"), + SND_SOC_DAPM_INPUT("INPUT1B"), + SND_SOC_DAPM_INPUT("INPUT2B"), + SND_SOC_DAPM_INPUT("INPUT3B"), + SND_SOC_DAPM_INPUT("INPUT4B"), + SND_SOC_DAPM_INPUT("MICA"), + SND_SOC_DAPM_INPUT("MICB"), + + /* Input path */ + SND_SOC_DAPM_ADC("ADC Left", "Capture", PWRCTL1, 1, 1), + SND_SOC_DAPM_ADC("ADC Right", "Capture", PWRCTL1, 2, 1), + /* PGA Power */ + SND_SOC_DAPM_PGA("PGA Left", PWRCTL1, 3, 1, NULL, 0), + SND_SOC_DAPM_PGA("PGA Right", PWRCTL1, 4, 1, NULL, 0), + + + /* MIC PGA Power */ + SND_SOC_DAPM_PGA("PGA MICA", PWRCTL2, 1, 1, NULL, 0), + SND_SOC_DAPM_PGA("PGA MICB", PWRCTL2, 2, 1, NULL, 0), + /* MIC bias */ + SND_SOC_DAPM_MICBIAS("Mic-Bias", PWRCTL2, 0, 1), + + SND_SOC_DAPM_DAC("DAC Left", "Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC Right", "Playback", SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_PGA("HP Amp Left", PWRCTL3, 4, 1, NULL, 0), + SND_SOC_DAPM_PGA("HP Amp Right", PWRCTL3, 6, 1, NULL, 0), + + SND_SOC_DAPM_PGA("SPK Pwr Left", PWRCTL3, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("SPK Pwr Right", PWRCTL3, 2, 1, NULL, 0), + + SND_SOC_DAPM_OUTPUT("HPA"), + SND_SOC_DAPM_OUTPUT("HPB"), + SND_SOC_DAPM_OUTPUT("SPKA"), + SND_SOC_DAPM_OUTPUT("SPKB"), + +}; + +static const struct snd_soc_dapm_route cs42l52_audio_map[] = { + + /* adc select path */ + {"ADC Left", "AIN1", "INPUT1A"}, + {"ADC Right", "AIN1", "INPUT1B"}, + {"ADC Left", "AIN2", "INPUT2A"}, + {"ADC Right", "AIN2", "INPUT2B"}, + {"ADC Left", "AIN3", "INPUT3A"}, + {"ADC Right", "AIN3", "INPUT3B"}, + {"ADC Left", "AIN4", "INPUT4A"}, + {"ADC Right", "AIN4", "INPUT4B"}, + + /* left capture part */ + {"AIN1A Switch", NULL, "INPUT1A"}, + {"AIN2A Switch", NULL, "INPUT2A"}, + {"AIN3A Switch", NULL, "INPUT3A"}, + {"AIN4A Switch", NULL, "INPUT4A"}, + {"MICA Switch", NULL, "MICA"}, + {"PGA MICA", NULL, "MICA Switch"}, + + {"PGA Left", NULL, "AIN1A Switch"}, + {"PGA Left", NULL, "AIN2A Switch"}, + {"PGA Left", NULL, "AIN3A Switch"}, + {"PGA Left", NULL, "AIN4A Switch"}, + {"PGA Left", NULL, "PGA MICA"}, + + /* right capture part */ + {"AIN1B Switch", NULL, "INPUT1B"}, + {"AIN2B Switch", NULL, "INPUT2B"}, + {"AIN3B Switch", NULL, "INPUT3B"}, + {"AIN4B Switch", NULL, "INPUT4B"}, + {"MICB Switch", NULL, "MICB"}, + {"PGA MICB", NULL, "MICB Switch"}, + + {"PGA Right", NULL, "AIN1B Switch"}, + {"PGA Right", NULL, "AIN2B Switch"}, + {"PGA Right", NULL, "AIN3B Switch"}, + {"PGA Right", NULL, "AIN4B Switch"}, + {"PGA Right", NULL, "PGA MICB"}, + + {"ADC Mux Left", "PGA", "PGA Left"}, + {"ADC Mux Right", "PGA", "PGA Right"}, + {"ADC Left", NULL, "ADC Mux Left"}, + {"ADC Right", NULL, "ADC Mux Right"}, + +/* Output map */ + /* Headphone */ + {"HP Amp Left", NULL, "Passthrough Left"}, + {"HP Amp Right", NULL, "Passthrough Right"}, + {"HPA", NULL, "HP Amp Left"}, + {"HPB", NULL, "HP Amp Right"}, + + /* Speakers */ + + {"SPK Pwr Left", NULL, "DAC Left"}, + {"SPK Pwr Right", NULL, "DAC Right"}, + {"SPKA", NULL, "SPK Pwr Left"}, + {"SPKB", NULL, "SPK Pwr Right"}, + +}; + +static int cs42l52_add_widgets(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_new_controls(dapm, cs42l52_dapm_widgets, + ARRAY_SIZE(cs42l52_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm,cs42l52_audio_map, + ARRAY_SIZE(cs42l52_audio_map)); + + return 0; +} + +#define SOC_CS42L52_RATES ( SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ + SNDRV_PCM_RATE_96000 ) /*refer to cs42l52 datasheet page35*/ + +#define SOC_CS42L52_FORMATS ( SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ + SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE ) + + +struct cs42l52_clk_para { + u32 mclk; + u32 rate; + u8 speed; + u8 group; + u8 videoclk; + u8 ratio; + u8 mclkdiv2; +}; + +static const struct cs42l52_clk_para clk_map_table[] = { + /*8k*/ + {12288000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {18432000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {12000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0}, + {24000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1}, + {27000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0}, /*4*/ + + /*11.025k*/ + {11289600, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {16934400, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + + /*16k*/ + {12288000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {18432000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {12000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},/*9*/ + {24000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1}, + {27000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1}, + + /*22.05k*/ + {11289600, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {16934400, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + + /* 32k */ + {12288000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*14*/ + {18432000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {12000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0}, + {24000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1}, + {27000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0}, + + /* 44.1k */ + {11289600, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*19*/ + {16934400, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + + /* 48k */ + {12288000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {18432000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {12000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0}, + {24000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},/*24*/ + {27000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1}, + + /* 88.2k */ + {11289600, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {16934400, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + + /* 96k */ + {12288000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0}, + {18432000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*29*/ + {12000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0}, + {24000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1}, +}; + +static int cs42l52_get_clk(int mclk, int rate) +{ + + int i , ret = 0; + u_int mclk1, mclk2 = 0; + + for(i = 0; i < ARRAY_SIZE(clk_map_table); i++) + { + if(clk_map_table[i].rate == rate) + { + mclk1 = clk_map_table[i].mclk; + { + if(abs(mclk - mclk1) < abs(mclk - mclk2)) + { + mclk2 = mclk1; + ret = i; + } + } + } + } + + return ret < ARRAY_SIZE(clk_map_table) ? ret : -EINVAL; +} + + +static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42l52_private *info = snd_soc_codec_get_drvdata(codec); + + if((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) + { + info->sysclk = freq; + dev_info(codec->dev,"sysclk %d\n", info->sysclk); + } + else{ + dev_err(codec->dev,"invalid paramter\n"); + return -EINVAL; + } + return 0; +} + +static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42l52_private *priv = snd_soc_codec_get_drvdata(codec); + int ret = 0; + u8 iface = 0; + + dev_info(codec->dev,"Enter soc_cs42l52_set_fmt\n"); + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + + case SND_SOC_DAIFMT_CBM_CFM: + dev_info(codec->dev,"codec dai fmt master\n"); + iface = IFACE_CTL1_MASTER; + break; + case SND_SOC_DAIFMT_CBS_CFS: + dev_info(codec->dev,"codec dai fmt slave\n"); + break; + default: + dev_err(codec->dev,"invaild formate\n"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + + case SND_SOC_DAIFMT_I2S: + iface |= (IFACE_CTL1_ADC_FMT_I2S | IFACE_CTL1_DAC_FMT_I2S); + break; + case SND_SOC_DAIFMT_RIGHT_J: + iface |= IFACE_CTL1_DAC_FMT_RIGHT_J; + break; + case SND_SOC_DAIFMT_LEFT_J: + iface |= (IFACE_CTL1_ADC_FMT_LEFT_J | IFACE_CTL1_DAC_FMT_LEFT_J); + break; + case SND_SOC_DAIFMT_DSP_A: + iface |= IFACE_CTL1_DSP_MODE_EN; + break; + case SND_SOC_DAIFMT_DSP_B: + dev_err(codec->dev,"unsupported format\n"); + return -EINVAL; + default: + dev_err(codec->dev,"invaild format\n"); + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { /*tonyliu*/ + + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + iface |= IFACE_CTL1_INV_SCLK; + break; + case SND_SOC_DAIFMT_IB_NF: + iface |= IFACE_CTL1_INV_SCLK; + break; + case SND_SOC_DAIFMT_NB_IF: + break; + default: + dev_err(codec->dev,"unsupported format\n"); + ret = -EINVAL; + } + + priv->config.format = iface; + + return 0; + +} + +static int cs42l52_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *soc_codec = dai->codec; + u8 mute_val = snd_soc_read(soc_codec, PB_CTL1) & PB_CTL1_MUTE_MASK; + + if(mute) + { + snd_soc_write(soc_codec, PB_CTL1, mute_val | PB_CTL1_MSTB_MUTE | PB_CTL1_MSTA_MUTE); + } + else{ + snd_soc_write(soc_codec, PB_CTL1, mute_val ); + } + + return 0; +} + +#define CONFIG_MANUAL_CLK +static int cs42l52_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct cs42l52_private *priv = snd_soc_codec_get_drvdata(codec); + u32 clk = 0; + int index = cs42l52_get_clk(priv->sysclk, params_rate(params)); + + if(index >= 0) + { + priv->sysclk = clk_map_table[index].mclk; + clk |= (clk_map_table[index].speed << CLK_CTL_SPEED_SHIFT) | + (clk_map_table[index].group << CLK_CTL_32K_SR_SHIFT) | + (clk_map_table[index].videoclk << CLK_CTL_27M_MCLK_SHIFT) | + (clk_map_table[index].ratio << CLK_CTL_RATIO_SHIFT) | + clk_map_table[index].mclkdiv2; +#ifdef CONFIG_MANUAL_CLK + snd_soc_write(codec, CLK_CTL, clk); +#else + snd_soc_write(codec, CLK_CTL, 0xa0); +#endif + snd_soc_write(codec, IFACE_CTL1, priv->config.format ); + + } + else{ + dev_err(codec->dev,"can't find out right mclk\n"); + return -EINVAL; + } + + return 0; +} + +static int cs42l52_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + + u8 pwrctl1 = snd_soc_read(codec, PWRCTL1) & 0x9f; + u8 pwrctl2 = snd_soc_read(codec, PWRCTL2) & 0x07; + + switch (level) { + case SND_SOC_BIAS_ON: /* full On */ + break; + case SND_SOC_BIAS_PREPARE: /* partial On */ + pwrctl1 &= ~(PWRCTL1_PDN_CHRG | PWRCTL1_PDN_CODEC); + snd_soc_write(codec, PWRCTL1, pwrctl1); + break; + case SND_SOC_BIAS_STANDBY: /* Off, with power */ + pwrctl1 &= ~(PWRCTL1_PDN_CHRG | PWRCTL1_PDN_CODEC); + snd_soc_write(codec, PWRCTL1, pwrctl1); + break; + case SND_SOC_BIAS_OFF: /* Off, without power */ + snd_soc_write(codec, PWRCTL1, pwrctl1 | 0x9f); + snd_soc_write(codec, PWRCTL2, pwrctl2 | 0x07); + break; + } + codec->dapm.bias_level = level; + return 0; +} + +#define CS42L52_RATES ( SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ + SNDRV_PCM_RATE_96000 ) /*refer to cs42l52 datasheet page35*/ + +#define CS42L52_FORMATS ( SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ + SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE ) + +static struct snd_soc_dai_ops cs42l52_ops = { + .hw_params = cs42l52_pcm_hw_params, + .digital_mute = cs42l52_digital_mute, + .set_fmt = cs42l52_set_fmt, + .set_sysclk = cs42l52_set_sysclk, +}; + +struct snd_soc_dai_driver cs42l52_dai = { + .name = "cs42l52-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = CS42L52_RATES, + .formats = CS42L52_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = CS42L52_RATES, + .formats = CS42L52_FORMATS, + }, + .ops = &cs42l52_ops, +}; + + +static int cs42l52_suspend(struct snd_soc_codec *codec, pm_message_t state) +{ + cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int cs42l52_resume(struct snd_soc_codec *codec) +{ + + int i, reg; + u8 *cache = codec->reg_cache; + + /* Sync reg_cache with the hardware */ + for (i = PWRCTL1; i < ARRAY_SIZE(cs42l52_reg); i++) { + snd_soc_write(codec, i, cache[i]); + } + + cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; + +} + +/* page 37 from cs42l52 datasheet */ +static void cs42l52_required_setup(struct snd_soc_codec *codec) +{ + u8 data; + snd_soc_write(codec, 0x00, 0x99); + snd_soc_write(codec, 0x3e, 0xba); + snd_soc_write(codec, 0x47, 0x80); + data = snd_soc_read(codec, 0x32); + snd_soc_write(codec, 0x32, data | 0x80); + snd_soc_write(codec, 0x32, data & 0x7f); + snd_soc_write(codec, 0x00, 0x00); +} + + +static int cs42l52_probe(struct snd_soc_codec *codec) +{ + + struct cs42l52_private *info = snd_soc_codec_get_drvdata(codec); + int i, ret = 0; + + info->sysclk = CS42L52_DEFAULT_CLK; + info->config.format = CS42L52_DEFAULT_FORMAT; + + cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + cs42l52_required_setup(codec); + + info->flags |= CS42L52_CHIP_SWICTH; + /*initialize codec*/ +/* + for(i = 0; i < codec->num_dai; i++) + { + info->flags |= i; + + ret = cs42l52_get_revison(codec); + if(ret < 0) + { + dev_err(codec->dev,"get chip id failed\n"); + return 0; + } + + dev_info(codec->dev,"Cirrus CS42L52 codec , revision %d\n", ret & CHIP_REV_MASK); + + + } +*/ + info->flags |= 0; + + info->flags &= ~(CS42L52_CHIP_SWICTH); + info->flags |= CS42L52_ALL_IN_ONE; + + /*init done*/ + snd_soc_add_controls(codec, cs42l52_snd_controls, + ARRAY_SIZE(cs42l52_snd_controls)); + + cs42l52_add_widgets(codec); + + return 0; +} + +/* power down chip */ +static int cs42l52_remove(struct snd_soc_codec *codec) +{ + cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + + +struct i2c_client *cs_control; + +static inline unsigned int cs42l52_read(struct snd_soc_codec *codec, unsigned int reg){ + return i2c_smbus_read_byte_data(cs_control, reg); +} +static inline int cs42l52_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val){ + i2c_smbus_write_byte_data(cs_control, reg, val); + return 0; +} + +struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { + .probe = cs42l52_probe, + .remove = cs42l52_remove, + .suspend = cs42l52_suspend, + .resume = cs42l52_resume, + .set_bias_level = cs42l52_set_bias_level, + .reg_cache_size = CS42L52_CACHEREGNUM, + .reg_cache_default = cs42l52_reg, + .read = cs42l52_read, + .write = cs42l52_write, +}; + +static int cs42l52_i2c_probe(struct i2c_client *i2c_client, + const struct i2c_device_id *id) +{ + + struct cs42l52_private *cs42l52; + int ret; + +/* DEBUG + ret = i2c_smbus_read_byte_data(i2c_client, CS42L52_CHIP); + printk(KERN_ERR "We have %x from CS42L52_CHIP \n", ret); +*/ + cs42l52 = kzalloc(sizeof(struct cs42l52_private), GFP_KERNEL); + if (!cs42l52) { + dev_err(&i2c_client->dev, "could not allocate codec\n"); + return -ENOMEM; + } + + i2c_set_clientdata(i2c_client, cs42l52); + cs42l52->control_data = i2c_client; + cs42l52->control_type = SND_SOC_I2C; + + cs_control = i2c_client; + + ret = snd_soc_register_codec(&i2c_client->dev, + &soc_codec_dev_cs42l52, &cs42l52_dai, 1); + if (ret < 0){ + kfree(cs42l52); + } + return ret; +} + +static int cs42l52_i2c_remove(struct i2c_client *client) +{ + struct cs42l52_private *cs42l52 = i2c_get_clientdata(client); + snd_soc_unregister_codec(&client->dev); + kfree(cs42l52); + + return 0; +} + +static const struct i2c_device_id cs42l52_id[] = { + { "cs42l52", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cs42l52_id); + +static struct i2c_driver cs42l52_i2c_driver = { + .driver = { + .name = "cs42l52-codec", + .owner = THIS_MODULE, + }, + .probe = cs42l52_i2c_probe, + .remove = __devexit_p(cs42l52_i2c_remove), + .id_table = cs42l52_id, + +}; + +static int __init cs42l52_modinit(void) +{ + int ret; + ret = i2c_add_driver(&cs42l52_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "%s: can't add i2c driver\n", __func__); + return ret; + } + return 0; +} + +module_init(cs42l52_modinit); + +static void __exit cs42l52_exit(void) +{ + i2c_del_driver(&cs42l52_i2c_driver); +} + +module_exit(cs42l52_exit); + +MODULE_DESCRIPTION("ASoC CS42L52 driver"); +MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h new file mode 100644 index 00000000000..4f0fe3d37de --- /dev/null +++ b/sound/soc/codecs/cs42l52.h @@ -0,0 +1,298 @@ +/* + * cs42l52.h -- CS42L52 ALSA SoC audio driver + * + * Copyright 2010 CirrusLogic, Inc. + * + * Author: Brian Austin + * + * 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. + * Revision history + * Nov 2007 Initial version. + * Feb 2010 Update to latest asoc git tree + */ + +#ifndef __CS42L52_H__ +#define __CS42L52_H__ + +#include +#include + + +#define CS42L52_NAME "CS42L52" +#define CS42L52_DEFAULT_CLK 12000000 +#define CS42L52_MIN_CLK 11000000 +#define CS42L52_MAX_CLK 27000000 +#define CS42L52_DEFAULT_FORMAT SNDRV_PCM_FMTBIT_S16_LE +#define CS42L52_DEFAULT_MAX_CHANS 2 +#define CS42L52_SYSCLK 1 + + +#define CS42L52_CHIP_SWICTH (1 << 17) +#define CS42L52_ALL_IN_ONE (1 << 16) +#define CS42L52_CHIP_ONE 0x00 +#define CS42L52_CHIP_TWO 0x01 +#define CS42L52_CHIP_THR 0x02 +#define CS42L52_CHIP_MASK 0x0f + +/* + *CS42L52 internal registers + */ +#define CS42L52_CHIP 0x01 +#define CHIP_ID 0xE0 +#define CHIP_ID_MASK 0xF8 +#define CHIP_REV_A0 0x00 +#define CHIP_REV_A1 0x01 +#define CHIP_REV_B0 0x02 +#define CHIP_REV_MASK 0x03 + +#define PWRCTL1 0x02 //0x01 +#define PWRCTL1_PDN_CHRG (1 << 7) +#define PWRCTL1_PDN_PGAB (1 << 4) +#define PWRCTL1_PDN_PGAB_SHIFT 4 +#define PWRCTL1_PDN_PGAA (1 << 3) +#define PWRCTL1_PDN_PGAA_SHIFT 3 +#define PWRCTL1_PDN_ADCB (1 << 2) +#define PWRCTL1_PDN_ADCB_SHIFT 2 +#define PWRCTL1_PDN_ADCA (1 << 1) +#define PWRCTL1_PDN_ADCA_SHIFT 1 +#define PWRCTL1_PDN_CODEC (1 << 0) + +#define PWRCTL2 0x03 //0x07 +#define PWRCTL2_OVRDB (1 << 4) +#define PWRCTL2_OVRDA (1 << 3) +#define PWRCTL2_PDN_MICB (1 << 2) +#define PWRCTL2_PDN_MICB_SHIFT 2 +#define PWRCTL2_PDN_MICA (1 << 1) +#define PWRCTL2_PDN_MICA_SHIFT 1 +#define PWRCTL2_PDN_MICBIAS (1 << 0) +#define PWRCTL2_PDN_MICBIAS_SHIFT 0 + +#define PWRCTL3 0x04 //0x08 +#define PWRCTL3_HPB_PDN_SHIFT 6 +#define PWRCTL3_HPB_ON_LOW 0x00 +#define PWRCTL3_HPB_ON_HIGH 0x01 +#define PWRCTL3_HPB_ALWAYS_ON 0x02 +#define PWRCTL3_HPB_ALWAYS_OFF 0x03 +#define PWRCTL3_HPA_PDN_SHIFT 4 +#define PWRCTL3_HPA_ON_LOW 0x00 +#define PWRCTL3_HPA_ON_HIGH 0x01 +#define PWRCTL3_HPA_ALWAYS_ON 0x02 +#define PWRCTL3_HPA_ALWAYS_OFF 0x03 +#define PWRCTL3_SPKB_PDN_SHIFT 2 +#define PWRCTL3_SPKB_ON_LOW 0x00 +#define PWRCTL3_SPKB_ON_HIGH 0x01 +#define PWRCTL3_SPKB_ALWAYS_ON 0x02 +#define PWRCTL3_SPKB_ALWAYS_OFF 0x03 +#define PWRCTL3_SPKA_PDN_SHIFT 0 +#define PWRCTL3_SPKA_ON_LOW 0x00 +#define PWRCTL3_SPKA_ON_HIGH 0x01 +#define PWRCTL3_SPKA_ALWAYS_ON 0x02 +#define PWRCTL3_SPKA_ALWAYS_OFF 0x03 +#define DEFAULT_OUTPUT_STATE 0x05 +#define PWRCTL3_CONF_MASK 0x03 + + + +#define CLK_CTL 0x05 //0xa0 +#define CLK_CTL_AUTODECT_ENABLE (1 << 7) +#define CLK_CTL_SPEED_SHIFT 5 +#define CLK_CTL_S_DS_MODE 0x00 +#define CLK_CTL_S_SS_MODE 0x01 +#define CLK_CTL_S_HS_MODE 0x02 +#define CLK_CTL_S_QS_MODE 0x03 +#define CLK_CTL_32K_SR_SHIFT 4 +#define CLK_CTL_32K_SR 1 +#define CLK_CTL_NOT_32K 0 +#define CLK_CTL_27M_MCLK_SHIFT 3 +#define CLK_CTL_27M_MCLK 1 +#define CLK_CTL_NOT_27M 0 +#define CLK_CTL_RATIO_SHIFT 1 +#define CLK_CTL_RATIO_128 0x00 +#define CLK_CTL_RATIO_125 0x01 +#define CLK_CTL_RATIO_132 0x02 +#define CLK_CTL_RATIO_136 0x03 +#define CLK_CTL_MCLKDIV2 1 +#define CLK_CTL_NOT_MCLKDIV2 0 + + +#define IFACE_CTL1 0x06 //0 +#define IFACE_CTL1_MASTER (1 << 7) +#define IFACE_CTL1_INV_SCLK (1 << 6) +#define IFACE_CTL1_ADC_FMT_I2S (1 << 5) +#define IFACE_CTL1_ADC_FMT_LEFT_J (0 << 5) +#define IFACE_CTL1_DSP_MODE_EN (1 << 4) +#define IFACE_CTL1_DAC_FMT_LEFT_J (0 << 2) +#define IFACE_CTL1_DAC_FMT_I2S (1 << 2) +#define IFACE_CTL1_DAC_FMT_RIGHT_J (2 << 2) +#define IFACE_CTL1_WL_32BIT (0x00) +#define IFACE_CTL1_WL_24BIT (0x01) +#define IFACE_CTL1_WL_20BIT (0x02) +#define IFACE_CTL1_WL_16BIT (0x03) +#define IFACE_CTL1_WL_MASK 0xFFFF + + +#define IFACE_CTL2 0x07 //0 +#define IFACE_CTL2_SC_MC_EQ (1 << 6) +#define IFACE_CTL2_LOOPBACK (1 << 5) +#define IFACE_CTL2_S_MODE_OUTPUT_EN (0 << 4) +#define IFACE_CTL2_S_MODE_OUTPUT_HIZ (1 << 4) +#define IFACE_CTL2_HP_SW_INV (1 << 3) +#define IFACE_CTL2_MIC_BIAS_5X 0x00 +#define IFACE_CTL2_MIC_BIAS_6X 0x01 +#define IFACE_CTL2_MIC_BIAS_7X 0x02 +#define IFACE_CTL2_MIC_BIAS_8X 0x03 +#define IFACE_CTL2_MIC_BIAS_83X 0x04 +#define IFACE_CTL2_MIC_BIAS_91X 0x05 + +#define ADC_PGA_A 0x08 //0x81 +#define ADC_PGA_B 0x09 //0x81 +#define ADC_SEL_SHIFT 5 +#define PGA_SEL_SHIFT 0 +#define ADC_SEL_AIN1 0x00 +#define ADC_SEL_AIN2 0x01 +#define ADC_SEL_AIN3 0x02 +#define ADC_SEL_AIN4 0x03 +#define ADC_SEL_PGA 0x04 +#define PGA_SEL_NONE 0x00 +#define PGA_SEL_AIN1 0x01 +#define PGA_SEL_AIN2 0x02 +#define PGA_SEL_AIN3 0x04 +#define PGA_SEL_AIN4 0x08 +#define PGA_SEL_MIC 0x10 +#define PGA_SEL_MIC_AIN1 0x11 +#define PGA_SEL_MIC_AIN1_AIN2 0x13 + +#define ANALOG_HPF_CTL 0x0A //0xa5 +#define HPF_CTL_ANLGSFTB (1 << 3) +#define HPF_CTL_ANLGSFTA (1 << 0) + + +#define ADC_HPF_FREQ 0x0B //0 +#define ADC_MISC_CTL 0x0C //0 +#define ADC_MISC_CTL_SOURCE_DSP (1 << 6) + + +#define PB_CTL1 0x0D //0x60 +#define PB_CTL1_HP_GAIN_SHIFT 5 +#define PB_CTL1_HP_GAIN_03959 0x00 +#define PB_CTL1_HP_GAIN_04571 0x01 +#define PB_CTL1_HP_GAIN_05111 0x02 +#define PB_CTL1_HP_GAIN_06047 0x03 +#define PB_CTL1_HP_GAIN_07099 0x04 +#define PB_CTL1_HP_GAIN_08399 0x05 +#define PB_CTL1_HP_GAIN_10000 0x06 +#define PB_CTL1_HP_GAIN_11430 0x07 +#define PB_CTL1_INV_PCMB (1 << 3) +#define PB_CTL1_INV_PCMA (1 << 2) +#define PB_CTL1_MSTB_MUTE (1 << 1) +#define PB_CTL1_MSTA_MUTE (1 << 0) +#define PB_CTL1_MUTE_MASK 0xFFFD + +#define MISC_CTL 0x0E //0x02 +#define MISC_CTL_DEEMPH (1 << 2) +#define MISC_CTL_DIGSFT (1 << 1) +#define MISC_CTL_DIGZC (1 << 0) + + +#define PB_CTL2 0x0F //0 +#define PB_CTL2_HPB_MUTE (1 << 7) +#define PB_CTL2_HPA_MUTE (1 << 6) +#define PB_CTL2_SPKB_MUTE (1 << 5) +#define PB_CTL2_SPKA_MUTE (1 << 4) +#define PB_CTL2_SPK_SWAP (1 << 2) +#define PB_CTL2_SPK_MONO (1 << 1) +#define PB_CTL2_SPK_MUTE50 (1 << 0) + +#define MICA_CTL 0x10 //0 +#define MICB_CTL 0x11 //0 +#define MIC_CTL_SEL_MIC1 (0 << 6) +#define MIC_CTL_SEL_MIC2 (1 << 6) +#define MIC_CTL_SEL_DIFF (1 << 5) + +#define PGAA_CTL 0x12 //0 +#define PGAB_CTL 0x13 //0 +#define PGAX_CTL_VOL_12DB 24 +#define PGAX_CTL_VOL_6DB 12 /*step size 0.5db*/ + +#define PASSTHRUA_VOL 0x14 //0 +#define PASSTHRUB_VOL 0x15 //0 + +#define ADCA_VOL 0x16 //0 +#define ADCB_VOL 0x17 //0 +#define ADCX_VOL_24DB 24 /*step size 1db*/ +#define ADCX_VOL_12DB 12 +#define ADCX_VOL_6DB 6 + +#define ADCA_MIXER_VOL 0x18 // 0x80 +#define ADCB_MIXER_VOL 0x19 //0x80 +#define ADC_MIXER_VOL_12DB 0x18 + +#define PCMA_MIXER_VOL 0x1A //0 +#define PCMB_MIXER_VOL 0x1B //0 + +#define BEEP_FREQ 0x1C //0 +#define BEEP_VOL 0x1D //0 +#define BEEP_VOL_12DB 0x06 + + +#define BEEP_TONE_CTL 0x1E //0 + +#define TONE_CTL 0x1F //0x88 + +#define MASTERA_VOL 0x20 //0 +#define MASTERB_VOL 0x21 //0 + +#define HPA_VOL 0x22 //0 +#define HPB_VOL 0x23 //0 +#define DEFAULT_HP_VOL 0xF0 + +#define SPKA_VOL 0x24 //0 +#define SPKB_VOL 0x25 //0 +#define DEFAULT_SPK_VOL 0xF0 + +#define ADC_PCM_MIXER 0x26 //0 + +#define LIMITER_CTL1 0x27 //0 +#define LIMITER_CTL2 0x28 //0x7f +#define LIMITER_AT_RATE 0x29 //0xc0 + +#define ALC_CTL 0x2A //0 +#define ALC_CTL_ALCB_ENABLE (1 << 7) +#define ALC_CTL_ALCA_ENABLE (1 << 6) +#define ALC_CTL_FASTEST_ATTACK 0 + +#define ALC_RATE 0x2B //0x3f +#define ALC_SLOWEST_RELEASE 0x3F + +#define ALC_THRESHOLD 0x2C //0 +#define ALC_MAX_RATE_SHIFT 5 +#define ALC_MIN_RATE_SHIFT 2 +#define ALC_RATE_0DB 0 +#define ALC_RATE_3DB 1 +#define ALC_RATE_6DB 2 + +#define NOISE_GATE_CTL 0x2D //0 +#define NG_ENABLE (1 << 6) +#define NG_THRESHOLD_SHIFT 2 +#define NG_MIN_70DB 2 +#define NG_DELAY_SHIFT 0 +#define NG_DELAY_100MS 1 + +#define CLK_STATUS 0x2E //0 +#define BATT_COMPEN 0x2F //0 + +#define BATT_LEVEL 0x30 //0 +#define SPK_STATUS 0x31 //0 +#define SPK_STATUS_PIN_SHIFT 3 +#define SPK_STATUS_PIN_HIGH 1 + +#define TEM_CTL 0x32 //0x3b +#define THE_FOLDBACK 0x33 //0 +#define CHARGE_PUMP 0x34 //0x5f + + +#define CS42L52_CACHEREGNUM 56 + +#endif From beb603382dcc48750ecdd6e2886a92c690460791 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:45:37 +0300 Subject: [PATCH 05/32] The CS42L52 machine driver, and make sure arch/arm/mach-mx5/Kconfig has ARCH_MXC_AUDMUX_V2 selected for this to work. --- arch/arm/mach-mx5/Kconfig | 1 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/imx/Kconfig | 9 ++ sound/soc/imx/Makefile | 2 + sound/soc/imx/imx-cs42l52.c | 223 ++++++++++++++++++++++++++++++++++++ 6 files changed, 241 insertions(+) create mode 100644 sound/soc/imx/imx-cs42l52.c diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig index 482bf9be450..710059580da 100644 --- a/arch/arm/mach-mx5/Kconfig +++ b/arch/arm/mach-mx5/Kconfig @@ -40,6 +40,7 @@ config SOC_IMX53 bool select MXC_TZIC select ARCH_MXC_IOMUX_V3 + select ARCH_MXC_AUDMUX_V2 select ARCH_HAS_CPUFREQ select ARCH_MX53 select IMX_HAVE_PLATFORM_FEC diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 28e1739286c..eb84fd7b73f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -25,6 +25,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ALC5623 if I2C select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC select SND_SOC_CS42L51 if I2C + select SND_SOC_CS42L52 if I2C select SND_SOC_CS4270 if I2C select SND_SOC_CX20442 select SND_SOC_DA7210 if I2C @@ -144,6 +145,9 @@ config SND_SOC_CQ0093VC config SND_SOC_CS42L51 tristate +config SND_SOC_CS42L52 + tristate + # Cirrus Logic CS4270 Codec config SND_SOC_CS4270 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 16752a64975..aef985fc633 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -11,6 +11,7 @@ snd-soc-ak4642-objs := ak4642.o snd-soc-ak4671-objs := ak4671.o snd-soc-cq93vc-objs := cq93vc.o snd-soc-cs42l51-objs := cs42l51.o +snd-soc-cs42l52-objs := cs42l52.o snd-soc-cs4270-objs := cs4270.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o @@ -91,6 +92,7 @@ obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o +obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index feab5d38bfd..de8feb2a46d 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -49,6 +49,15 @@ config SND_SOC_IMX_SGTL5000 Say Y if you want to add support for SoC audio on an i.MX board with a sgtl5000 codec. +config SND_SOC_IMX_CS42L52 + tristate "SoC Audio support for i.MX efikasb with cs42l52" + depends on MACH_MX53_EFIKASB + select SND_SOC_CS42L52 + select SND_MXC_SOC_MX2 + help + Say Y if you want to add support for SoC audio on an efikasb board with + a cs42l52 codec + config SND_SOC_EUKREA_TLV320 tristate "Eukrea TLV320" depends on MACH_EUKREA_MBIMX27_BASEBOARD \ diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 9d9ac39c4c4..71e360b40e5 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -12,8 +12,10 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o snd-soc-wm1133-ev1-objs := wm1133-ev1.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o +snd-soc-imx-cs42l52-objs := imx-cs42l52.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o +obj-$(CONFIG_SND_SOC_IMX_CS42L52) += snd-soc-imx-cs42l52.o diff --git a/sound/soc/imx/imx-cs42l52.c b/sound/soc/imx/imx-cs42l52.c new file mode 100644 index 00000000000..c2effa4e34d --- /dev/null +++ b/sound/soc/imx/imx-cs42l52.c @@ -0,0 +1,223 @@ +/* + * imx-cs42l52.c -- SoC audio for IMX / Cirrus platform + * + * Author: Johan Dams, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "imx-ssi.h" + +#include "../codecs/cs42l52.h" + + +static struct imx_cs42l52_priv { + int sysclk; + struct platform_device *pdev; +} card_priv; + +static int imx_efikasb_cs42l52_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret; + + /* TODO: The SSI driver should figure this out for us */ + unsigned int channels = params_channels(params); + switch (channels) { + case 2: + snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffc, 0xfffffffc, 2, 0); + break; + case 1: + snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffe, 0xfffffffe, 1, 0); + break; + default: + return -EINVAL; + } + + /* Set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM); + + if (ret < 0) { + printk(KERN_ERR "can't set codec DAI configuration\n"); + return ret; + } + + /* Set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) { + printk(KERN_ERR "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, CS42L52_SYSCLK, + card_priv.sysclk, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + return ret; +} + +/* EfikaSB I2S */ +static struct snd_soc_ops efikasbcs42l52_ops = { + .hw_params = imx_efikasb_cs42l52_hw_params, +}; + + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link efikasb_cs42l52_dai = { + .name = "cs42l52", + .stream_name = "CS42L52", + .cpu_dai_name = "imx-ssi.1", + .platform_name = "imx-pcm-audio.1", + .codec_dai_name = "cs42l52-hifi", + .codec_name = "cs42l52-codec.0-004a", + .ops = &efikasbcs42l52_ops, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_efikasb_cs42l52 = { + .name = "efikasb-cs42l52", + .dai_link = &efikasb_cs42l52_dai, + .num_links = 1, +}; + +/* Configure the AUDMUX */ +static int imx_audmux_config(int slave, int master) +{ + unsigned int ptcr, pdcr; + slave = slave - 1; + master = master - 1; + + ptcr = MXC_AUDMUX_V2_PTCR_SYN | + MXC_AUDMUX_V2_PTCR_TFSDIR | + MXC_AUDMUX_V2_PTCR_TFSEL(master) | + MXC_AUDMUX_V2_PTCR_TCLKDIR | + MXC_AUDMUX_V2_PTCR_TCSEL(master); + pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(master); + mxc_audmux_v2_configure_port(slave, ptcr, pdcr); + + ptcr = MXC_AUDMUX_V2_PTCR_SYN; + pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(slave); + mxc_audmux_v2_configure_port(master, ptcr, pdcr); + + return 0; +} + +static int __devinit imx_cs42l52_probe(struct platform_device *pdev) +{ + struct mxc_audio_platform_data *plat = pdev->dev.platform_data; + + card_priv.pdev = pdev; + + imx_audmux_config(plat->src_port, plat->ext_port); + + card_priv.sysclk = plat->sysclk; + + + return 0; +} + +static int imx_cs42l52_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver imx_cs42l52_audio_driver = { + .probe = imx_cs42l52_probe, + .remove = imx_cs42l52_remove, + .driver = { + .name = "imx-cs42l52", + }, +}; + +static struct platform_device *efikasb_cs42l52_snd_device; + +static int __init efikasb_cs42l52_soc_init(void) +{ + int ret; + + ret = platform_driver_register(&imx_cs42l52_audio_driver); + if (ret) + return -ENOMEM; + efikasb_cs42l52_snd_device = platform_device_alloc("soc-audio", -1); + + if (!efikasb_cs42l52_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(efikasb_cs42l52_snd_device, + &snd_soc_efikasb_cs42l52); + + ret = platform_device_add(efikasb_cs42l52_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + pr_err("Unable to add platform device\n"); + platform_device_put(efikasb_cs42l52_snd_device); + + return ret; +} + +static void __exit efikasb_cs42l52_soc_exit(void) +{ + platform_device_unregister(efikasb_cs42l52_snd_device); +} + +module_init(efikasb_cs42l52_soc_init); +module_exit(efikasb_cs42l52_soc_exit); + + +MODULE_AUTHOR("Johan Dams "); +MODULE_DESCRIPTION("ALSA SoC IMX / Cirrus"); +MODULE_LICENSE("GPL"); From fc0f6d4d6333e22716c40c193ca046993eca303d Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:48:11 +0300 Subject: [PATCH 06/32] Fall back to the mxc_nd2 NAND driver instead of mxc_nand. --- drivers/mtd/nand/mxc_nd2.c | 1757 +++++++++++++++++++ drivers/mtd/nand/mxc_nd2.h | 731 ++++++++ drivers/mtd/nand/nand_device_info.c | 2413 +++++++++++++++++++++++++++ drivers/mtd/nand/nand_device_info.h | 152 ++ 4 files changed, 5053 insertions(+) create mode 100644 drivers/mtd/nand/mxc_nd2.c create mode 100644 drivers/mtd/nand/mxc_nd2.h create mode 100644 drivers/mtd/nand/nand_device_info.c create mode 100644 drivers/mtd/nand/nand_device_info.h diff --git a/drivers/mtd/nand/mxc_nd2.c b/drivers/mtd/nand/mxc_nd2.c new file mode 100644 index 00000000000..960829de307 --- /dev/null +++ b/drivers/mtd/nand/mxc_nd2.c @@ -0,0 +1,1757 @@ +/* + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mxc_nd2.h" +#include "nand_device_info.h" + +#define DVR_VER "3.0" + +/* Global address Variables */ +static void __iomem *nfc_axi_base, *nfc_ip_base; +static int nfc_irq; + +struct mxc_mtd_s { + struct mtd_info mtd; + struct nand_chip nand; + struct mtd_partition *parts; + struct device *dev; + int disable_bi_swap; /* disable bi swap */ + int ignore_bad_block; /* ignore bad block marker */ + void *saved_bbt; + int (*saved_block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); + int clk_active; +}; + +static struct mxc_mtd_s *mxc_nand_data; + +/* + * Define delay timeout value + */ +#define TROP_US_DELAY (1000 * 1000) + +struct nand_info { + bool bStatusRequest; + u16 colAddr; +}; + +static struct nand_info g_nandfc_info; + +#ifdef MTD_NAND_MXC_SWECC +static int hardware_ecc; +#else +static int hardware_ecc = 1; +#endif + + +static u8 num_of_interleave = 1; + +static u8 *data_buf; +static u8 *oob_buf; + +static int g_page_mask; + +static struct clk *nfc_clk; + +/* + * OOB placement block for use with hardware ecc generation + */ +static struct nand_ecclayout nand_hw_eccoob_512 = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobavail = 4, + .oobfree = {{0, 4} } +}; + +static struct nand_ecclayout nand_hw_eccoob_2k = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobavail = 4, + .oobfree = {{2, 4} } +}; + +static struct nand_ecclayout nand_hw_eccoob_4k = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobavail = 4, + .oobfree = {{2, 4} } +}; + +/*! + * @defgroup NAND_MTD NAND Flash MTD Driver for MXC processors + */ + +/*! + * @file mxc_nd2.c + * + * @brief This file contains the hardware specific layer for NAND Flash on + * MXC processor + * + * @ingroup NAND_MTD + */ + +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; +#endif + +static wait_queue_head_t irq_waitq; + +static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) +{ + /* Disable Interuupt */ + raw_write(raw_read(REG_NFC_INTRRUPT) | NFC_INT_MSK, REG_NFC_INTRRUPT); + wake_up(&irq_waitq); + + return IRQ_HANDLED; +} + +static void mxc_nand_bi_swap(struct mtd_info *mtd) +{ + u16 ma, sa, nma, nsa; + + if (!IS_LARGE_PAGE_NAND) + return; + + /* Disable bi swap if the user set disable_bi_swap at sys entry */ + if (mxc_nand_data->disable_bi_swap) + return; + + ma = __raw_readw(BAD_BLK_MARKER_MAIN); + sa = __raw_readw(BAD_BLK_MARKER_SP); + + nma = (ma & 0xFF00) | (sa >> 8); + nsa = (sa & 0x00FF) | (ma << 8); + + __raw_writew(nma, BAD_BLK_MARKER_MAIN); + __raw_writew(nsa, BAD_BLK_MARKER_SP); +} + +static void nfc_memcpy(void *dest, void *src, int len) +{ + u8 *d = dest; + u8 *s = src; + + while (len > 0) { + if (len >= 4) { + *(u32 *)d = *(u32 *)s; + d += 4; + s += 4; + len -= 4; + } else { + *(u16 *)d = *(u16 *)s; + len -= 2; + break; + } + } + + if (len) + BUG(); +} + +/* + * Functions to transfer data to/from spare erea. + */ +static void +copy_spare(struct mtd_info *mtd, void *pbuf, void *pspare, int len, bool bfrom) +{ + u16 i, j; + u16 m = mtd->oobsize; + u16 n = mtd->writesize >> 9; + u8 *d = (u8 *) pbuf; + u8 *s = (u8 *) pspare; + u16 t = SPARE_LEN; + + m /= num_of_interleave; + n /= num_of_interleave; + + j = (m / n >> 1) << 1; + + if (bfrom) { + for (i = 0; i < n - 1; i++) + nfc_memcpy(&d[i * j], &s[i * t], j); + + /* the last section */ + nfc_memcpy(&d[i * j], &s[i * t], len - i * j); + } else { + for (i = 0; i < n - 1; i++) + nfc_memcpy(&s[i * t], &d[i * j], j); + + /* the last section */ + nfc_memcpy(&s[i * t], &d[i * j], len - i * j); + } +} + +/*! + * This function polls the NFC to wait for the basic operation to complete by + * checking the INT bit of config2 register. + * + * @param maxRetries number of retry attempts (separated by 1 us) + * @param useirq True if IRQ should be used rather than polling + */ +static void wait_op_done(int maxRetries, bool useirq) +{ + if (useirq) { + if ((raw_read(REG_NFC_OPS_STAT) & NFC_OPS_STAT) == 0) { + /* enable interrupt */ + raw_write(raw_read(REG_NFC_INTRRUPT) & ~NFC_INT_MSK, + REG_NFC_INTRRUPT); + if (!wait_event_timeout(irq_waitq, + (raw_read(REG_NFC_OPS_STAT) & NFC_OPS_STAT), + msecs_to_jiffies(TROP_US_DELAY / 1000)) > 0) { + /* disable interrupt */ + raw_write(raw_read(REG_NFC_INTRRUPT) + | NFC_INT_MSK, REG_NFC_INTRRUPT); + + printk(KERN_WARNING "%s(%d): INT not set\n", + __func__, __LINE__); + return; + } + } + WRITE_NFC_IP_REG((raw_read(REG_NFC_OPS_STAT) & + ~NFC_OPS_STAT), REG_NFC_OPS_STAT); + } else { + while (1) { + maxRetries--; + if (raw_read(REG_NFC_OPS_STAT) & NFC_OPS_STAT) { + WRITE_NFC_IP_REG((raw_read(REG_NFC_OPS_STAT) & + ~NFC_OPS_STAT), + REG_NFC_OPS_STAT); + break; + } + udelay(1); + if (maxRetries <= 0) { + printk(KERN_WARNING "%s(%d): INT not set\n", + __func__, __LINE__); + break; + } + } + } +} + +static inline void send_atomic_cmd(u16 cmd, bool useirq) +{ + /* fill command */ + raw_write(cmd, REG_NFC_FLASH_CMD); + + /* send out command */ + raw_write(NFC_CMD, REG_NFC_OPS); + + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY, useirq); +} + +static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr); +static int mxc_check_ecc_status(struct mtd_info *mtd); + +#ifdef NFC_AUTO_MODE_ENABLE +/*! + * This function handle the interleave related work + * @param mtd mtd info + * @param cmd command + */ +static void auto_cmd_interleave(struct mtd_info *mtd, u16 cmd) +{ + u32 i, page_addr, ncs; + u32 j = num_of_interleave; + struct nand_chip *this = mtd->priv; + u32 addr_low = raw_read(NFC_FLASH_ADDR0); + u32 addr_high = raw_read(NFC_FLASH_ADDR8); + u8 *dbuf = data_buf; + u8 *obuf = oob_buf; + u32 dlen = mtd->writesize / j; + u32 olen = mtd->oobsize / j; + + /* adjust the addr value + * since ADD_OP mode is 01 + */ + if (cmd == NAND_CMD_ERASE2) + page_addr = addr_low; + else + page_addr = addr_low >> 16 | addr_high << 16; + + ncs = NFC_GET_NFC_ACTIVE_CS(); + + if (j > 1) { + page_addr *= j; + } else { + page_addr *= this->numchips; + page_addr += ncs; + } + + switch (cmd) { + case NAND_CMD_PAGEPROG: + for (i = 0; i < j; i++) { + /* reset addr cycle */ + mxc_do_addr_cycle(mtd, 0, page_addr++); + + /* data transfer */ + memcpy(MAIN_AREA0, dbuf, dlen); + copy_spare(mtd, obuf, SPARE_AREA0, olen, false); + mxc_nand_bi_swap(mtd); + + /* update the value */ + dbuf += dlen; + obuf += olen; + + NFC_SET_RBA(0); + raw_write(NFC_AUTO_PROG, REG_NFC_OPS); + + /* wait auto_prog_done bit set */ + while (!(raw_read(REG_NFC_OPS_STAT) & NFC_OP_DONE)) + ; + } + + wait_op_done(TROP_US_DELAY, true); + while (!(raw_read(REG_NFC_OPS_STAT) & NFC_RB)); + + break; + case NAND_CMD_READSTART: + for (i = 0; i < j; i++) { + /* reset addr cycle */ + mxc_do_addr_cycle(mtd, 0, page_addr++); + + NFC_SET_RBA(0); + raw_write(NFC_AUTO_READ, REG_NFC_OPS); + wait_op_done(TROP_US_DELAY, true); + + /* check ecc error */ + mxc_check_ecc_status(mtd); + + /* data transfer */ + mxc_nand_bi_swap(mtd); + memcpy(dbuf, MAIN_AREA0, dlen); + copy_spare(mtd, obuf, SPARE_AREA0, olen, true); + + /* update the value */ + dbuf += dlen; + obuf += olen; + } + break; + case NAND_CMD_ERASE2: + for (i = 0; i < j; i++) { + mxc_do_addr_cycle(mtd, -1, page_addr++); + raw_write(NFC_AUTO_ERASE, REG_NFC_OPS); + wait_op_done(TROP_US_DELAY, true); + } + break; + case NAND_CMD_RESET: + for (i = 0; i < j; i++) { + if (j > 1) + NFC_SET_NFC_ACTIVE_CS(i); + send_atomic_cmd(cmd, false); + } + break; + default: + break; + } +} +#endif + +static void send_addr(u16 addr, bool useirq); + +/*! + * This function issues the specified command to the NAND device and + * waits for completion. + * + * @param cmd command for NAND Flash + * @param useirq True if IRQ should be used rather than polling + */ +static void send_cmd(struct mtd_info *mtd, u16 cmd, bool useirq) +{ + DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x, %d)\n", cmd, useirq); + +#ifdef NFC_AUTO_MODE_ENABLE + switch (cmd) { + case NAND_CMD_READ0: + case NAND_CMD_READOOB: + raw_write(NAND_CMD_READ0, REG_NFC_FLASH_CMD); + break; + case NAND_CMD_SEQIN: + case NAND_CMD_ERASE1: + raw_write(cmd, REG_NFC_FLASH_CMD); + break; + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE2: + case NAND_CMD_READSTART: + raw_write(raw_read(REG_NFC_FLASH_CMD) | cmd << NFC_CMD_1_SHIFT, + REG_NFC_FLASH_CMD); + auto_cmd_interleave(mtd, cmd); + break; + case NAND_CMD_READID: + send_atomic_cmd(cmd, useirq); + send_addr(0, false); + break; + case NAND_CMD_RESET: + auto_cmd_interleave(mtd, cmd); + break; + case NAND_CMD_STATUS: + send_atomic_cmd(cmd, useirq); + break; + default: + break; + } +#else + send_atomic_cmd(cmd, useirq); +#endif +} + +/*! + * This function sends an address (or partial address) to the + * NAND device. The address is used to select the source/destination for + * a NAND command. + * + * @param addr address to be written to NFC. + * @param useirq True if IRQ should be used rather than polling + */ +static void send_addr(u16 addr, bool useirq) +{ + DEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr, useirq); + + /* fill address */ + raw_write((addr << NFC_FLASH_ADDR_SHIFT), REG_NFC_FLASH_ADDR); + + /* send out address */ + raw_write(NFC_ADDR, REG_NFC_OPS); + + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY, useirq); +} + +/*! + * This function requests the NFC to initate the transfer + * of data currently in the NFC RAM buffer to the NAND device. + * + * @param buf_id Specify Internal RAM Buffer number + */ +static void send_prog_page(u8 buf_id) +{ +#ifndef NFC_AUTO_MODE_ENABLE + DEBUG(MTD_DEBUG_LEVEL3, "%s\n", __FUNCTION__); + + /* set ram buffer id */ + NFC_SET_RBA(buf_id); + + /* transfer data from NFC ram to nand */ + raw_write(NFC_INPUT, REG_NFC_OPS); + + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY, true); +#endif +} + +/*! + * This function requests the NFC to initated the transfer + * of data from the NAND device into in the NFC ram buffer. + * + * @param buf_id Specify Internal RAM Buffer number + */ +static void send_read_page(u8 buf_id) +{ +#ifndef NFC_AUTO_MODE_ENABLE + DEBUG(MTD_DEBUG_LEVEL3, "%s(%d)\n", __FUNCTION__, buf_id); + + /* set ram buffer id */ + NFC_SET_RBA(buf_id); + + /* transfer data from nand to NFC ram */ + raw_write(NFC_OUTPUT, REG_NFC_OPS); + + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY, true); +#endif +} + +/*! + * This function requests the NFC to perform a read of the + * NAND device ID. + */ +static void send_read_id(void) +{ + /* Set RBA bits for BUFFER0 */ + NFC_SET_RBA(0); + + /* Read ID into main buffer */ + raw_write(NFC_ID, REG_NFC_OPS); + + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY, false); + +} + +#ifdef NFC_AUTO_MODE_ENABLE +static inline void read_dev_status(u16 *status) +{ + u32 mask = 0xFF << 16; + + /* use atomic mode to read status instead + of using auto mode,auto-mode has issues + and the status is not correct. + */ + raw_write(NFC_STATUS, REG_NFC_OPS); + + wait_op_done(TROP_US_DELAY, true); + + *status = (raw_read(NFC_CONFIG1) & mask) >> 16; + +} +#endif + +/*! + * This function requests the NFC to perform a read of the + * NAND device status and returns the current status. + * + * @return device status + */ +static u16 get_dev_status(void) +{ +#ifdef NFC_AUTO_MODE_ENABLE + int i; + u16 status = 0; + int cs = NFC_GET_NFC_ACTIVE_CS(); + + for (i = 0; i < num_of_interleave; i++) { + + /* set ative cs */ + NFC_SET_NFC_ACTIVE_CS(i); + + /* FIXME, NFC Auto erase may have + * problem, have to pollingit until + * the nand get idle, otherwise + * it may get error + */ + read_dev_status(&status); + if (status & NAND_STATUS_FAIL) + break; + } + + /* Restore active CS */ + NFC_SET_NFC_ACTIVE_CS(cs); + + return status; +#else + volatile u16 *mainBuf = MAIN_AREA1; + u8 val = 1; + u16 ret; + + /* Set ram buffer id */ + NFC_SET_RBA(val); + + /* Read status into main buffer */ + raw_write(NFC_STATUS, REG_NFC_OPS); + + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY, true); + + /* Status is placed in first word of main buffer */ + /* get status, then recovery area 1 data */ + ret = *mainBuf; + + return ret; +#endif +} + +static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + raw_write((raw_read(REG_NFC_ECC_EN) | NFC_ECC_EN), REG_NFC_ECC_EN); + return; +} + +/* + * Function to record the ECC corrected/uncorrected errors resulted + * after a page read. This NFC detects and corrects upto to 4 symbols + * of 9-bits each. + */ +static int mxc_check_ecc_status(struct mtd_info *mtd) +{ + u32 ecc_stat, err; + int no_subpages = 1; + int ret = 0; + u8 ecc_bit_mask = 0xf; + + no_subpages = mtd->writesize >> 9; + + no_subpages /= num_of_interleave; + + ecc_stat = GET_NFC_ECC_STATUS(); + do { + err = ecc_stat & ecc_bit_mask; + if (err == ecc_bit_mask) { + mtd->ecc_stats.failed++; + printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); + return -1; + } else { + ret += err; + } + ecc_stat >>= 4; + } while (--no_subpages); + + pr_debug("Correctable ECC Error(%d)\n", ret); + + return ret; +} + +/* + * Function to correct the detected errors. This NFC corrects all the errors + * detected. So this function just return 0. + */ +static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) +{ + return 0; +} + +/* + * Function to calculate the ECC for the data to be stored in the Nand device. + * This NFC has a hardware RS(511,503) ECC engine together with the RS ECC + * CONTROL blocks are responsible for detection and correction of up to + * 8 symbols of 9 bits each in 528 byte page. + * So this function is just return 0. + */ + +static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u_char *ecc_code) +{ + return 0; +} + +/*! + * This function id is used to read the data buffer from the NAND Flash. To + * read the data from NAND Flash first the data output cycle is initiated by + * the NFC, which copies the data to RAMbuffer. This data of length \b len is + * then copied to buffer \b buf. + * + * @param mtd MTD structure for the NAND Flash + * @param buf data to be read from NAND Flash + * @param len number of bytes to be read + */ +static void mxc_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len) +{ + u16 col = g_nandfc_info.colAddr; + + if (mtd->writesize) { + + int j = mtd->writesize - col; + int n = mtd->oobsize + j; + + n = min(n, len); + + if (j > 0) { + if (n > j) { + memcpy(buf, &data_buf[col], j); + memcpy(buf + j, &oob_buf[0], n - j); + } else { + memcpy(buf, &data_buf[col], n); + } + } else { + col -= mtd->writesize; + memcpy(buf, &oob_buf[col], len); + } + + /* update */ + g_nandfc_info.colAddr += n; + + } else { + /* At flash identify phase, + * mtd->writesize has not been + * set correctly, it should + * be zero.And len will less 2 + */ + memcpy(buf, &data_buf[col], len); + + /* update */ + g_nandfc_info.colAddr += len; + } + +} + +/*! + * This function reads byte from the NAND Flash + * + * @param mtd MTD structure for the NAND Flash + * + * @return data read from the NAND Flash + */ +static uint8_t mxc_nand_read_byte(struct mtd_info *mtd) +{ + uint8_t ret; + + /* Check for status request */ + if (g_nandfc_info.bStatusRequest) { + return get_dev_status() & 0xFF; + } + + mxc_nand_read_buf(mtd, &ret, 1); + + return ret; +} + +/*! + * This function reads word from the NAND Flash + * + * @param mtd MTD structure for the NAND Flash + * + * @return data read from the NAND Flash + */ +static u16 mxc_nand_read_word(struct mtd_info *mtd) +{ + u16 ret; + + mxc_nand_read_buf(mtd, (uint8_t *) &ret, sizeof(u16)); + + return ret; +} + +/*! + * This function reads byte from the NAND Flash + * + * @param mtd MTD structure for the NAND Flash + * + * @return data read from the NAND Flash + */ +static u_char mxc_nand_read_byte16(struct mtd_info *mtd) +{ + /* Check for status request */ + if (g_nandfc_info.bStatusRequest) { + return get_dev_status() & 0xFF; + } + + return mxc_nand_read_word(mtd) & 0xFF; +} + +/*! + * This function writes data of length \b len from buffer \b buf to the NAND + * internal RAM buffer's MAIN area 0. + * + * @param mtd MTD structure for the NAND Flash + * @param buf data to be written to NAND Flash + * @param len number of bytes to be written + */ +static void mxc_nand_write_buf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + u16 col = g_nandfc_info.colAddr; + int j = mtd->writesize - col; + int n = mtd->oobsize + j; + + n = min(n, len); + + if (j > 0) { + if (n > j) { + memcpy(&data_buf[col], buf, j); + memcpy(&oob_buf[0], buf + j, n - j); + } else { + memcpy(&data_buf[col], buf, n); + } + } else { + col -= mtd->writesize; + memcpy(&oob_buf[col], buf, len); + } + + /* update */ + g_nandfc_info.colAddr += n; +} + +/*! + * This function is used by the upper layer to verify the data in NAND Flash + * with the data in the \b buf. + * + * @param mtd MTD structure for the NAND Flash + * @param buf data to be verified + * @param len length of the data to be verified + * + * @return -EFAULT if error else 0 + * + */ +static int mxc_nand_verify_buf(struct mtd_info *mtd, const u_char * buf, + int len) +{ + u_char *s = data_buf; + + const u_char *p = buf; + + for (; len > 0; len--) { + if (*p++ != *s++) + return -EFAULT; + } + + return 0; +} + +/*! + * This function will enable NFC clock + * + */ +static inline void mxc_nand_clk_enable(void) +{ + if (!mxc_nand_data->clk_active) { + clk_enable(nfc_clk); + mxc_nand_data->clk_active = 1; + } +} + +/*! + * This function will disable NFC clock + * + */ +static inline void mxc_nand_clk_disable(void) +{ + if (mxc_nand_data->clk_active) { + clk_disable(nfc_clk); + mxc_nand_data->clk_active = 0; + } +} + +/*! + * This function is used by upper layer for select and deselect of the NAND + * chip + * + * @param mtd MTD structure for the NAND Flash + * @param chip val indicating select or deselect + */ +static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) +{ + + switch (chip) { + case -1: + /* Disable the NFC clock */ + mxc_nand_clk_disable(); + + break; + case 0 ... NFC_GET_MAXCHIP_SP(): + /* Enable the NFC clock */ + mxc_nand_clk_enable(); + NFC_SET_NFC_ACTIVE_CS(chip); + + break; + + default: + break; + } +} + +/* + * Function to perform the address cycles. + */ +static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) +{ +#ifdef NFC_AUTO_MODE_ENABLE + + if (page_addr != -1 && column != -1) { + u32 mask = 0xFFFF; + /* the column address */ + raw_write(column & mask, NFC_FLASH_ADDR0); + raw_write((raw_read(NFC_FLASH_ADDR0) | + ((page_addr & mask) << 16)), NFC_FLASH_ADDR0); + /* the row address */ + raw_write(((raw_read(NFC_FLASH_ADDR8) & (mask << 16)) | + ((page_addr & (mask << 16)) >> 16)), + NFC_FLASH_ADDR8); + } else if (page_addr != -1) { + raw_write(page_addr, NFC_FLASH_ADDR0); + raw_write(0, NFC_FLASH_ADDR8); + } + + DEBUG(MTD_DEBUG_LEVEL3, + "AutoMode:the ADDR REGS value is (0x%x, 0x%x)\n", + raw_read(NFC_FLASH_ADDR0), raw_read(NFC_FLASH_ADDR8)); +#else + + u32 page_mask = g_page_mask; + + if (column != -1) { + send_addr(column & 0xFF, true); + if (IS_2K_PAGE_NAND) { + /* another col addr cycle for 2k page */ + send_addr((column >> 8) & 0xF, true); + } else if (IS_4K_PAGE_NAND) { + /* another col addr cycle for 4k page */ + send_addr((column >> 8) & 0x1F, true); + } + } + if (page_addr != -1) { + do { + send_addr((page_addr & 0xff), true); + page_mask >>= 8; + page_addr >>= 8; + } while (page_mask != 0); + } +#endif +} + +/*! + * This function is used by the upper layer to write command to NAND Flash for + * different operations to be carried out on NAND Flash + * + * @param mtd MTD structure for the NAND Flash + * @param command command for NAND Flash + * @param column column offset for the page read + * @param page_addr page to be read from NAND Flash + */ +static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + int column, int page_addr) +{ + bool useirq = true; + + DEBUG(MTD_DEBUG_LEVEL3, + "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", + command, column, page_addr); + /* + * Reset command state information + */ + g_nandfc_info.bStatusRequest = false; + + /* + * Command pre-processing step + */ + switch (command) { + case NAND_CMD_STATUS: + g_nandfc_info.colAddr = 0; + g_nandfc_info.bStatusRequest = true; + break; + + case NAND_CMD_READ0: + g_nandfc_info.colAddr = column; + break; + + case NAND_CMD_READOOB: + g_nandfc_info.colAddr = column; + command = NAND_CMD_READ0; + break; + + case NAND_CMD_SEQIN: + if (column != 0) { + + /* FIXME: before send SEQIN command for + * partial write,We need read one page out. + * FSL NFC does not support partial write + * It alway send out 512+ecc+512+ecc ... + * for large page nand flash. But for small + * page nand flash, it did support SPARE + * ONLY operation. But to make driver + * simple. We take the same as large page,read + * whole page out and update. As for MLC nand + * NOP(num of operation) = 1. Partial written + * on one programed page is not allowed! We + * can't limit it on the driver, it need the + * upper layer applicaiton take care it + */ + + mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); + } + + g_nandfc_info.colAddr = column; + column = 0; + + break; + + case NAND_CMD_PAGEPROG: +#ifndef NFC_AUTO_MODE_ENABLE + /* FIXME:the NFC interal buffer + * access has some limitation, it + * does not allow byte access. To + * make the code simple and ease use + * not every time check the address + * alignment.Use the temp buffer + * to accomadate the data.since We + * know data_buf will be at leat 4 + * byte alignment, so we can use + * memcpy safely + */ + nfc_memcpy(MAIN_AREA0, data_buf, mtd->writesize); + copy_spare(mtd, oob_buf, SPARE_AREA0, mtd->oobsize, false); + mxc_nand_bi_swap(mtd); +#endif + + if (IS_LARGE_PAGE_NAND) + PROG_PAGE(); + else + send_prog_page(0); + + break; + + case NAND_CMD_ERASE1: + break; + case NAND_CMD_ERASE2: + break; + } + + /* + * Write out the command to the device. + */ + send_cmd(mtd, command, useirq); + + mxc_do_addr_cycle(mtd, column, page_addr); + + /* + * Command post-processing step + */ + switch (command) { + + case NAND_CMD_READOOB: + case NAND_CMD_READ0: + if (IS_LARGE_PAGE_NAND) { + /* send read confirm command */ + send_cmd(mtd, NAND_CMD_READSTART, true); + /* read for each AREA */ + READ_PAGE(); + } else { + send_read_page(0); + } + +#ifndef NFC_AUTO_MODE_ENABLE + /* FIXME, the NFC interal buffer + * access has some limitation, it + * does not allow byte access. To + * make the code simple and ease use + * not every time check the address + * alignment.Use the temp buffer + * to accomadate the data.since We + * know data_buf will be at leat 4 + * byte alignment, so we can use + * memcpy safely + */ + mxc_nand_bi_swap(mtd); + nfc_memcpy(data_buf, MAIN_AREA0, mtd->writesize); + copy_spare(mtd, oob_buf, SPARE_AREA0, mtd->oobsize, true); +#endif + + break; + + case NAND_CMD_READID: + send_read_id(); + g_nandfc_info.colAddr = column; + nfc_memcpy(data_buf, MAIN_AREA0, 2048); + + break; + } +} + +static int mxc_nand_read_oob(struct mtd_info *mtd, + struct nand_chip *chip, int page, int sndcmd) +{ + if (sndcmd) { + + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; + } + + memcpy(chip->oob_poi, oob_buf, mtd->oobsize); + + return sndcmd; +} + +static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int page) +{ + +#ifndef NFC_AUTO_MODE_ENABLE + mxc_check_ecc_status(mtd); +#endif + + memcpy(buf, data_buf, mtd->writesize); + memcpy(chip->oob_poi, oob_buf, mtd->oobsize); + + return 0; +} + +static void mxc_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf) +{ + memcpy(data_buf, buf, mtd->writesize); + memcpy(oob_buf, chip->oob_poi, mtd->oobsize); + +} + +/*! + * mxc_nand_block_bad - Claims all blocks are good + * In principle, this function is *only* called when the NAND Flash MTD system + * isn't allowed to keep an in-memory bad block table, so it is forced to ask + * the driver for bad block information. + * + * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so + * this function is *only* called when we take it away. + * + * We take away the in-memory BBT when the user sets the "ignorebad" parameter, + * which indicates that all blocks should be reported good. + * + * Thus, this function is only called when we want *all* blocks to look good, + * so it *always* return success. + * + * @mtd: Ignored. + * @ofs: Ignored. + * @getchip: Ignored. + */ +static int mxc_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + return 0; +} + +/* Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks. */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr smallpage_memorybased = { + .options = NAND_BBT_SCAN2NDPAGE, + .offs = 5, + .len = 1, + .pattern = scan_ff_pattern +}; + +static struct nand_bbt_descr largepage_memorybased = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern +}; + +/* Generic flash bbt decriptors +*/ +static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; +static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' }; + +static struct nand_bbt_descr bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION, + .offs = 0, + .len = 4, + .veroffs = 4, + .maxblocks = 4, + .pattern = bbt_pattern +}; + +static struct nand_bbt_descr bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION, + .offs = 0, + .len = 4, + .veroffs = 4, + .maxblocks = 4, + .pattern = mirror_pattern +}; + +static int mxc_nand_scan_bbt(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + g_page_mask = this->pagemask; + + if (IS_2K_PAGE_NAND) { + NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); + this->ecc.layout = &nand_hw_eccoob_2k; + } else if (IS_4K_PAGE_NAND) { + NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); + this->ecc.layout = &nand_hw_eccoob_4k; + } else { + this->ecc.layout = &nand_hw_eccoob_512; + } + + /* propagate ecc.layout to mtd_info */ + mtd->ecclayout = this->ecc.layout; + + /* jffs2 not write oob */ + mtd->flags &= ~MTD_OOB_WRITEABLE; + + /* fix up the offset */ + largepage_memorybased.offs = BAD_BLK_MARKER_OOB_OFFS; + + /* keep compatible for bbt table with old soc */ + if (cpu_is_mx53()) { + bbt_mirror_descr.offs = BAD_BLK_MARKER_OOB_OFFS + 2; + bbt_main_descr.offs = BAD_BLK_MARKER_OOB_OFFS + 2; + bbt_mirror_descr.veroffs = bbt_mirror_descr.offs + 4; + bbt_main_descr.veroffs = bbt_main_descr.offs + 4; + } + + /* use flash based bbt */ + this->bbt_td = &bbt_main_descr; + this->bbt_md = &bbt_mirror_descr; + + /* update flash based bbt */ + this->options |= NAND_USE_FLASH_BBT; + + if (!this->badblock_pattern) { + this->badblock_pattern = (mtd->writesize > 512) ? + &largepage_memorybased : &smallpage_memorybased; + } + + /* Build bad block table */ + return nand_scan_bbt(mtd, this->badblock_pattern); +} + +static int mxc_get_resources(struct platform_device *pdev) +{ + struct resource *r; + int error = 0; + +#define MXC_NFC_NO_IP_REG \ + (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx32() || cpu_is_mx35()) + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + error = -ENXIO; + goto out_0; + } + nfc_axi_base = ioremap(r->start, resource_size(r)); + + if (!MXC_NFC_NO_IP_REG) { + r = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!r) { + error = -ENXIO; + goto out_1; + } + } + nfc_ip_base = ioremap(r->start, resource_size(r)); + + r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!r) { + error = -ENXIO; + goto out_2; + } + nfc_irq = r->start; + + init_waitqueue_head(&irq_waitq); + error = request_irq(nfc_irq, mxc_nfc_irq, 0, "mxc_nd", NULL); + if (error) + goto out_3; + + return 0; +out_3: +out_2: + if (!MXC_NFC_NO_IP_REG) + iounmap(nfc_ip_base); +out_1: + iounmap(nfc_axi_base); +out_0: + return error; +} + +static void mxc_nfc_init(void) +{ + /* Disable interrupt */ + raw_write((raw_read(REG_NFC_INTRRUPT) | NFC_INT_MSK), REG_NFC_INTRRUPT); + + /* disable spare enable */ + raw_write(raw_read(REG_NFC_SP_EN) & ~NFC_SP_EN, REG_NFC_SP_EN); + + /* Unlock the internal RAM Buffer */ + raw_write(NFC_SET_BLS(NFC_BLS_UNLCOKED), REG_NFC_BLS); + + if (!(cpu_is_mx53())) { + /* Blocks to be unlocked */ + UNLOCK_ADDR(0x0, 0xFFFF); + + /* Unlock Block Command for given address range */ + raw_write(NFC_SET_WPC(NFC_WPC_UNLOCK), REG_NFC_WPC); + } + + /* Enable symetric mode by default except mx37TO1.0 */ + if (!(cpu_is_mx37_rev(CHIP_REV_1_0) == 1)) + raw_write(raw_read(REG_NFC_ONE_CYCLE) | + NFC_ONE_CYCLE, REG_NFC_ONE_CYCLE); +} + +static int mxc_alloc_buf(void) +{ + int err = 0; + + data_buf = kzalloc(NAND_MAX_PAGESIZE, GFP_KERNEL); + if (!data_buf) { + printk(KERN_ERR "%s: failed to allocate data_buf\n", __func__); + err = -ENOMEM; + goto out; + } + oob_buf = kzalloc(NAND_MAX_OOBSIZE, GFP_KERNEL); + if (!oob_buf) { + printk(KERN_ERR "%s: failed to allocate oob_buf\n", __func__); + err = -ENOMEM; + goto out; + } + + out: + return err; +} + +static void mxc_free_buf(void) +{ + kfree(data_buf); + kfree(oob_buf); +} + +int nand_scan_mid(struct mtd_info *mtd) +{ + int i; + uint8_t id_bytes[NAND_DEVICE_ID_BYTE_COUNT]; + struct nand_chip *this = mtd->priv; + struct nand_device_info *dev_info; + + if (!IS_LARGE_PAGE_NAND) + return 0; + + /* Read ID bytes from the first NAND Flash chip. */ + this->select_chip(mtd, 0); + + this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); + + for (i = 0; i < NAND_DEVICE_ID_BYTE_COUNT; i++) + id_bytes[i] = this->read_byte(mtd); + + /* Get information about this device, based on the ID bytes. */ + dev_info = nand_device_get_info(id_bytes); + + /* Check if we understand this device. */ + if (!dev_info) { + printk(KERN_ERR "Unrecognized NAND Flash device.\n"); + return !0; + } + + /* Correct mtd setting */ + this->chipsize = dev_info->chip_size_in_bytes; + mtd->size = dev_info->chip_size_in_bytes * this->numchips; + mtd->writesize = dev_info->page_total_size_in_bytes & ~0x3ff; + mtd->oobsize = dev_info->page_total_size_in_bytes & 0x3ff; + mtd->erasesize = dev_info->block_size_in_pages * mtd->writesize; + + /* Calculate the address shift from the page size */ + this->page_shift = ffs(mtd->writesize) - 1; + /* Convert chipsize to number of pages per chip -1. */ + this->pagemask = (this->chipsize >> this->page_shift) - 1; + + this->bbt_erase_shift = this->phys_erase_shift = + ffs(mtd->erasesize) - 1; + this->chip_shift = ffs(this->chipsize) - 1; + + return 0; +} + +/*! + * show_device_disable_bi_swap() + * Shows the value of the 'disable_bi_swap' flag. + * + * @dev: The device of interest. + * @attr: The attribute of interest. + * @buf: A buffer that will receive a representation of the attribute. + */ +static ssize_t show_device_disable_bi_swap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", mxc_nand_data->disable_bi_swap); +} + +/*! + * store_device_disable_bi_swap() + * Sets the value of the 'disable_bi_swap' flag. + * + * @dev: The device of interest. + * @attr: The attribute of interest. + * @buf: A buffer containing a new attribute value. + * @size: The size of the buffer. + */ +static ssize_t store_device_disable_bi_swap(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + const char *p = buf; + unsigned long v; + + /* Try to make sense of what arrived from user space. */ + + if (strict_strtoul(p, 0, &v) < 0) + return size; + + if (v > 0) + v = 1; + mxc_nand_data->disable_bi_swap = v; + return size; + +} + +static DEVICE_ATTR(disable_bi_swap, 0644, + show_device_disable_bi_swap, store_device_disable_bi_swap); + +/*! + * show_device_ignorebad() + * Shows the value of the 'ignore_bad_block' flag. + * + * @dev: The device of interest. + * @attr: The attribute of interest. + * @buf: A buffer that will receive a representation of the attribute. + */ +static ssize_t show_device_ignorebad(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", mxc_nand_data->ignore_bad_block); +} + +/*! + * store_device_ignorebad() + * Sets the value of the 'ignore_bad_block' flag. + * + * @dev: The device of interest. + * @attr: The attribute of interest. + * @buf: A buffer containing a new attribute value. + * @size: The size of the buffer. + */ +static ssize_t store_device_ignorebad(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + const char *p = buf; + unsigned long v; + + /* Try to make sense of what arrived from user space. */ + + if (strict_strtoul(p, 0, &v) < 0) + return size; + + if (v > 0) + v = 1; + + /* Only do something if the value is changing. */ + if (v != mxc_nand_data->ignore_bad_block) { + if (v) { + /* + * If control arrives here, we want to begin ignoring + * bad block marks. Reach into the NAND Flash MTD data + * structures and set the in-memory BBT pointer to NULL. + * This will cause the NAND Flash MTD code to believe + * that it never created a BBT and force it to call our + * block_bad function. + */ + mxc_nand_data->saved_bbt = mxc_nand_data->nand.bbt; + mxc_nand_data->nand.bbt = 0; + mxc_nand_data->saved_block_bad = + mxc_nand_data->nand.block_bad; + mxc_nand_data->nand.block_bad = + mxc_nand_block_bad; + } else { + /* + * If control arrives here, we want to stop ignoring + * bad block marks. Restore the NAND Flash MTD's pointer + * to its in-memory BBT. + */ + mxc_nand_data->nand.bbt = mxc_nand_data->saved_bbt; + mxc_nand_data->nand.block_bad = + mxc_nand_data->saved_block_bad; + } + mxc_nand_data->ignore_bad_block = v; + } + + return size; + +} + +static DEVICE_ATTR(ignorebad, 0644, + show_device_ignorebad, store_device_ignorebad); + + +static struct device_attribute *device_attributes[] = { + &dev_attr_disable_bi_swap, + &dev_attr_ignorebad, +}; +/*! + * manage_sysfs_files() - Creates/removes sysfs files for this device. + * + * @create: create/remove the sys entry. + */ +static void manage_sysfs_files(int create) +{ + struct device *dev = mxc_nand_data->dev; + int error; + unsigned int i; + struct device_attribute **attr; + + for (i = 0, attr = device_attributes; + i < ARRAY_SIZE(device_attributes); i++, attr++) { + + if (create) { + error = device_create_file(dev, *attr); + if (error) { + while (--attr >= device_attributes) + device_remove_file(dev, *attr); + return; + } + } else { + device_remove_file(dev, *attr); + } + } + +} + + +/*! + * This function is called during the driver binding process. + * + * @param pdev the device structure used to store device specific + * information that is used by the suspend, resume and + * remove functions + * + * @return The function always returns 0. + */ +static int __devinit mxcnd_probe(struct platform_device *pdev) +{ + struct nand_chip *this; + struct mtd_info *mtd; + struct flash_platform_data *flash = pdev->dev.platform_data; + int nr_parts = 0, err = 0; + + /* get the resource */ + err = mxc_get_resources(pdev); + if (err) + goto out; + + /* init the nfc */ + mxc_nfc_init(); + + /* init data buf */ + if (mxc_alloc_buf()) + goto out; + + /* Allocate memory for MTD device structure and private data */ + mxc_nand_data = kzalloc(sizeof(struct mxc_mtd_s), GFP_KERNEL); + if (!mxc_nand_data) { + printk(KERN_ERR "%s: failed to allocate mtd_info\n", + __FUNCTION__); + err = -ENOMEM; + goto out; + } + + memset((char *)&g_nandfc_info, 0, sizeof(g_nandfc_info)); + + mxc_nand_data->dev = &pdev->dev; + /* structures must be linked */ + this = &mxc_nand_data->nand; + mtd = &mxc_nand_data->mtd; + mtd->priv = this; + mtd->owner = THIS_MODULE; + + this->priv = mxc_nand_data; + this->cmdfunc = mxc_nand_command; + this->select_chip = mxc_nand_select_chip; + this->read_byte = mxc_nand_read_byte; + this->read_word = mxc_nand_read_word; + this->write_buf = mxc_nand_write_buf; + this->read_buf = mxc_nand_read_buf; + this->verify_buf = mxc_nand_verify_buf; + this->scan_bbt = mxc_nand_scan_bbt; + + /* NAND bus width determines access funtions used by upper layer */ + if (flash->width == 2) { + this->read_byte = mxc_nand_read_byte16; + this->options |= NAND_BUSWIDTH_16; + NFC_SET_NFMS(1 << NFMS_NF_DWIDTH); + } else { + NFC_SET_NFMS(0); + } + + nfc_clk = clk_get(&pdev->dev, "nfc_clk"); + clk_enable(nfc_clk); + mxc_nand_data->clk_active = 1; + + if (hardware_ecc) { + this->ecc.read_page = mxc_nand_read_page; + this->ecc.write_page = mxc_nand_write_page; + this->ecc.read_oob = mxc_nand_read_oob; + this->ecc.layout = &nand_hw_eccoob_512; + this->ecc.calculate = mxc_nand_calculate_ecc; + this->ecc.hwctl = mxc_nand_enable_hwecc; + this->ecc.correct = mxc_nand_correct_data; + this->ecc.mode = NAND_ECC_HW; + this->ecc.size = 512; + this->ecc.bytes = 9; + raw_write((raw_read(REG_NFC_ECC_EN) | NFC_ECC_EN), + REG_NFC_ECC_EN); + } else { + this->ecc.mode = NAND_ECC_SOFT; + raw_write((raw_read(REG_NFC_ECC_EN) & ~NFC_ECC_EN), + REG_NFC_ECC_EN); + } + + /* config the gpio */ + if (flash->init) + flash->init(); + + /* Reset NAND */ + this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + + /* Scan to find existence of the device */ + if (nand_scan_ident(mtd, NFC_GET_MAXCHIP_SP(), NULL) + || nand_scan_mid(mtd) + || nand_scan_tail(mtd)) { + DEBUG(MTD_DEBUG_LEVEL0, + "MXC_ND2: Unable to find any NAND device.\n"); + err = -ENXIO; + goto out_1; + } + + /* Register the partitions */ +#ifdef CONFIG_MTD_PARTITIONS + nr_parts = + parse_mtd_partitions(mtd, part_probes, &mxc_nand_data->parts, 0); + if (nr_parts > 0) + add_mtd_partitions(mtd, mxc_nand_data->parts, nr_parts); + else if (flash->parts) + add_mtd_partitions(mtd, flash->parts, flash->nr_parts); + else +#endif + { + pr_info("Registering %s as whole device\n", mtd->name); + add_mtd_device(mtd); + } + + /* Create sysfs entries for this device. */ + manage_sysfs_files(true); + + platform_set_drvdata(pdev, mtd); + + return 0; + + out_1: + kfree(mxc_nand_data); + out: + return err; + +} + + /*! + * Dissociates the driver from the device. + * + * @param pdev the device structure used to give information on which + * + * @return The function always returns 0. + */ + +static int __exit mxcnd_remove(struct platform_device *pdev) +{ + struct mtd_info *mtd = platform_get_drvdata(pdev); + struct flash_platform_data *flash = pdev->dev.platform_data; + + if (flash->exit) + flash->exit(); + + manage_sysfs_files(false); + mxc_free_buf(); + + mxc_nand_clk_disable(); + clk_put(nfc_clk); + platform_set_drvdata(pdev, NULL); + + if (mxc_nand_data) { + nand_release(mtd); + free_irq(nfc_irq, NULL); + kfree(mxc_nand_data); + } + + return 0; +} + +#ifdef CONFIG_PM +/*! + * This function is called to put the NAND in a low power state. Refer to the + * document driver-model/driver.txt in the kernel source tree for more + * information. + * + * @param pdev the device information structure + * + * @param state the power state the device is entering + * + * @return The function returns 0 on success and -1 on failure + */ + +static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) +{ + DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2 : NAND suspend\n"); + + /* Disable the NFC clock */ + mxc_nand_clk_disable(); + + return 0; +} + +/*! + * This function is called to bring the NAND back from a low power state. Refer + * to the document driver-model/driver.txt in the kernel source tree for more + * information. + * + * @param pdev the device information structure + * + * @return The function returns 0 on success and -1 on failure + */ +static int mxcnd_resume(struct platform_device *pdev) +{ + DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2 : NAND resume\n"); + + /* Enable the NFC clock */ + mxc_nand_clk_enable(); + + return 0; +} + +#else +#define mxcnd_suspend NULL +#define mxcnd_resume NULL +#endif /* CONFIG_PM */ + +/*! + * This structure contains pointers to the power management callback functions. + */ +static struct platform_driver mxcnd_driver = { + .driver = { + .name = "mxc_nandv2_flash", + }, + .probe = mxcnd_probe, + .remove = __exit_p(mxcnd_remove), + .suspend = mxcnd_suspend, + .resume = mxcnd_resume, +}; + +/*! + * Main initialization routine + * @return 0 if successful; non-zero otherwise + */ +static int __init mxc_nd_init(void) +{ + /* Register the device driver structure. */ + pr_info("MXC MTD nand Driver %s\n", DVR_VER); + if (platform_driver_register(&mxcnd_driver) != 0) { + printk(KERN_ERR "Driver register failed for mxcnd_driver\n"); + return -ENODEV; + } + return 0; +} + +/*! + * Clean up routine + */ +static void __exit mxc_nd_cleanup(void) +{ + /* Unregister the device structure */ + platform_driver_unregister(&mxcnd_driver); +} + +module_init(mxc_nd_init); +module_exit(mxc_nd_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("MXC NAND MTD driver Version 2-5"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/mxc_nd2.h b/drivers/mtd/nand/mxc_nd2.h new file mode 100644 index 00000000000..224b422bc92 --- /dev/null +++ b/drivers/mtd/nand/mxc_nd2.h @@ -0,0 +1,731 @@ +/* + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/*! + * @file mxc_nd2.h + * + * @brief This file contains the NAND Flash Controller register information. + * + * + * @ingroup NAND_MTD + */ + +#ifndef __MXC_ND2_H__ +#define __MXC_ND2_H__ + +#include + +#define CHIP_REV_1_0 0x00 +#define CHIP_REV_2_0 0x20 + +#define mxc_cpu_rev() (system_rev & 0xFF) +#define mxc_cpu_is_rev(rev) \ + ((mxc_cpu_rev() == rev) ? 1 : ((mxc_cpu_rev() < rev) ? -1 : 2)) +#define cpu_rev(type, rev) (cpu_is_##type() ? mxc_cpu_is_rev(rev) : 0) +#define cpu_is_mx51_rev(rev) cpu_rev(mx51, rev) +#define cpu_is_mx37_rev(rev) cpu_rev(mx37, rev) + +#define CONFIG_ARCH_MXC_HAS_NFC_V3 +#define CONFIG_ARCH_MXC_HAS_NFC_V3_2 + +#define IS_2K_PAGE_NAND ((mtd->writesize / num_of_interleave) \ + == NAND_PAGESIZE_2KB) +#define IS_4K_PAGE_NAND ((mtd->writesize / num_of_interleave) \ + == NAND_PAGESIZE_4KB) +#define IS_LARGE_PAGE_NAND ((mtd->writesize / num_of_interleave) > 512) + +#define GET_NAND_OOB_SIZE (mtd->oobsize / num_of_interleave) +#define GET_NAND_PAGE_SIZE (mtd->writesize / num_of_interleave) + +#define NAND_PAGESIZE_2KB 2048 +#define NAND_PAGESIZE_4KB 4096 + +/* + * main area for bad block marker is in the last data section + * the spare area for swapped bad block marker is the second + * byte of last spare section + */ +#define NAND_SECTIONS (GET_NAND_PAGE_SIZE >> 9) +#define NAND_OOB_PER_SECTION (((GET_NAND_OOB_SIZE / NAND_SECTIONS) >> 1) << 1) +#define NAND_CHUNKS (GET_NAND_PAGE_SIZE / (512 + NAND_OOB_PER_SECTION)) + +#define BAD_BLK_MARKER_MAIN_OFFS \ + (GET_NAND_PAGE_SIZE - NAND_CHUNKS * NAND_OOB_PER_SECTION) + +#define BAD_BLK_MARKER_SP_OFFS (NAND_CHUNKS * SPARE_LEN) + +#define BAD_BLK_MARKER_OOB_OFFS (NAND_CHUNKS * NAND_OOB_PER_SECTION) + +#define BAD_BLK_MARKER_MAIN \ + ((u32)MAIN_AREA0 + BAD_BLK_MARKER_MAIN_OFFS) + +#define BAD_BLK_MARKER_SP \ + ((u32)SPARE_AREA0 + BAD_BLK_MARKER_SP_OFFS) + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3 +/* + * For V3 NFC registers Definition + */ + +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_1) /* mx37 */ +#define MXC_INT_NANDFC MXC_INT_EMI +#define NFC_FLASH_ADDR_CMD (nfc_axi_base + 0x1E00) +#define NFC_CONFIG1 (nfc_axi_base + 0x1E04) +#define NFC_ECC_STATUS_RESULT (nfc_axi_base + 0x1E08) +#define LAUNCH_NFC (nfc_axi_base + 0x1E0c) +#define NFC_WRPROT (nfc_ip_base + 0x00) +#define NFC_WRPROT_UNLOCK_BLK_ADD0 (nfc_ip_base + 0x04) +#define NFC_CONFIG2 (nfc_ip_base + 0x14) +#define NFC_IPC (nfc_ip_base + 0x18) +#elif defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) /* mx51 */ +#define MXC_INT_NANDFC MXC_INT_NFC +#define NFC_AUTO_MODE_ENABLE +#define NFC_FLASH_CMD (nfc_axi_base + 0x1E00) +#define NFC_FLASH_ADDR0 (nfc_axi_base + 0x1E04) +#define NFC_FLASH_ADDR8 (nfc_axi_base + 0x1E24) +#define NFC_CONFIG1 (nfc_axi_base + 0x1E34) +#define NFC_ECC_STATUS_RESULT (nfc_axi_base + 0x1E38) +#define NFC_ECC_STATUS_SUM (nfc_axi_base + 0x1E3C) +#define LAUNCH_NFC (nfc_axi_base + 0x1E40) +#define NFC_WRPROT (nfc_ip_base + 0x00) +#define NFC_WRPROT_UNLOCK_BLK_ADD0 (nfc_ip_base + 0x04) +#define NFC_CONFIG2 (nfc_ip_base + 0x24) +#define NFC_CONFIG3 (nfc_ip_base + 0x28) +#define NFC_IPC (nfc_ip_base + 0x2C) +#define NFC_DELAY_LINE (nfc_ip_base + 0x34) +#else /* skye */ +#define NFC_FLASH_ADDR_CMD (nfc_axi_base + 0xE00) +#define NFC_CONFIG1 (nfc_axi_base + 0xE04) +#define NFC_ECC_STATUS_RESULT (nfc_axi_base + 0xE08) +#define LAUNCH_NFC (nfc_axi_base + 0xE0C) +#define NFC_WRPROT (nfc_ip_base + 0x00) +#define NFC_WRPROT_UNLOCK_BLK_ADD0 (nfc_ip_base + 0x04) +#define NFC_CONFIG2 (nfc_ip_base + 0x14) +#define NFC_IPC (nfc_ip_base + 0x18) +#endif +/*! + * Addresses for NFC RAM BUFFER Main area 0 + */ +#define MAIN_AREA0 ((u16 *)(nfc_axi_base + 0x000)) +#define MAIN_AREA1 ((u16 *)(nfc_axi_base + 0x200)) + +/*! + * Addresses for NFC SPARE BUFFER Spare area 0 + */ +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_1) || \ + defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) +#define SPARE_AREA0 ((u16 *)(nfc_axi_base + 0x1000)) +#define SPARE_LEN 64 +#define SPARE_COUNT 8 +#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) +#else +#define SPARE_AREA0 ((u16 *)(nfc_axi_base + 0x800)) +#define SPARE_LEN 16 +#define SPARE_COUNT 4 +#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) +#endif + +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_1) || \ + defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) +#define NFC_SPAS_WIDTH 8 +#define NFC_SPAS_SHIFT 16 + +#define NFC_SET_SPAS(v) \ + raw_write((((raw_read(NFC_CONFIG2) & \ + NFC_FIELD_RESET(NFC_SPAS_WIDTH, NFC_SPAS_SHIFT)) | ((v) << 16))), \ + NFC_CONFIG2) + +#define NFC_SET_ECC_MODE(v) \ +do { \ + if (cpu_is_mx53() > 0) { \ + if ((v) == NFC_SPAS_218 || (v) == NFC_SPAS_112) \ + raw_write(((raw_read(NFC_CONFIG2) & \ + ~(3 << 6)) | \ + NFC_ECC_MODE_16), NFC_CONFIG2); \ + else \ + raw_write(((raw_read(NFC_CONFIG2) & \ + ~(3 << 6)) | \ + NFC_ECC_MODE_4), NFC_CONFIG2); \ + } else if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0) { \ + if ((v) == NFC_SPAS_218 || (v) == NFC_SPAS_112) \ + raw_write(((raw_read(NFC_CONFIG2) & \ + ~(1 << 6)) | \ + NFC_ECC_MODE_8), NFC_CONFIG2); \ + else \ + raw_write(((raw_read(NFC_CONFIG2) & \ + ~(1 << 6)) | \ + NFC_ECC_MODE_4), NFC_CONFIG2); \ + } else { \ + if ((v) == NFC_SPAS_218 || (v) == NFC_SPAS_112) \ + raw_write(((raw_read(NFC_CONFIG2) & \ + ~(1 << 6)) | \ + NFC_ECC_MODE_4), NFC_CONFIG2); \ + else \ + raw_write(((raw_read(NFC_CONFIG2) & \ + ~(1 << 6)) | \ + NFC_ECC_MODE_8), NFC_CONFIG2); \ + } \ +} while (0) + +#define WRITE_NFC_IP_REG(val, reg) \ + do { \ + raw_write(raw_read(NFC_IPC) | NFC_IPC_CREQ, NFC_IPC); \ + while (!(raw_read(NFC_IPC) & NFC_IPC_ACK)) \ + ; \ + raw_write(val, reg); \ + raw_write(raw_read(NFC_IPC) & ~NFC_IPC_CREQ, NFC_IPC); \ + } while (0) + +#else +#define NFC_SET_SPAS(v) +#define NFC_SET_ECC_MODE(v) +#define NFC_SET_NFMS(v) (NFMS |= (v)) + +#define WRITE_NFC_IP_REG(val, reg) \ + raw_write((raw_read(REG_NFC_OPS_STAT) & ~NFC_OPS_STAT), \ + REG_NFC_OPS_STAT) +#endif + +#define GET_NFC_ECC_STATUS() raw_read(REG_NFC_ECC_STATUS_RESULT); + +/*! + * Set 1 to specific operation bit, rest to 0 in LAUNCH_NFC Register for + * Specific operation + */ +#define NFC_CMD 0x1 +#define NFC_ADDR 0x2 +#define NFC_INPUT 0x4 +#define NFC_OUTPUT 0x8 +#define NFC_ID 0x10 +#define NFC_STATUS 0x20 + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3_2 /* mx51 */ +#define NFC_AUTO_PROG 0x40 +#define NFC_AUTO_READ 0x80 +#define NFC_AUTO_ERASE 0x200 +#define NFC_COPY_BACK_0 0x400 +#define NFC_COPY_BACK_1 0x800 +#define NFC_AUTO_STATE 0x1000 +#endif + +/* Bit Definitions for NFC_IPC*/ +#define NFC_OPS_STAT (1 << 31) + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3_2 /* mx51 */ +#define NFC_OP_DONE (1 << 30) +#define NFC_RB (1 << 28) +#define NFC_PS_WIDTH 2 +#define NFC_PS_SHIFT 0 +#define NFC_PS_512 0 +#define NFC_PS_2K 1 +#define NFC_PS_4K 2 +#else +#define NFC_RB (1 << 29) +#endif + +#define NFC_ONE_CYCLE (1 << 2) + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3_2 /* mx51 */ +#define NFC_INT_MSK (1 << 15) +#define NFC_AUTO_PROG_DONE_MSK (1 << 14) +#define NFC_NUM_ADDR_PHASE1_WIDTH 2 +#define NFC_NUM_ADDR_PHASE1_SHIFT 12 + +#define NFC_NUM_ADDR_PHASE0_WIDTH 1 +#define NFC_NUM_ADDR_PHASE0_SHIFT 5 + +#define NFC_ONE_LESS_PHASE1 0 +#define NFC_TWO_LESS_PHASE1 1 + +#define NFC_FLASH_ADDR_SHIFT 0 +#else +#define NFC_INT_MSK (1 << 4) +#define NFC_BIG (1 << 5) +#define NFC_FLASH_ADDR_SHIFT 16 +#endif + +#define NFC_UNLOCK_END_ADDR_SHIFT 16 + +/* Bit definition for NFC_CONFIGRATION_1 */ +#define NFC_SP_EN (1 << 0) +#define NFC_CE (1 << 1) +#define NFC_RST (1 << 2) +#define NFC_ECC_EN (1 << 3) + +#define NFC_FIELD_RESET(width, shift) (~((((1 << (width)) - 1) << (shift)))) + +#define NFC_RBA_SHIFT 4 + +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_1) || \ + defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) /* mx51 */ +#define NFC_RBA_WIDTH 3 +#else +#define NFC_RBA_WIDTH 2 +#endif + +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) /* mx51 */ +#define NFC_ITERATION_SHIFT 8 +#define NFC_ITERATION_WIDTH 4 +#define NFC_ACTIVE_CS_SHIFT 12 +#define NFC_ACTIVE_CS_WIDTH 3 +/* bit definition for CONFIGRATION3 */ +#define NFC_NO_SDMA (1 << 20) +#define NFC_FMP_SHIFT 16 +#define NFC_FMP_WIDTH 4 +#define NFC_RBB_MODE (1 << 15) +#define NFC_NUM_OF_DEVICES_SHIFT 12 +#define NFC_NUM_OF_DEVICES_WIDTH 4 +#define NFC_DMA_MODE_SHIFT 11 +#define NFC_DMA_MODE_WIDTH 1 +#define NFC_SBB_SHIFT 8 +#define NFC_SBB_WIDTH 3 +#define NFC_BIG (1 << 7) +#define NFC_SB2R_SHIFT 4 +#define NFC_SB2R_WIDTH 3 +#define NFC_FW_SHIFT 3 +#define NFC_FW_WIDTH 1 +#define NFC_TOO (1 << 2) +#define NFC_ADD_OP_SHIFT 0 +#define NFC_ADD_OP_WIDTH 2 +#define NFC_FW_8 1 +#define NFC_FW_16 0 +#define NFC_ST_CMD_SHITF 24 +#define NFC_ST_CMD_WIDTH 8 +#endif + +#define NFC_PPB_32 (0 << 7) +#define NFC_PPB_64 (1 << 7) +#define NFC_PPB_128 (2 << 7) +#define NFC_PPB_256 (3 << 7) +#define NFC_PPB_RESET (~(3 << 7)) + +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) +#define NFC_BLS_LOCKED (0 << 6) +#define NFC_BLS_LOCKED_DEFAULT (1 << 6) +#define NFC_BLS_UNLCOKED (2 << 6) +#define NFC_BLS_RESET (~(3 << 6)) +#else +#define NFC_BLS_LOCKED (0 << 16) +#define NFC_BLS_LOCKED_DEFAULT (1 << 16) +#define NFC_BLS_UNLCOKED (2 << 16) +#define NFC_BLS_RESET (~(3 << 16)) +#endif + +#define NFC_WPC_LOCK_TIGHT 1 +#define NFC_WPC_LOCK (1 << 1) +#define NFC_WPC_UNLOCK (1 << 2) +#define NFC_WPC_RESET (~(7)) +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_1) || \ + defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) +#define NFC_ECC_MODE_4 (0x0 << 6) +#define NFC_ECC_MODE_8 (0x1 << 6) +#define NFC_ECC_MODE_16 (0x3 << 6) +#define NFC_SPAS_16 8 +#define NFC_SPAS_64 32 +#define NFC_SPAS_128 64 +#define NFC_SPAS_112 56 +#define NFC_SPAS_218 109 +#define NFC_IPC_CREQ (1 << 0) +#define NFC_IPC_ACK (1 << 1) +#endif + +#define REG_NFC_OPS_STAT NFC_IPC +#define REG_NFC_INTRRUPT NFC_CONFIG2 +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3_2 +#define REG_NFC_FLASH_ADDR NFC_FLASH_ADDR0 +#define REG_NFC_FLASH_CMD NFC_FLASH_CMD +#else +#define REG_NFC_FLASH_ADDR NFC_FLASH_ADDR_CMD +#define REG_NFC_FLASH_CMD NFC_FLASH_ADDR_CMD +#endif +#define REG_NFC_OPS LAUNCH_NFC +#define REG_NFC_SET_RBA NFC_CONFIG1 +#define REG_NFC_RB NFC_IPC +#define REG_NFC_ECC_EN NFC_CONFIG2 +#define REG_NFC_ECC_STATUS_RESULT NFC_ECC_STATUS_RESULT +#define REG_NFC_CE NFC_CONFIG1 +#define REG_NFC_RST NFC_CONFIG1 +#define REG_NFC_PPB NFC_CONFIG2 +#define REG_NFC_SP_EN NFC_CONFIG1 +#define REG_NFC_BLS NFC_WRPROT +#define REG_UNLOCK_BLK_ADD0 NFC_WRPROT_UNLOCK_BLK_ADD0 +#define REG_UNLOCK_BLK_ADD1 NFC_WRPROT_UNLOCK_BLK_ADD1 +#define REG_UNLOCK_BLK_ADD2 NFC_WRPROT_UNLOCK_BLK_ADD2 +#define REG_UNLOCK_BLK_ADD3 NFC_WRPROT_UNLOCK_BLK_ADD3 +#define REG_NFC_WPC NFC_WRPROT +#define REG_NFC_ONE_CYCLE NFC_CONFIG2 + +/* NFC V3 Specific MACRO functions definitions */ +#define raw_write(v, a) __raw_writel(v, a) +#define raw_read(a) __raw_readl(a) + +/* Set RBA buffer id*/ +#define NFC_SET_RBA(val) \ + raw_write((raw_read(REG_NFC_SET_RBA) & \ + (NFC_FIELD_RESET(NFC_RBA_WIDTH, NFC_RBA_SHIFT))) | \ + ((val) << NFC_RBA_SHIFT), REG_NFC_SET_RBA); + +#define NFC_SET_PS(val) \ + raw_write((raw_read(NFC_CONFIG2) & \ + (NFC_FIELD_RESET(NFC_PS_WIDTH, NFC_PS_SHIFT))) | \ + ((val) << NFC_PS_SHIFT), NFC_CONFIG2); + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3_2 +#define UNLOCK_ADDR(start_addr, end_addr) \ +{ \ + int i = 0; \ + for (; i < NAND_MAX_CHIPS; i++) \ + raw_write(start_addr | \ + (end_addr << NFC_UNLOCK_END_ADDR_SHIFT), \ + REG_UNLOCK_BLK_ADD0 + (i << 2)); \ +} +#define NFC_SET_NFC_ACTIVE_CS(val) \ + raw_write((raw_read(NFC_CONFIG1) & \ + (NFC_FIELD_RESET(NFC_ACTIVE_CS_WIDTH, NFC_ACTIVE_CS_SHIFT))) | \ + ((val) << NFC_ACTIVE_CS_SHIFT), NFC_CONFIG1); + +#define NFC_GET_NFC_ACTIVE_CS() \ + ((raw_read(NFC_CONFIG1) >> NFC_ACTIVE_CS_SHIFT) & \ + ((1 << NFC_ACTIVE_CS_WIDTH) - 1)) + +#define NFC_GET_MAXCHIP_SP() 8 + +#else +#define UNLOCK_ADDR(start_addr, end_addr) \ + raw_write(start_addr | \ + (end_addr << NFC_UNLOCK_END_ADDR_SHIFT), REG_UNLOCK_BLK_ADD0); + +#define NFC_SET_NFC_ACTIVE_CS(val) +#define NFC_GET_NFC_ACTIVE_CS() +#define NFC_GET_MAXCHIP_SP() 1 +#endif + +#define NFC_SET_BLS(val) ((raw_read(REG_NFC_BLS) & NFC_BLS_RESET) | val) +#define NFC_SET_WPC(val) ((raw_read(REG_NFC_WPC) & NFC_WPC_RESET) | val) +#define CHECK_NFC_RB (raw_read(REG_NFC_RB) & NFC_RB) + +#if defined(CONFIG_ARCH_MXC_HAS_NFC_V3_2) +#define NFC_SET_NFC_NUM_ADDR_PHASE1(val) \ + raw_write((raw_read(NFC_CONFIG2) & \ + (NFC_FIELD_RESET(NFC_NUM_ADDR_PHASE1_WIDTH, \ + NFC_NUM_ADDR_PHASE1_SHIFT))) | \ + ((val) << NFC_NUM_ADDR_PHASE1_SHIFT), NFC_CONFIG2); + +#define NFC_SET_NFC_NUM_ADDR_PHASE0(val) \ + raw_write((raw_read(NFC_CONFIG2) & \ + (NFC_FIELD_RESET(NFC_NUM_ADDR_PHASE0_WIDTH, \ + NFC_NUM_ADDR_PHASE0_SHIFT))) | \ + ((val) << NFC_NUM_ADDR_PHASE0_SHIFT), NFC_CONFIG2); + +#define NFC_SET_NFC_ITERATION(val) \ + raw_write((raw_read(NFC_CONFIG1) & \ + (NFC_FIELD_RESET(NFC_ITERATION_WIDTH, NFC_ITERATION_SHIFT))) | \ + ((val) << NFC_ITERATION_SHIFT), NFC_CONFIG1); + +#define NFC_SET_FW(val) \ + raw_write((raw_read(NFC_CONFIG3) & \ + (NFC_FIELD_RESET(NFC_FW_WIDTH, NFC_FW_SHIFT))) | \ + ((val) << NFC_FW_SHIFT), NFC_CONFIG3); + +#define NFC_SET_NUM_OF_DEVICE(val) \ + raw_write((raw_read(NFC_CONFIG3) & \ + (NFC_FIELD_RESET(NFC_NUM_OF_DEVICES_WIDTH, \ + NFC_NUM_OF_DEVICES_SHIFT))) | \ + ((val) << NFC_NUM_OF_DEVICES_SHIFT), NFC_CONFIG3); + +#define NFC_SET_ADD_OP_MODE(val) \ + raw_write((raw_read(NFC_CONFIG3) & \ + (NFC_FIELD_RESET(NFC_ADD_OP_WIDTH, NFC_ADD_OP_SHIFT))) | \ + ((val) << NFC_ADD_OP_SHIFT), NFC_CONFIG3); + +#define NFC_SET_ADD_CS_MODE(val) \ +{ \ + NFC_SET_ADD_OP_MODE(val); \ + NFC_SET_NUM_OF_DEVICE(this->numchips - 1); \ +} + +#define NFC_SET_ST_CMD(val) \ + raw_write((raw_read(NFC_CONFIG2) & \ + (NFC_FIELD_RESET(NFC_ST_CMD_WIDTH, \ + NFC_ST_CMD_SHITF))) | \ + ((val) << NFC_ST_CMD_SHITF), NFC_CONFIG2); + +#define NFMS_NF_DWIDTH 0 +#define NFMS_NF_PG_SZ 1 +#define NFC_CMD_1_SHIFT 8 + +#define NUM_OF_ADDR_CYCLE (fls(g_page_mask) >> 3) +#define SET_NFC_DELAY_LINE(val) raw_write((val), NFC_DELAY_LINE) + +/*should set the fw,ps,spas,ppb*/ +#define NFC_SET_NFMS(v) \ +do { \ + if (!(v)) \ + NFC_SET_FW(NFC_FW_8); \ + if (((v) & (1 << NFMS_NF_DWIDTH))) \ + NFC_SET_FW(NFC_FW_16); \ + if (((v) & (1 << NFMS_NF_PG_SZ))) { \ + if (IS_2K_PAGE_NAND) { \ + NFC_SET_PS(NFC_PS_2K); \ + NFC_SET_NFC_NUM_ADDR_PHASE1(NUM_OF_ADDR_CYCLE); \ + NFC_SET_NFC_NUM_ADDR_PHASE0(NFC_TWO_LESS_PHASE1); \ + } else if (IS_4K_PAGE_NAND) { \ + NFC_SET_PS(NFC_PS_4K); \ + NFC_SET_NFC_NUM_ADDR_PHASE1(NUM_OF_ADDR_CYCLE); \ + NFC_SET_NFC_NUM_ADDR_PHASE0(NFC_TWO_LESS_PHASE1); \ + } else { \ + NFC_SET_PS(NFC_PS_512); \ + NFC_SET_NFC_NUM_ADDR_PHASE1(NUM_OF_ADDR_CYCLE - 1); \ + NFC_SET_NFC_NUM_ADDR_PHASE0(NFC_ONE_LESS_PHASE1); \ + } \ + NFC_SET_ADD_CS_MODE(1); \ + NFC_SET_SPAS(GET_NAND_OOB_SIZE >> 1); \ + NFC_SET_ECC_MODE(GET_NAND_OOB_SIZE >> 1); \ + NFC_SET_ST_CMD(0x70); \ + raw_write(raw_read(NFC_CONFIG3) | NFC_NO_SDMA, NFC_CONFIG3); \ + raw_write(raw_read(NFC_CONFIG3) | NFC_RBB_MODE, NFC_CONFIG3); \ + if (cpu_is_mx51()) \ + SET_NFC_DELAY_LINE(0); \ + } \ +} while (0) +#endif + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V3_1 +#define NFC_SET_NFMS(v) +#endif + +#define READ_PAGE() send_read_page(0) +#define PROG_PAGE() send_prog_page(0) + +#elif defined(CONFIG_ARCH_MXC_HAS_NFC_V2) + +/* + * For V1/V2 NFC registers Definition + */ + +/* + * Addresses for NFC registers + */ +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define NFC_REG_BASE (nfc_axi_base + 0x1000) +#else +#define NFC_REG_BASE nfc_axi_base +#endif +#define NFC_BUF_SIZE (NFC_REG_BASE + 0xE00) +#define NFC_BUF_ADDR (NFC_REG_BASE + 0xE04) +#define NFC_FLASH_ADDR (NFC_REG_BASE + 0xE06) +#define NFC_FLASH_CMD (NFC_REG_BASE + 0xE08) +#define NFC_CONFIG (NFC_REG_BASE + 0xE0A) +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define NFC_ECC_STATUS_RESULT (NFC_REG_BASE + 0xE0C) +#define NFC_ECC_STATUS_RESULT_1 (NFC_REG_BASE + 0xE0C) +#define NFC_ECC_STATUS_RESULT_2 (NFC_REG_BASE + 0xE0E) +#define NFC_SPAS (NFC_REG_BASE + 0xE10) +#else +#define NFC_ECC_STATUS_RESULT (NFC_REG_BASE + 0xE0C) +#define NFC_RSLTMAIN_AREA (NFC_REG_BASE + 0xE0E) +#define NFC_RSLTSPARE_AREA (NFC_REG_BASE + 0xE10) +#endif +#define NFC_WRPROT (NFC_REG_BASE + 0xE12) +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define NFC_UNLOCKSTART_BLKADDR (NFC_REG_BASE + 0xE20) +#define NFC_UNLOCKEND_BLKADDR (NFC_REG_BASE + 0xE22) +#define NFC_UNLOCKSTART_BLKADDR1 (NFC_REG_BASE + 0xE24) +#define NFC_UNLOCKEND_BLKADDR1 (NFC_REG_BASE + 0xE26) +#define NFC_UNLOCKSTART_BLKADDR2 (NFC_REG_BASE + 0xE28) +#define NFC_UNLOCKEND_BLKADDR2 (NFC_REG_BASE + 0xE2A) +#define NFC_UNLOCKSTART_BLKADDR3 (NFC_REG_BASE + 0xE2C) +#define NFC_UNLOCKEND_BLKADDR3 (NFC_REG_BASE + 0xE2E) +#else +#define NFC_UNLOCKSTART_BLKADDR (NFC_REG_BASE + 0xE14) +#define NFC_UNLOCKEND_BLKADDR (NFC_REG_BASE + 0xE16) +#endif +#define NFC_NF_WRPRST (NFC_REG_BASE + 0xE18) +#define NFC_CONFIG1 (NFC_REG_BASE + 0xE1A) +#define NFC_CONFIG2 (NFC_REG_BASE + 0xE1C) + +/*! + * Addresses for NFC RAM BUFFER Main area 0 + */ +#define MAIN_AREA0 (u16 *)(nfc_axi_base + 0x000) +#define MAIN_AREA1 (u16 *)(nfc_axi_base + 0x200) + +/*! + * Addresses for NFC SPARE BUFFER Spare area 0 + */ +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define SPARE_AREA0 (u16 *)(nfc_axi_base + 0x1000) +#define SPARE_LEN 64 +#define SPARE_COUNT 8 +#else +#define SPARE_AREA0 (u16 *)(nfc_axi_base + 0x800) +#define SPARE_LEN 16 +#define SPARE_COUNT 4 +#endif +#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define REG_NFC_ECC_MODE NFC_CONFIG1 +#define SPAS_SHIFT (0) +#define REG_NFC_SPAS NFC_SPAS +#define SPAS_MASK (0xFF00) + +#define NFC_SET_SPAS(v) \ + raw_write(((raw_read(REG_NFC_SPAS) & SPAS_MASK) | ((v<> 1); \ + } \ +} while (0) +#else +#define NFC_SET_SPAS(v) +#define NFC_SET_ECC_MODE(v) +#define GET_ECC_STATUS() raw_read(REG_NFC_ECC_STATUS_RESULT); +#define NFC_SET_NFMS(v) (NFMS |= (v)) +#endif + +#define WRITE_NFC_IP_REG(val, reg) \ + raw_write((raw_read(REG_NFC_OPS_STAT) & ~NFC_OPS_STAT), \ + REG_NFC_OPS_STAT) + +#define GET_NFC_ECC_STATUS() raw_read(REG_NFC_ECC_STATUS_RESULT); + +/*! + * Set INT to 0, Set 1 to specific operation bit, rest to 0 in LAUNCH_NFC Register for + * Specific operation + */ +#define NFC_CMD 0x1 +#define NFC_ADDR 0x2 +#define NFC_INPUT 0x4 +#define NFC_OUTPUT 0x8 +#define NFC_ID 0x10 +#define NFC_STATUS 0x20 + +/* Bit Definitions */ +#define NFC_OPS_STAT (1 << 15) +#define NFC_SP_EN (1 << 2) +#define NFC_ECC_EN (1 << 3) +#define NFC_INT_MSK (1 << 4) +#define NFC_BIG (1 << 5) +#define NFC_RST (1 << 6) +#define NFC_CE (1 << 7) +#define NFC_ONE_CYCLE (1 << 8) +#define NFC_BLS_LOCKED 0 +#define NFC_BLS_LOCKED_DEFAULT 1 +#define NFC_BLS_UNLCOKED 2 +#define NFC_WPC_LOCK_TIGHT 1 +#define NFC_WPC_LOCK (1 << 1) +#define NFC_WPC_UNLOCK (1 << 2) +#define NFC_FLASH_ADDR_SHIFT 0 +#define NFC_UNLOCK_END_ADDR_SHIFT 0 + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define NFC_ECC_MODE_4 (1<<0) +#define NFC_ECC_MODE_8 (~(1<<0)) +#define NFC_SPAS_16 8 +#define NFC_SPAS_64 32 +#define NFC_SPAS_112 56 +#define NFC_SPAS_128 64 +#define NFC_SPAS_218 109 +#endif +/* NFC Register Mapping */ +#define REG_NFC_OPS_STAT NFC_CONFIG2 +#define REG_NFC_INTRRUPT NFC_CONFIG1 +#define REG_NFC_FLASH_ADDR NFC_FLASH_ADDR +#define REG_NFC_FLASH_CMD NFC_FLASH_CMD +#define REG_NFC_OPS NFC_CONFIG2 +#define REG_NFC_SET_RBA NFC_BUF_ADDR +#define REG_NFC_ECC_EN NFC_CONFIG1 +#define REG_NFC_ECC_STATUS_RESULT NFC_ECC_STATUS_RESULT +#define REG_NFC_CE NFC_CONFIG1 +#define REG_NFC_SP_EN NFC_CONFIG1 +#define REG_NFC_BLS NFC_CONFIG +#define REG_NFC_WPC NFC_WRPROT +#define REG_START_BLKADDR NFC_UNLOCKSTART_BLKADDR +#define REG_END_BLKADDR NFC_UNLOCKEND_BLKADDR +#define REG_NFC_RST NFC_CONFIG1 +#define REG_NFC_ONE_CYCLE NFC_CONFIG1 + +/* NFC V1/V2 Specific MACRO functions definitions */ + +#define raw_write(v, a) __raw_writew(v, a) +#define raw_read(a) __raw_readw(a) + +#define NFC_SET_BLS(val) val + +#define UNLOCK_ADDR(start_addr, end_addr) \ +{ \ + raw_write(start_addr, REG_START_BLKADDR); \ + raw_write(end_addr, REG_END_BLKADDR); \ +} + +#define NFC_SET_NFC_ACTIVE_CS(val) +#define NFC_GET_NFC_ACTIVE_CS() +#define NFC_GET_MAXCHIP_SP() 1 +#define NFC_SET_WPC(val) val + +#define NFC_SET_RBA(val) raw_write(val, REG_NFC_SET_RBA); + +#ifdef CONFIG_ARCH_MXC_HAS_NFC_V2_1 +#define READ_PAGE() send_read_page(0) +#define PROG_PAGE() send_prog_page(0) +#else +#define READ_PAGE() \ +do { \ + send_read_page(0); \ + send_read_page(1); \ + send_read_page(2); \ + send_read_page(3); \ +} while (0) + +#define PROG_PAGE() \ +do { \ + send_prog_page(0); \ + send_prog_page(1); \ + send_prog_page(2); \ + send_prog_page(3); \ +} while (0) +#endif +#define CHECK_NFC_RB 1 + +#endif + +#endif /* __MXC_ND2_H__ */ diff --git a/drivers/mtd/nand/nand_device_info.c b/drivers/mtd/nand/nand_device_info.c new file mode 100644 index 00000000000..6a23810ebad --- /dev/null +++ b/drivers/mtd/nand/nand_device_info.c @@ -0,0 +1,2413 @@ +/* + * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include + +#include "nand_device_info.h" + +/* + * Type 2 + */ +static struct nand_device_info nand_device_info_table_type_2[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0x20, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 30, + .data_hold_in_ns = 20, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "NAND01GW3", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 30, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 30, + .data_hold_in_ns = 20, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 35, + .data_hold_in_ns = 25, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9F1F08", + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 30, + .data_hold_in_ns = 20, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TC58NVG0S3", + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 32, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x20, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "NAND02GW3", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 30, + .data_hold_in_ns = 25, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "HY27UF082G2M, HY27UG082G2M, HY27UG082G1M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F2G08", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9F2G08U0M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TC58NVG1S3", + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 32, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x20, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 30, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 30, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 10, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "HY27UH084G2M, HY27UG084G2M, HY27UH084G1M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F4G08", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 25, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 25, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TH58NVG2S3", + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 32, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 30, + .data_hold_in_ns = 25, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "HY27UH088G2M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x20, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 30, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "NAND08GW3BxANx", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 15, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F8G08FABWG", + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 32, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x20, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 30, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 30, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 32, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0x48, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + /* TODO: The actual oob size for MT29F16G08ABACA is + 224 bytes. Use oob 218 bytes since MX53 NFC controller + mentions the spare area size must be less or equal 218 + byte if ECC is enabled */ + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F16G08ABACA(2GB)", + }, + {true} +}; + +/* + * Large MLC + */ +static struct nand_device_info nand_device_info_table_large_mlc[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TC58NVG1D4BFT00", + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 35, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TH58NVG3D4xFT00", + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 35, + .data_hold_in_ns = 20, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 35, + .data_hold_in_ns = 15, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TH58NVG4D4xFT00", + }, + { + .end_of_table = false, + .manufacturer_code = 0x45, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 35, + .data_hold_in_ns = 15, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 30, + .address_setup_in_ns = 0, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TC58NVG2D4BFT00", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 15, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9G4G08U0M", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 45, + .data_hold_in_ns = 25, + .address_setup_in_ns = 50, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "HY27UT084G2M, HY27UU088G5M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x20, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 40, + .data_hold_in_ns = 20, + .address_setup_in_ns = 30, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "NAND04GW3C2AN1E", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 15, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9G8G08U0M, K9HAG08U1M", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 60, + .data_hold_in_ns = 30, + .address_setup_in_ns = 50, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "HY27UV08AG5M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 15, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "Intel JS29F08G08AAMiB1 and Micron MT29F8G08MAA; " + "Intel JS29F08G08CAMiB1 and Micron MT29F16G08QAA", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 15, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9LAG08U0M K9HBG08U1M K9GAG08U0M", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "Intel JS29F32G08FAMiB1 and Micron MT29F32G08TAA", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 20, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F4G08", + }, + { + .end_of_table = false, + .manufacturer_code = 0x89, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "JS29F08G08AAMiB2, JS29F08G08CAMiB2", + }, + { + .end_of_table = false, + .manufacturer_code = 0x89, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "JS29F32G08FAMiB2", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "HY27UW08CGFM", + }, + {true} +}; + +/* + * Type 7 + */ +static struct nand_device_info nand_device_info_table_type_7[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 15, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F8G08FABWG", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F4G08AAA", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xdc, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 512LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 12, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9F4G08", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 15, + .address_setup_in_ns = 35, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9K8G08UXM, K9NBG08U5A, K9WAG08U1A", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 12, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9WAG08UXM", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xda, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 256LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9F2G08U0A", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xf1, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 128LL*SZ_1M, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 2*SZ_1K + 64, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 12, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9F1F08", + }, + {true} +}; + +/* + * Type 8 + */ +static struct nand_device_info nand_device_info_table_type_8[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9GAG08U0M", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 15, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9LBG08U0M (32Gb), K9HCG08U1M (64Gb), K9MDG08U5M (128Gb)", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 20, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 0, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "H27UAG, H27UBG", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 23, + .data_hold_in_ns = 20, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 0, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "H27UCG", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "H27U8G8T2B", + }, + {true} +}; + +/* + * Type 9 + */ +static struct nand_device_info nand_device_info_table_type_9[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 15, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TC58NVG3D1DTG00", + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 15, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TC58NVG4D1DTG00", + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 15, + .address_setup_in_ns = 10, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "TH58NVG6D1DTG20", + }, + { + .end_of_table = false, + .manufacturer_code = 0x89, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 10, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "JS29F16G08AAMC1, JS29F32G08CAMC1", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F16G08MAA, MT29F32G08QAA", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F64G08TAA (32Gb), MT29F32G08CBAAA (32Gb) MT29F64G08CFAAA (64Gb)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd9, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 10, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "MT29F128G08CJAAA", + }, + { + .end_of_table = false, + .manufacturer_code = 0x89, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 10, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "JSF64G08FAMC1", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "K9LBG08U0D", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 8, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9GAG08U0D, K9LBG08U1D, K9HCG08U5D", + }, + {true} +}; + +/* + * Type 10 + */ +static struct nand_device_info nand_device_info_table_type_10[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd3, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 1LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 25, + .data_hold_in_ns = 15, + .address_setup_in_ns = 30, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + "K9NCG08U5M", + }, + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_SLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 64, + .page_total_size_in_bytes = 4*SZ_1K + 128, + .ecc_strength_in_bits = 4, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 15, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = -1, + .tRLOH_in_ns = -1, + .tRHOH_in_ns = -1, + NULL, + }, + {true} +}; + +/* + * Type 11 + */ +static struct nand_device_info nand_device_info_table_type_11[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 8*SZ_1K + 376, + .ecc_strength_in_bits = 14, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 8, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 25, + "TC58NVG5D2ELAM8 (4GB), TH58NVG6D2ELAM8 (8GB)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x98, + .device_code = 0xde, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 8*SZ_1K + 376, + .ecc_strength_in_bits = 14, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 8, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 25, + "TH58NVG7D2ELAM8", + }, + {true} +}; + +/* + * Type 15 + */ +static struct nand_device_info nand_device_info_table_type_15[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 8*SZ_1K + 436, + .ecc_strength_in_bits = 16, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 25, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "K9GBG08U0M (4GB, 1CE); K9LCG08U1M (8GB, 2CE); K9HDG08U5M (16GB, 4CE)", + }, + {true} +}; + +static struct nand_device_info nand_device_info_table_type_16[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0xec, + .device_code = 0xd7, + .is_ddr_ok = true, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 8*SZ_1K + 512, + .ecc_strength_in_bits = 24, + .ecc_size_in_bytes = 1024, + .data_setup_in_ns = 20, + .data_hold_in_ns = 10, + .address_setup_in_ns = 25, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 25, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "K9LCGD88X1M(8GB, 1CE); K9HDGD8X5M(8GB, 2CE); K9PFGD8X7M(16GB, 4CE)", + }, + {true} +}; +/* + * BCH ECC12 + */ +static struct nand_device_info nand_device_info_table_bch_ecc12[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd5, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 224, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "H27UAG8T2ATR (2GB, 1CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 224, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "H27UBG8T2M (4GB, 1CE), H27UCG8UDM (8GB, 2CE), H27UDG8VEM (16GB, 4CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0xad, + .device_code = 0xde, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 224, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "H27UEG8YEM (32GB, 4CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd7, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 10, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 16, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F32G08CBAAA (4GB, 1CE), MT29F64G08CFAAA (8GB, 2CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0xd9, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL*SZ_1G, + .block_size_in_pages = 128, + .page_total_size_in_bytes = 4*SZ_1K + 218, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 10, + .data_hold_in_ns = 10, + .address_setup_in_ns = 15, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 16, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F128G08CJAAA (16GB, 2CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0x48, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 2LL*SZ_1G, + .block_size_in_pages = 256, + .page_total_size_in_bytes = 4*SZ_1K + 224, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F16G08CBABA (2GB, 1CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0x68, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 4LL*SZ_1G, + .block_size_in_pages = 256, + .page_total_size_in_bytes = 4*SZ_1K + 224, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F32G08CBABA (4GB, 1CE); " + "MT29F64G08CEABA (8GB, 2CE); " + "MT29F64G08CFABA (8GB, 2CE)", + }, + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0x88, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL*SZ_1G, + .block_size_in_pages = 256, + .page_total_size_in_bytes = 4*SZ_1K + 224, + .ecc_strength_in_bits = 12, + .ecc_size_in_bytes = 512, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F128G08CJABA (16GB, 2CE); " + "MT29F128G08CKABA (16GB, 2CE); " + "MT29F256G08CUABA (32GB, 4CE)", + }, + {true} +}; + +/* + * BCH ECC24 + */ +static struct nand_device_info nand_device_info_table_bch_ecc24[] __initdata = { + { + .end_of_table = false, + .manufacturer_code = 0x2c, + .device_code = 0x88, + .is_ddr_ok = true, + .cell_technology = NAND_DEVICE_CELL_TECH_MLC, + .chip_size_in_bytes = 8LL * SZ_1G, + .block_size_in_pages = 256, + .page_total_size_in_bytes = 8 * SZ_1K + 448, + .ecc_strength_in_bits = 24, + .ecc_size_in_bytes = 1024, + .data_setup_in_ns = 15, + .data_hold_in_ns = 10, + .address_setup_in_ns = 20, + .gpmi_sample_delay_in_ns = 6, + .tREA_in_ns = 20, + .tRLOH_in_ns = 5, + .tRHOH_in_ns = 15, + "MT29F64G08CBAAA(8GB, 2CE) ", + }, + {true} +}; + +/* + * The following macros make it convenient to extract information from an ID + * byte array. All these macros begin with the prefix "ID_". + * + * Macros of the form: + * + * ID_GET_[_[_]] + * + * extract the given field from an ID byte array. Macros of the form: + * + * ID_[_[_]]_ + * + * contain the value for the given field that has the given meaning. + * + * If the appears, it means this macro represents a view of this + * field that is specific to the given manufacturer. + * + * If the appears, it means this macro represents a view of this + * field that the given manufacturer applies only under specific conditions. + * + * Here is a simple example: + * + * ID_PAGE_SIZE_CODE_2K + * + * This macro has the value of the "Page Size" field that indicates the page + * size is 2K. + * + * A more complicated example: + * + * ID_SAMSUNG_6_BYTE_PAGE_SIZE_CODE_8K (0x2) + * + * This macro has the value of the "Page Size" field for Samsung parts that + * indicates the page size is 8K. However, this interpretation is only correct + * for devices that return 6 ID bytes. + */ + +/* Byte 1 ------------------------------------------------------------------- */ + +#define ID_GET_BYTE_1(id) ((id)[0]) + +#define ID_GET_MFR_CODE(id) ID_GET_BYTE_1(id) + +/* Byte 2 ------------------------------------------------------------------- */ + +#define ID_GET_BYTE_2(id) ((id)[1]) + +#define ID_GET_DEVICE_CODE(id) ID_GET_BYTE_2(id) + #define ID_SAMSUNG_DEVICE_CODE_1_GBIT (0xf1) + #define ID_SAMSUNG_DEVICE_CODE_2_GBIT (0xda) + #define ID_HYNIX_DEVICE_CODE_ECC12 (0xd7) + #define ID_HYNIX_DEVICE_CODE_ECC12_ODD (0xd5) + #define ID_HYNIX_DEVICE_CODE_ECC12_LARGE (0xde) + #define ID_MICRON_DEVICE_CODE_ECC12 (0xd7) /* ECC12 */ + #define ID_MICRON_DEVICE_CODE_ECC12_LARGE (0xd9) /* ECC12 8GB/CE */ + #define ID_MICRON_DEVICE_CODE_ECC12_2GB_PER_CE (0x48) /* L63B 2GB/CE */ + #define ID_MICRON_DEVICE_CODE_ECC12_4GB_PER_CE (0x68) /* L63B 4GB/CE */ + #define ID_MICRON_DEVICE_CODE_ECC12_8GB_PER_CE (0x88) /* L63B 8GB/CE */ + #define ID_MICRON_DEVICE_CODE_ECC24_8GB_PER_CE (0x88) /* L63B 8GB/CE */ + +/* Byte 3 ------------------------------------------------------------------- */ + +#define ID_GET_BYTE_3(id) ((id)[2]) + +#define ID_GET_DIE_COUNT_CODE(id) ((ID_GET_BYTE_3(id) >> 0) & 0x3) + +#define ID_GET_CELL_TYPE_CODE(id) ((ID_GET_BYTE_3(id) >> 2) & 0x3) + #define ID_CELL_TYPE_CODE_SLC (0x0) /* All others => MLC. */ + +#define ID_GET_SAMSUNG_SIMUL_PROG(id) ((ID_GET_BYTE_3(id) >> 4) & 0x3) + +#define ID_GET_MICRON_SIMUL_PROG(id) ((ID_GET_BYTE_3(id) >> 4) & 0x3) + +#define ID_GET_CACHE_PROGRAM(id) ((ID_GET_BYTE_3(id) >> 7) & 0x1) + +#define ID_ONFI_NAND_BYTE3 (0x04) +/* Byte 4 ------------------------------------------------------------------- */ + +#define ID_GET_BYTE_4(id) ((id)[3]) + #define ID_HYNIX_BYTE_4_ECC12_DEVICE (0x25) + +#define ID_GET_PAGE_SIZE_CODE(id) ((ID_GET_BYTE_4(id) >> 0) & 0x3) + #define ID_PAGE_SIZE_CODE_1K (0x0) + #define ID_PAGE_SIZE_CODE_2K (0x1) + #define ID_PAGE_SIZE_CODE_4K (0x2) + #define ID_PAGE_SIZE_CODE_8K (0x3) + #define ID_SAMSUNG_6_BYTE_PAGE_SIZE_CODE_8K (0x2) + +#define ID_GET_OOB_SIZE_CODE(id) ((ID_GET_BYTE_4(id) >> 2) & 0x1) + +#define ID_GET_BLOCK_SIZE_CODE(id) ((ID_GET_BYTE_4(id) >> 4) & 0x3) + +/* Byte 5 ------------------------------------------------------------------- */ + +#define ID_GET_BYTE_5(id) ((id)[4]) + #define ID_MICRON_BYTE_5_ECC12 (0x84) + +#define ID_GET_SAMSUNG_ECC_LEVEL_CODE(id) ((ID_GET_BYTE_5(id) >> 4) & 0x7) + #define ID_SAMSUNG_ECC_LEVEL_CODE_8 (0x03) + #define ID_SAMSUNG_ECC_LEVEL_CODE_24 (0x05) + +#define ID_GET_PLANE_COUNT_CODE(id) ((ID_GET_BYTE_5(id) >> 2) & 0x3) + +/* Byte 6 ------------------------------------------------------------------- */ + +#define ID_GET_BYTE_6(id) ((id)[5]) + #define ID_TOSHIBA_BYTE_6_PAGE_SIZE_CODE_8K (0x54) + #define ID_TOSHIBA_BYTE_6_PAGE_SIZE_CODE_4K (0x13) + +#define ID_GET_SAMSUNG_DEVICE_VERSION_CODE(id) ((ID_GET_BYTE_6(id)>>0) & 0x7) + #define ID_SAMSUNG_DEVICE_VERSION_CODE_40NM (0x01) + +#define ID_GET_TOGGLE_NAND(id) ((ID_GET_BYTE_6(id) >> 7) & 0x1) + +/* -------------------------------------------------------------------------- */ + +void nand_device_print_info(struct nand_device_info *info) +{ + unsigned i; + const char *mfr_name; + const char *cell_technology_name; + uint64_t chip_size; + const char *chip_size_units; + unsigned page_data_size_in_bytes; + unsigned page_oob_size_in_bytes; + + /* Check for nonsense. */ + + if (!info) + return; + + /* Prepare the manufacturer name. */ + + mfr_name = "Unknown"; + + for (i = 0; nand_manuf_ids[i].id; i++) { + if (nand_manuf_ids[i].id == info->manufacturer_code) { + mfr_name = nand_manuf_ids[i].name; + break; + } + } + + /* Prepare the name of the cell technology. */ + + switch (info->cell_technology) { + case NAND_DEVICE_CELL_TECH_SLC: + cell_technology_name = "SLC"; + break; + case NAND_DEVICE_CELL_TECH_MLC: + cell_technology_name = "MLC"; + break; + default: + cell_technology_name = "Unknown"; + break; + } + + /* Prepare the chip size. */ + + if ((info->chip_size_in_bytes >= SZ_1G) && + !(info->chip_size_in_bytes % SZ_1G)) { + chip_size = info->chip_size_in_bytes / ((uint64_t) SZ_1G); + chip_size_units = "GiB"; + } else if ((info->chip_size_in_bytes >= SZ_1M) && + !(info->chip_size_in_bytes % SZ_1M)) { + chip_size = info->chip_size_in_bytes / ((uint64_t) SZ_1M); + chip_size_units = "MiB"; + } else { + chip_size = info->chip_size_in_bytes; + chip_size_units = "B"; + } + + /* Prepare the page geometry. */ + + page_data_size_in_bytes = (1<<(fls(info->page_total_size_in_bytes)-1)); + page_oob_size_in_bytes = info->page_total_size_in_bytes - + page_data_size_in_bytes; + + /* Print the information. */ + + printk(KERN_INFO "Manufacturer : %s (0x%02x)\n", mfr_name, + info->manufacturer_code); + printk(KERN_INFO "Device Code : 0x%02x\n", info->device_code); + printk(KERN_INFO "Cell Technology : %s\n", cell_technology_name); + printk(KERN_INFO "Chip Size : %llu %s\n", chip_size, + chip_size_units); + printk(KERN_INFO "Pages per Block : %u\n", + info->block_size_in_pages); + printk(KERN_INFO "Page Geometry : %u+%u\n", page_data_size_in_bytes, + page_oob_size_in_bytes); + printk(KERN_INFO "ECC Strength : %u bits\n", + info->ecc_strength_in_bits); + printk(KERN_INFO "ECC Size : %u B\n", info->ecc_size_in_bytes); + printk(KERN_INFO "Data Setup Time : %u ns\n", info->data_setup_in_ns); + printk(KERN_INFO "Data Hold Time : %u ns\n", info->data_hold_in_ns); + printk(KERN_INFO "Address Setup Time: %u ns\n", + info->address_setup_in_ns); + printk(KERN_INFO "GPMI Sample Delay : %u ns\n", + info->gpmi_sample_delay_in_ns); + if (info->tREA_in_ns >= 0) + printk(KERN_INFO "tREA : %u ns\n", + info->tREA_in_ns); + else + printk(KERN_INFO "tREA : Unknown\n"); + if (info->tREA_in_ns >= 0) + printk(KERN_INFO "tRLOH : %u ns\n", + info->tRLOH_in_ns); + else + printk(KERN_INFO "tRLOH : Unknown\n"); + if (info->tREA_in_ns >= 0) + printk(KERN_INFO "tRHOH : %u ns\n", + info->tRHOH_in_ns); + else + printk(KERN_INFO "tRHOH : Unknown\n"); + if (info->description) + printk(KERN_INFO "Description : %s\n", info->description); + else + printk(KERN_INFO "Description : \n"); + +} + +static struct nand_device_info *nand_device_info_search( + struct nand_device_info *table, uint8_t mfr_code, uint8_t device_code) +{ + + for (; !table->end_of_table; table++) { + if (table->manufacturer_code != mfr_code) + continue; + if (table->device_code != device_code) + continue; + return table; + } + + return 0; + +} + +static struct nand_device_info * __init nand_device_info_fn_toshiba(const uint8_t id[]) +{ + struct nand_device_info *table; + + /* Check for an SLC device. */ + + if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) { + /* Type 2 */ + return nand_device_info_search(nand_device_info_table_type_2, + ID_GET_MFR_CODE(id), ID_GET_DEVICE_CODE(id)); + } + + /* + * Look for 8K page Toshiba MLC devices. + * + * The page size field in byte 4 can't be used because the field was + * redefined in the 8K parts so the value meaning "8K page" is the same + * as the value meaning "4K page" on the 4K page devices. + * + * The only identifiable difference between the 4K and 8K page Toshiba + * devices with a device code of 0xd7 is the undocumented 6th ID byte. + * The 4K device returns a value of 0x13 and the 8K a value of 0x54. + * Toshiba has verified that this is an acceptable method to distinguish + * the two device families. + */ + + if (ID_GET_BYTE_6(id) == ID_TOSHIBA_BYTE_6_PAGE_SIZE_CODE_8K) { + /* Type 11 */ + table = nand_device_info_table_type_11; + } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) { + /* Type 9 */ + table = nand_device_info_table_type_9; + } else { + /* Large MLC */ + table = nand_device_info_table_large_mlc; + } + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +static struct nand_device_info * __init nand_device_info_fn_samsung(const uint8_t id[]) +{ + struct nand_device_info *table; + + /* Check for an MLC device. */ + + if (ID_GET_CELL_TYPE_CODE(id) != ID_CELL_TYPE_CODE_SLC) { + + /* Is this a Samsung 8K Page MLC device with 16 bit ECC? */ + if ((ID_GET_SAMSUNG_ECC_LEVEL_CODE(id) == + ID_SAMSUNG_ECC_LEVEL_CODE_24) && + (ID_GET_PAGE_SIZE_CODE(id) == + ID_SAMSUNG_6_BYTE_PAGE_SIZE_CODE_8K)) { + if (ID_GET_TOGGLE_NAND(id)) + table = nand_device_info_table_type_16; + else + /* Type 15 */ + table = nand_device_info_table_type_15; + } + /* Is this a Samsung 42nm ECC8 device with a 6 byte ID? */ + else if ((ID_GET_SAMSUNG_ECC_LEVEL_CODE(id) == + ID_SAMSUNG_ECC_LEVEL_CODE_8) && + (ID_GET_SAMSUNG_DEVICE_VERSION_CODE(id) == + ID_SAMSUNG_DEVICE_VERSION_CODE_40NM)) { + /* Type 9 */ + table = nand_device_info_table_type_9; + } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) { + /* Type 8 */ + table = nand_device_info_table_type_8; + } else { + /* Large MLC */ + table = nand_device_info_table_large_mlc; + } + + } else { + + /* Check the page size first. */ + if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) { + /* Type 10 */ + table = nand_device_info_table_type_10; + } + /* Check the chip size. */ + else if (ID_GET_DEVICE_CODE(id) == + ID_SAMSUNG_DEVICE_CODE_1_GBIT) { + if (!ID_GET_CACHE_PROGRAM(id)) { + /* + * 128 MiB Samsung chips without cache program + * are Type 7. + * + * The K9F1G08U0B does not support multi-plane + * program, so the if statement below cannot be + * used to identify it. + */ + table = nand_device_info_table_type_7; + + } else { + /* Smaller sizes are Type 2 by default. */ + table = nand_device_info_table_type_2; + } + } else { + /* Check number of simultaneously programmed pages. */ + if (ID_GET_SAMSUNG_SIMUL_PROG(id) && + ID_GET_PLANE_COUNT_CODE(id)) { + /* Type 7 */ + table = nand_device_info_table_type_7; + } else { + /* Type 2 */ + table = nand_device_info_table_type_2; + } + + } + + } + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +static struct nand_device_info * __init nand_device_info_fn_stmicro(const uint8_t id[]) +{ + struct nand_device_info *table; + + /* Check for an SLC device. */ + + if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) + /* Type 2 */ + table = nand_device_info_table_type_2; + else + /* Large MLC */ + table = nand_device_info_table_large_mlc; + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +static struct nand_device_info * __init nand_device_info_fn_hynix(const uint8_t id[]) +{ + struct nand_device_info *table; + + /* Check for an SLC device. */ + + if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) { + /* Type 2 */ + return nand_device_info_search(nand_device_info_table_type_2, + ID_GET_MFR_CODE(id), ID_GET_DEVICE_CODE(id)); + } + + /* + * Check for ECC12 devices. + * + * We look at the 4th ID byte to distinguish some Hynix ECC12 devices + * from the similar ECC8 part. For example H27UBG8T2M (ECC12) 4th byte + * is 0x25, whereas H27UDG8WFM (ECC8) 4th byte is 0xB6. + */ + + if ((((ID_GET_DEVICE_CODE(id) == ID_HYNIX_DEVICE_CODE_ECC12) || + (ID_GET_DEVICE_CODE(id) == ID_HYNIX_DEVICE_CODE_ECC12_ODD)) && + ID_GET_BYTE_4(id) == ID_HYNIX_BYTE_4_ECC12_DEVICE) || + (ID_GET_DEVICE_CODE(id) == ID_HYNIX_DEVICE_CODE_ECC12_LARGE)) { + /* BCH ECC 12 */ + table = nand_device_info_table_bch_ecc12; + } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) { + /* + * So far, all other Samsung and Hynix 4K page devices are + * Type 8. + */ + table = nand_device_info_table_type_8; + } else + /* Large MLC */ + table = nand_device_info_table_large_mlc; + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +static struct nand_device_info * __init nand_device_info_fn_micron(const uint8_t id[]) +{ + struct nand_device_info *table; + + /* Check for an SLC device. */ + + if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) { + + /* Check number of simultaneously programmed pages. */ + + if (ID_GET_MICRON_SIMUL_PROG(id)) { + /* Type 7 */ + table = nand_device_info_table_type_7; + } else { + /* Zero simultaneously programmed pages means Type 2. */ + table = nand_device_info_table_type_2; + } + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + + } + + if (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC24_8GB_PER_CE + && ID_GET_BYTE_3(id) == ID_ONFI_NAND_BYTE3) { + /* BCH ECC 24 */ + table = nand_device_info_table_bch_ecc24; + } else + /* + * We look at the 5th ID byte to distinguish some Micron ECC12 NANDs + * from the similar ECC8 part. + * + * For example MT29F64G08CFAAA (ECC12) 5th byte is 0x84, whereas + * MT29F64G08TAA (ECC8) 5th byte is 0x78. + * + * We also have a special case for the Micron L63B family + * (256 page/block), which has unique device codes but no ID fields that + * can easily be used to distinguish the family. + */ + + if ((ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12 && + ID_GET_BYTE_5(id) == ID_MICRON_BYTE_5_ECC12) || + (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_LARGE) || + (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_2GB_PER_CE) || + (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_4GB_PER_CE) || + (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_8GB_PER_CE)) { + /* BCH ECC 12 */ + table = nand_device_info_table_bch_ecc12; + } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) { + /* Toshiba devices with 4K pages are Type 9. */ + table = nand_device_info_table_type_9; + } else { + /* Large MLC */ + table = nand_device_info_table_large_mlc; + } + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +static struct nand_device_info * __init nand_device_info_fn_sandisk(const uint8_t id[]) +{ + struct nand_device_info *table; + + if (ID_GET_CELL_TYPE_CODE(id) != ID_CELL_TYPE_CODE_SLC) { + /* Large MLC */ + table = nand_device_info_table_large_mlc; + } else { + /* Type 2 */ + table = nand_device_info_table_type_2; + } + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +static struct nand_device_info * __init nand_device_info_fn_intel(const uint8_t id[]) +{ + struct nand_device_info *table; + + /* Check for an SLC device. */ + + if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) { + /* Type 2 */ + return nand_device_info_search(nand_device_info_table_type_2, + ID_GET_MFR_CODE(id), ID_GET_DEVICE_CODE(id)); + } + + if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) { + /* Type 9 */ + table = nand_device_info_table_type_9; + } else { + /* Large MLC */ + table = nand_device_info_table_large_mlc; + } + + return nand_device_info_search(table, ID_GET_MFR_CODE(id), + ID_GET_DEVICE_CODE(id)); + +} + +/** + * struct nand_device_type_info - Information about a NAND Flash type. + * + * @name: A human-readable name for this type. + * @table: The device info table for this type. + */ + +struct nand_device_type_info { + struct nand_device_info *table; + const char *name; +}; + +/* + * A table that maps manufacturer IDs to device information tables. + */ + +static struct nand_device_type_info nand_device_type_directory[] __initdata = { + {nand_device_info_table_type_2, "Type 2" }, + {nand_device_info_table_large_mlc, "Large MLC"}, + {nand_device_info_table_type_7, "Type 7" }, + {nand_device_info_table_type_8, "Type 8" }, + {nand_device_info_table_type_9, "Type 9" }, + {nand_device_info_table_type_10, "Type 10" }, + {nand_device_info_table_type_11, "Type 11" }, + {nand_device_info_table_type_15, "Type 15" }, + {nand_device_info_table_type_16, "Type 16" }, + {nand_device_info_table_bch_ecc12, "BCH ECC12"}, + {nand_device_info_table_bch_ecc24, "BCH ECC24"}, + {0, 0}, +}; + +/** + * struct nand_device_mfr_info - Information about a NAND Flash manufacturer. + * + * @id: The value of the first NAND Flash ID byte, which identifies the + * manufacturer. + * @fn: A pointer to a function to use for identifying devices from the + * given manufacturer. + */ + +struct nand_device_mfr_info { + uint8_t id; + struct nand_device_info *(*fn)(const uint8_t id[]); +}; + +/* + * A table that maps manufacturer IDs to device information tables. + */ + +static struct nand_device_mfr_info nand_device_mfr_directory[] __initdata = { + { + .id = NAND_MFR_TOSHIBA, + .fn = nand_device_info_fn_toshiba, + }, + { + .id = NAND_MFR_SAMSUNG, + .fn = nand_device_info_fn_samsung, + }, + { + .id = NAND_MFR_FUJITSU, + .fn = 0, + }, + { + .id = NAND_MFR_NATIONAL, + .fn = 0, + }, + { + .id = NAND_MFR_RENESAS, + .fn = 0, + }, + { + .id = NAND_MFR_STMICRO, + .fn = nand_device_info_fn_stmicro, + }, + { + .id = NAND_MFR_HYNIX, + .fn = nand_device_info_fn_hynix, + }, + { + .id = NAND_MFR_MICRON, + .fn = nand_device_info_fn_micron, + }, + { + .id = NAND_MFR_AMD, + .fn = 0, + }, + { + .id = NAND_MFR_SANDISK, + .fn = nand_device_info_fn_sandisk, + }, + { + .id = NAND_MFR_INTEL, + .fn = nand_device_info_fn_intel, + }, + {0, 0} +}; + +/** + * nand_device_info_test_table - Validate a device info table. + * + * This function runs tests on the given device info table to check that it + * meets the current assumptions. + */ + +static void __init nand_device_info_test_table( + struct nand_device_info *table, const char *name) +{ + unsigned i; + unsigned j; + uint8_t mfr_code; + uint8_t device_code; + + /* Loop over entries in this table. */ + + for (i = 0; !table[i].end_of_table; i++) { + + /* Get discriminating attributes of the current device. */ + + mfr_code = table[i].manufacturer_code; + device_code = table[i].device_code; + + /* Compare with the remaining devices in this table. */ + + for (j = i + 1; !table[j].end_of_table; j++) { + if ((mfr_code == table[j].manufacturer_code) && + (device_code == table[j].device_code)) + goto error; + } + + } + + return; + +error: + + printk(KERN_EMERG + "\n== NAND Flash device info table failed validity check ==\n"); + + printk(KERN_EMERG "\nDevice Info Table: %s\n", name); + printk(KERN_EMERG "\nTable Index %u\n", i); + nand_device_print_info(table + i); + printk(KERN_EMERG "\nTable Index %u\n", j); + nand_device_print_info(table + j); + printk(KERN_EMERG "\n"); + + BUG(); + +} + +/** + * nand_device_info_test_data - Test the NAND Flash device data. + */ + +static void __init nand_device_info_test_data(void) +{ + + unsigned i; + + for (i = 0; nand_device_type_directory[i].name; i++) { + nand_device_info_test_table( + nand_device_type_directory[i].table, + nand_device_type_directory[i].name); + } + +} + +struct nand_device_info * __init nand_device_get_info(const uint8_t id[]) +{ + unsigned i; + uint8_t mfr_id = ID_GET_MFR_CODE(id); + struct nand_device_info *(*fn)(const uint8_t id[]) = 0; + + /* Test the data. */ + + nand_device_info_test_data(); + + /* Look for information about this manufacturer. */ + + for (i = 0; nand_device_mfr_directory[i].id; i++) { + if (nand_device_mfr_directory[i].id == mfr_id) { + fn = nand_device_mfr_directory[i].fn; + break; + } + } + + if (!fn) + return 0; + + /* + * If control arrives here, we found both a table of device information, + * and a function we can use to identify the current device. Attempt to + * identify the device and return the result. + */ + + return fn(id); + +} diff --git a/drivers/mtd/nand/nand_device_info.h b/drivers/mtd/nand/nand_device_info.h new file mode 100644 index 00000000000..f74c975b2fb --- /dev/null +++ b/drivers/mtd/nand/nand_device_info.h @@ -0,0 +1,152 @@ +/* + * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __DRIVERS_NAND_DEVICE_INFO_H +#define __DRIVERS_NAND_DEVICE_INFO_H + + /* + * The number of ID bytes to read from the NAND Flash device and hand over to + * the identification system. + */ + +#define NAND_DEVICE_ID_BYTE_COUNT (6) + + /* + * The number of ID bytes to read from the NAND Flash device and hand over to + * the identification system. + */ + +enum nand_device_cell_technology { + NAND_DEVICE_CELL_TECH_SLC = 0, + NAND_DEVICE_CELL_TECH_MLC = 1, +}; + +/** + * struct nand_device_info - Information about a single NAND Flash device. + * + * This structure contains all the *essential* information about a NAND Flash + * device, derived from the device's data sheet. For each manufacturer, we have + * an array of these structures. + * + * @end_of_table: If true, marks the end of a table of device + * information. + * @manufacturer_code: The manufacturer code (1st ID byte) reported by + * the device. + * @device_code: The device code (2nd ID byte) reported by the + * device. + * @is_ddr_ok: Is this nand an ONFI nand or TOGGLE nand ? + * @cell_technology: The storage cell technology. + * @chip_size_in_bytes: The total size of the storage behind a single + * chip select, in bytes. Notice that this is *not* + * necessarily the total size of the storage in a + * *package*, which may contain several chips. + * @block_size_in_pages: The number of pages in a block. + * @page_total_size_in_bytes: The total size of a page, in bytes, including + * both the data and the OOB. + * @ecc_strength_in_bits: The strength of the ECC called for by the + * manufacturer, in number of correctable bits. + * @ecc_size_in_bytes: The size of the data block over which the + * manufacturer calls for the given ECC algorithm + * and strength. + * @data_setup_in_ns: The data setup time, in nanoseconds. Usually the + * maximum of tDS and tWP. A negative value + * indicates this characteristic isn't known. + * @data_hold_in_ns: The data hold time, in nanoseconds. Usually the + * maximum of tDH, tWH and tREH. A negative value + * indicates this characteristic isn't known. + * @address_setup_in_ns: The address setup time, in nanoseconds. Usually + * the maximum of tCLS, tCS and tALS. A negative + * value indicates this characteristic isn't known. + * @gpmi_sample_delay_in_ns: A GPMI-specific timing parameter. A negative + * value indicates this characteristic isn't known. + * @tREA_in_ns: tREA, in nanoseconds, from the data sheet. A + * negative value indicates this characteristic + * isn't known. + * @tRLOH_in_ns: tRLOH, in nanoseconds, from the data sheet. A + * negative value indicates this characteristic + * isn't known. + * @tRHOH_in_ns: tRHOH, in nanoseconds, from the data sheet. A + * negative value indicates this characteristic + * isn't known. + */ + +struct nand_device_info { + + /* End of table marker */ + + bool end_of_table; + + /* Manufacturer and Device codes */ + + uint8_t manufacturer_code; + uint8_t device_code; + + /* Does the nand support DDR? (ONFI or TOGGLE) */ + bool is_ddr_ok; + + /* Technology */ + + enum nand_device_cell_technology cell_technology; + + /* Geometry */ + + uint64_t chip_size_in_bytes; + uint32_t block_size_in_pages; + uint16_t page_total_size_in_bytes; + + /* ECC */ + + uint8_t ecc_strength_in_bits; + uint16_t ecc_size_in_bytes; + + /* Timing */ + + int8_t data_setup_in_ns; + int8_t data_hold_in_ns; + int8_t address_setup_in_ns; + int8_t gpmi_sample_delay_in_ns; + int8_t tREA_in_ns; + int8_t tRLOH_in_ns; + int8_t tRHOH_in_ns; + + /* Description */ + + const char *description; + +}; + +/** + * nand_device_get_info - Get info about a device based on ID bytes. + * + * @id_bytes: An array of NAND_DEVICE_ID_BYTE_COUNT ID bytes retrieved from the + * NAND Flash device. + */ + +struct nand_device_info *nand_device_get_info(const uint8_t id_bytes[]); + +/** + * nand_device_print_info - Prints information about a NAND Flash device. + * + * @info A pointer to a NAND Flash device information structure. + */ + +void nand_device_print_info(struct nand_device_info *info); + +/* + * Check the NAND whether it supports the DDR mode. + * Only the ONFI nand and TOGGLE nand support the DDR now. + */ +static inline bool is_ddr_nand(struct nand_device_info *info) +{ + return info->is_ddr_ok; +} +#endif From cd015c032ddda65bb80f4b0ad3b18b1547d638ef Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 04:54:50 +0300 Subject: [PATCH 07/32] Add correct NAND chip id for the EfikaSB NAND and correct the buswidth. Make sure we compile the correct NAND driver. --- drivers/mtd/nand/Makefile | 2 +- drivers/mtd/nand/nand_base.c | 5 ++++- drivers/mtd/nand/nand_ids.c | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 8ad6faec72c..5ef6c5a90be 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -39,7 +39,7 @@ obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o -obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o +obj-$(CONFIG_MTD_NAND_MXC) += nand_device_info.o mxc_nd2.o obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 2e94c8e2f7a..db066082542 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3040,7 +3040,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->erasesize = (64 * 1024) << (extid & 0x03); extid >>= 2; /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + if(id_data[0] == NAND_MFR_MICRON) /* Micron is only 8-bit but reports 16-bit */ + busw = 0; + else + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; } } else { /* diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 251cb84b4d5..bb46a9b3a21 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -159,6 +159,8 @@ struct nand_flash_dev nand_flash_ids[] = { NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH }, + + {"NAND 4GiB 3,3V 8-bit", 0x68, 0, 4096, 0, LP_OPTIONS}, {NULL,} }; From 7c6587f6bcea79f87d42f118283c246a87099d12 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 05:01:22 +0300 Subject: [PATCH 08/32] Add our screenmode to ldb. --- drivers/video/mxc/ldb.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c index 24ad8e61713..8ccc52feb30 100644 --- a/drivers/video/mxc/ldb.c +++ b/drivers/video/mxc/ldb.c @@ -131,6 +131,14 @@ struct fb_videomode mxcfb_ldb_modedb[] = { 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_DETAILED,}, + { + "WSVGA", 60, 1024, 600, 22800, + 80, 40, + 20, 21, + 4, 4, + 0, + FB_VMODE_NONINTERLACED, + FB_MODE_IS_DETAILED,}, }; int mxcfb_ldb_modedb_sz = ARRAY_SIZE(mxcfb_ldb_modedb); @@ -486,6 +494,18 @@ static int ldb_fb_pre_setup(struct fb_info *fbi) dev_warn(g_ldb_dev, "default di1 single mode\n"); } + } else if (fb_mode_is_equal(fbi->mode, &mxcfb_ldb_modedb[2])) { + if (ipu_di == 0) { + ldb.chan_mode_opt = LDB_SIN_DI0; + ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG; + dev_warn(g_ldb_dev, + "default di0 single mode\n"); + } else { + ldb.chan_mode_opt = LDB_SIN_DI1; + ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG; + dev_warn(g_ldb_dev, + "default di1 single mode\n"); + } } } From e340b67ec2370fe5cb4611e930c6b674462b2002 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 05:11:02 +0300 Subject: [PATCH 09/32] Set NAND clock to Micron max freq. TODO: benchmark and see if it actually makes a difference. --- arch/arm/mach-mx5/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mx5/clock.c b/arch/arm/mach-mx5/clock.c index 974b8e34fac..a5495233382 100644 --- a/arch/arm/mach-mx5/clock.c +++ b/arch/arm/mach-mx5/clock.c @@ -87,7 +87,7 @@ extern int dvfs_core_is_active; /* To keep compatible with some NAND flash, limit * max NAND clk to 34MHZ. The user can modify it for * dedicate NAND flash */ -#define MAX_NFC_CLK 34000000 +#define MAX_NFC_CLK 48000000 /* Default: 34000000 Micron: 48000000 */ #define UART1_DMA_ENABLE 0 #define UART2_DMA_ENABLE 0 From 3cc6b6a29caa235b6f6a60219a5145fa7295ddd6 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 20 Sep 2011 05:14:42 +0300 Subject: [PATCH 10/32] Proper defconfig for mx53 efikasb. --- arch/arm/configs/mx53_efikasb_defconfig | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/arch/arm/configs/mx53_efikasb_defconfig b/arch/arm/configs/mx53_efikasb_defconfig index 6b399a9dd03..4839f88a134 100644 --- a/arch/arm/configs/mx53_efikasb_defconfig +++ b/arch/arm/configs/mx53_efikasb_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux/arm 2.6.38 Kernel Configuration -# Thu Sep 15 16:09:13 2011 +# Linux/arm 2.6.38.3 Kernel Configuration +# Tue Sep 20 04:45:01 2011 # CONFIG_ARM=y CONFIG_HAVE_PWM=y @@ -10,6 +10,7 @@ CONFIG_HAVE_SCHED_CLOCK=y CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_USES_GETTIMEOFFSET is not set CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_KTIME_SCALAR=y CONFIG_HAVE_PROC_CPU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -25,7 +26,6 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ZONE_DMA=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_FIQ=y -CONFIG_ARM_L1_CACHE_SHIFT_6=y CONFIG_VECTORS_BASE=0xffff0000 # CONFIG_ARM_PATCH_PHYS_VIRT is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -84,6 +84,11 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_NAMESPACES is not set +# CONFIG_HAVE_GET_CYCLES is not set +# CONFIG_HAVE_TRACE_CLOCK is not set +CONFIG_HAVE_TRACE_CLOCK_GENERIC=y +CONFIG_HAVE_TRACE_CLOCK_32_TO_64=y +# CONFIG_HAVE_UNSYNCHRONIZED_TSC is not set # CONFIG_SCHED_AUTOGROUP is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_SYSFS_DEPRECATED_V2 is not set @@ -126,6 +131,7 @@ CONFIG_COMPAT_BRK=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_KPROBES=y @@ -137,6 +143,7 @@ CONFIG_HAVE_DMA_API_DEBUG=y # # GCOV-based kernel profiling # +CONFIG_HAVE_LTT_DUMP_TABLES=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -245,7 +252,7 @@ CONFIG_ARCH_MXC=y # CONFIG_ARCH_S5P6442 is not set # CONFIG_ARCH_S5PC100 is not set # CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_S5PV310 is not set +# CONFIG_ARCH_EXYNOS4 is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_TCC_926 is not set # CONFIG_ARCH_LH7A40X is not set @@ -255,6 +262,7 @@ CONFIG_ARCH_MXC=y # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set # CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set CONFIG_GPIO_PCA953X=y # CONFIG_KEYBOARD_GPIO_POLLED is not set CONFIG_IMX_HAVE_PLATFORM_FEC=y @@ -270,11 +278,9 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_IPUV3=y CONFIG_IMX_HAVE_PLATFORM_IMX_TVE=y CONFIG_IMX_HAVE_PLATFORM_IMX_VPU=y CONFIG_IMX_HAVE_PLATFORM_IMX_DVFS=y -CONFIG_IMX_HAVE_PLATFORM_AHCI=y CONFIG_IMX_HAVE_PLATFORM_IMX_IIM=y CONFIG_IMX_HAVE_PLATFORM_MXC_GPU=y CONFIG_IMX_HAVE_PLATFORM_LDB=y -CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y # # Freescale MXC Implementations @@ -285,7 +291,6 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y # CONFIG_ARCH_MX3 is not set # CONFIG_ARCH_MXC91231 is not set CONFIG_ARCH_MX5=y -# CONFIG_ARCH_MX6 is not set CONFIG_ARCH_MX53=y CONFIG_SOC_IMX53=y CONFIG_FORCE_MAX_ZONEORDER=11 @@ -306,7 +311,6 @@ CONFIG_MACH_MX53_EFIKASB=y # CONFIG_MACH_MX53_ARD is not set # CONFIG_MACH_MX50_RDP is not set # CONFIG_MACH_IMX_BLUETOOTH_RFKILL is not set -CONFIG_DMA_ZONE_SIZE=24 CONFIG_ISP1504_MXC=y CONFIG_UTMI_MXC=y # CONFIG_MXC_IRQ_PRIOR is not set @@ -316,6 +320,7 @@ CONFIG_MXC_PWM=y CONFIG_ARCH_MXC_IOMUX_V3=y CONFIG_ARCH_MXC_AUDMUX_V2=y CONFIG_IRAM_ALLOC=y +CONFIG_DMA_ZONE_SIZE=24 # # System MMU @@ -324,8 +329,8 @@ CONFIG_IRAM_ALLOC=y # # Processor Type # -CONFIG_CPU_32v6K=y CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y CONFIG_CPU_32v7=y CONFIG_CPU_ABRT_EV7=y CONFIG_CPU_PABRT_V7=y @@ -346,6 +351,7 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT_6=y CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_CPU_HAS_PMU=y @@ -353,6 +359,7 @@ CONFIG_CPU_HAS_PMU=y # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set # CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_754322 is not set # # Bus support @@ -407,6 +414,7 @@ CONFIG_ALIGNMENT_TRAP=y # # Boot options # +# CONFIG_USE_OF is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=223.223.223.11:/srv/arm2_new,v3 ip=dhcp" @@ -1000,7 +1008,6 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_DYNAPRO is not set # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set # CONFIG_TOUCHSCREEN_EETI is not set -# CONFIG_TOUCHSCREEN_EGALAX is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set @@ -1260,7 +1267,6 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_MAX1111 is not set # CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX17135 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1293,7 +1299,6 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83627EHF is not set # CONFIG_SENSORS_LIS3_SPI is not set # CONFIG_SENSORS_LIS3_I2C is not set -# CONFIG_SENSORS_IMX_AHCI is not set # CONFIG_MXC_MMA8450 is not set # CONFIG_MXC_MMA8451 is not set # CONFIG_THERMAL is not set @@ -1326,6 +1331,7 @@ CONFIG_MFD_SUPPORT=y # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_UCB1400_CORE is not set +# CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set # CONFIG_TWL4030_CORE is not set @@ -1338,6 +1344,7 @@ CONFIG_MFD_SUPPORT=y # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set @@ -1351,7 +1358,6 @@ CONFIG_MFD_SUPPORT=y # CONFIG_EZX_PCAP is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_MAX17135 is not set CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_DUMMY is not set @@ -1624,7 +1630,6 @@ CONFIG_FB_MXC_LDB=y # CONFIG_FB_MXC_ASYNC_PANEL is not set # CONFIG_FB_MXC_EINK_PANEL is not set # CONFIG_FB_MXC_ELCDIF_FB is not set -# CONFIG_FB_MXC_HDMI is not set # # Console display driver support @@ -1689,9 +1694,9 @@ CONFIG_SND_SOC_AC97_BUS=y CONFIG_SND_IMX_SOC=y CONFIG_SND_MXC_SOC_MX2=y CONFIG_SND_SOC_IMX_CS42L52=y -# CONFIG_SND_SOC_IMX_SPDIF is not set CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_CS42L52=y # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=y CONFIG_HID_SUPPORT=y @@ -1710,7 +1715,7 @@ CONFIG_USB_HID=y # # CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=m -# CONFIG_HID_ACRUX_FF is not set +# CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=m CONFIG_HID_BELKIN=m # CONFIG_HID_CANDO is not set @@ -1819,6 +1824,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set @@ -1925,6 +1931,7 @@ CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_SELECTED=y # CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_FUSB300 is not set # CONFIG_USB_GADGET_R8A66597 is not set # CONFIG_USB_GADGET_PXA_U2O is not set # CONFIG_USB_GADGET_M66592 is not set @@ -1978,7 +1985,6 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_IO_ACCESSORS=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_ESDHC_IMX=y -# CONFIG_MMC_MXC is not set # CONFIG_MMC_DW is not set # CONFIG_MMC_USHC is not set # CONFIG_MEMSTICK is not set @@ -2073,7 +2079,6 @@ CONFIG_RTC_INTF_DEV_UIE_EMUL=y # CONFIG_RTC_DRV_MSM6242 is not set # CONFIG_RTC_MXC is not set CONFIG_RTC_DRV_MXC_V2=y -# CONFIG_RTC_DRV_SNVS is not set # CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_RP5C01 is not set # CONFIG_RTC_DRV_V3020 is not set @@ -2087,8 +2092,7 @@ CONFIG_DMADEVICES=y # # DMA Devices # -CONFIG_MXC_PXP=y -CONFIG_MXC_PXP_CLIENT_DEVICE=y +# CONFIG_DW_DMAC is not set # CONFIG_TIMB_DMA is not set CONFIG_IMX_SDMA=y CONFIG_DMA_ENGINE=y @@ -2109,7 +2113,6 @@ CONFIG_CLKDEV_LOOKUP=y # CONFIG_MXC_IPU=y CONFIG_MXC_IPU_V3=y -CONFIG_MXC_IPU_V3EX=y # # MXC SSI support @@ -2156,12 +2159,13 @@ CONFIG_MXC_DAM=y # MXC VPU(Video Processing Unit) support # CONFIG_MXC_VPU=y +CONFIG_MXC_VPU_IRAM=y # CONFIG_MXC_VPU_DEBUG is not set # # MXC Asynchronous Sample Rate Converter support # -CONFIG_MXC_ASRC=y +# CONFIG_MXC_ASRC is not set # # MXC Bluetooth support @@ -2186,10 +2190,6 @@ CONFIG_MXC_ASRC=y # CONFIG_MXC_AMD_GPU=y -# -# ANATOP_THERMAL -# - # # File systems # From a5f63f5e0925421f1129a245bd21222aa3c19124 Mon Sep 17 00:00:00 2001 From: Steev Klimaszewski Date: Mon, 26 Sep 2011 17:34:46 -0500 Subject: [PATCH 11/32] mach-types: Fix white space issues Fix the whitespace issues. Kernel use is tabs, not spaces. Signed-off-by: Steev Klimaszewski --- arch/arm/tools/mach-types | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 1c92901f318..7de6e1a26b1 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -1099,4 +1099,4 @@ ecuv5 MACH_ECUV5 ECUV5 3421 hsgx6d MACH_HSGX6D HSGX6D 3422 dawad7 MACH_DAWAD7 DAWAD7 3423 sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424 -mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610 +mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610 From f70c1a1f1052c9aab553a5fb8294653399b9c684 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Wed, 28 Sep 2011 14:13:03 +0300 Subject: [PATCH 12/32] Removed 'extern' variable. Not needed. --- arch/arm/mach-mx5/board-mx53_efikasb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c index 8096350970f..ad65463a093 100644 --- a/arch/arm/mach-mx5/board-mx53_efikasb.c +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -73,8 +73,6 @@ #define GPIO_SDA IMX_GPIO_NR(5, 27) /* GPIO_5_27 */ #define GPIO_SCL IMX_GPIO_NR(5, 26) /* GPIO_5_26 */ -extern void __iomem *imx_otg_base; - static iomux_v3_cfg_t mx53_efikasb_pads[] = { /* USB */ MX53_PAD_KEY_COL4__GPIO4_14, /* overcurrent */ From 9264bd89b6ae13aeb0fc14865f201e854d67b8d3 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Mon, 10 Oct 2011 01:47:33 +0300 Subject: [PATCH 13/32] Better reset sequence for WiFi. --- arch/arm/mach-mx5/board-mx53_efikasb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c index ad65463a093..afcdbcd611d 100644 --- a/arch/arm/mach-mx5/board-mx53_efikasb.c +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -386,9 +386,12 @@ static void mx53_efikasb_periph_power(bool on) static void mx53_efikasb_do_periph_reset(void) { + gpio_set_value(PERIPH_RESET, 1); + msleep(50); gpio_set_value(PERIPH_RESET, 0); - mdelay(10); /* Should be fine... */ + msleep(1); gpio_set_value(PERIPH_RESET, 1); + msleep(30); } static struct imx_ssi_platform_data efikasb_ssi_pdata = { From f42be05ecd5165c68b544a7e98ef441e90054db2 Mon Sep 17 00:00:00 2001 From: Matt Sealey Date: Tue, 27 Sep 2011 14:10:02 -0500 Subject: [PATCH 14/32] Clean up GPU driver of old unused files --- drivers/mxc/amd-gpu/common/gsl_cmdstream.c | 267 --- drivers/mxc/amd-gpu/common/gsl_cmdwindow.c | 161 -- drivers/mxc/amd-gpu/common/gsl_context.c | 74 - drivers/mxc/amd-gpu/common/gsl_debug_pm4.c | 1015 --------- drivers/mxc/amd-gpu/common/gsl_device.c | 694 ------- drivers/mxc/amd-gpu/common/gsl_drawctxt.c | 1828 ----------------- drivers/mxc/amd-gpu/common/gsl_driver.c | 329 --- drivers/mxc/amd-gpu/common/gsl_g12.c | 1025 --------- drivers/mxc/amd-gpu/common/gsl_intrmgr.c | 300 --- drivers/mxc/amd-gpu/common/gsl_log.c | 591 ------ drivers/mxc/amd-gpu/common/gsl_memmgr.c | 949 --------- drivers/mxc/amd-gpu/common/gsl_mmu.c | 1084 ---------- drivers/mxc/amd-gpu/common/gsl_ringbuffer.c | 1163 ----------- drivers/mxc/amd-gpu/common/gsl_sharedmem.c | 937 --------- drivers/mxc/amd-gpu/common/gsl_tbdump.c | 228 -- drivers/mxc/amd-gpu/common/gsl_yamato.c | 924 --------- .../mxc/amd-gpu/common/pfp_microcode_nrt.inl | 327 --- drivers/mxc/amd-gpu/common/pm4_microcode.inl | 815 -------- drivers/mxc/amd-gpu/include/gsl_context.h | 45 - drivers/mxc/amd-gpu/os/include/os_types.h | 138 -- .../amd-gpu/os/kernel/include/kos_libapi.h | 813 -------- .../mxc/amd-gpu/platform/hal/linux/gsl_hal.c | 579 ------ .../amd-gpu/platform/hal/linux/gsl_hwaccess.h | 142 -- .../mxc/amd-gpu/platform/hal/linux/gsl_kmod.c | 977 --------- .../platform/hal/linux/gsl_kmod_cleanup.c | 269 --- .../platform/hal/linux/gsl_kmod_cleanup.h | 90 - .../platform/hal/linux/gsl_linux_map.c | 221 -- .../platform/hal/linux/gsl_linux_map.h | 46 - drivers/mxc/amd-gpu/platform/hal/linux/misc.c | 171 -- 29 files changed, 16202 deletions(-) delete mode 100644 drivers/mxc/amd-gpu/common/gsl_cmdstream.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_cmdwindow.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_context.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_debug_pm4.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_device.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_drawctxt.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_driver.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_g12.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_intrmgr.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_log.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_memmgr.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_mmu.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_ringbuffer.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_sharedmem.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_tbdump.c delete mode 100644 drivers/mxc/amd-gpu/common/gsl_yamato.c delete mode 100644 drivers/mxc/amd-gpu/common/pfp_microcode_nrt.inl delete mode 100644 drivers/mxc/amd-gpu/common/pm4_microcode.inl delete mode 100644 drivers/mxc/amd-gpu/include/gsl_context.h delete mode 100644 drivers/mxc/amd-gpu/os/include/os_types.h delete mode 100644 drivers/mxc/amd-gpu/os/kernel/include/kos_libapi.h delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_hal.c delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h delete mode 100644 drivers/mxc/amd-gpu/platform/hal/linux/misc.c diff --git a/drivers/mxc/amd-gpu/common/gsl_cmdstream.c b/drivers/mxc/amd-gpu/common/gsl_cmdstream.c deleted file mode 100644 index 4f0d107f2f6..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_cmdstream.c +++ /dev/null @@ -1,267 +0,0 @@ -/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#include "gsl_cmdstream.h" - -#ifdef GSL_LOCKING_FINEGRAIN -#define GSL_CMDSTREAM_MUTEX_CREATE() device->cmdstream_mutex = kos_mutex_create("gsl_cmdstream"); \ - if (!device->cmdstream_mutex) return (GSL_FAILURE); -#define GSL_CMDSTREAM_MUTEX_LOCK() kos_mutex_lock(device->cmdstream_mutex) -#define GSL_CMDSTREAM_MUTEX_UNLOCK() kos_mutex_unlock(device->cmdstream_mutex) -#define GSL_CMDSTREAM_MUTEX_FREE() kos_mutex_free(device->cmdstream_mutex); device->cmdstream_mutex = 0; -#else -#define GSL_CMDSTREAM_MUTEX_CREATE() -#define GSL_CMDSTREAM_MUTEX_LOCK() -#define GSL_CMDSTREAM_MUTEX_UNLOCK() -#define GSL_CMDSTREAM_MUTEX_FREE() -#endif - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_cmdstream_init(gsl_device_t *device) -{ - GSL_CMDSTREAM_MUTEX_CREATE(); - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -int -kgsl_cmdstream_close(gsl_device_t *device) -{ - GSL_CMDSTREAM_MUTEX_FREE(); - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -gsl_timestamp_t -kgsl_cmdstream_readtimestamp0(gsl_deviceid_t device_id, gsl_timestamp_type_t type) -{ - gsl_timestamp_t timestamp = -1; - gsl_device_t* device = &gsl_driver.device[device_id-1]; - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> gsl_timestamp_t kgsl_cmdstream_readtimestamp(gsl_deviceid_t device_id=%d gsl_timestamp_type_t type=%d)\n", device_id, type ); -#if (defined(GSL_BLD_G12) && defined(IRQTHREAD_POLL)) - kos_event_signal(device->irqthread_event); -#endif - if (type == GSL_TIMESTAMP_CONSUMED) - { - // start-of-pipeline timestamp - GSL_CMDSTREAM_GET_SOP_TIMESTAMP(device, (unsigned int*)×tamp); - } - else if (type == GSL_TIMESTAMP_RETIRED) - { - // end-of-pipeline timestamp - GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (unsigned int*)×tamp); - } - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_readtimestamp. Return value %d\n", timestamp ); - return (timestamp); -} - -//---------------------------------------------------------------------------- - -KGSL_API gsl_timestamp_t -kgsl_cmdstream_readtimestamp(gsl_deviceid_t device_id, gsl_timestamp_type_t type) -{ - gsl_timestamp_t timestamp = -1; - GSL_API_MUTEX_LOCK(); - timestamp = kgsl_cmdstream_readtimestamp0(device_id, type); - GSL_API_MUTEX_UNLOCK(); - return timestamp; -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_cmdstream_issueibcmds(gsl_deviceid_t device_id, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, unsigned int flags) -{ - gsl_device_t* device = &gsl_driver.device[device_id-1]; - int status = GSL_FAILURE; - GSL_API_MUTEX_LOCK(); - - kgsl_device_active(device); - - if (device->ftbl.cmdstream_issueibcmds) - { - status = device->ftbl.cmdstream_issueibcmds(device, drawctxt_index, ibaddr, sizedwords, timestamp, flags); - } - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_add_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t *timestamp) -{ - gsl_device_t* device = &gsl_driver.device[device_id-1]; - int status = GSL_FAILURE; - GSL_API_MUTEX_LOCK(); - if (device->ftbl.device_addtimestamp) - { - status = device->ftbl.device_addtimestamp(device, timestamp); - } - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -KGSL_API -int kgsl_cmdstream_waittimestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp, unsigned int timeout) -{ - gsl_device_t* device = &gsl_driver.device[device_id-1]; - int status = GSL_FAILURE; - if (device->ftbl.device_waittimestamp) - { - status = device->ftbl.device_waittimestamp(device, timestamp, timeout); - } - return status; -} - -//---------------------------------------------------------------------------- - -void -kgsl_cmdstream_memqueue_drain(gsl_device_t *device) -{ - gsl_memnode_t *memnode, *nextnode, *freehead; - gsl_timestamp_t timestamp, ts_processed; - gsl_memqueue_t *memqueue = &device->memqueue; - - GSL_CMDSTREAM_MUTEX_LOCK(); - - // check head - if (memqueue->head == NULL) - { - GSL_CMDSTREAM_MUTEX_UNLOCK(); - return; - } - // get current EOP timestamp - ts_processed = kgsl_cmdstream_readtimestamp0(device->id, GSL_TIMESTAMP_RETIRED); - timestamp = memqueue->head->timestamp; - // check head timestamp - if (!(((ts_processed - timestamp) >= 0) || ((ts_processed - timestamp) < -GSL_TIMESTAMP_EPSILON))) - { - GSL_CMDSTREAM_MUTEX_UNLOCK(); - return; - } - memnode = memqueue->head; - freehead = memqueue->head; - // get node list to free - for(;;) - { - nextnode = memnode->next; - if (nextnode == NULL) - { - // entire queue drained - memqueue->head = NULL; - memqueue->tail = NULL; - break; - } - timestamp = nextnode->timestamp; - if (!(((ts_processed - timestamp) >= 0) || ((ts_processed - timestamp) < -GSL_TIMESTAMP_EPSILON))) - { - // drained up to a point - memqueue->head = nextnode; - memnode->next = NULL; - break; - } - memnode = nextnode; - } - // free nodes - while (freehead) - { - memnode = freehead; - freehead = memnode->next; - kgsl_sharedmem_free0(&memnode->memdesc, memnode->pid); - kos_free(memnode); - } - - GSL_CMDSTREAM_MUTEX_UNLOCK(); -} - -//---------------------------------------------------------------------------- - -int -kgsl_cmdstream_freememontimestamp(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, gsl_timestamp_t timestamp, gsl_timestamp_type_t type) -{ - gsl_memnode_t *memnode; - gsl_device_t *device = &gsl_driver.device[device_id-1]; - gsl_memqueue_t *memqueue; - (void)type; // unref. For now just use EOP timestamp - - GSL_API_MUTEX_LOCK(); - GSL_CMDSTREAM_MUTEX_LOCK(); - - memqueue = &device->memqueue; - - memnode = kos_malloc(sizeof(gsl_memnode_t)); - - if (!memnode) - { - // other solution is to idle and free which given that the upper level driver probably wont check, probably a better idea - GSL_CMDSTREAM_MUTEX_UNLOCK(); - GSL_API_MUTEX_UNLOCK(); - return (GSL_FAILURE); - } - - memnode->timestamp = timestamp; - memnode->pid = GSL_CALLER_PROCESSID_GET(); - memnode->next = NULL; - kos_memcpy(&memnode->memdesc, memdesc, sizeof(gsl_memdesc_t)); - - // add to end of queue - if (memqueue->tail != NULL) - { - memqueue->tail->next = memnode; - memqueue->tail = memnode; - } - else - { - KOS_ASSERT(memqueue->head == NULL); - memqueue->head = memnode; - memqueue->tail = memnode; - } - - GSL_CMDSTREAM_MUTEX_UNLOCK(); - GSL_API_MUTEX_UNLOCK(); - - return (GSL_SUCCESS); -} - -static int kgsl_cmdstream_timestamp_cmp(gsl_timestamp_t ts_new, gsl_timestamp_t ts_old) -{ - gsl_timestamp_t ts_diff = ts_new - ts_old; - return (ts_diff >= 0) || (ts_diff < -GSL_TIMESTAMP_EPSILON); -} - -int kgsl_cmdstream_check_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp) -{ - gsl_timestamp_t ts_processed; - ts_processed = kgsl_cmdstream_readtimestamp0(device_id, GSL_TIMESTAMP_RETIRED); - return kgsl_cmdstream_timestamp_cmp(ts_processed, timestamp); -} diff --git a/drivers/mxc/amd-gpu/common/gsl_cmdwindow.c b/drivers/mxc/amd-gpu/common/gsl_cmdwindow.c deleted file mode 100644 index d19832d8da4..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_cmdwindow.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" - -#ifdef GSL_BLD_G12 - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -#define GSL_CMDWINDOW_TARGET_MASK 0x000000FF -#define GSL_CMDWINDOW_ADDR_MASK 0x00FFFF00 -#define GSL_CMDWINDOW_TARGET_SHIFT 0 -#define GSL_CMDWINDOW_ADDR_SHIFT 8 - - -////////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#ifdef GSL_LOCKING_FINEGRAIN -#define GSL_CMDWINDOW_MUTEX_CREATE() device->cmdwindow_mutex = kos_mutex_create("gsl_cmdwindow"); \ - if (!device->cmdwindow_mutex) return (GSL_FAILURE); -#define GSL_CMDWINDOW_MUTEX_LOCK() kos_mutex_lock(device->cmdwindow_mutex) -#define GSL_CMDWINDOW_MUTEX_UNLOCK() kos_mutex_unlock(device->cmdwindow_mutex) -#define GSL_CMDWINDOW_MUTEX_FREE() kos_mutex_free(device->cmdwindow_mutex); device->cmdwindow_mutex = 0; -#else -#define GSL_CMDWINDOW_MUTEX_CREATE() -#define GSL_CMDWINDOW_MUTEX_LOCK() -#define GSL_CMDWINDOW_MUTEX_UNLOCK() -#define GSL_CMDWINDOW_MUTEX_FREE() -#endif - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_cmdwindow_init(gsl_device_t *device) -{ - GSL_CMDWINDOW_MUTEX_CREATE(); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_cmdwindow_close(gsl_device_t *device) -{ - GSL_CMDWINDOW_MUTEX_FREE(); - - return (GSL_SUCCESS); -} - -#endif // GSL_BLD_G12 - -//---------------------------------------------------------------------------- - -int -kgsl_cmdwindow_write0(gsl_deviceid_t device_id, gsl_cmdwindow_t target, unsigned int addr, unsigned int data) -{ -#ifdef GSL_BLD_G12 - gsl_device_t *device; - unsigned int cmdwinaddr; - unsigned int cmdstream; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_cmdwindow_write( gsl_device_id_t device_id=%d, gsl_cmdwindow_t target=%d, unsigned int addr=0x%08x, unsigned int data=0x%08x)\n", device_id, target, addr, data ); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - if (target < GSL_CMDWINDOW_MIN || target > GSL_CMDWINDOW_MAX) - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid target.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - if ((!(device->flags & GSL_FLAGS_INITIALIZED) && target == GSL_CMDWINDOW_MMU) || - (!(device->flags & GSL_FLAGS_STARTED) && target != GSL_CMDWINDOW_MMU)) - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid device state to write to selected targer.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // set command stream - if (target == GSL_CMDWINDOW_MMU) - { -#ifdef GSL_NO_MMU - return (GSL_SUCCESS); -#endif - cmdstream = ADDR_VGC_MMUCOMMANDSTREAM; - } - else - { - cmdstream = ADDR_VGC_COMMANDSTREAM; - } - - - // set command window address - cmdwinaddr = ((target << GSL_CMDWINDOW_TARGET_SHIFT) & GSL_CMDWINDOW_TARGET_MASK); - cmdwinaddr |= ((addr << GSL_CMDWINDOW_ADDR_SHIFT) & GSL_CMDWINDOW_ADDR_MASK); - - GSL_CMDWINDOW_MUTEX_LOCK(); - -#ifndef GSL_NO_MMU - // set mmu pagetable - kgsl_mmu_setpagetable(device, GSL_CALLER_PROCESSID_GET()); -#endif - - // write command window address - device->ftbl.device_regwrite(device, (cmdstream)>>2, cmdwinaddr); - - // write data - device->ftbl.device_regwrite(device, (cmdstream)>>2, data); - - GSL_CMDWINDOW_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -#else - // unreferenced formal parameter - (void) device_id; - (void) target; - (void) addr; - (void) data; - - return (GSL_FAILURE); -#endif // GSL_BLD_G12 -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_cmdwindow_write(gsl_deviceid_t device_id, gsl_cmdwindow_t target, unsigned int addr, unsigned int data) -{ - int status = GSL_SUCCESS; - GSL_API_MUTEX_LOCK(); - status = kgsl_cmdwindow_write0(device_id, target, addr, data); - GSL_API_MUTEX_UNLOCK(); - return status; -} diff --git a/drivers/mxc/amd-gpu/common/gsl_context.c b/drivers/mxc/amd-gpu/common/gsl_context.c deleted file mode 100644 index c999247b3af..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_context.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#include "gsl_context.h" - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -KGSL_API int -kgsl_context_create(gsl_deviceid_t device_id, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags) -{ - gsl_device_t* device = &gsl_driver.device[device_id-1]; - int status; - - GSL_API_MUTEX_LOCK(); - - if (device->ftbl.context_create) - { - status = device->ftbl.context_create(device, type, drawctxt_id, flags); - } - else - { - status = GSL_FAILURE; - } - - GSL_API_MUTEX_UNLOCK(); - - return status; -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_context_destroy(gsl_deviceid_t device_id, unsigned int drawctxt_id) -{ - gsl_device_t* device = &gsl_driver.device[device_id-1]; - int status; - - GSL_API_MUTEX_LOCK(); - - if (device->ftbl.context_destroy) - { - status = device->ftbl.context_destroy(device, drawctxt_id); - } - else - { - status = GSL_FAILURE; - } - - GSL_API_MUTEX_UNLOCK(); - - return status; -} - -//---------------------------------------------------------------------------- - diff --git a/drivers/mxc/amd-gpu/common/gsl_debug_pm4.c b/drivers/mxc/amd-gpu/common/gsl_debug_pm4.c deleted file mode 100644 index 847df8dbe38..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_debug_pm4.c +++ /dev/null @@ -1,1015 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" - -#if defined(_WIN32) && defined (GSL_BLD_YAMATO) - -#include -#include -#include - -//#define PM4_DEBUG_USE_MEMBUF - -#ifdef PM4_DEBUG_USE_MEMBUF - -#define MEMBUF_SIZE 100000 -#define BUFFER_END_MARGIN 1000 -char memBuf[MEMBUF_SIZE]; -static int writePtr = 0; -static unsigned int lineNumber = 0; -//#define fprintf(A,...); writePtr += sprintf( memBuf+writePtr, __VA_ARGS__ ); sprintf( memBuf+writePtr, "###" ); if( writePtr > MEMBUF_SIZE-BUFFER_END_MARGIN ) { memset(memBuf+writePtr, '#', MEMBUF_SIZE-writePtr); writePtr = 0; } -#define FILE char -#define fopen(X,Y) 0 -#define fclose(X) - -int printString( FILE *_File, const char * _Format, ...) -{ - int ret; - va_list ap; - (void)_File; - - va_start(ap, _Format); - if( writePtr > 0 && memBuf[writePtr-1] == '\n' ) - { - // Add line number if last written character was newline - writePtr += sprintf( memBuf+writePtr, "%d: ", lineNumber++ ); - } - ret = vsprintf(memBuf+writePtr, _Format, ap); - writePtr += ret; - sprintf( memBuf+writePtr, "###" ); - if( writePtr > MEMBUF_SIZE-BUFFER_END_MARGIN ) - { - memset(memBuf+writePtr, '#', MEMBUF_SIZE-writePtr); - writePtr = 0; - } - - va_end(ap); - - return ret; -} - -#else - -int printString( FILE *_File, const char * _Format, ...) -{ - int ret; - va_list ap; - va_start(ap, _Format); - ret = vfprintf(_File, _Format, ap); - va_end(ap); - fflush(_File); - return ret; -} - -#endif - -#ifndef _WIN32_WCE -#define PM4_DUMPFILE "pm4dump.txt" -#else -#define PM4_DUMPFILE "\\Release\\pm4dump.txt" -#endif - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -#define EXPAND_OPCODE(opcode) ((opcode << 8) | PM4_PKT_MASK) - -#define GetString_uint GetString_int -#define GetString_fixed12_4(val, szValue) GetString_fixed(val, 12, 4, szValue) -#define GetString_signedint15(val, szValue) GetString_signedint(val, 15, szValue) - -// Need a prototype for this function -void WritePM4Packet_Type3(FILE* pFile, unsigned int dwHeader, unsigned int** ppBuffer); - -static int indirectionLevel = 0; - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -void WriteDWORD(FILE* pFile, unsigned int dwValue) -{ - printString(pFile, " 0x%08x", dwValue); -} - -void WriteDWORD2(FILE* pFile, unsigned int dwValue) -{ - printString(pFile, " 0x%08x\n", dwValue); -} - -//---------------------------------------------------------------------------- - -// Generate the GetString_## functions for enumerated types -#define START_ENUMTYPE(__type) \ -void GetString_##__type(unsigned int val, char* szValue) \ -{ \ - switch(val) \ - { - -#define GENERATE_ENUM(__enumname, __val) \ - case __val: \ - kos_strcpy(szValue, #__enumname); \ - break; - -#define END_ENUMTYPE(__type) \ - default: \ - sprintf(szValue, "Unknown: %d", val); \ - break; \ - } \ -} - -#include _YAMATO_GENENUM_H - -//---------------------------------------------------------------------------- - -void -GetString_hex(unsigned int val, char* szValue) -{ - sprintf(szValue, "0x%x", val); -} - -//---------------------------------------------------------------------------- - -void -GetString_float(unsigned int val, char* szValue) -{ - float fval = *((float*) &val); - sprintf(szValue, "%.4f", fval); -} - -//---------------------------------------------------------------------------- - -void -GetString_bool(unsigned int val, char* szValue) -{ - if (val) - { - kos_strcpy(szValue, "TRUE"); - } - else - { - kos_strcpy(szValue, "FALSE"); - } -} - -//---------------------------------------------------------------------------- - -void GetString_int(unsigned int val, char* szValue) -{ - sprintf(szValue, "%d", val); -} - -//---------------------------------------------------------------------------- - -void -GetString_intMinusOne(unsigned int val, char* szValue) -{ - sprintf(szValue, "%d+1", val); -} - -//---------------------------------------------------------------------------- - -void -GetString_signedint(unsigned int val, unsigned int dwNumBits, char* szValue) -{ - int nValue = val; - - if (val & (1<<(dwNumBits-1))) - { - nValue |= 0xffffffff << dwNumBits; - } - - sprintf(szValue, "%d", nValue); -} - -//---------------------------------------------------------------------------- - -void -GetString_fixed(unsigned int val, unsigned int dwNumInt, unsigned int dwNumFrac, char* szValue) -{ - - (void) dwNumInt; // unreferenced formal parameter - - if (val>>dwNumFrac == 0) - { - // Integer part is 0 - just print out the fractional part - sprintf(szValue, "%d/%d", - val&((1<>dwNumFrac, - val&((1<> 16) == 0x4)) - registerAddr = (*pBuffer) & 0xffff; - - // Write unsigned int - WriteDWORD(pFile, *pBuffer); - - // Starting at Ordinal 2 is actual register values - if((dwIndex > 0) && (registerAddr != 0xffffffff)) - { - // Write register string based on address - GetString_Register(registerAddr + 0x2000, *pBuffer, szRegister); - printString(pFile, " // %s\n", szRegister); - registerAddr++; - } - else - { - // Write out newline if we aren't augmenting with register fields - printString(pFile, "\n"); - } - - pBuffer++; - } - } - *ppBuffer = pBuffer; -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpInitParams(unsigned int dwEDRAMBase, unsigned int dwEDRAMSize) -{ - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "InitParams, edrambase=0x%x, edramsize=%d\n", - dwEDRAMBase, dwEDRAMSize); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpSwapBuffers(unsigned int dwAddress, unsigned int dwWidth, - unsigned int dwHeight, unsigned int dwPitch, unsigned int dwAlignedHeight, unsigned int dwBitsPerPixel) -{ - // Open file - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "SwapBuffers, address=0x%08x, width=%d, height=%d, pitch=%d, alignedheight=%d, bpp=%d\n", - dwAddress, dwWidth, dwHeight, dwPitch, dwAlignedHeight, dwBitsPerPixel); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpRegSpace(gsl_device_t *device) -{ - int regsPerLine = 0x20; - unsigned int dwOffset; - unsigned int value; - - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "Start_RegisterSpace\n"); - - for (dwOffset = 0; dwOffset < device->regspace.sizebytes; dwOffset += 4) - { - if (dwOffset % regsPerLine == 0) - { - printString(pFile, " 0x%08x ", dwOffset); - } - - GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, (dwOffset >> 2), &value); - - printString(pFile, " 0x%08x", value); - - if (((dwOffset + 4) % regsPerLine == 0) && ((dwOffset + 4) < device->regspace.sizebytes)) - { - printString(pFile, "\n"); - } - } - - printString(pFile, "\nEnd_RegisterSpace\n"); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpAllocateMemory(unsigned int dwSize, unsigned int dwFlags, unsigned int dwAddress, - unsigned int dwActualSize) -{ - // Open file - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "AllocateMemory, size=%d, flags=0x%x, address=0x%x, actualSize=%d\n", - dwSize, dwFlags, dwAddress, dwActualSize); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpFreeMemory(unsigned int dwAddress) -{ - // Open file - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "FreeMemory, address=0x%x\n", dwAddress); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpWriteMemory(unsigned int dwAddress, unsigned int dwSize, void* pData) -{ - // Open file - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - unsigned int dwNumDWORDs; - unsigned int dwIndex; - unsigned int *pDataPtr; - - printString(pFile, "StartWriteMemory, address=0x%x, size=%d\n", dwAddress, dwSize); - - // Now write the data, in dwNumDWORDs - dwNumDWORDs = dwSize >> 2; - - // If there are spillover bytes into the next dword, increment the amount dumped out here. - // The reader needs to take care of not overwriting the nonvalid bytes - if((dwSize % 4) != 0) - dwNumDWORDs++; - - for (dwIndex = 0, pDataPtr = (unsigned int *)pData; dwIndex < dwNumDWORDs; dwIndex++, pDataPtr++) - { - WriteDWORD2(pFile, *pDataPtr); - } - - printString(pFile, "EndWriteMemory\n"); - - fclose(pFile); -} - -void -Yamato_DumpSetMemory(unsigned int dwAddress, unsigned int dwSize, unsigned int pData) -{ - // Open file - FILE* pFile = fopen(PM4_DUMPFILE, "a"); -// unsigned int* pDataPtr; - - printString(pFile, "SetMemory, address=0x%x, size=%d, value=0x%x\n", - dwAddress, dwSize, pData); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- -void -Yamato_ConvertIBAddr(unsigned int dwHeader, unsigned int *pBuffer, int gpuToHost) -{ - unsigned int hostaddr; - unsigned int *ibend; - unsigned int *addr; - unsigned int *ib = pBuffer; - pm4_type3 header = *((pm4_type3*) &dwHeader); - - // convert ib1 base address - if((EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER) || - (EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER_PFD)) - { - if (gpuToHost) - { - // from gpu to host - *ib = kgsl_sharedmem_convertaddr(*ib, 0); - - hostaddr = *ib; - } - else - { - // from host to gpu - hostaddr = *ib; - *ib = kgsl_sharedmem_convertaddr(*ib, 1); - } - - // walk through ib1 and convert any ib2 base address - - ib = (unsigned int *) hostaddr; - ibend = (unsigned int *) (ib + *(++pBuffer)); - - while (ib < ibend) - { - dwHeader = *(ib); - header = *((pm4_type3*) (&dwHeader)); - - switch(dwHeader & PM4_PKT_MASK) - { - case PM4_TYPE0_PKT: - ib += header.count + 2; - break; - - case PM4_TYPE1_PKT: - break; - - case PM4_TYPE2_PKT: - ib++; - break; - - case PM4_TYPE3_PKT: - if((EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER) || - (EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER_PFD)) - { - addr = ib + 1; - if (gpuToHost) - { - // from gpu to host - *addr = kgsl_sharedmem_convertaddr(*addr, 0); - } - else - { - // from host to gpu - *addr = kgsl_sharedmem_convertaddr(*addr, 1); - } - } - ib += header.count + 2; - break; - } - } - } -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpPM4(unsigned int* pBuffer, unsigned int sizeDWords) -{ - unsigned int *pBufferEnd = pBuffer + sizeDWords; - unsigned int *tmp; - - // Open file - FILE* pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "Start_PM4Buffer\n");//, count=%d\n", sizeDWords); - - // So look at the first unsigned int - should be a header - while(pBuffer < pBufferEnd) - { - unsigned int dwHeader = *(pBuffer++); - - //printString(pFile, " Start_Packet\n"); - switch(dwHeader & PM4_PKT_MASK) - { - case PM4_TYPE0_PKT: - WritePM4Packet_Type0(pFile, dwHeader, &pBuffer); - break; - - case PM4_TYPE1_PKT: - break; - - case PM4_TYPE2_PKT: - WritePM4Packet_Type2(pFile, dwHeader, &pBuffer); - break; - - case PM4_TYPE3_PKT: - indirectionLevel = 0; - tmp = pBuffer; - Yamato_ConvertIBAddr(dwHeader, tmp, 1); - WritePM4Packet_Type3(pFile, dwHeader, &pBuffer); - Yamato_ConvertIBAddr(dwHeader, tmp, 0); - break; - } - //printString(pFile, " End_Packet\n"); - } - - printString(pFile, "End_PM4Buffer\n"); - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpRegisterWrite(unsigned int dwAddress, unsigned int value) -{ - FILE *pFile; - - // Build a Type-0 packet that maps to this register write - unsigned int pBuffer[100], *pBuf = &pBuffer[1]; - - // Don't dump CP_RB_WPTR (switch statement may be necessary here for future additions) - if(dwAddress == mmCP_RB_WPTR) - return; - - pFile = fopen(PM4_DUMPFILE, "a"); - - pBuffer[0] = dwAddress; - pBuffer[1] = value; - - printString(pFile, "StartRegisterWrite\n"); - WritePM4Packet_Type0(pFile, pBuffer[0], &pBuf); - printString(pFile, "EndRegisterWrite\n"); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpFbStart(gsl_device_t *device) -{ - FILE *pFile; - - static int firstCall = 0; - - // We only want to call this once - if(firstCall) - return; - - pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "FbStart, value=0x%x\n", device->mmu.mpu_base); - printString(pFile, "FbSize, value=0x%x\n", device->mmu.mpu_range); - - fclose(pFile); - - firstCall = 1; -} - -//---------------------------------------------------------------------------- - -void -Yamato_DumpWindow(unsigned int addr, unsigned int width, unsigned int height) -{ - FILE *pFile; - - pFile = fopen(PM4_DUMPFILE, "a"); - - printString(pFile, "DumpWindow, addr=0x%x, width=0x%x, height=0x%x\n", addr, width, height); - - fclose(pFile); -} - -//---------------------------------------------------------------------------- -#ifdef _DEBUG - -#define ADDRESS_STACK_SIZE 256 -#define GET_PM4_TYPE3_OPCODE(x) ((*(x) >> 8) & 0xFF) -#define IF_REGISTER_IN_RANGE(reg, base, count) \ - offset = (reg) - (base); \ - if(offset >= 0 && offset <= (count) - 2) -#define GET_CP_CONSTANT_DATA(x) (*((x) + offset + 2)) - -static const char format2bpp[] = -{ - 2, // COLORX_4_4_4_4 - 2, // COLORX_1_5_5_5 - 2, // COLORX_5_6_5 - 1, // COLORX_8 - 2, // COLORX_8_8 - 4, // COLORX_8_8_8_8 - 4, // COLORX_S8_8_8_8 - 2, // COLORX_16_FLOAT - 4, // COLORX_16_16_FLOAT - 8, // COLORX_16_16_16_16_FLOAT - 4, // COLORX_32_FLOAT - 8, // COLORX_32_32_FLOAT - 16, // COLORX_32_32_32_32_FLOAT , - 1, // COLORX_2_3_3 - 3, // COLORX_8_8_8 -}; - -static unsigned int kgsl_dumpx_addr_count = 0; //unique command buffer addresses encountered -static int kgsl_dumpx_handle_type3(unsigned int* hostaddr, int count) -{ - // For swap detection we need to find the below declared static values, and detect DI during EDRAM copy - static unsigned int width = 0, height = 0, format = 0, baseaddr = 0, iscopy = 0; - - static unsigned int addr_stack[ADDRESS_STACK_SIZE]; - static unsigned int size_stack[ADDRESS_STACK_SIZE]; - int swap = 0; // have we encountered a swap during recursion (return value) - - switch(GET_PM4_TYPE3_OPCODE(hostaddr)) - { - case PM4_INDIRECT_BUFFER_PFD: - case PM4_INDIRECT_BUFFER: - { - // traverse indirect buffers - unsigned int i; - unsigned int ibaddr = *(hostaddr+1); - unsigned int ibsize = *(hostaddr+2); - - // is this address already in encountered? - for(i = 0; i < kgsl_dumpx_addr_count && addr_stack[i] != ibaddr; i++); - - if(kgsl_dumpx_addr_count == i) - { - // yes it was, store the address so we don't dump this buffer twice - addr_stack[kgsl_dumpx_addr_count] = ibaddr; - // just for sanity checking - size_stack[kgsl_dumpx_addr_count++] = ibsize; - KOS_ASSERT(kgsl_dumpx_addr_count < ADDRESS_STACK_SIZE); - - // recursively follow the indirect link and update swap if indirect buffer had resolve - swap |= kgsl_dumpx_parse_ibs(ibaddr, ibsize); - } - else - { - KOS_ASSERT(size_stack[i] == ibsize); - } - } - break; - - case PM4_SET_CONSTANT: - if((*(hostaddr+1) >> 16) == 0x4) - { - // parse register writes, and figure out framebuffer configuration - - unsigned int regaddr = (*(hostaddr + 1) & 0xFFFF) + 0x2000; //dword address in register space - int offset; // used by the macros - - IF_REGISTER_IN_RANGE(mmPA_SC_WINDOW_SCISSOR_BR, regaddr, count) - { - // found write to PA_SC_WINDOW_SCISSOR_BR, we use this to detect current - // width and height of the framebuffer (TODO: find more reliable way of achieving this) - unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); - width = data & 0xFFFF; - height = data >> 16; - } - - IF_REGISTER_IN_RANGE(mmRB_MODECONTROL, regaddr, count) - { - // found write to RB_MODECONTROL, we use this to find out if next DI is resolve - unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); - iscopy = (data & RB_MODECONTROL__EDRAM_MODE_MASK) == (EDRAM_COPY << RB_MODECONTROL__EDRAM_MODE__SHIFT); - } - - IF_REGISTER_IN_RANGE(mmRB_COPY_DEST_BASE, regaddr, count) - { - // found write to RB_COPY_DEST_BASE, we use this to find out the framebuffer base address - unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); - baseaddr = (data & RB_COPY_DEST_BASE__COPY_DEST_BASE_MASK); - } - - IF_REGISTER_IN_RANGE(mmRB_COPY_DEST_INFO, regaddr, count) - { - // found write to RB_COPY_DEST_INFO, we use this to find out the framebuffer format - unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); - format = (data & RB_COPY_DEST_INFO__COPY_DEST_FORMAT_MASK) >> RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT; - } - } - break; - - case PM4_DRAW_INDX: - case PM4_DRAW_INDX_2: - { - // DI found - // check if it is resolve - if(iscopy && !swap) - { - // printf("resolve: %ix%i @ 0x%08x, format = 0x%08x\n", width, height, baseaddr, format); - KOS_ASSERT(format < 15); - - // yes it was and we need to update color buffer config because this is the first bin - // dumpx framebuffer base address, and dimensions - KGSL_DEBUG_DUMPX( BB_DUMP_CBUF_AWH, (unsigned int)baseaddr, width, height, " "); - - // find aligned width - width = (width + 31) & ~31; - - //dump bytes-per-pixel and aligned width - KGSL_DEBUG_DUMPX( BB_DUMP_CBUF_FS, format2bpp[format], width, 0, " "); - swap = 1; - } - - } - break; - - default: - break; - } - return swap; -} - -// Traverse IBs and dump them to test vector. Detect swap by inspecting register -// writes, keeping note of the current state, and dump framebuffer config to test vector -int kgsl_dumpx_parse_ibs(gpuaddr_t gpuaddr, int sizedwords) -{ - static unsigned int level = 0; //recursion level - - int swap = 0; // have we encountered a swap during recursion (return value) - unsigned int *hostaddr; - int dwords_left = sizedwords; //dwords left in the current command buffer - - level++; - - KOS_ASSERT(sizeof(unsigned int *) == sizeof(unsigned int)); - KOS_ASSERT(level <= 2); - hostaddr = (unsigned int *)kgsl_sharedmem_convertaddr(gpuaddr, 0); - - // dump the IB to test vector - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MEMWRITE, gpuaddr, (unsigned int)hostaddr, sizedwords*4, "kgsl_dumpx_write_ibs")); - - while(dwords_left) - { - int count = 0; //dword count including packet header - - switch(*hostaddr >> 30) - { - case 0x0: // type-0 - count = (*hostaddr >> 16)+2; - break; - case 0x1: // type-1 - count = 2; - break; - case 0x3: // type-3 - count = ((*hostaddr >> 16) & 0x3fff) + 2; - swap |= kgsl_dumpx_handle_type3(hostaddr, count); - break; // type-3 - default: - KOS_ASSERT(!"unknown packet type"); - } - - // jump to next packet - dwords_left -= count; - hostaddr += count; - KOS_ASSERT(dwords_left >= 0 && "PM4 parsing error"); - } - - level--; - - // if this is the starting level of recursion, we are done. clean-up - if(level == 0) kgsl_dumpx_addr_count = 0; - - return swap; -} -#endif - -#endif // WIN32 - diff --git a/drivers/mxc/amd-gpu/common/gsl_device.c b/drivers/mxc/amd-gpu/common/gsl_device.c deleted file mode 100644 index 6c41d3dd6dc..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_device.c +++ /dev/null @@ -1,694 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#ifdef _LINUX -#include -#endif - -////////////////////////////////////////////////////////////////////////////// -// inline functions -////////////////////////////////////////////////////////////////////////////// -OSINLINE void -kgsl_device_getfunctable(gsl_deviceid_t device_id, gsl_functable_t *ftbl) -{ - switch (device_id) - { -#ifdef GSL_BLD_YAMATO - case GSL_DEVICE_YAMATO: - kgsl_yamato_getfunctable(ftbl); - break; -#endif // GSL_BLD_YAMATO -#ifdef GSL_BLD_G12 - case GSL_DEVICE_G12: - kgsl_g12_getfunctable(ftbl); - break; -#endif // GSL_BLD_G12 - default: - break; - } -} - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_device_init(gsl_device_t *device, gsl_deviceid_t device_id) -{ - int status = GSL_SUCCESS; - gsl_devconfig_t config; - gsl_hal_t *hal = (gsl_hal_t *)gsl_driver.hal; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_init(gsl_device_t *device=0x%08x, gsl_deviceid_t device_id=%D )\n", device, device_id ); - - if ((GSL_DEVICE_YAMATO == device_id) && !(hal->has_z430)) { - return GSL_FAILURE_NOTSUPPORTED; - } - - if ((GSL_DEVICE_G12 == device_id) && !(hal->has_z160)) { - return GSL_FAILURE_NOTSUPPORTED; - } - - if (device->flags & GSL_FLAGS_INITIALIZED) - { - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_init. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); - } - - kos_memset(device, 0, sizeof(gsl_device_t)); - - // if device configuration is present - if (kgsl_hal_getdevconfig(device_id, &config) == GSL_SUCCESS) - { - kgsl_device_getfunctable(device_id, &device->ftbl); - - kos_memcpy(&device->regspace, &config.regspace, sizeof(gsl_memregion_t)); -#ifdef GSL_BLD_YAMATO - kos_memcpy(&device->gmemspace, &config.gmemspace, sizeof(gsl_memregion_t)); -#endif // GSL_BLD_YAMATO - - device->refcnt = 0; - device->id = device_id; - -#ifndef GSL_NO_MMU - device->mmu.config = config.mmu_config; - device->mmu.mpu_base = config.mpu_base; - device->mmu.mpu_range = config.mpu_range; - device->mmu.va_base = config.va_base; - device->mmu.va_range = config.va_range; -#endif - - if (device->ftbl.device_init) - { - status = device->ftbl.device_init(device); - } - else - { - status = GSL_FAILURE_NOTINITIALIZED; - } - - // allocate memory store - status = kgsl_sharedmem_alloc0(device->id, GSL_MEMFLAGS_ALIGNPAGE | GSL_MEMFLAGS_CONPHYS, sizeof(gsl_devmemstore_t), &device->memstore); - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, - { - // dumpx needs this to be in EMEM0 aperture - kgsl_sharedmem_free0(&device->memstore, GSL_CALLER_PROCESSID_GET()); - status = kgsl_sharedmem_alloc0(device->id, GSL_MEMFLAGS_ALIGNPAGE, sizeof(gsl_devmemstore_t), &device->memstore); - }); - - if (status != GSL_SUCCESS) - { - kgsl_device_stop(device->id); - return (status); - } - kgsl_sharedmem_set0(&device->memstore, 0, 0, device->memstore.size); - - // init memqueue - device->memqueue.head = NULL; - device->memqueue.tail = NULL; - - // init cmdstream - status = kgsl_cmdstream_init(device); - if (status != GSL_SUCCESS) - { - kgsl_device_stop(device->id); - return (status); - } - -#ifndef _LINUX - // Create timestamp event - device->timestamp_event = kos_event_create(0); - if( !device->timestamp_event ) - { - kgsl_device_stop(device->id); - return (status); - } -#else - // Create timestamp wait queue - init_waitqueue_head(&device->timestamp_waitq); -#endif - - // - // Read the chip ID after the device has been initialized. - // - device->chip_id = kgsl_hal_getchipid(device->id); - } - - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_init. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_device_close(gsl_device_t *device) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_close(gsl_device_t *device=0x%08x )\n", device ); - - if (!(device->flags & GSL_FLAGS_INITIALIZED)) { - return status; - } - - /* make sure the device is stopped before close - kgsl_device_close is only called for last running caller process - */ - while (device->refcnt > 0) { - GSL_API_MUTEX_UNLOCK(); - kgsl_device_stop(device->id); - GSL_API_MUTEX_LOCK(); - } - - // close cmdstream - status = kgsl_cmdstream_close(device); - if( status != GSL_SUCCESS ) return status; - - if (device->ftbl.device_close) { - status = device->ftbl.device_close(device); - } - - // DumpX allocates memstore from MMU aperture - if ((device->refcnt == 0) && device->memstore.hostptr - && !(gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX)) - { - kgsl_sharedmem_free0(&device->memstore, GSL_CALLER_PROCESSID_GET()); - } - -#ifndef _LINUX - // destroy timestamp event - if(device->timestamp_event) - { - kos_event_signal(device->timestamp_event); // wake up waiting threads before destroying the structure - kos_event_destroy( device->timestamp_event ); - device->timestamp_event = 0; - } -#else - wake_up_interruptible_all(&(device->timestamp_waitq)); -#endif - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_close. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_device_destroy(gsl_device_t *device) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_destroy(gsl_device_t *device=0x%08x )\n", device ); - - if (device->flags & GSL_FLAGS_INITIALIZED) - { - if (device->ftbl.device_destroy) - { - status = device->ftbl.device_destroy(device); - } - } - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_destroy. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_device_attachcallback(gsl_device_t *device, unsigned int pid) -{ - int status = GSL_SUCCESS; - int pindex; - -#ifndef GSL_NO_MMU - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_device_attachcallback(gsl_device_t *device=0x%08x, unsigned int pid=0x%08x)\n", device, pid ); - - if (device->flags & GSL_FLAGS_INITIALIZED) - { - if (kgsl_driver_getcallerprocessindex(pid, &pindex) == GSL_SUCCESS) - { - device->callerprocess[pindex] = pid; - - status = kgsl_mmu_attachcallback(&device->mmu, pid); - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_attachcallback. Return value: %B\n", status ); - -#else - (void)pid; - (void)device; -#endif - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_device_detachcallback(gsl_device_t *device, unsigned int pid) -{ - int status = GSL_SUCCESS; - int pindex; - -#ifndef GSL_NO_MMU - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_device_detachcallback(gsl_device_t *device=0x%08x, unsigned int pid=0x%08x)\n", device, pid ); - - if (device->flags & GSL_FLAGS_INITIALIZED) - { - if (kgsl_driver_getcallerprocessindex(pid, &pindex) == GSL_SUCCESS) - { - status |= kgsl_mmu_detachcallback(&device->mmu, pid); - - device->callerprocess[pindex] = 0; - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_detachcallback. Return value: %B\n", status ); - -#else - (void)pid; - (void)device; -#endif - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_getproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes) -{ - int status = GSL_SUCCESS; - gsl_device_t *device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_getproperty(gsl_deviceid_t device_id=%D, gsl_property_type_t type=%d, void *value=0x08x, unsigned int sizebytes=%d)\n", device_id, type, value, sizebytes ); - - KOS_ASSERT(value); - -#ifndef _DEBUG - (void) sizebytes; // unreferenced formal parameter -#endif - - switch (type) - { - case GSL_PROP_SHMEM: - { - gsl_shmemprop_t *shem = (gsl_shmemprop_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_shmemprop_t)); - - shem->numapertures = gsl_driver.shmem.numapertures; - shem->aperture_mask = GSL_APERTURE_MASK; - shem->aperture_shift = GSL_APERTURE_SHIFT; - - break; - } - - case GSL_PROP_SHMEM_APERTURES: - { - int i; - gsl_apertureprop_t *aperture = (gsl_apertureprop_t *) value; - - KOS_ASSERT(sizebytes == (sizeof(gsl_apertureprop_t) * gsl_driver.shmem.numapertures)); - - for (i = 0; i < gsl_driver.shmem.numapertures; i++) - { - if (gsl_driver.shmem.apertures[i].memarena) - { - aperture->gpuaddr = GSL_APERTURE_GETGPUADDR(gsl_driver.shmem, i); - aperture->hostaddr = GSL_APERTURE_GETHOSTADDR(gsl_driver.shmem, i); - } - else - { - aperture->gpuaddr = 0x0; - aperture->hostaddr = 0x0; - } - aperture++; - } - - break; - } - - case GSL_PROP_DEVICE_SHADOW: - { - gsl_shadowprop_t *shadowprop = (gsl_shadowprop_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_shadowprop_t)); - - kos_memset(shadowprop, 0, sizeof(gsl_shadowprop_t)); - -#ifdef GSL_DEVICE_SHADOW_MEMSTORE_TO_USER - if (device->memstore.hostptr) - { - shadowprop->hostaddr = (unsigned int) device->memstore.hostptr; - shadowprop->size = device->memstore.size; - shadowprop->flags = GSL_FLAGS_INITIALIZED; - } -#endif // GSL_DEVICE_SHADOW_MEMSTORE_TO_USER - - break; - } - - default: - { - if (device->ftbl.device_getproperty) - { - status = device->ftbl.device_getproperty(device, type, value, sizebytes); - } - - break; - } - } - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_getproperty. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_setproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes) -{ - int status = GSL_SUCCESS; - gsl_device_t *device; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_setproperty(gsl_deviceid_t device_id=%D, gsl_property_type_t type=%d, void *value=0x08x, unsigned int sizebytes=%d)\n", device_id, type, value, sizebytes ); - - KOS_ASSERT(value); - - GSL_API_MUTEX_LOCK(); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - if (device->flags & GSL_FLAGS_INITIALIZED) - { - if (device->ftbl.device_setproperty) - { - status = device->ftbl.device_setproperty(device, type, value, sizebytes); - } - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_setproperty. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_start(gsl_deviceid_t device_id, gsl_flags_t flags) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - gsl_device_t *device; - gsl_hal_t *hal = (gsl_hal_t *)gsl_driver.hal; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_start(gsl_deviceid_t device_id=%D, gsl_flags_t flags=%d)\n", device_id, flags ); - - GSL_API_MUTEX_LOCK(); - - if ((GSL_DEVICE_G12 == device_id) && !(hal->has_z160)) { - GSL_API_MUTEX_UNLOCK(); - return GSL_FAILURE_NOTSUPPORTED; - } - - if ((GSL_DEVICE_YAMATO == device_id) && !(hal->has_z430)) { - GSL_API_MUTEX_UNLOCK(); - return GSL_FAILURE_NOTSUPPORTED; - } - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - kgsl_device_active(device); - - if (!(device->flags & GSL_FLAGS_INITIALIZED)) - { - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_ERROR, "ERROR: Trying to start uninitialized device.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_start. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - device->refcnt++; - - if (device->flags & GSL_FLAGS_STARTED) - { - GSL_API_MUTEX_UNLOCK(); - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_start. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); - } - - // start device in safe mode - if (flags & GSL_FLAGS_SAFEMODE) - { - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_INFO, "Running the device in safe mode.\n" ); - device->flags |= GSL_FLAGS_SAFEMODE; - } - - if (device->ftbl.device_start) - { - status = device->ftbl.device_start(device, flags); - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_start. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_stop(gsl_deviceid_t device_id) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - gsl_device_t *device; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_stop(gsl_deviceid_t device_id=%D)\n", device_id ); - - GSL_API_MUTEX_LOCK(); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - if (device->flags & GSL_FLAGS_STARTED) - { - KOS_ASSERT(device->refcnt); - - device->refcnt--; - - if (device->refcnt == 0) - { - if (device->ftbl.device_stop) - { - status = device->ftbl.device_stop(device); - } - } - else - { - status = GSL_SUCCESS; - } - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_stop. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_idle(gsl_deviceid_t device_id, unsigned int timeout) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - gsl_device_t *device; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_idle(gsl_deviceid_t device_id=%D, unsigned int timeout=%d)\n", device_id, timeout ); - - GSL_API_MUTEX_LOCK(); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - kgsl_device_active(device); - - if (device->ftbl.device_idle) - { - status = device->ftbl.device_idle(device, timeout); - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_idle. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_isidle(gsl_deviceid_t device_id) -{ - gsl_timestamp_t retired = kgsl_cmdstream_readtimestamp0(device_id, GSL_TIMESTAMP_RETIRED); - gsl_timestamp_t consumed = kgsl_cmdstream_readtimestamp0(device_id, GSL_TIMESTAMP_CONSUMED); - gsl_timestamp_t ts_diff = retired - consumed; - return (ts_diff >= 0) || (ts_diff < -GSL_TIMESTAMP_EPSILON) ? GSL_SUCCESS : GSL_FAILURE; -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_regread(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int *value) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - gsl_device_t *device; - - -#ifdef GSL_LOG - if( offsetwords != mmRBBM_STATUS && offsetwords != mmCP_RB_RPTR ) // Would otherwise flood the log - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_regread(gsl_deviceid_t device_id=%D, unsigned int offsetwords=%R, unsigned int *value=0x%08x)\n", device_id, offsetwords, value ); -#endif - - GSL_API_MUTEX_LOCK(); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - KOS_ASSERT(value); - KOS_ASSERT(offsetwords < device->regspace.sizebytes); - - if (device->ftbl.device_regread) - { - status = device->ftbl.device_regread(device, offsetwords, value); - } - - GSL_API_MUTEX_UNLOCK(); - -#ifdef GSL_LOG - if( offsetwords != mmRBBM_STATUS && offsetwords != mmCP_RB_RPTR ) - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_regread. Return value %B\n", status ); -#endif - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_regwrite(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int value) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - gsl_device_t *device; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_regwrite(gsl_deviceid_t device_id=%D, unsigned int offsetwords=%R, unsigned int value=0x%08x)\n", device_id, offsetwords, value ); - - GSL_API_MUTEX_LOCK(); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - KOS_ASSERT(offsetwords < device->regspace.sizebytes); - - if (device->ftbl.device_regwrite) - { - status = device->ftbl.device_regwrite(device, offsetwords, value); - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_regwrite. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_device_waitirq(gsl_deviceid_t device_id, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - gsl_device_t *device; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_waitirq(gsl_deviceid_t device_id=%D, gsl_intrid_t intr_id=%d, unsigned int *count=0x%08x, unsigned int timout=0x%08x)\n", device_id, intr_id, count, timeout); - - GSL_API_MUTEX_LOCK(); - - device = &gsl_driver.device[device_id-1]; // device_id is 1 based - - if (device->ftbl.device_waitirq) - { - status = device->ftbl.device_waitirq(device, intr_id, count, timeout); - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_waitirq. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_device_runpending(gsl_device_t *device) -{ - int status = GSL_FAILURE_NOTINITIALIZED; - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_device_runpending(gsl_device_t *device=0x%08x )\n", device ); - - if (device->flags & GSL_FLAGS_INITIALIZED) - { - if (device->ftbl.device_runpending) - { - status = device->ftbl.device_runpending(device); - } - } - - // free any pending freeontimestamps - kgsl_cmdstream_memqueue_drain(device); - - kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_runpending. Return value %B\n", status ); - - return (status); -} - diff --git a/drivers/mxc/amd-gpu/common/gsl_drawctxt.c b/drivers/mxc/amd-gpu/common/gsl_drawctxt.c deleted file mode 100644 index 1e8fa1a4962..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_drawctxt.c +++ /dev/null @@ -1,1828 +0,0 @@ -/* Copyright (c) 2002,2007-2009, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#ifdef _LINUX -#include -#endif - -#ifdef GSL_BLD_YAMATO - -////////////////////////////////////////////////////////////////////////////// -// -// Memory Map for Register, Constant & Instruction Shadow, and Command Buffers (34.5KB) -// -// +---------------------+------------+-------------+---+---------------------+ -// | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow | -// +---------------------+------------+-------------+---+---------------------+ -// ________________________________' '___________________ -// ' ' -// +--------------+-----------+------+-----------+------------------------+ -// | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused | -// +--------------+-----------+------+-----------+------------------------+ -// -// 8K - ALU Constant Shadow (8K aligned) -// 4K - H/W Register Shadow (8K aligned) -// 9K - Command and Vertex Buffers -// - Indirect command buffer : Const/Reg restore -// - includes Loop & Bool const shadows -// - Indirect command buffer : Const/Reg save -// - Quad vertices & texture coordinates -// - Indirect command buffer : Gmem save -// - Indirect command buffer : Gmem restore -// - Unused (padding to 8KB boundary) -// <1K - Texture Constant Shadow (768 bytes) (8K aligned) -// 18K - Shader Instruction Shadow -// - 6K vertex (32 byte aligned) -// - 6K pixel (32 byte aligned) -// - 6K shared (32 byte aligned) -// -// Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes -// 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of -// 16 bytes per constant. If the texture constants were transfered this way, -// the Command & Vertex Buffers section would extend past the 16K boundary. -// By moving the texture constant shadow area to start at 16KB boundary, we -// only require approximately 40 bytes more memory, but are able to use the -// LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up -// context switching. -// -// [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool -// constants would require an additional 8KB each, for alignment.] -// -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// Constants -////////////////////////////////////////////////////////////////////////////// - -#define ALU_CONSTANTS 2048 // DWORDS -#define NUM_REGISTERS 1024 // DWORDS -#ifdef DISABLE_SHADOW_WRITES - #define CMD_BUFFER_LEN 9216 // DWORDS -#else - #define CMD_BUFFER_LEN 3072 // DWORDS -#endif -#define TEX_CONSTANTS (32*6) // DWORDS -#define BOOL_CONSTANTS 8 // DWORDS -#define LOOP_CONSTANTS 56 // DWORDS -#define SHADER_INSTRUCT_LOG2 9U // 2^n == SHADER_INSTRUCTIONS - -#if defined(PM4_IM_STORE) -#define SHADER_INSTRUCT (1<drawctxt_mutex = kos_mutex_create("gsl_drawctxt"); \ - if (!device->drawctxt_mutex) {return (GSL_FAILURE);} -#define GSL_CONTEXT_MUTEX_LOCK() kos_mutex_lock(device->drawctxt_mutex) -#define GSL_CONTEXT_MUTEX_UNLOCK() kos_mutex_unlock(device->drawctxt_mutex) -#define GSL_CONTEXT_MUTEX_FREE() kos_mutex_free(device->drawctxt_mutex); device->drawctxt_mutex = 0; -#else -#define GSL_CONTEXT_MUTEX_CREATE() -#define GSL_CONTEXT_MUTEX_LOCK() -#define GSL_CONTEXT_MUTEX_UNLOCK() -#define GSL_CONTEXT_MUTEX_FREE() -#endif - - -////////////////////////////////////////////////////////////////////////////// -// temporary work structure -////////////////////////////////////////////////////////////////////////////// - -typedef struct -{ - unsigned int *start; // Command & Vertex buffer start - unsigned int *cmd; // Next available dword in C&V buffer - - // address of buffers, needed when creating IB1 command buffers. - gpuaddr_t bool_shadow; // Address where bool constants are shadowed - gpuaddr_t loop_shadow; // Address where loop constants are shadowed - -#if defined(PM4_IM_STORE) - gpuaddr_t shader_shared; // Address of shared shader instruction shadow - gpuaddr_t shader_vertex; // Address of vertex shader instruction shadow - gpuaddr_t shader_pixel; // Address of pixel shader instruction shadow -#endif - - gpuaddr_t reg_values[2]; // Addresses in command buffer where separately handled registers are saved - gpuaddr_t chicken_restore;// Address where the TP0_CHICKEN register value is written - gpuaddr_t gmem_base; // Base gpu address of GMEM -} -ctx_t; - -////////////////////////////////////////////////////////////////////////////// -// Helper function to calculate IEEE754 single precision float values without FPU -////////////////////////////////////////////////////////////////////////////// -unsigned int uint2float( unsigned int uintval ) -{ - unsigned int exp = 0; - unsigned int frac = 0; - unsigned int u = uintval; - - // Handle zero separately - if( uintval == 0 ) return 0; - - // Find log2 of u - if(u>=0x10000) { exp+=16; u>>=16; } - if(u>=0x100 ) { exp+=8; u>>=8; } - if(u>=0x10 ) { exp+=4; u>>=4; } - if(u>=0x4 ) { exp+=2; u>>=2; } - if(u>=0x2 ) { exp+=1; u>>=1; } - - // Calculate fraction - frac = ( uintval & ( ~( 1 << exp ) ) ) << ( 23 - exp ); - - // Exp is biased by 127 and shifted 23 bits - exp = ( exp + 127 ) << 23; - - return ( exp | frac ); -} - -////////////////////////////////////////////////////////////////////////////// -// Helper function to divide two unsigned ints and return the result as a floating point value -////////////////////////////////////////////////////////////////////////////// -unsigned int uintdivide(unsigned int a, unsigned int b) -{ -#ifdef _LINUX - uint64_t a_fixed = a << 16; - uint64_t b_fixed = b << 16; -#else - unsigned int a_fixed = a << 16; - unsigned int b_fixed = b << 16; -#endif - // Assume the result is 0.fraction - unsigned int fraction; - unsigned int exp = 126; - - if( b == 0 ) return 0; - -#ifdef _LINUX - a_fixed = a_fixed << 32; - do_div(a_fixed, b_fixed); - fraction = (unsigned int)a_fixed; -#else - fraction = ((unsigned int)((((__int64)a_fixed) << 32) / (__int64)b_fixed)); -#endif - - if( fraction == 0 ) return 0; - - // Normalize - while( !(fraction & (1<<31)) ) - { - fraction <<= 1; - exp--; - } - // Remove hidden bit - fraction <<= 1; - - // Round - if( ( fraction & 0x1ff ) > 256 ) - { - int rounded = 0; - int i = 9; - - // Do the bit addition - while( !rounded ) - { - if( fraction & (1<>= 9; - - return ( ( exp << 23 ) | fraction ); -} - - - -////////////////////////////////////////////////////////////////////////////// -// context save (gmem -> sys) -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// pre-compiled vertex shader program -// -// attribute vec4 P; -// void main(void) -// { -// gl_Position = P; -// } -// -////////////////////////////////////////////////////////////////////////////// - -#define GMEM2SYS_VTX_PGM_LEN 0x12 - -static const unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = { - 0x00011003, 0x00001000, 0xc2000000, - 0x00001004, 0x00001000, 0xc4000000, - 0x00001005, 0x00002000, 0x00000000, - 0x1cb81000, 0x00398a88, 0x00000003, - 0x140f803e, 0x00000000, 0xe2010100, - 0x14000000, 0x00000000, 0xe2000000 -}; - - -////////////////////////////////////////////////////////////////////////////// -// pre-compiled fragment shader program -// -// precision highp float; -// uniform vec4 clear_color; -// void main(void) -// { -// gl_FragColor = clear_color; -// } -// -////////////////////////////////////////////////////////////////////////////// - -#define GMEM2SYS_FRAG_PGM_LEN 0x0c - -static const unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = { - 0x00000000, 0x1002c400, 0x10000000, - 0x00001003, 0x00002000, 0x00000000, - 0x140f8000, 0x00000000, 0x22000000, - 0x14000000, 0x00000000, 0xe2000000 -}; - - -////////////////////////////////////////////////////////////////////////////// -// context restore (sys -> gmem) -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// pre-compiled vertex shader program -// -// attribute vec4 position; -// attribute vec4 texcoord; -// varying vec4 texcoord0; -// void main() -// { -// gl_Position = position; -// texcoord0 = texcoord; -// } -// -////////////////////////////////////////////////////////////////////////////// - -#define SYS2GMEM_VTX_PGM_LEN 0x18 - -static const unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = { - 0x00052003, 0x00001000, 0xc2000000, 0x00001005, - 0x00001000, 0xc4000000, 0x00001006, 0x10071000, - 0x20000000, 0x18981000, 0x0039ba88, 0x00000003, - 0x12982000, 0x40257b08, 0x00000002, 0x140f803e, - 0x00000000, 0xe2010100, 0x140f8000, 0x00000000, - 0xe2020200, 0x14000000, 0x00000000, 0xe2000000 -}; - - -////////////////////////////////////////////////////////////////////////////// -// pre-compiled fragment shader program -// -// precision mediump float; -// uniform sampler2D tex0; -// varying vec4 texcoord0; -// void main() -// { -// gl_FragColor = texture2D(tex0, texcoord0.xy); -// } -// -////////////////////////////////////////////////////////////////////////////// - -#define SYS2GMEM_FRAG_PGM_LEN 0x0f - -static const unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = { - 0x00011002, 0x00001000, 0xc4000000, 0x00001003, - 0x10041000, 0x20000000, 0x10000001, 0x1ffff688, - 0x00000002, 0x140f8000, 0x00000000, 0xe2000000, - 0x14000000, 0x00000000, 0xe2000000 -}; - - -////////////////////////////////////////////////////////////////////////////// -// shader texture constants (sysmem -> gmem) -////////////////////////////////////////////////////////////////////////////// - -#define SYS2GMEM_TEX_CONST_LEN 6 - -static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = -{ - // Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,RFMode=ZeroClamp-1,Dim=1:2d - 0x00000002, // Pitch = TBD - - // Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0, NearestClamp=1:OGL Mode - 0x00000806, // Address[31:12] = TBD - - // Width, Height, EndianSwap=0:None - 0, // Width & Height = TBD - - // NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point, Mip=2:BaseMap - 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23, - - // VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0, Dim3d=0 - 0, - - // BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0, Dim=1:2d, MipPacking=0 - 1 << 9 // Mip Address[31:12] = TBD -}; - - -////////////////////////////////////////////////////////////////////////////// -// quad for copying GMEM to context shadow -////////////////////////////////////////////////////////////////////////////// - -#define QUAD_LEN 12 - -static unsigned int gmem_copy_quad[QUAD_LEN] = { - 0x00000000, 0x00000000, 0x3f800000, - 0x00000000, 0x00000000, 0x3f800000, - 0x00000000, 0x00000000, 0x3f800000, - 0x00000000, 0x00000000, 0x3f800000 -}; - -#define TEXCOORD_LEN 8 - -static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = { - 0x00000000, 0x3f800000, - 0x3f800000, 0x3f800000, - 0x00000000, 0x00000000, - 0x3f800000, 0x00000000 -}; - -#define NUM_COLOR_FORMATS 13 - -static SurfaceFormat surface_format_table[NUM_COLOR_FORMATS] = -{ - FMT_4_4_4_4, // COLORX_4_4_4_4 - FMT_1_5_5_5, // COLORX_1_5_5_5 - FMT_5_6_5, // COLORX_5_6_5 - FMT_8, // COLORX_8 - FMT_8_8, // COLORX_8_8 - FMT_8_8_8_8, // COLORX_8_8_8_8 - FMT_8_8_8_8, // COLORX_S8_8_8_8 - FMT_16_FLOAT, // COLORX_16_FLOAT - FMT_16_16_FLOAT, // COLORX_16_16_FLOAT - FMT_16_16_16_16_FLOAT, // COLORX_16_16_16_16_FLOAT - FMT_32_FLOAT, // COLORX_32_FLOAT - FMT_32_32_FLOAT, // COLORX_32_32_FLOAT - FMT_32_32_32_32_FLOAT, // COLORX_32_32_32_32_FLOAT -}; - -static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = -{ - 2, // COLORX_4_4_4_4 - 2, // COLORX_1_5_5_5 - 2, // COLORX_5_6_5 - 1, // COLORX_8 - 2, // COLORX_8_8_8 - 4, // COLORX_8_8_8_8 - 4, // COLORX_S8_8_8_8 - 2, // COLORX_16_FLOAT - 4, // COLORX_16_16_FLOAT - 8, // COLORX_16_16_16_16_FLOAT - 4, // COLORX_32_FLOAT - 8, // COLORX_32_32_FLOAT - 16, // COLORX_32_32_32_32_FLOAT -}; - -////////////////////////////////////////////////////////////////////////////// -// shader linkage info -////////////////////////////////////////////////////////////////////////////// - -#define SHADER_CONST_ADDR (11 * 6 + 3) - - -////////////////////////////////////////////////////////////////////////////// -// gmem command buffer length -////////////////////////////////////////////////////////////////////////////// - -#define PM4_REG(reg) ((0x4 << 16) | (GSL_HAL_SUBBLOCK_OFFSET(reg))) - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -static void -config_gmemsize(gmem_shadow_t *shadow, int gmem_size) -{ - int w=64, h=64; // 16KB surface, minimum - - // convert from bytes to 32-bit words - gmem_size = (gmem_size + 3)/4; - - // find the right surface size, close to a square. - while (w * h < gmem_size) - if (w < h) - w *= 2; - else - h *= 2; - - shadow->width = w; - shadow->height = h; - shadow->pitch = w; - shadow->format = COLORX_8_8_8_8; - shadow->size = shadow->pitch * shadow->height * 4; - - shadow->gmem_width = w; - shadow->gmem_height = h; - shadow->gmem_pitch = w; -} - - -////////////////////////////////////////////////////////////////////////////// - -static unsigned int -gpuaddr(unsigned int *cmd, gsl_memdesc_t *memdesc) -{ - return memdesc->gpuaddr + ((char *)cmd - (char *)memdesc->hostptr); -} - - -////////////////////////////////////////////////////////////////////////////// - -static void -create_ib1(gsl_drawctxt_t *drawctxt, unsigned int *cmd, unsigned int *start, unsigned int *end) -{ - cmd[0] = PM4_HDR_INDIRECT_BUFFER_PFD; - cmd[1] = gpuaddr(start, &drawctxt->gpustate); - cmd[2] = end - start; -} - - -////////////////////////////////////////////////////////////////////////////// - -static unsigned int * -program_shader(unsigned int *cmds, int vtxfrag, const unsigned int *shader_pgm, int dwords) -{ - // load the patched vertex shader stream - *cmds++ = pm4_type3_packet(PM4_IM_LOAD_IMMEDIATE, 2 + dwords); - *cmds++ = vtxfrag; // 0=vertex shader, 1=fragment shader - *cmds++ = ( (0 << 16) | dwords ); // instruction start & size (in 32-bit words) - - kos_memcpy(cmds, shader_pgm, dwords<<2); - cmds += dwords; - - return cmds; -} - - -////////////////////////////////////////////////////////////////////////////// - -static unsigned int * -reg_to_mem(unsigned int *cmds, gpuaddr_t dst, gpuaddr_t src, int dwords) -{ - while (dwords-- > 0) - { - *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmds++ = src++; - *cmds++ = dst; - dst += 4; - } - - return cmds; -} - - - -#ifdef DISABLE_SHADOW_WRITES - -static void build_reg_to_mem_range(unsigned int start, unsigned int end, unsigned int** cmd, gsl_drawctxt_t *drawctxt) -{ - unsigned int i = start; - - for(i=start; i<=end; i++) - { - *(*cmd)++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *(*cmd)++ = i | (1<<30); - *(*cmd)++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) + (i-0x2000)*4; - } -} - -#endif - -////////////////////////////////////////////////////////////////////////////// -// chicken restore -////////////////////////////////////////////////////////////////////////////// -static unsigned int* -build_chicken_restore_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) -{ - unsigned int *start = ctx->cmd; - unsigned int *cmds = start; - - *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *cmds++ = 0; - - *cmds++ = pm4_type0_packet(mmTP0_CHICKEN, 1); - ctx->chicken_restore = gpuaddr(cmds, &drawctxt->gpustate); - *cmds++ = 0x00000000; - - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds); - - return cmds; -} - - - -////////////////////////////////////////////////////////////////////////////// -// context save -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// save h/w regs, alu constants, texture contants, etc. ... -// requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr -////////////////////////////////////////////////////////////////////////////// - -static void -build_regsave_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) -{ - unsigned int *start = ctx->cmd; - unsigned int *cmd = start; - -#ifdef DISABLE_SHADOW_WRITES - // Write HW registers into shadow - build_reg_to_mem_range(mmRB_SURFACE_INFO, mmRB_DEPTH_INFO, &cmd, drawctxt); - build_reg_to_mem_range(mmCOHER_DEST_BASE_0, mmPA_SC_SCREEN_SCISSOR_BR, &cmd, drawctxt); - build_reg_to_mem_range(mmPA_SC_WINDOW_OFFSET, mmPA_SC_WINDOW_SCISSOR_BR, &cmd, drawctxt); - build_reg_to_mem_range(mmVGT_MAX_VTX_INDX, mmRB_FOG_COLOR, &cmd, drawctxt); - build_reg_to_mem_range(mmRB_STENCILREFMASK_BF, mmPA_CL_VPORT_ZOFFSET, &cmd, drawctxt); - build_reg_to_mem_range(mmSQ_PROGRAM_CNTL, mmSQ_WRAPPING_1, &cmd, drawctxt); - build_reg_to_mem_range(mmRB_DEPTHCONTROL, mmRB_MODECONTROL, &cmd, drawctxt); - build_reg_to_mem_range(mmPA_SU_POINT_SIZE, mmPA_SC_LINE_STIPPLE, &cmd, drawctxt); - build_reg_to_mem_range(mmPA_SC_VIZ_QUERY, mmPA_SC_VIZ_QUERY, &cmd, drawctxt); - build_reg_to_mem_range(mmPA_SC_LINE_CNTL, mmSQ_PS_CONST, &cmd, drawctxt); - build_reg_to_mem_range(mmPA_SC_AA_MASK, mmPA_SC_AA_MASK, &cmd, drawctxt); - build_reg_to_mem_range(mmVGT_VERTEX_REUSE_BLOCK_CNTL, mmRB_DEPTH_CLEAR, &cmd, drawctxt); - build_reg_to_mem_range(mmRB_SAMPLE_COUNT_CTL, mmRB_COLOR_DEST_MASK, &cmd, drawctxt); - build_reg_to_mem_range(mmPA_SU_POLY_OFFSET_FRONT_SCALE, mmPA_SU_POLY_OFFSET_BACK_OFFSET, &cmd, drawctxt); - - // Copy ALU constants - cmd = reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000, mmSQ_CONSTANT_0, ALU_CONSTANTS); - - // Copy Tex constants - cmd = reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000, mmSQ_FETCH_0, TEX_CONSTANTS); -#else - // H/w registers are already shadowed; just need to disable shadowing to prevent corruption. - *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); - *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000; - *cmd++ = 4 << 16; // regs, start=0 - *cmd++ = 0x0; // count = 0 - - // ALU constants are already shadowed; just need to disable shadowing to prevent corruption. - *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); - *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000; - *cmd++ = 0 << 16; // ALU, start=0 - *cmd++ = 0x0; // count = 0 - - // Tex constants are already shadowed; just need to disable shadowing to prevent corruption. - *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); - *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000; - *cmd++ = 1 << 16; // Tex, start=0 - *cmd++ = 0x0; // count = 0 -#endif - - - - - // Need to handle some of the registers separately - *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmd++ = mmSQ_GPR_MANAGEMENT; - *cmd++ = ctx->reg_values[0]; - *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmd++ = mmTP0_CHICKEN; - *cmd++ = ctx->reg_values[1]; - - // Copy Boolean constants - cmd = reg_to_mem(cmd, ctx->bool_shadow, mmSQ_CF_BOOLEANS, BOOL_CONSTANTS); - - // Copy Loop constants - cmd = reg_to_mem(cmd, ctx->loop_shadow, mmSQ_CF_LOOP, LOOP_CONSTANTS); - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, drawctxt->reg_save, start, cmd); - - ctx->cmd = cmd; -} - - -////////////////////////////////////////////////////////////////////////////// -// copy colour, depth, & stencil buffers from graphics memory to system memory -////////////////////////////////////////////////////////////////////////////// - -static unsigned int* -build_gmem2sys_cmds(gsl_drawctxt_t *drawctxt, ctx_t* ctx, gmem_shadow_t *shadow) -{ - unsigned int *cmds = shadow->gmem_save_commands; - unsigned int *start = cmds; - - // Store TP0_CHICKEN register - *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmds++ = mmTP0_CHICKEN; - if( ctx ) - *cmds++ = ctx->chicken_restore; - else - cmds++; - - *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *cmds++ = 0; - - // Set TP0_CHICKEN to zero - *cmds++ = pm4_type0_packet(mmTP0_CHICKEN, 1); - *cmds++ = 0x00000000; - - // -------------- - // program shader - // -------------- - - // load shader vtx constants ... 5 dwords - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4); - *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR; - *cmds++ = 0; - *cmds++ = shadow->quad_vertices.gpuaddr | 0x3; // valid(?) vtx constant flag & addr - *cmds++ = 0x00000030; // limit = 12 dwords - - // Invalidate L2 cache to make sure vertices are updated - *cmds++ = pm4_type0_packet(mmTC_CNTL_STATUS, 1); - *cmds++ = 0x1; - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4); - *cmds++ = PM4_REG(mmVGT_MAX_VTX_INDX); - *cmds++ = 0x00ffffff; //mmVGT_MAX_VTX_INDX - *cmds++ = 0x0; //mmVGT_MIN_VTX_INDX - *cmds++ = 0x00000000; //mmVGT_INDX_OFFSET - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_SC_AA_MASK); - *cmds++ = 0x0000ffff; //mmPA_SC_AA_MASK - - - // load the patched vertex shader stream - cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN); - - // Load the patched fragment shader stream - cmds = program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN); - - // SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmSQ_PROGRAM_CNTL); - *cmds++ = 0x10010001; - *cmds++ = 0x00000008; - - - // -------------- - // resolve - // -------------- - - // PA_CL_VTE_CNTL - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_CL_VTE_CNTL); - *cmds++ = 0x00000b00; // disable X/Y/Z transforms, X/Y/Z are premultiplied by W - - // change colour buffer to RGBA8888, MSAA = 1, and matching pitch - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmRB_SURFACE_INFO); - *cmds++ = shadow->gmem_pitch; - - // RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0, Base=gmem_base - if( ctx ) - { - KOS_ASSERT((ctx->gmem_base & 0xFFF) == 0); // gmem base assumed 4K aligned. - *cmds++ = (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | ctx->gmem_base; - } - else - { - unsigned int temp = *cmds; - *cmds++ = (temp & ~RB_COLOR_INFO__COLOR_FORMAT_MASK) | (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT); - } - - // disable Z - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_DEPTHCONTROL); - *cmds++ = 0; - - // set mmPA_SU_SC_MODE_CNTL - // Front_ptype = draw triangles - // Back_ptype = draw triangles - // Provoking vertex = last - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_SU_SC_MODE_CNTL); - *cmds++ = 0x00080240; - - // set the scissor to the extents of the draw surface - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmPA_SC_SCREEN_SCISSOR_TL); - *cmds++ = (shadow->gmem_offset_y << 16) | shadow->gmem_offset_x; - *cmds++ = (shadow->gmem_height << 16) | shadow->gmem_width; - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmPA_SC_WINDOW_SCISSOR_TL); - *cmds++ = (1U << 31) | (0 << 16) | 0; - *cmds++ = (shadow->height << 16) | shadow->width; - - // load the viewport so that z scale = clear depth and z offset = 0.0f - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmPA_CL_VPORT_ZSCALE); - *cmds++ = 0xbf800000; // -1.0f - *cmds++ = 0x0; - - // load the COPY state - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 6); - *cmds++ = PM4_REG(mmRB_COPY_CONTROL); - *cmds++ = 0; // RB_COPY_CONTROL - - { - // Calculate the new offset based on the adjusted base - unsigned int bytesperpixel = format2bytesperpixel[shadow->format]; - unsigned int addr = (shadow->gmemshadow.gpuaddr + shadow->offset * bytesperpixel); - unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel; - - *cmds++ = addr & 0xfffff000; // RB_COPY_DEST_BASE - *cmds++ = shadow->pitch >> 5; // RB_COPY_DEST_PITCH - *cmds++ = 0x0003c008 | (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT); // Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,MaskWrite:R=G=B=A=1 - - KOS_ASSERT( (offset & 0xfffff000) == 0 ); // Make sure we stay in offsetx field. - *cmds++ = offset; - } - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_MODECONTROL); - *cmds++ = 0x6; // EDRAM copy - - // queue the draw packet - *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2); - *cmds++ = 0; // viz query info. - *cmds++ = 0x00030088; // PrimType=RectList, NumIndices=3, SrcSel=AutoIndex - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, shadow->gmem_save, start, cmds); - - return cmds; -} - - -////////////////////////////////////////////////////////////////////////////// -// context restore -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// copy colour, depth, & stencil buffers from system memory to graphics memory -////////////////////////////////////////////////////////////////////////////// - -static unsigned int* -build_sys2gmem_cmds(gsl_drawctxt_t *drawctxt, ctx_t* ctx, gmem_shadow_t *shadow) -{ - unsigned int *cmds = shadow->gmem_restore_commands; - unsigned int *start = cmds; - - // Store TP0_CHICKEN register - *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmds++ = mmTP0_CHICKEN; - if( ctx ) - *cmds++ = ctx->chicken_restore; - else - cmds++; - - *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *cmds++ = 0; - - // Set TP0_CHICKEN to zero - *cmds++ = pm4_type0_packet(mmTP0_CHICKEN, 1); - *cmds++ = 0x00000000; - - // ---------------- - // shader constants - // ---------------- - - // vertex buffer constants - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 7); - - *cmds++ = (0x1 << 16) | (9 * 6); - *cmds++ = shadow->quad_vertices.gpuaddr | 0x3; // valid(?) vtx constant flag & addr - *cmds++ = 0x00000030; // limit = 12 dwords - *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3; // valid(?) vtx constant flag & addr - *cmds++ = 0x00000020; // limit = 8 dwords - *cmds++ = 0; - *cmds++ = 0; - - // Invalidate L2 cache to make sure vertices and texture coordinates are updated - *cmds++ = pm4_type0_packet(mmTC_CNTL_STATUS, 1); - *cmds++ = 0x1; - - // load the patched vertex shader stream - cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN); - - // Load the patched fragment shader stream - cmds = program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN); - - // SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmSQ_PROGRAM_CNTL); - *cmds++ = 0x10030002; - *cmds++ = 0x00000008; - - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_SC_AA_MASK); - *cmds++ = 0x0000ffff; //mmPA_SC_AA_MASK - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_SC_VIZ_QUERY); - *cmds++ = 0x0; //mmPA_SC_VIZ_QUERY - - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_COLORCONTROL); - *cmds++ = 0x00000c20; // RB_COLORCONTROL - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4); - *cmds++ = PM4_REG(mmVGT_MAX_VTX_INDX); - *cmds++ = 0x00ffffff; //mmVGT_MAX_VTX_INDX - *cmds++ = 0x0; //mmVGT_MIN_VTX_INDX - *cmds++ = 0x00000000; //mmVGT_INDX_OFFSET - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmVGT_VERTEX_REUSE_BLOCK_CNTL); - *cmds++ = 0x00000002; //mmVGT_VERTEX_REUSE_BLOCK_CNTL - *cmds++ = 0x00000002; //mmVGT_OUT_DEALLOC_CNTL - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmSQ_INTERPOLATOR_CNTL); - *cmds++ = 0xffffffff; //mmSQ_INTERPOLATOR_CNTL - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_SC_AA_CONFIG); - *cmds++ = 0x00000000; //mmPA_SC_AA_CONFIG - - - // set mmPA_SU_SC_MODE_CNTL - // Front_ptype = draw triangles - // Back_ptype = draw triangles - // Provoking vertex = last - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_SU_SC_MODE_CNTL); - *cmds++ = 0x00080240; - - // texture constants - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1)); - *cmds++ = (0x1 << 16) | (0 * 6); - kos_memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN<<2); - cmds[0] |= (shadow->pitch >> 5) << 22; - cmds[1] |= shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format]; - cmds[2] |= (shadow->width+shadow->offset_x-1) | (shadow->height+shadow->offset_y-1) << 13; - cmds += SYS2GMEM_TEX_CONST_LEN; - - // change colour buffer to RGBA8888, MSAA = 1, and matching pitch - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmRB_SURFACE_INFO); - *cmds++ = shadow->gmem_pitch; // GMEM pitch is equal to context GMEM shadow pitch - - // RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0, Base=gmem_base - if( ctx ) - { - *cmds++ = (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | ctx->gmem_base; - } - else - { - unsigned int temp = *cmds; - *cmds++ = (temp & ~RB_COLOR_INFO__COLOR_FORMAT_MASK) | (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT); - } - - // RB_DEPTHCONTROL - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_DEPTHCONTROL); - *cmds++ = 0; // disable Z - - // set the scissor to the extents of the draw surface - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmPA_SC_SCREEN_SCISSOR_TL); - *cmds++ = (0 << 16) | 0; - *cmds++ = (shadow->height << 16) | shadow->width; - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmPA_SC_WINDOW_SCISSOR_TL); - *cmds++ = (1U << 31) | (shadow->gmem_offset_y << 16) | shadow->gmem_offset_x; - *cmds++ = (shadow->gmem_height << 16) | shadow->gmem_width; - - // PA_CL_VTE_CNTL - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmPA_CL_VTE_CNTL); - *cmds++ = 0x00000b00; // disable X/Y/Z transforms, X/Y/Z are premultiplied by W - - // load the viewport so that z scale = clear depth and z offset = 0.0f - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmPA_CL_VPORT_ZSCALE); - *cmds++ = 0xbf800000; - *cmds++ = 0x0; - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_COLOR_MASK); - *cmds++ = 0x0000000f; // R = G = B = 1:enabled - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_COLOR_DEST_MASK); - *cmds++ = 0xffffffff; - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); - *cmds++ = PM4_REG(mmSQ_WRAPPING_0); - *cmds++ = 0x00000000; - *cmds++ = 0x00000000; - - *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); - *cmds++ = PM4_REG(mmRB_MODECONTROL); - *cmds++ = 0x4; // draw pixels with color and depth/stencil component - - // queue the draw packet - *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2); - *cmds++ = 0; // viz query info. - *cmds++ = 0x00030088; // PrimType=RectList, NumIndices=3, SrcSel=AutoIndex - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, shadow->gmem_restore, start, cmds); - - return cmds; -} - - -////////////////////////////////////////////////////////////////////////////// -// restore h/w regs, alu constants, texture constants, etc. ... -////////////////////////////////////////////////////////////////////////////// - -static unsigned * -reg_range(unsigned int *cmd, unsigned int start, unsigned int end) -{ - *cmd++ = PM4_REG(start); // h/w regs, start addr - *cmd++ = end - start + 1; // count - return cmd; -} - - -////////////////////////////////////////////////////////////////////////////// - -static void -build_regrestore_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) -{ - unsigned int *start = ctx->cmd; - unsigned int *cmd = start; - - // H/W Registers - cmd++; // deferred pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, ???); -#ifdef DISABLE_SHADOW_WRITES - *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1; // Force mismatch -#else - *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000; -#endif - - cmd = reg_range(cmd, mmRB_SURFACE_INFO, mmPA_SC_SCREEN_SCISSOR_BR); - cmd = reg_range(cmd, mmPA_SC_WINDOW_OFFSET, mmPA_SC_WINDOW_SCISSOR_BR); - cmd = reg_range(cmd, mmVGT_MAX_VTX_INDX, mmPA_CL_VPORT_ZOFFSET); - cmd = reg_range(cmd, mmSQ_PROGRAM_CNTL, mmSQ_WRAPPING_1); - cmd = reg_range(cmd, mmRB_DEPTHCONTROL, mmRB_MODECONTROL); - cmd = reg_range(cmd, mmPA_SU_POINT_SIZE, mmPA_SC_VIZ_QUERY); - cmd = reg_range(cmd, mmPA_SC_LINE_CNTL, mmRB_COLOR_DEST_MASK); - cmd = reg_range(cmd, mmPA_SU_POLY_OFFSET_FRONT_SCALE, mmPA_SU_POLY_OFFSET_BACK_OFFSET); - - // Now we know how many register blocks we have, we can compute command length - start[0] = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, (cmd-start)-1); -#ifdef DISABLE_SHADOW_WRITES - start[2] |= (0<<24) | (4 << 16); // Disable shadowing. -#else - start[2] |= (1<<24) | (4 << 16); // Enable shadowing for the entire register block. -#endif - - // Need to handle some of the registers separately - *cmd++ = pm4_type0_packet(mmSQ_GPR_MANAGEMENT, 1); - ctx->reg_values[0] = gpuaddr(cmd, &drawctxt->gpustate); - *cmd++ = 0x00040400; - - *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *cmd++ = 0; - *cmd++ = pm4_type0_packet(mmTP0_CHICKEN, 1); - ctx->reg_values[1] = gpuaddr(cmd, &drawctxt->gpustate); - *cmd++ = 0x00000000; - - // ALU Constants - *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); - *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000; -#ifdef DISABLE_SHADOW_WRITES - *cmd++ = (0<<24) | (0<<16) | 0; // Disable shadowing -#else - *cmd++ = (1<<24) | (0<<16) | 0; -#endif - *cmd++ = ALU_CONSTANTS; - - - // Texture Constants - *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); - *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000; -#ifdef DISABLE_SHADOW_WRITES - *cmd++ = (0<<24) | (1<<16) | 0; // Disable shadowing -#else - *cmd++ = (1<<24) | (1<<16) | 0; -#endif - *cmd++ = TEX_CONSTANTS; - - - // Boolean Constants - *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + BOOL_CONSTANTS); - *cmd++ = (2<<16) | 0; - - // the next BOOL_CONSTANT dwords is the shadow area for boolean constants. - ctx->bool_shadow = gpuaddr(cmd, &drawctxt->gpustate); - cmd += BOOL_CONSTANTS; - - - // Loop Constants - *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + LOOP_CONSTANTS); - *cmd++ = (3<<16) | 0; - - // the next LOOP_CONSTANTS dwords is the shadow area for loop constants. - ctx->loop_shadow = gpuaddr(cmd, &drawctxt->gpustate); - cmd += LOOP_CONSTANTS; - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, drawctxt->reg_restore, start, cmd); - - ctx->cmd = cmd; -} - - -////////////////////////////////////////////////////////////////////////////// -// quad for saving/restoring gmem -////////////////////////////////////////////////////////////////////////////// - -static void set_gmem_copy_quad( gmem_shadow_t* shadow ) -{ - unsigned int tex_offset[2]; - - // set vertex buffer values - - gmem_copy_quad[1] = uint2float( shadow->gmem_height + shadow->gmem_offset_y ); - gmem_copy_quad[3] = uint2float( shadow->gmem_width + shadow->gmem_offset_x ); - gmem_copy_quad[4] = uint2float( shadow->gmem_height + shadow->gmem_offset_y ); - gmem_copy_quad[9] = uint2float( shadow->gmem_width + shadow->gmem_offset_x ); - - gmem_copy_quad[0] = uint2float( shadow->gmem_offset_x ); - gmem_copy_quad[6] = uint2float( shadow->gmem_offset_x ); - gmem_copy_quad[7] = uint2float( shadow->gmem_offset_y ); - gmem_copy_quad[10] = uint2float( shadow->gmem_offset_y ); - - tex_offset[0] = uintdivide( shadow->offset_x, (shadow->offset_x+shadow->width) ); - tex_offset[1] = uintdivide( shadow->offset_y, (shadow->offset_y+shadow->height) ); - - gmem_copy_texcoord[0] = gmem_copy_texcoord[4] = tex_offset[0]; - gmem_copy_texcoord[5] = gmem_copy_texcoord[7] = tex_offset[1]; - - // copy quad data to vertex buffer - kos_memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2); - - // copy tex coord data to tex coord buffer - kos_memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord, TEXCOORD_LEN << 2); -} - - -static void -build_quad_vtxbuff(gsl_drawctxt_t *drawctxt, ctx_t *ctx, gmem_shadow_t* shadow) -{ - unsigned int *cmd = ctx->cmd; - - // quad vertex buffer location - shadow->quad_vertices.hostptr = cmd; - shadow->quad_vertices.gpuaddr = gpuaddr(cmd, &drawctxt->gpustate); - cmd += QUAD_LEN; - - // tex coord buffer location (in GPU space) - shadow->quad_texcoords.hostptr = cmd; - shadow->quad_texcoords.gpuaddr = gpuaddr(cmd, &drawctxt->gpustate); - - - cmd += TEXCOORD_LEN; - - set_gmem_copy_quad(shadow); - - - ctx->cmd = cmd; -} - - -////////////////////////////////////////////////////////////////////////////// - -static void -build_shader_save_restore_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) -{ - unsigned int *cmd = ctx->cmd; - unsigned int *save, *restore, *fixup; -#if defined(PM4_IM_STORE) - unsigned int *startSizeVtx, *startSizePix, *startSizeShared; -#endif - unsigned int *partition1; - unsigned int *shaderBases, *partition2; - -#if defined(PM4_IM_STORE) - // compute vertex, pixel and shared instruction shadow GPU addresses - ctx->shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET; - ctx->shader_pixel = ctx->shader_vertex + SHADER_SHADOW_SIZE; - ctx->shader_shared = ctx->shader_pixel + SHADER_SHADOW_SIZE; -#endif - - - //------------------------------------------------------------------- - // restore shader partitioning and instructions - //------------------------------------------------------------------- - - restore = cmd; // start address - - // Invalidate Vertex & Pixel instruction code address and sizes - *cmd++ = pm4_type3_packet(PM4_INVALIDATE_STATE, 1); - *cmd++ = 0x00000300; // 0x100 = Vertex, 0x200 = Pixel - - // Restore previous shader vertex & pixel instruction bases. - *cmd++ = pm4_type3_packet(PM4_SET_SHADER_BASES, 1); - shaderBases = cmd++; // TBD #5: shader bases (from fixup) - - // write the shader partition information to a scratch register - *cmd++ = pm4_type0_packet(mmSQ_INST_STORE_MANAGMENT, 1); - partition1 = cmd++; // TBD #4a: partition info (from save) - -#if defined(PM4_IM_STORE) - // load vertex shader instructions from the shadow. - *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2); - *cmd++ = ctx->shader_vertex + 0x0; // 0x0 = Vertex - startSizeVtx = cmd++; // TBD #1: start/size (from save) - - // load pixel shader instructions from the shadow. - *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2); - *cmd++ = ctx->shader_pixel + 0x1; // 0x1 = Pixel - startSizePix = cmd++; // TBD #2: start/size (from save) - - // load shared shader instructions from the shadow. - *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2); - *cmd++ = ctx->shader_shared + 0x2; // 0x2 = Shared - startSizeShared = cmd++; // TBD #3: start/size (from save) -#endif - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd); - - - //------------------------------------------------------------------- - // fixup SET_SHADER_BASES data - // - // since self-modifying PM4 code is being used here, a seperate - // command buffer is used for this fixup operation, to ensure the - // commands are not read by the PM4 engine before the data fields - // have been written. - //------------------------------------------------------------------- - - fixup = cmd; // start address - - // write the shader partition information to a scratch register - *cmd++ = pm4_type0_packet(mmSCRATCH_REG2, 1); - partition2 = cmd++; // TBD #4b: partition info (from save) - - // mask off unused bits, then OR with shader instruction memory size - *cmd++ = pm4_type3_packet(PM4_REG_RMW, 3); - *cmd++ = mmSCRATCH_REG2; - *cmd++ = 0x0FFF0FFF; // AND off invalid bits. - *cmd++ = (unsigned int)((SHADER_INSTRUCT_LOG2-5U) << 29); // OR in instruction memory size - - // write the computed value to the SET_SHADER_BASES data field - *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmd++ = mmSCRATCH_REG2; - *cmd++ = gpuaddr(shaderBases, &drawctxt->gpustate); // TBD #5: shader bases (to restore) - - // create indirect buffer command for above command sequence - create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd); - - - //------------------------------------------------------------------- - // save shader partitioning and instructions - //------------------------------------------------------------------- - - save = cmd; // start address - - *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *cmd++ = 0; - - // Fetch the SQ_INST_STORE_MANAGMENT register value, - // Store the value in the data fields of the SET_CONSTANT commands above. - *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmd++ = mmSQ_INST_STORE_MANAGMENT; - *cmd++ = gpuaddr(partition1, &drawctxt->gpustate); // TBD #4a: partition info (to restore) - *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); - *cmd++ = mmSQ_INST_STORE_MANAGMENT; - *cmd++ = gpuaddr(partition2, &drawctxt->gpustate); // TBD #4b: partition info (to fixup) - -#if defined(PM4_IM_STORE) - // Store the vertex shader instructions - *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2); - *cmd++ = ctx->shader_vertex + 0x0; // 0x0 = Vertex - *cmd++ = gpuaddr(startSizeVtx, &drawctxt->gpustate); // TBD #1: start/size (to restore) - - // store the pixel shader instructions - *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2); - *cmd++ = ctx->shader_pixel + 0x1; // 0x1 = Pixel - *cmd++ = gpuaddr(startSizePix, &drawctxt->gpustate); // TBD #2: start/size (to restore) - - // Store the shared shader instructions - *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2); - *cmd++ = ctx->shader_shared + 0x2; // 0x2 = Shared - *cmd++ = gpuaddr(startSizeShared, &drawctxt->gpustate); // TBD #3: start/size (to restore) -#endif - - *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *cmd++ = 0; - - - - // Create indirect buffer command for above command sequence - create_ib1(drawctxt, drawctxt->shader_save, save, cmd); - - - ctx->cmd = cmd; -} - - - -////////////////////////////////////////////////////////////////////////////// -// create buffers for saving/restoring registers and constants -////////////////////////////////////////////////////////////////////////////// - -static int -create_gpustate_shadow(gsl_device_t *device, gsl_drawctxt_t *drawctxt, ctx_t *ctx) -{ - gsl_flags_t flags; - - flags = (GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_ALIGN8K); - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, flags = (GSL_MEMFLAGS_EMEM | GSL_MEMFLAGS_ALIGN8K)); - - // allocate memory to allow HW to save sub-blocks for efficient context save/restore - if (kgsl_sharedmem_alloc0(device->id, flags, CONTEXT_SIZE, &drawctxt->gpustate) != GSL_SUCCESS) - return GSL_FAILURE; - - drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW; - - // Blank out h/w register, constant, and command buffer shadows. - kgsl_sharedmem_set0(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE); - - // set-up command and vertex buffer pointers - ctx->cmd = ctx->start = (unsigned int *) ((char *)drawctxt->gpustate.hostptr + CMD_OFFSET); - - // build indirect command buffers to save & restore regs/constants - build_regrestore_cmds(drawctxt, ctx); - build_regsave_cmds(drawctxt, ctx); - - build_shader_save_restore_cmds(drawctxt, ctx); - - return GSL_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -// Allocate GMEM shadow buffer -////////////////////////////////////////////////////////////////////////////// -static int -allocate_gmem_shadow_buffer(gsl_device_t *device, gsl_drawctxt_t *drawctxt) -{ - // allocate memory for GMEM shadow - if (kgsl_sharedmem_alloc0(device->id, (GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_ALIGN8K), - drawctxt->context_gmem_shadow.size, &drawctxt->context_gmem_shadow.gmemshadow) != GSL_SUCCESS) - return GSL_FAILURE; - - // blank out gmem shadow. - kgsl_sharedmem_set0(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0, drawctxt->context_gmem_shadow.size); - - return GSL_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -// create GMEM save/restore specific stuff -////////////////////////////////////////////////////////////////////////////// - -static int -create_gmem_shadow(gsl_device_t *device, gsl_drawctxt_t *drawctxt, ctx_t *ctx) -{ - unsigned int i; - config_gmemsize(&drawctxt->context_gmem_shadow, device->gmemspace.sizebytes); - ctx->gmem_base = device->gmemspace.gpu_base; - - if( drawctxt->flags & CTXT_FLAGS_GMEM_SHADOW ) - { - if( allocate_gmem_shadow_buffer(device, drawctxt) != GSL_SUCCESS ) - return GSL_FAILURE; - } - else - { - kos_memset( &drawctxt->context_gmem_shadow.gmemshadow, 0, sizeof( gsl_memdesc_t ) ); - } - - // build quad vertex buffer - build_quad_vtxbuff(drawctxt, ctx, &drawctxt->context_gmem_shadow); - - // build TP0_CHICKEN register restore command buffer - ctx->cmd = build_chicken_restore_cmds(drawctxt, ctx); - - // build indirect command buffers to save & restore gmem - drawctxt->context_gmem_shadow.gmem_save_commands = ctx->cmd; - ctx->cmd = build_gmem2sys_cmds(drawctxt, ctx, &drawctxt->context_gmem_shadow); - drawctxt->context_gmem_shadow.gmem_restore_commands = ctx->cmd; - ctx->cmd = build_sys2gmem_cmds(drawctxt, ctx, &drawctxt->context_gmem_shadow); - - for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) - { - // build quad vertex buffer - build_quad_vtxbuff(drawctxt, ctx, &drawctxt->user_gmem_shadow[i]); - - // build indirect command buffers to save & restore gmem - drawctxt->user_gmem_shadow[i].gmem_save_commands = ctx->cmd; - ctx->cmd = build_gmem2sys_cmds(drawctxt, ctx, &drawctxt->user_gmem_shadow[i]); - - drawctxt->user_gmem_shadow[i].gmem_restore_commands = ctx->cmd; - ctx->cmd = build_sys2gmem_cmds(drawctxt, ctx, &drawctxt->user_gmem_shadow[i]); - } - - return GSL_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////// -// init draw context -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_drawctxt_init(gsl_device_t *device) -{ - GSL_CONTEXT_MUTEX_CREATE(); - - return (GSL_SUCCESS); -} - - -////////////////////////////////////////////////////////////////////////////// -// close draw context -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_drawctxt_close(gsl_device_t *device) -{ - GSL_CONTEXT_MUTEX_FREE(); - - return (GSL_SUCCESS); -} - - -////////////////////////////////////////////////////////////////////////////// -// create a new drawing context -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_drawctxt_create(gsl_device_t* device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags) -{ - gsl_drawctxt_t *drawctxt; - int index; - ctx_t ctx; - - kgsl_device_active(device); - - GSL_CONTEXT_MUTEX_LOCK(); - if (device->drawctxt_count >= GSL_CONTEXT_MAX) - { - GSL_CONTEXT_MUTEX_UNLOCK(); - return (GSL_FAILURE); - } - - // find a free context slot - index = 0; - while (index < GSL_CONTEXT_MAX) - { - if (device->drawctxt[index].flags == CTXT_FLAGS_NOT_IN_USE) - break; - - index++; - } - - if (index >= GSL_CONTEXT_MAX) - { - GSL_CONTEXT_MUTEX_UNLOCK(); - return (GSL_FAILURE); - } - - drawctxt = &device->drawctxt[index]; - - kos_memset( &drawctxt->context_gmem_shadow, 0, sizeof( gmem_shadow_t ) ); - - drawctxt->pid = GSL_CALLER_PROCESSID_GET(); - drawctxt->flags = CTXT_FLAGS_IN_USE; - drawctxt->type = type; - - device->drawctxt_count++; - - // create context shadows, when not running in safe mode - if (!(device->flags & GSL_FLAGS_SAFEMODE)) - { - if (create_gpustate_shadow(device, drawctxt, &ctx) != GSL_SUCCESS) - { - kgsl_drawctxt_destroy(device, index); - GSL_CONTEXT_MUTEX_UNLOCK(); - return (GSL_FAILURE); - } - - // Save the shader instruction memory & GMEM on context switching - drawctxt->flags |= ( CTXT_FLAGS_SHADER_SAVE | CTXT_FLAGS_GMEM_SHADOW ); - - // Clear out user defined GMEM shadow buffer structs - kos_memset( drawctxt->user_gmem_shadow, 0, sizeof(gmem_shadow_t)*GSL_MAX_GMEM_SHADOW_BUFFERS ); - - // create gmem shadow - if (create_gmem_shadow(device, drawctxt, &ctx) != GSL_SUCCESS) - { - kgsl_drawctxt_destroy(device, index); - GSL_CONTEXT_MUTEX_UNLOCK(); - return (GSL_FAILURE); - } - - KOS_ASSERT(ctx.cmd - ctx.start <= CMD_BUFFER_LEN); - } - - *drawctxt_id = index; - - GSL_CONTEXT_MUTEX_UNLOCK(); - return (GSL_SUCCESS); -} - - -////////////////////////////////////////////////////////////////////////////// -// destroy a drawing context -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_drawctxt_destroy(gsl_device_t* device, unsigned int drawctxt_id) -{ - gsl_drawctxt_t *drawctxt; - - GSL_CONTEXT_MUTEX_LOCK(); - - drawctxt = &device->drawctxt[drawctxt_id]; - - if (drawctxt->flags != CTXT_FLAGS_NOT_IN_USE) - { - // deactivate context - if (device->drawctxt_active == drawctxt) - { - // no need to save GMEM or shader, the context is being destroyed. - drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE | CTXT_FLAGS_SHADER_SAVE); - - kgsl_drawctxt_switch(device, GSL_CONTEXT_NONE, 0); - } - - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - - // destroy state shadow, if allocated - if (drawctxt->flags & CTXT_FLAGS_STATE_SHADOW) - kgsl_sharedmem_free0(&drawctxt->gpustate, GSL_CALLER_PROCESSID_GET()); - - - // destroy gmem shadow, if allocated - if (drawctxt->context_gmem_shadow.gmemshadow.size > 0) - { - kgsl_sharedmem_free0(&drawctxt->context_gmem_shadow.gmemshadow, GSL_CALLER_PROCESSID_GET()); - drawctxt->context_gmem_shadow.gmemshadow.size = 0; - } - - drawctxt->flags = CTXT_FLAGS_NOT_IN_USE; - drawctxt->pid = 0; - - device->drawctxt_count--; - KOS_ASSERT(device->drawctxt_count >= 0); - } - - GSL_CONTEXT_MUTEX_UNLOCK(); - - return (GSL_SUCCESS); -} - -////////////////////////////////////////////////////////////////////////////// -// Binds a user specified buffer as GMEM shadow area -// -// gmem_rect: defines the rectangle that is copied from GMEM. X and Y -// coordinates need to be multiples of 8 after conversion to 32bpp. -// X, Y, width, and height need to be at 32-bit boundary to avoid -// rounding. -// -// shadow_x & shadow_y: Position in GMEM shadow buffer where the contents of -// gmem_rect is copied. Both must be multiples of 8 after -// conversion to 32bpp. They also need to be at 32-bit -// boundary to avoid rounding. -// -// shadow_buffer: Description of the GMEM shadow buffer. BPP needs to be -// 8, 16, 32, 64, or 128. Enabled tells if the buffer is -// used or not (values 0 and 1). All the other buffer -// parameters are ignored when enabled=0. -// -// buffer_id: Two different buffers can be defined. Use buffer IDs 0 and 1. -// -// -////////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_drawctxt_bind_gmem_shadow(gsl_deviceid_t device_id, unsigned int drawctxt_id, const gsl_rect_t* gmem_rect, unsigned int shadow_x, unsigned int shadow_y, const gsl_buffer_desc_t* shadow_buffer, unsigned int buffer_id) -{ - gsl_device_t *device = &gsl_driver.device[device_id-1]; - gsl_drawctxt_t *drawctxt = &device->drawctxt[drawctxt_id]; - gmem_shadow_t *shadow = &drawctxt->user_gmem_shadow[buffer_id]; - unsigned int i; - - GSL_API_MUTEX_LOCK(); - GSL_CONTEXT_MUTEX_LOCK(); - - if( !shadow_buffer->enabled ) - { - // Disable shadow - shadow->gmemshadow.size = 0; - } - else - { - // Sanity checks - KOS_ASSERT((gmem_rect->x % 2) == 0); // Needs to be a multiple of 2 - KOS_ASSERT((gmem_rect->y % 2) == 0); // Needs to be a multiple of 2 - KOS_ASSERT((gmem_rect->width % 2) == 0); // Needs to be a multiple of 2 - KOS_ASSERT((gmem_rect->height % 2) == 0); // Needs to be a multiple of 2 - KOS_ASSERT((gmem_rect->pitch % 32) == 0); // Needs to be a multiple of 32 - - KOS_ASSERT((shadow_x % 2) == 0); // Needs to be a multiple of 2 - KOS_ASSERT((shadow_y % 2) == 0); // Needs to be a multiple of 2 - - KOS_ASSERT(shadow_buffer->format >= COLORX_4_4_4_4); - KOS_ASSERT(shadow_buffer->format <= COLORX_32_32_32_32_FLOAT); - KOS_ASSERT((shadow_buffer->pitch % 32) == 0); // Needs to be a multiple of 32 - KOS_ASSERT(buffer_id >= 0); - KOS_ASSERT(buffer_id < GSL_MAX_GMEM_SHADOW_BUFFERS); - - // Set up GMEM shadow regions - kos_memcpy( &shadow->gmemshadow, &shadow_buffer->data, sizeof( gsl_memdesc_t ) ); - shadow->size = shadow->gmemshadow.size; - - shadow->width = shadow_buffer->width; - shadow->height = shadow_buffer->height; - shadow->pitch = shadow_buffer->pitch; - shadow->format = shadow_buffer->format; - - shadow->offset = shadow->pitch * (shadow_y - gmem_rect->y) + shadow_x - gmem_rect->x; - - shadow->offset_x = shadow_x; - shadow->offset_y = shadow_y; - - shadow->gmem_width = gmem_rect->width; - shadow->gmem_height = gmem_rect->height; - shadow->gmem_pitch = gmem_rect->pitch; - - shadow->gmem_offset_x = gmem_rect->x; - shadow->gmem_offset_y = gmem_rect->y; - - // Modify quad vertices - set_gmem_copy_quad(shadow); - - // Modify commands - build_gmem2sys_cmds(drawctxt, NULL, shadow); - build_sys2gmem_cmds(drawctxt, NULL, shadow); - - // Release context GMEM shadow if found - if (drawctxt->context_gmem_shadow.gmemshadow.size > 0) - { - kgsl_sharedmem_free0(&drawctxt->context_gmem_shadow.gmemshadow, GSL_CALLER_PROCESSID_GET()); - drawctxt->context_gmem_shadow.gmemshadow.size = 0; - } - } - - // Enable GMEM shadowing if we have any of the user buffers enabled - drawctxt->flags &= ~CTXT_FLAGS_GMEM_SHADOW; - for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) - { - if( drawctxt->user_gmem_shadow[i].gmemshadow.size > 0 ) - { - drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW; - } - } - - GSL_CONTEXT_MUTEX_UNLOCK(); - GSL_API_MUTEX_UNLOCK(); - - return (GSL_SUCCESS); -} - - - -////////////////////////////////////////////////////////////////////////////// -// switch drawing contexts -////////////////////////////////////////////////////////////////////////////// - -void -kgsl_drawctxt_switch(gsl_device_t *device, gsl_drawctxt_t *drawctxt, gsl_flags_t flags) -{ - gsl_drawctxt_t *active_ctxt = device->drawctxt_active; - - if (drawctxt != GSL_CONTEXT_NONE) - { - if( flags & GSL_CONTEXT_SAVE_GMEM ) - { - // Set the flag in context so that the save is done when this context is switched out. - drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE; - } - else - { - // Remove GMEM saving flag from the context - drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE; - } - } - - // already current? - if (active_ctxt == drawctxt) - { - return; - } - - // save old context, when not running in safe mode - if (active_ctxt != GSL_CONTEXT_NONE && !(device->flags & GSL_FLAGS_SAFEMODE)) - { - // save registers and constants. - kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->reg_save, 3, active_ctxt->pid); - - if (active_ctxt->flags & CTXT_FLAGS_SHADER_SAVE) - { - // save shader partitioning and instructions. - kgsl_ringbuffer_issuecmds(device, 1, active_ctxt->shader_save, 3, active_ctxt->pid); - - // fixup shader partitioning parameter for SET_SHADER_BASES. - kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->shader_fixup, 3, active_ctxt->pid); - - active_ctxt->flags |= CTXT_FLAGS_SHADER_RESTORE; - } - - if (active_ctxt->flags & CTXT_FLAGS_GMEM_SHADOW && active_ctxt->flags & CTXT_FLAGS_GMEM_SAVE ) - { - // save gmem. (note: changes shader. shader must already be saved.) - - unsigned int i, numbuffers = 0; - - for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) - { - if( active_ctxt->user_gmem_shadow[i].gmemshadow.size > 0 ) - { - kgsl_ringbuffer_issuecmds(device, 1, active_ctxt->user_gmem_shadow[i].gmem_save, 3, active_ctxt->pid); - - // Restore TP0_CHICKEN - kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->chicken_restore, 3, active_ctxt->pid); - numbuffers++; - } - } - if( numbuffers == 0 ) - { - // No user defined buffers -> use context default - kgsl_ringbuffer_issuecmds(device, 1, active_ctxt->context_gmem_shadow.gmem_save, 3, active_ctxt->pid); - // Restore TP0_CHICKEN - kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->chicken_restore, 3, active_ctxt->pid); - } - - active_ctxt->flags |= CTXT_FLAGS_GMEM_RESTORE; - } - } - - device->drawctxt_active = drawctxt; - - // restore new context, when not running in safe mode - if (drawctxt != GSL_CONTEXT_NONE && !(device->flags & GSL_FLAGS_SAFEMODE)) - { - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MEMWRITE, drawctxt->gpustate.gpuaddr, (unsigned int)drawctxt->gpustate.hostptr, LCC_SHADOW_SIZE + REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE , "kgsl_drawctxt_switch")); - - // restore gmem. (note: changes shader. shader must not already be restored.) - if (drawctxt->flags & CTXT_FLAGS_GMEM_RESTORE) - { - unsigned int i, numbuffers = 0; - - for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) - { - if( drawctxt->user_gmem_shadow[i].gmemshadow.size > 0 ) - { - kgsl_ringbuffer_issuecmds(device, 1, drawctxt->user_gmem_shadow[i].gmem_restore, 3, drawctxt->pid); - - // Restore TP0_CHICKEN - kgsl_ringbuffer_issuecmds(device, 0, drawctxt->chicken_restore, 3, drawctxt->pid); - numbuffers++; - } - } - if( numbuffers == 0 ) - { - // No user defined buffers -> use context default - kgsl_ringbuffer_issuecmds(device, 1, drawctxt->context_gmem_shadow.gmem_restore, 3, drawctxt->pid); - // Restore TP0_CHICKEN - kgsl_ringbuffer_issuecmds(device, 0, drawctxt->chicken_restore, 3, drawctxt->pid); - } - - drawctxt->flags &= ~CTXT_FLAGS_GMEM_RESTORE; - } - - // restore registers and constants. - kgsl_ringbuffer_issuecmds(device, 0, drawctxt->reg_restore, 3, drawctxt->pid); - - // restore shader instructions & partitioning. - if (drawctxt->flags & CTXT_FLAGS_SHADER_RESTORE) - { - kgsl_ringbuffer_issuecmds(device, 0, drawctxt->shader_restore, 3, drawctxt->pid); - } - } -} - - -////////////////////////////////////////////////////////////////////////////// -// destroy all drawing contexts -////////////////////////////////////////////////////////////////////////////// -int -kgsl_drawctxt_destroyall(gsl_device_t *device) -{ - int i; - gsl_drawctxt_t *drawctxt; - - GSL_CONTEXT_MUTEX_LOCK(); - - for (i = 0; i < GSL_CONTEXT_MAX; i++) - { - drawctxt = &device->drawctxt[i]; - - if (drawctxt->flags != CTXT_FLAGS_NOT_IN_USE) - { - // destroy state shadow, if allocated - if (drawctxt->flags & CTXT_FLAGS_STATE_SHADOW) - kgsl_sharedmem_free0(&drawctxt->gpustate, GSL_CALLER_PROCESSID_GET()); - - // destroy gmem shadow, if allocated - if (drawctxt->context_gmem_shadow.gmemshadow.size > 0) - { - kgsl_sharedmem_free0(&drawctxt->context_gmem_shadow.gmemshadow, GSL_CALLER_PROCESSID_GET()); - drawctxt->context_gmem_shadow.gmemshadow.size = 0; - } - - drawctxt->flags = CTXT_FLAGS_NOT_IN_USE; - - device->drawctxt_count--; - KOS_ASSERT(device->drawctxt_count >= 0); - } - } - - GSL_CONTEXT_MUTEX_UNLOCK(); - - return (GSL_SUCCESS); -} - -#endif diff --git a/drivers/mxc/amd-gpu/common/gsl_driver.c b/drivers/mxc/amd-gpu/common/gsl_driver.c deleted file mode 100644 index b8c5170a142..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_driver.c +++ /dev/null @@ -1,329 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" - - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -#define GSL_PROCESSID_NONE 0x00000000 - -#define GSL_DRVFLAGS_EXTERNAL 0x10000000 -#define GSL_DRVFLAGS_INTERNAL 0x20000000 - - -////////////////////////////////////////////////////////////////////////////// -// globals -////////////////////////////////////////////////////////////////////////////// -#ifndef KGSL_USER_MODE -static gsl_flags_t gsl_driver_initialized = 0; -gsl_driver_t gsl_driver; -#else -extern gsl_flags_t gsl_driver_initialized; -extern gsl_driver_t gsl_driver; -#endif - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_driver_init0(gsl_flags_t flags, gsl_flags_t flags_debug) -{ - int status = GSL_SUCCESS; - - if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0)) - { -#ifdef GSL_LOG - // Uncomment these to enable logging. - //kgsl_log_init(); - //kgsl_log_open_stdout( KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP - // | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID ); - //kgsl_log_open_file( "c:\\kgsl_log.txt", KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP - // | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID ); -#endif - kos_memset(&gsl_driver, 0, sizeof(gsl_driver_t)); - - GSL_API_MUTEX_CREATE(); - } - -#ifdef _DEBUG - // set debug flags on every entry, and prior to hal initialization - gsl_driver.flags_debug |= flags_debug; -#else - (void) flags_debug; // unref formal parameter -#endif // _DEBUG - - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, - { - KGSL_DEBUG_DUMPX_OPEN("dumpx.tb", 0); - KGSL_DEBUG_DUMPX( BB_DUMP_ENABLE, 0, 0, 0, " "); - }); - - KGSL_DEBUG_TBDUMP_OPEN("tbdump.txt"); - - if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0)) - { - GSL_API_MUTEX_LOCK(); - - // init hal - status = kgsl_hal_init(); - - if (status == GSL_SUCCESS) - { - gsl_driver_initialized |= flags; - gsl_driver_initialized |= GSL_FLAGS_INITIALIZED0; - } - - GSL_API_MUTEX_UNLOCK(); - } - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_driver_close0(gsl_flags_t flags) -{ - int status = GSL_SUCCESS; - - if ((gsl_driver_initialized & GSL_FLAGS_INITIALIZED0) && (gsl_driver_initialized & flags)) - { - GSL_API_MUTEX_LOCK(); - - // close hall - status = kgsl_hal_close(); - - GSL_API_MUTEX_UNLOCK(); - - GSL_API_MUTEX_FREE(); - -#ifdef GSL_LOG - kgsl_log_close(); -#endif - - gsl_driver_initialized &= ~flags; - gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED0; - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, - { - KGSL_DEBUG_DUMPX_CLOSE(); - }); - - KGSL_DEBUG_TBDUMP_CLOSE(); - } - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_driver_init() -{ - // only an external (platform specific device driver) component should call this - - return(kgsl_driver_init0(GSL_DRVFLAGS_EXTERNAL, 0)); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_driver_close() -{ - // only an external (platform specific device driver) component should call this - - return(kgsl_driver_close0(GSL_DRVFLAGS_EXTERNAL)); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_driver_entry(gsl_flags_t flags) -{ - int status = GSL_FAILURE; - int index, i; - unsigned int pid; - - if (kgsl_driver_init0(GSL_DRVFLAGS_INTERNAL, flags) != GSL_SUCCESS) - { - return (GSL_FAILURE); - } - - kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_entry( gsl_flags_t flags=%d )\n", flags ); - - GSL_API_MUTEX_LOCK(); - - pid = GSL_CALLER_PROCESSID_GET(); - - // if caller process has not already opened access - status = kgsl_driver_getcallerprocessindex(pid, &index); - if (status != GSL_SUCCESS) - { - // then, add caller pid to process table - status = kgsl_driver_getcallerprocessindex(GSL_PROCESSID_NONE, &index); - if (status == GSL_SUCCESS) - { - gsl_driver.callerprocess[index] = pid; - gsl_driver.refcnt++; - } - } - - if (status == GSL_SUCCESS) - { - if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED)) - { - // init memory apertures - status = kgsl_sharedmem_init(&gsl_driver.shmem); - if (status == GSL_SUCCESS) - { - // init devices - status = GSL_FAILURE; - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - if (kgsl_device_init(&gsl_driver.device[i], (gsl_deviceid_t)(i + 1)) == GSL_SUCCESS) { - status = GSL_SUCCESS; - } - } - } - - if (status == GSL_SUCCESS) - { - gsl_driver_initialized |= GSL_FLAGS_INITIALIZED; - } - } - - // walk through process attach callbacks - if (status == GSL_SUCCESS) - { - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - status = kgsl_device_attachcallback(&gsl_driver.device[i], pid); - if (status != GSL_SUCCESS) - { - break; - } - } - } - - // if something went wrong - if (status != GSL_SUCCESS) - { - // then, remove caller pid from process table - if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS) - { - gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE; - gsl_driver.refcnt--; - } - } - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_entry. Return value: %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_driver_exit0(unsigned int pid) -{ - int status = GSL_SUCCESS; - int index, i; - - GSL_API_MUTEX_LOCK(); - - if (gsl_driver_initialized & GSL_FLAGS_INITIALIZED) - { - if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS) - { - // walk through process detach callbacks - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - // Empty the freememqueue of this device - kgsl_cmdstream_memqueue_drain(&gsl_driver.device[i]); - - // Detach callback - status = kgsl_device_detachcallback(&gsl_driver.device[i], pid); - if (status != GSL_SUCCESS) - { - break; - } - } - - // last running caller process - if (gsl_driver.refcnt - 1 == 0) - { - // close devices - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - kgsl_device_close(&gsl_driver.device[i]); - } - - // shutdown memory apertures - kgsl_sharedmem_close(&gsl_driver.shmem); - - gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED; - } - - // remove caller pid from process table - gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE; - gsl_driver.refcnt--; - } - } - - GSL_API_MUTEX_UNLOCK(); - - if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED)) - { - kgsl_driver_close0(GSL_DRVFLAGS_INTERNAL); - } - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_driver_exit(void) -{ - int status; - - kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_exit()\n" ); - - status = kgsl_driver_exit0(GSL_CALLER_PROCESSID_GET()); - - kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_exit(). Return value: %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_driver_destroy(unsigned int pid) -{ - return (kgsl_driver_exit0(pid)); -} diff --git a/drivers/mxc/amd-gpu/common/gsl_g12.c b/drivers/mxc/amd-gpu/common/gsl_g12.c deleted file mode 100644 index 8286e8e6a6a..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_g12.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#include "kos_libapi.h" -#include "gsl_cmdstream.h" -#ifdef _LINUX -#include -#endif - -#ifdef CONFIG_ARCH_MX35 -#define V3_SYNC -#endif - -#ifdef GSL_BLD_G12 -#define GSL_IRQ_TIMEOUT 200 - - -//---------------------------------------------------------------------------- - -#define GSL_HAL_NUMCMDBUFFERS 5 -#define GSL_HAL_CMDBUFFERSIZE (1024 + 13) * sizeof(unsigned int) - -#define ALIGN_IN_BYTES( dim, alignment ) ( ( (dim) + (alignment-1) ) & ~(alignment-1) ) - - -#ifdef _Z180 -#define NUMTEXUNITS 4 -#define TEXUNITREGCOUNT 25 -#define VG_REGCOUNT 0x39 -#define GSL_HAL_EDGE0BUFSIZE 0x3E8+64 -#define GSL_HAL_EDGE1BUFSIZE 0x8000+64 -#define GSL_HAL_EDGE2BUFSIZE 0x80020+64 -#define GSL_HAL_EDGE0REG ADDR_VGV1_CBUF -#define GSL_HAL_EDGE1REG ADDR_VGV1_BBUF -#define GSL_HAL_EDGE2REG ADDR_VGV1_EBUF -#else -#define NUMTEXUNITS 2 -#define TEXUNITREGCOUNT 24 -#define VG_REGCOUNT 0x3A -#define L1TILESIZE 64 -#define GSL_HAL_EDGE0BUFSIZE L1TILESIZE*L1TILESIZE*4+64 -#define GSL_HAL_EDGE1BUFSIZE L1TILESIZE*L1TILESIZE*16+64 -#define GSL_HAL_EDGE0REG ADDR_VGV1_CBASE1 -#define GSL_HAL_EDGE1REG ADDR_VGV1_UBASE2 -#endif - -#define PACKETSIZE_BEGIN 3 -#define PACKETSIZE_G2DCOLOR 2 -#define PACKETSIZE_TEXUNIT (TEXUNITREGCOUNT*2) -#define PACKETSIZE_REG (VG_REGCOUNT*2) -#define PACKETSIZE_STATE (PACKETSIZE_TEXUNIT*NUMTEXUNITS + PACKETSIZE_REG + PACKETSIZE_BEGIN + PACKETSIZE_G2DCOLOR) -#define PACKETSIZE_STATESTREAM ALIGN_IN_BYTES((PACKETSIZE_STATE*sizeof(unsigned int)), 32) / sizeof(unsigned int) - -//---------------------------------------------------------------------------- - -typedef struct -{ - unsigned int id; - // unsigned int regs[]; -}gsl_hal_z1xxdrawctx_t; - -typedef struct -{ - unsigned int offs; - unsigned int curr; - unsigned int prevctx; - - gsl_memdesc_t e0; - gsl_memdesc_t e1; - gsl_memdesc_t e2; - unsigned int* cmdbuf[GSL_HAL_NUMCMDBUFFERS]; - gsl_memdesc_t cmdbufdesc[GSL_HAL_NUMCMDBUFFERS]; - gsl_timestamp_t timestamp[GSL_HAL_NUMCMDBUFFERS]; - - unsigned int numcontext; - unsigned int nextUniqueContextID; -}gsl_z1xx_t; - -static gsl_z1xx_t g_z1xx = {0}; - -extern int z160_version; - -//---------------------------------------------------------------------------- - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -static int kgsl_g12_addtimestamp(gsl_device_t* device, gsl_timestamp_t *timestamp); -static int kgsl_g12_issueibcmds(gsl_device_t* device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, unsigned int flags); -static int kgsl_g12_context_create(gsl_device_t* device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags); -static int kgsl_g12_context_destroy(gsl_device_t* device, unsigned int drawctxt_id); -static unsigned int drawctx_id = 0; -static int kgsl_g12_idle(gsl_device_t *device, unsigned int timeout); -#ifndef _LINUX -static void irq_thread(void); -#endif - -//---------------------------------------------------------------------------- - -void -kgsl_g12_intrcallback(gsl_intrid_t id, void *cookie) -{ - gsl_device_t *device = (gsl_device_t *) cookie; - - switch(id) - { - // non-error condition interrupt - case GSL_INTR_G12_G2D: -#ifdef _LINUX - queue_work(device->irq_workq, &(device->irq_work)); - break; -#endif -#ifndef _Z180 - case GSL_INTR_G12_FBC: -#endif //_Z180 - // signal intr completion event - kos_event_signal(device->intr.evnt[id]); - break; - - // error condition interrupt - case GSL_INTR_G12_FIFO: - printk(KERN_ERR "GPU: Z160 FIFO Error\n"); - schedule_work(&device->irq_err_work); - break; - - case GSL_INTR_G12_MH: - // don't do anything. this is handled by the MMU manager - break; - - default: - break; - } -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_isr(gsl_device_t *device) -{ - unsigned int status; -#ifdef _DEBUG - REG_MH_MMU_PAGE_FAULT page_fault = {0}; - REG_MH_AXI_ERROR axi_error = {0}; -#endif // DEBUG - - // determine if G12 is interrupting - device->ftbl.device_regread(device, (ADDR_VGC_IRQSTATUS >> 2), &status); - - if (status) - { - // if G12 MH is interrupting, clear MH block interrupt first, then master G12 MH interrupt - if (status & (1 << VGC_IRQSTATUS_MH_FSHIFT)) - { -#ifdef _DEBUG - // obtain mh error information - device->ftbl.device_regread(device, ADDR_MH_MMU_PAGE_FAULT, (unsigned int *)&page_fault); - device->ftbl.device_regread(device, ADDR_MH_AXI_ERROR, (unsigned int *)&axi_error); -#endif // DEBUG - - kgsl_intr_decode(device, GSL_INTR_BLOCK_G12_MH); - } - - kgsl_intr_decode(device, GSL_INTR_BLOCK_G12); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_tlbinvalidate(gsl_device_t *device, unsigned int reg_invalidate, unsigned int pid) -{ -#ifndef GSL_NO_MMU - REG_MH_MMU_INVALIDATE mh_mmu_invalidate = {0}; - - // unreferenced formal parameter - (void) pid; - - mh_mmu_invalidate.INVALIDATE_ALL = 1; - mh_mmu_invalidate.INVALIDATE_TC = 1; - - device->ftbl.device_regwrite(device, reg_invalidate, *(unsigned int *) &mh_mmu_invalidate); -#else - (void)device; - (void)reg_invalidate; -#endif - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_setpagetable(gsl_device_t *device, unsigned int reg_ptbase, gpuaddr_t ptbase, unsigned int pid) -{ - // unreferenced formal parameter - (void) pid; -#ifndef GSL_NO_MMU - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - device->ftbl.device_regwrite(device, reg_ptbase, ptbase); -#else - (void)device; - (void)reg_ptbase; - (void)reg_varange; -#endif - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -#ifdef _LINUX -static void kgsl_g12_updatetimestamp(gsl_device_t *device) -{ - unsigned int count = 0; - device->ftbl.device_regread(device, (ADDR_VGC_IRQ_ACTIVE_CNT >> 2), &count); - count >>= 8; - count &= 255; - device->timestamp += count; -#ifdef V3_SYNC - if (device->current_timestamp > device->timestamp) - { - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 2); - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); - } -#endif - kgsl_sharedmem_write0(&device->memstore, GSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp), &device->timestamp, 4, 0); -} - -//---------------------------------------------------------------------------- - -static void kgsl_g12_irqtask(struct work_struct *work) -{ - gsl_device_t *device = &gsl_driver.device[GSL_DEVICE_G12-1]; - kgsl_g12_updatetimestamp(device); - wake_up_interruptible_all(&device->timestamp_waitq); -} - -static void kgsl_g12_irqerr(struct work_struct *work) -{ - gsl_device_t *device = &gsl_driver.device[GSL_DEVICE_G12-1]; - device->ftbl.device_destroy(device); -} -#endif - -//---------------------------------------------------------------------------- - -int -kgsl_g12_init(gsl_device_t *device) -{ - int status = GSL_FAILURE; - - device->flags |= GSL_FLAGS_INITIALIZED; - - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_ON, 100); - - // setup MH arbiter - MH offsets are considered to be dword based, therefore no down shift - device->ftbl.device_regwrite(device, ADDR_MH_ARBITER_CONFIG, *(unsigned int *) &gsl_cfg_g12_mharb); - - // init interrupt - status = kgsl_intr_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } - - // enable irq - device->ftbl.device_regwrite(device, (ADDR_VGC_IRQENABLE >> 2), 0x3); - -#ifndef GSL_NO_MMU - // enable master interrupt for G12 MH - kgsl_intr_attach(&device->intr, GSL_INTR_G12_MH, kgsl_g12_intrcallback, (void *) device); - kgsl_intr_enable(&device->intr, GSL_INTR_G12_MH); - - // init mmu - status = kgsl_mmu_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } -#endif - -#ifdef IRQTHREAD_POLL - // Create event to trigger IRQ polling thread - device->irqthread_event = kos_event_create(0); -#endif - - // enable interrupts - kgsl_intr_attach(&device->intr, GSL_INTR_G12_G2D, kgsl_g12_intrcallback, (void *) device); - kgsl_intr_attach(&device->intr, GSL_INTR_G12_FIFO, kgsl_g12_intrcallback, (void *) device); - kgsl_intr_enable(&device->intr, GSL_INTR_G12_G2D); - kgsl_intr_enable(&device->intr, GSL_INTR_G12_FIFO); - -#ifndef _Z180 - kgsl_intr_attach(&device->intr, GSL_INTR_G12_FBC, kgsl_g12_intrcallback, (void *) device); - //kgsl_intr_enable(&device->intr, GSL_INTR_G12_FBC); -#endif //_Z180 - - // create thread for IRQ handling -#if defined(__SYMBIAN32__) - kos_thread_create( (oshandle_t)irq_thread, &(device->irq_thread) ); -#elif defined(_LINUX) - device->irq_workq = create_singlethread_workqueue("z1xx_workq"); - INIT_WORK(&device->irq_work, kgsl_g12_irqtask); - INIT_WORK(&device->irq_err_work, kgsl_g12_irqerr); -#else - #pragma warning(disable:4152) - device->irq_thread_handle = kos_thread_create( (oshandle_t)irq_thread, &(device->irq_thread) ); -#endif - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_close(gsl_device_t *device) -{ - int status = GSL_FAILURE; - - if (device->refcnt == 0) - { - // wait pending interrupts before shutting down G12 intr thread to - // empty irq counters. Otherwise there's a possibility to have them in - // registers next time systems starts up and this results in a hang. - status = device->ftbl.device_idle(device, 1000); - KOS_ASSERT(status == GSL_SUCCESS); - -#ifndef _LINUX - kos_thread_destroy(device->irq_thread_handle); -#else - destroy_workqueue(device->irq_workq); -#endif - - // shutdown command window - kgsl_cmdwindow_close(device); - -#ifndef GSL_NO_MMU - // shutdown mmu - kgsl_mmu_close(device); -#endif - // disable interrupts - kgsl_intr_detach(&device->intr, GSL_INTR_G12_MH); - kgsl_intr_detach(&device->intr, GSL_INTR_G12_G2D); - kgsl_intr_detach(&device->intr, GSL_INTR_G12_FIFO); -#ifndef _Z180 - kgsl_intr_detach(&device->intr, GSL_INTR_G12_FBC); -#endif //_Z180 - - // shutdown interrupt - kgsl_intr_close(device); - - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_OFF, 0); - - device->flags &= ~GSL_FLAGS_INITIALIZED; - -#if defined(__SYMBIAN32__) - while(device->irq_thread) - { - kos_sleep(20); - } -#endif - drawctx_id = 0; - - KOS_ASSERT(g_z1xx.numcontext == 0); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_destroy(gsl_device_t *device) -{ - int i; - unsigned int pid; - -#ifdef _DEBUG - // for now, signal catastrophic failure in a brute force way - KOS_ASSERT(0); -#endif // _DEBUG - - //todo: hard reset core? - - for (i = 0; i < GSL_CALLER_PROCESS_MAX; i++) - { - pid = device->callerprocess[i]; - if (pid) - { - device->ftbl.device_stop(device); - kgsl_driver_destroy(pid); - - // todo: terminate client process? - } - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_start(gsl_device_t *device, gsl_flags_t flags) -{ - int status = GSL_SUCCESS; - - (void) flags; // unreferenced formal parameter - - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_ON, 100); - - // init command window - status = kgsl_cmdwindow_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } - - KOS_ASSERT(g_z1xx.numcontext == 0); - - device->flags |= GSL_FLAGS_STARTED; - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_stop(gsl_device_t *device) -{ - int status; - - KOS_ASSERT(device->refcnt == 0); - - /* wait for device to idle before setting it's clock off */ - status = device->ftbl.device_idle(device, 1000); - KOS_ASSERT(status == GSL_SUCCESS); - - status = kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_OFF, 0); - device->flags &= ~GSL_FLAGS_STARTED; - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_getproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) -{ - int status = GSL_FAILURE; - // unreferenced formal parameter - (void) sizebytes; - - if (type == GSL_PROP_DEVICE_INFO) - { - gsl_devinfo_t *devinfo = (gsl_devinfo_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_devinfo_t)); - - devinfo->device_id = device->id; - devinfo->chip_id = (gsl_chipid_t)device->chip_id; -#ifndef GSL_NO_MMU - devinfo->mmu_enabled = kgsl_mmu_isenabled(&device->mmu); -#endif - if (z160_version == 1) - devinfo->high_precision = 1; - else - devinfo->high_precision = 0; - - status = GSL_SUCCESS; - } - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_setproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) -{ - int status = GSL_FAILURE; - - // unreferenced formal parameters - (void) device; - - if (type == GSL_PROP_DEVICE_POWER) - { - gsl_powerprop_t *power = (gsl_powerprop_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_powerprop_t)); - - if (!(device->flags & GSL_FLAGS_SAFEMODE)) - { - kgsl_hal_setpowerstate(device->id, power->flags, power->value); - } - - status = GSL_SUCCESS; - } - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_idle(gsl_device_t *device, unsigned int timeout) -{ - if ( device->flags & GSL_FLAGS_STARTED ) - { - for ( ; ; ) - { - gsl_timestamp_t retired = kgsl_cmdstream_readtimestamp0( device->id, GSL_TIMESTAMP_RETIRED ); - gsl_timestamp_t ts_diff = retired - device->current_timestamp; - if ( ts_diff >= 0 || ts_diff < -GSL_TIMESTAMP_EPSILON ) - break; - kos_sleep(10); - } - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_regread(gsl_device_t *device, unsigned int offsetwords, unsigned int *value) -{ - // G12 MH register values can only be retrieved via dedicated read registers - if ((offsetwords >= ADDR_MH_ARBITER_CONFIG && offsetwords <= ADDR_MH_AXI_HALT_CONTROL) || - (offsetwords >= ADDR_MH_MMU_CONFIG && offsetwords <= ADDR_MH_MMU_MPU_END)) - { -#ifdef _Z180 - device->ftbl.device_regwrite(device, (ADDR_VGC_MH_READ_ADDR >> 2), offsetwords); - GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, (ADDR_VGC_MH_READ_ADDR >> 2), value); -#else - device->ftbl.device_regwrite(device, (ADDR_MMU_READ_ADDR >> 2), offsetwords); - GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, (ADDR_MMU_READ_DATA >> 2), value); -#endif - } - else - { - GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_regwrite(gsl_device_t *device, unsigned int offsetwords, unsigned int value) -{ - // G12 MH registers can only be written via the command window - if ((offsetwords >= ADDR_MH_ARBITER_CONFIG && offsetwords <= ADDR_MH_AXI_HALT_CONTROL) || - (offsetwords >= ADDR_MH_MMU_CONFIG && offsetwords <= ADDR_MH_MMU_MPU_END)) - { - kgsl_cmdwindow_write0(device->id, GSL_CMDWINDOW_MMU, offsetwords, value); - } - else - { - GSL_HAL_REG_WRITE(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); - } - - // idle device when running in safe mode - if (device->flags & GSL_FLAGS_SAFEMODE) - { - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_waitirq(gsl_device_t *device, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout) -{ - int status = GSL_FAILURE_NOTSUPPORTED; -#ifdef VG_HDK - (void)timeout; -#endif - -#ifndef _Z180 - if (intr_id == GSL_INTR_G12_G2D || intr_id == GSL_INTR_G12_FBC) -#else - if (intr_id == GSL_INTR_G12_G2D) -#endif //_Z180 - { -#ifndef VG_HDK - if (kgsl_intr_isenabled(&device->intr, intr_id) == GSL_SUCCESS) -#endif - { - // wait until intr completion event is received and check that - // the interrupt is still enabled. If event is received, but - // interrupt is not enabled any more, the driver is shutting - // down and event structure is not valid anymore. -#ifndef VG_HDK - if (kos_event_wait(device->intr.evnt[intr_id], timeout) == OS_SUCCESS && kgsl_intr_isenabled(&device->intr, intr_id) == GSL_SUCCESS) -#endif - { - unsigned int cntrs; - int i; - kgsl_device_active(device); -#ifndef VG_HDK - kos_event_reset(device->intr.evnt[intr_id]); - device->ftbl.device_regread(device, (ADDR_VGC_IRQ_ACTIVE_CNT >> 2), &cntrs); -#else - device->ftbl.device_regread(device, (0x38 >> 2), &cntrs); -#endif - - for (i = 0; i < GSL_G12_INTR_COUNT; i++) - { - int intrcnt = cntrs >> ((8 * i)) & 255; - - // maximum allowed counter value is 254. if set to 255 then something has gone wrong - if (intrcnt && (intrcnt < 0xFF)) - { - device->intrcnt[i] += intrcnt; - } - } - - *count = device->intrcnt[intr_id - GSL_INTR_G12_MH]; - device->intrcnt[intr_id - GSL_INTR_G12_MH] = 0; - status = GSL_SUCCESS; - } -#ifndef VG_HDK - else - { - status = GSL_FAILURE_TIMEOUT; - } -#endif - } - } - else if(intr_id == GSL_INTR_FOOBAR) - { - if (kgsl_intr_isenabled(&device->intr, GSL_INTR_G12_G2D) == GSL_SUCCESS) - { - kos_event_signal(device->intr.evnt[GSL_INTR_G12_G2D]); - } - } - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_g12_waittimestamp(gsl_device_t *device, gsl_timestamp_t timestamp, unsigned int timeout) -{ -#ifndef _LINUX - return kos_event_wait( device->timestamp_event, timeout ); -#else - int status = wait_event_interruptible_timeout(device->timestamp_waitq, - kgsl_cmdstream_check_timestamp(device->id, timestamp), - msecs_to_jiffies(timeout)); - if (status > 0) - return GSL_SUCCESS; - else - return GSL_FAILURE; -#endif -} - -int -kgsl_g12_getfunctable(gsl_functable_t *ftbl) -{ - ftbl->device_init = kgsl_g12_init; - ftbl->device_close = kgsl_g12_close; - ftbl->device_destroy = kgsl_g12_destroy; - ftbl->device_start = kgsl_g12_start; - ftbl->device_stop = kgsl_g12_stop; - ftbl->device_getproperty = kgsl_g12_getproperty; - ftbl->device_setproperty = kgsl_g12_setproperty; - ftbl->device_idle = kgsl_g12_idle; - ftbl->device_regread = kgsl_g12_regread; - ftbl->device_regwrite = kgsl_g12_regwrite; - ftbl->device_waitirq = kgsl_g12_waitirq; - ftbl->device_waittimestamp = kgsl_g12_waittimestamp; - ftbl->device_runpending = NULL; - ftbl->device_addtimestamp = kgsl_g12_addtimestamp; - ftbl->intr_isr = kgsl_g12_isr; - ftbl->mmu_tlbinvalidate = kgsl_g12_tlbinvalidate; - ftbl->mmu_setpagetable = kgsl_g12_setpagetable; - ftbl->cmdstream_issueibcmds = kgsl_g12_issueibcmds; - ftbl->context_create = kgsl_g12_context_create; - ftbl->context_destroy = kgsl_g12_context_destroy; - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -static void addmarker(gsl_z1xx_t* z1xx) -{ - KOS_ASSERT(z1xx); - { - unsigned int *p = z1xx->cmdbuf[z1xx->curr]; - /* todo: use symbolic values */ - p[z1xx->offs++] = 0x7C000176; - p[z1xx->offs++] = (0x8000|5); - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = 0x7C000176; - p[z1xx->offs++] = 5; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - } -} - -//---------------------------------------------------------------------------- -static void beginpacket(gsl_z1xx_t* z1xx, gpuaddr_t cmd, unsigned int nextcnt) -{ - unsigned int *p = z1xx->cmdbuf[z1xx->curr]; - - p[z1xx->offs++] = 0x7C000176; - p[z1xx->offs++] = 5; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = 0x7C000275; - p[z1xx->offs++] = cmd; - p[z1xx->offs++] = 0x1000|nextcnt; // nextcount - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; - p[z1xx->offs++] = ADDR_VGV3_LAST<<24; -} - -//---------------------------------------------------------------------------- - -static int -kgsl_g12_issueibcmds(gsl_device_t* device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, unsigned int flags) -{ - unsigned int ofs = PACKETSIZE_STATESTREAM*sizeof(unsigned int); - unsigned int cnt = 5; - unsigned int cmd = ibaddr; - unsigned int nextbuf = (g_z1xx.curr+1)%GSL_HAL_NUMCMDBUFFERS; - unsigned int nextaddr = g_z1xx.cmdbufdesc[nextbuf].gpuaddr; - unsigned int nextcnt = 0x9000|5; - gsl_memdesc_t tmp = {0}; - gsl_timestamp_t processed_timestamp; - - (void) flags; - - // read what is the latest timestamp device have processed - GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (int *)&processed_timestamp); - - /* wait for the next buffer's timestamp to occur */ - while(processed_timestamp < g_z1xx.timestamp[nextbuf]) - { -#ifndef _LINUX - kos_event_wait(device->timestamp_event, 1000); - kos_event_reset(device->timestamp_event); -#else - kgsl_cmdstream_waittimestamp(device->id, g_z1xx.timestamp[nextbuf], 1000); -#endif - GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (int *)&processed_timestamp); - } - - *timestamp = g_z1xx.timestamp[nextbuf] = device->current_timestamp + 1; - - /* context switch */ - if (drawctxt_index != (int)g_z1xx.prevctx) - { - cnt = PACKETSIZE_STATESTREAM; - ofs = 0; - } - g_z1xx.prevctx = drawctxt_index; - - g_z1xx.offs = 10; - beginpacket(&g_z1xx, cmd+ofs, cnt); - - tmp.gpuaddr=ibaddr+(sizedwords*sizeof(unsigned int)); - kgsl_sharedmem_write0(&tmp, 4, &nextaddr, 4, false); - kgsl_sharedmem_write0(&tmp, 8, &nextcnt, 4, false); - - /* sync mem */ - kgsl_sharedmem_write0((const gsl_memdesc_t *)&g_z1xx.cmdbufdesc[g_z1xx.curr], 0, g_z1xx.cmdbuf[g_z1xx.curr], (512 + 13) * sizeof(unsigned int), false); - - g_z1xx.offs = 0; - g_z1xx.curr = nextbuf; - - /* increment mark counter */ -#ifdef V3_SYNC - if (device->timestamp == device->current_timestamp) - { - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, flags); - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); - } -#else - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, flags); - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); -#endif - - /* increment consumed timestamp */ - device->current_timestamp++; - kgsl_sharedmem_write0(&device->memstore, GSL_DEVICE_MEMSTORE_OFFSET(soptimestamp), &device->current_timestamp, 4, 0); - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -static int -kgsl_g12_context_create(gsl_device_t* device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags) -{ - int status = 0; - int i; - int cmd; - gsl_flags_t gslflags = (GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_ALIGNPAGE); - - // unreferenced formal parameters - (void) device; - (void) type; - //(void) drawctxt_id; - (void) flags; - - kgsl_device_active(device); - - if (g_z1xx.numcontext==0) - { - g_z1xx.nextUniqueContextID = 0; - /* todo: move this to device create or start. Error checking!! */ - for (i=0;iirqthread_event, GSL_IRQ_TIMEOUT)==GSL_SUCCESS) - { - kgsl_g12_waitirq(device, GSL_INTR_G12_G2D, &irq_count, GSL_IRQ_TIMEOUT); -#else - - if( kgsl_g12_waitirq(device, GSL_INTR_G12_G2D, &irq_count, GSL_IRQ_TIMEOUT) == GSL_SUCCESS ) - { -#endif - /* Read a timestamp value */ -#ifdef VG_HDK - timestamp = device->timestamp; -#else - GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (int *)×tamp); -#endif - /* Increase the timestamp value */ - timestamp += irq_count; - - /* Write the new timestamp value */ - device->timestamp = timestamp; - kgsl_sharedmem_write0(&device->memstore, GSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp), ×tamp, 4, false); - -#ifdef V3_SYNC - if (device->current_timestamp > device->timestamp) - { - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 2); - kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); - } -#endif - - /* Notify timestamp event */ -#ifndef _LINUX - kos_event_signal( device->timestamp_event ); -#else - wake_up_interruptible_all(&(device->timestamp_waitq)); -#endif - } - else - { - /* Timeout */ - - - if(!(device->flags&GSL_FLAGS_INITIALIZED)) - { - /* if device is closed -> thread exit */ -#if defined(__SYMBIAN32__) - device->irq_thread = 0; -#endif - return; - } - } - } -} -#endif - -//---------------------------------------------------------------------------- - -static int -kgsl_g12_addtimestamp(gsl_device_t* device, gsl_timestamp_t *timestamp) -{ - device->current_timestamp++; - *timestamp = device->current_timestamp; - - return (GSL_SUCCESS); -} -#endif diff --git a/drivers/mxc/amd-gpu/common/gsl_intrmgr.c b/drivers/mxc/amd-gpu/common/gsl_intrmgr.c deleted file mode 100644 index 4ea3bab594d..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_intrmgr.c +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" - -////////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#define GSL_INTRID_VALIDATE(id) (((id) < 0) || ((id) >= GSL_INTR_COUNT)) - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -static const gsl_intrblock_reg_t * -kgsl_intr_id2block(gsl_intrid_t id) -{ - const gsl_intrblock_reg_t *block; - int i; - - // interrupt id to hw block - for (i = 0; i < GSL_INTR_BLOCK_COUNT; i++) - { - block = &gsl_cfg_intrblock_reg[i]; - - if (block->first_id <= id && id <= block->last_id) - { - return (block); - } - } - - return (NULL); -} - -//---------------------------------------------------------------------------- - -void -kgsl_intr_decode(gsl_device_t *device, gsl_intrblock_t block_id) -{ - const gsl_intrblock_reg_t *block = &gsl_cfg_intrblock_reg[block_id]; - gsl_intrid_t id; - unsigned int status; - - // read the block's interrupt status bits - /* exclude CP block here to avoid hang in heavy loading with VPU+GPU */ - if ((block_id == GSL_INTR_BLOCK_YDX_CP) && (device->flags & GSL_FLAGS_STARTED)) { - status = 0x80000000; - } else { - device->ftbl.device_regread(device, block->status_reg, &status); - } - - // mask off any interrupts which are disabled - status &= device->intr.enabled[block->id]; - - // acknowledge the block's interrupts - device->ftbl.device_regwrite(device, block->clear_reg, status); - - // loop through the block's masks, determine which interrupt bits are active, and call callback (or TODO queue DPC) - for (id = block->first_id; id <= block->last_id; id++) - { - if (status & gsl_cfg_intr_mask[id]) - { - device->intr.handler[id].callback(id, device->intr.handler[id].cookie); - } - } -} - -//---------------------------------------------------------------------------- - -KGSL_API void -kgsl_intr_isr(gsl_device_t *device) -{ - if (device->intr.flags & GSL_FLAGS_INITIALIZED) { - kgsl_device_active(device); - device->ftbl.intr_isr(device); - } -} - -//---------------------------------------------------------------------------- - -int kgsl_intr_init(gsl_device_t *device) -{ - if (device->ftbl.intr_isr == NULL) - { - return (GSL_FAILURE_BADPARAM); - } - - if (device->intr.flags & GSL_FLAGS_INITIALIZED) - { - return (GSL_SUCCESS); - } - - device->intr.device = device; - device->intr.flags |= GSL_FLAGS_INITIALIZED; - - // os_interrupt_setcallback(YAMATO_INTR, kgsl_intr_isr); - // os_interrupt_enable(YAMATO_INTR); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int kgsl_intr_close(gsl_device_t *device) -{ - const gsl_intrblock_reg_t *block; - int i, id; - - if (device->intr.flags & GSL_FLAGS_INITIALIZED) - { - // check if there are any enabled interrupts lingering around - for (i = 0; i < GSL_INTR_BLOCK_COUNT; i++) - { - if (device->intr.enabled[i]) - { - block = &gsl_cfg_intrblock_reg[i]; - - // loop through the block's masks, disable interrupts which active - for (id = block->first_id; id <= block->last_id; id++) - { - if (device->intr.enabled[i] & gsl_cfg_intr_mask[id]) - { - kgsl_intr_disable(&device->intr, (gsl_intrid_t)id); - } - } - } - } - - kos_memset(&device->intr, 0, sizeof(gsl_intr_t)); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int kgsl_intr_enable(gsl_intr_t *intr, gsl_intrid_t id) -{ - const gsl_intrblock_reg_t *block; - unsigned int mask; - unsigned int enabled; - - if (GSL_INTRID_VALIDATE(id)) - { - return (GSL_FAILURE_BADPARAM); - } - - if (intr->handler[id].callback == NULL) - { - return (GSL_FAILURE_NOTINITIALIZED); - } - - block = kgsl_intr_id2block(id); - if (block == NULL) - { - return (GSL_FAILURE_SYSTEMERROR); - } - - mask = gsl_cfg_intr_mask[id]; - enabled = intr->enabled[block->id]; - - if (mask && !(enabled & mask)) - { - intr->evnt[id] = kos_event_create(0); - - enabled |= mask; - intr->enabled[block->id] = enabled; - intr->device->ftbl.device_regwrite(intr->device, block->mask_reg, enabled); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int kgsl_intr_disable(gsl_intr_t *intr, gsl_intrid_t id) -{ - const gsl_intrblock_reg_t *block; - unsigned int mask; - unsigned int enabled; - - if (GSL_INTRID_VALIDATE(id)) - { - return (GSL_FAILURE_BADPARAM); - } - - if (intr->handler[id].callback == NULL) - { - return (GSL_FAILURE_NOTINITIALIZED); - } - - block = kgsl_intr_id2block(id); - if (block == NULL) - { - return (GSL_FAILURE_SYSTEMERROR); - } - - mask = gsl_cfg_intr_mask[id]; - enabled = intr->enabled[block->id]; - - if (enabled & mask) - { - enabled &= ~mask; - intr->enabled[block->id] = enabled; - intr->device->ftbl.device_regwrite(intr->device, block->mask_reg, enabled); - - kos_event_signal(intr->evnt[id]); // wake up waiting threads before destroying the event - kos_event_destroy(intr->evnt[id]); - intr->evnt[id] = 0; - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_intr_attach(gsl_intr_t *intr, gsl_intrid_t id, gsl_intr_callback_t callback, void *cookie) -{ - if (GSL_INTRID_VALIDATE(id) || callback == NULL) - { - return (GSL_FAILURE_BADPARAM); - } - - if (intr->handler[id].callback != NULL) - { - if (intr->handler[id].callback == callback && intr->handler[id].cookie == cookie) - { - return (GSL_FAILURE_ALREADYINITIALIZED); - } - else - { - return (GSL_FAILURE_NOMOREAVAILABLE); - } - } - - intr->handler[id].callback = callback; - intr->handler[id].cookie = cookie; - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_intr_detach(gsl_intr_t *intr, gsl_intrid_t id) -{ - if (GSL_INTRID_VALIDATE(id)) - { - return (GSL_FAILURE_BADPARAM); - } - - if (intr->handler[id].callback == NULL) - { - return (GSL_FAILURE_NOTINITIALIZED); - } - - kgsl_intr_disable(intr, id); - - intr->handler[id].callback = NULL; - intr->handler[id].cookie = NULL; - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_intr_isenabled(gsl_intr_t *intr, gsl_intrid_t id) -{ - int status = GSL_FAILURE; - const gsl_intrblock_reg_t *block = kgsl_intr_id2block(id); - - if (block != NULL) - { - // check if interrupt is enabled - if (intr->enabled[block->id] & gsl_cfg_intr_mask[id]) - { - status = GSL_SUCCESS; - } - } - - return (status); -} diff --git a/drivers/mxc/amd-gpu/common/gsl_log.c b/drivers/mxc/amd-gpu/common/gsl_log.c deleted file mode 100644 index 79a14a5f4b2..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_log.c +++ /dev/null @@ -1,591 +0,0 @@ -/* Copyright (c) 2002,2008-2009, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#ifdef GSL_LOG - -#define _CRT_SECURE_NO_WARNINGS - -#include -#include -#include -#include "gsl.h" - -#define KGSL_OUTPUT_TYPE_MEMBUF 0 -#define KGSL_OUTPUT_TYPE_STDOUT 1 -#define KGSL_OUTPUT_TYPE_FILE 2 - -#define REG_OUTPUT( X ) case X: b += sprintf( b, "%s", #X ); break; -#define INTRID_OUTPUT( X ) case X: b += sprintf( b, "%s", #X ); break; - -typedef struct log_output -{ - unsigned char type; - unsigned int flags; - oshandle_t file; - - struct log_output* next; -} log_output_t; - -static log_output_t* outputs = NULL; - -static oshandle_t log_mutex = NULL; -static char buffer[256]; -static char buffer2[256]; -static int log_initialized = 0; - -//---------------------------------------------------------------------------- - -int kgsl_log_init() -{ - log_mutex = kos_mutex_create( "log_mutex" ); - - log_initialized = 1; - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -int kgsl_log_close() -{ - if( !log_initialized ) return GSL_SUCCESS; - - // Go throught output list and free every node - while( outputs != NULL ) - { - log_output_t* temp = outputs->next; - - switch( outputs->type ) - { - case KGSL_OUTPUT_TYPE_FILE: - kos_fclose( outputs->file ); - break; - } - - kos_free( outputs ); - outputs = temp; - } - - kos_mutex_free( log_mutex ); - - log_initialized = 0; - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -int kgsl_log_open_stdout( unsigned int log_flags ) -{ - log_output_t* output; - - if( !log_initialized ) return GSL_SUCCESS; - - output = kos_malloc( sizeof( log_output_t ) ); - output->type = KGSL_OUTPUT_TYPE_STDOUT; - output->flags = log_flags; - - // Add to the list - if( outputs == NULL ) - { - // First node in the list. - outputs = output; - output->next = NULL; - } - else - { - // Add to the start of the list - output->next = outputs; - outputs = output; - } - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -int kgsl_log_open_membuf( int* memBufId, unsigned int log_flags ) -{ - // TODO - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -int kgsl_log_open_file( char* filename, unsigned int log_flags ) -{ - log_output_t* output; - - if( !log_initialized ) return GSL_SUCCESS; - - output = kos_malloc( sizeof( log_output_t ) ); - output->type = KGSL_OUTPUT_TYPE_FILE; - output->flags = log_flags; - output->file = kos_fopen( filename, "w" ); - - // Add to the list - if( outputs == NULL ) - { - // First node in the list. - outputs = output; - output->next = NULL; - } - else - { - // Add to the start of the list - output->next = outputs; - outputs = output; - } - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- - -int kgsl_log_flush_membuf( char* filename, int memBufId ) -{ - // TODO - - return GSL_SUCCESS; -} -//---------------------------------------------------------------------------- - -int kgsl_log_write( unsigned int log_flags, char* format, ... ) -{ - char *c = format; - char *b = buffer; - char *p1, *p2; - log_output_t* output; - va_list arguments; - - if( !log_initialized ) return GSL_SUCCESS; - - // Acquire mutex lock as we are using shared buffer for the string parsing - kos_mutex_lock( log_mutex ); - - // Add separator - *(b++) = '|'; *(b++) = ' '; - - va_start( arguments, format ); - - while( 1 ) - { - // Find the first occurence of % - p1 = strchr( c, '%' ); - if( !p1 ) - { - // No more % characters -> copy rest of the string - strcpy( b, c ); - - break; - } - - // Find the second occurence of % and handle the string until that point - p2 = strchr( p1+1, '%' ); - - // If not found, just use the end of the buffer - if( !p2 ) p2 = strchr( p1+1, '\0' ); - - // Break the string to this point - kos_memcpy( buffer2, c, p2-c ); - *(buffer2+(unsigned int)(p2-c)) = '\0'; - - switch( *(p1+1) ) - { - // gsl_memdesc_t - case 'M': - { - gsl_memdesc_t val = va_arg( arguments, gsl_memdesc_t ); - // Handle string before %M - kos_memcpy( b, c, p1-c ); - b += (unsigned int)p1-(unsigned int)c; - // Replace %M - b += sprintf( b, "[hostptr=0x%08x, gpuaddr=0x%08x]", val.hostptr, val.gpuaddr ); - // Handle string after %M - kos_memcpy( b, p1+2, p2-(p1+2) ); - b += (unsigned int)p2-(unsigned int)(p1+2); - *b = '\0'; - } - break; - - // GSL_SUCCESS/GSL_FAILURE - case 'B': - { - int val = va_arg( arguments, int ); - // Handle string before %B - kos_memcpy( b, c, p1-c ); - b += (unsigned int)p1-(unsigned int)c; - // Replace %B - if( val == GSL_SUCCESS ) - b += sprintf( b, "%s", "GSL_SUCCESS" ); - else - b += sprintf( b, "%s", "GSL_FAILURE" ); - // Handle string after %B - kos_memcpy( b, p1+2, p2-(p1+2) ); - b += (unsigned int)p2-(unsigned int)(p1+2); - *b = '\0'; - } - break; - - // gsl_deviceid_t - case 'D': - { - gsl_deviceid_t val = va_arg( arguments, gsl_deviceid_t ); - // Handle string before %D - kos_memcpy( b, c, p1-c ); - b += (unsigned int)p1-(unsigned int)c; - // Replace %D - switch( val ) - { - case GSL_DEVICE_ANY: - b += sprintf( b, "%s", "GSL_DEVICE_ANY" ); - break; - case GSL_DEVICE_YAMATO: - b += sprintf( b, "%s", "GSL_DEVICE_YAMATO" ); - break; - case GSL_DEVICE_G12: - b += sprintf( b, "%s", "GSL_DEVICE_G12" ); - break; - default: - b += sprintf( b, "%s", "UNKNOWN DEVICE" ); - break; - } - // Handle string after %D - kos_memcpy( b, p1+2, p2-(p1+2) ); - b += (unsigned int)p2-(unsigned int)(p1+2); - *b = '\0'; - } - break; - - // gsl_intrid_t - case 'I': - { - unsigned int val = va_arg( arguments, unsigned int ); - // Handle string before %I - kos_memcpy( b, c, p1-c ); - b += (unsigned int)p1-(unsigned int)c; - // Replace %I - switch( val ) - { - INTRID_OUTPUT( GSL_INTR_YDX_MH_AXI_READ_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_MH_AXI_WRITE_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_MH_MMU_PAGE_FAULT ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_SW_INT ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_T0_PACKET_IN_IB ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_OPCODE_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_RESERVED_BIT_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_IB_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_IB2_INT ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_IB1_INT ); - INTRID_OUTPUT( GSL_INTR_YDX_CP_RING_BUFFER ); - INTRID_OUTPUT( GSL_INTR_YDX_RBBM_READ_ERROR ); - INTRID_OUTPUT( GSL_INTR_YDX_RBBM_DISPLAY_UPDATE ); - INTRID_OUTPUT( GSL_INTR_YDX_RBBM_GUI_IDLE ); - INTRID_OUTPUT( GSL_INTR_YDX_SQ_PS_WATCHDOG ); - INTRID_OUTPUT( GSL_INTR_YDX_SQ_VS_WATCHDOG ); - INTRID_OUTPUT( GSL_INTR_G12_MH ); - INTRID_OUTPUT( GSL_INTR_G12_G2D ); - INTRID_OUTPUT( GSL_INTR_G12_FIFO ); -#ifndef _Z180 - INTRID_OUTPUT( GSL_INTR_G12_FBC ); -#endif // _Z180 - INTRID_OUTPUT( GSL_INTR_G12_MH_AXI_READ_ERROR ); - INTRID_OUTPUT( GSL_INTR_G12_MH_AXI_WRITE_ERROR ); - INTRID_OUTPUT( GSL_INTR_G12_MH_MMU_PAGE_FAULT ); - INTRID_OUTPUT( GSL_INTR_COUNT ); - INTRID_OUTPUT( GSL_INTR_FOOBAR ); - - default: - b += sprintf( b, "%s", "UNKNOWN INTERRUPT ID" ); - break; - } - // Handle string after %I - kos_memcpy( b, p1+2, p2-(p1+2) ); - b += (unsigned int)p2-(unsigned int)(p1+2); - *b = '\0'; - } - break; - - // Register offset - case 'R': - { - unsigned int val = va_arg( arguments, unsigned int ); - - // Handle string before %R - kos_memcpy( b, c, p1-c ); - b += (unsigned int)p1-(unsigned int)c; - // Replace %R - switch( val ) - { - REG_OUTPUT( mmPA_CL_VPORT_XSCALE ); REG_OUTPUT( mmPA_CL_VPORT_XOFFSET ); REG_OUTPUT( mmPA_CL_VPORT_YSCALE ); - REG_OUTPUT( mmPA_CL_VPORT_YOFFSET ); REG_OUTPUT( mmPA_CL_VPORT_ZSCALE ); REG_OUTPUT( mmPA_CL_VPORT_ZOFFSET ); - REG_OUTPUT( mmPA_CL_VTE_CNTL ); REG_OUTPUT( mmPA_CL_CLIP_CNTL ); REG_OUTPUT( mmPA_CL_GB_VERT_CLIP_ADJ ); - REG_OUTPUT( mmPA_CL_GB_VERT_DISC_ADJ ); REG_OUTPUT( mmPA_CL_GB_HORZ_CLIP_ADJ ); REG_OUTPUT( mmPA_CL_GB_HORZ_DISC_ADJ ); - REG_OUTPUT( mmPA_CL_ENHANCE ); REG_OUTPUT( mmPA_SC_ENHANCE ); REG_OUTPUT( mmPA_SU_VTX_CNTL ); - REG_OUTPUT( mmPA_SU_POINT_SIZE ); REG_OUTPUT( mmPA_SU_POINT_MINMAX ); REG_OUTPUT( mmPA_SU_LINE_CNTL ); - REG_OUTPUT( mmPA_SU_FACE_DATA ); REG_OUTPUT( mmPA_SU_SC_MODE_CNTL ); REG_OUTPUT( mmPA_SU_POLY_OFFSET_FRONT_SCALE ); - REG_OUTPUT( mmPA_SU_POLY_OFFSET_FRONT_OFFSET ); REG_OUTPUT( mmPA_SU_POLY_OFFSET_BACK_SCALE ); REG_OUTPUT( mmPA_SU_POLY_OFFSET_BACK_OFFSET ); - REG_OUTPUT( mmPA_SU_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmPA_SU_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmPA_SU_PERFCOUNTER2_SELECT ); - REG_OUTPUT( mmPA_SU_PERFCOUNTER3_SELECT ); REG_OUTPUT( mmPA_SU_PERFCOUNTER0_LOW ); REG_OUTPUT( mmPA_SU_PERFCOUNTER0_HI ); - REG_OUTPUT( mmPA_SU_PERFCOUNTER1_LOW ); REG_OUTPUT( mmPA_SU_PERFCOUNTER1_HI ); REG_OUTPUT( mmPA_SU_PERFCOUNTER2_LOW ); - REG_OUTPUT( mmPA_SU_PERFCOUNTER2_HI ); REG_OUTPUT( mmPA_SU_PERFCOUNTER3_LOW ); REG_OUTPUT( mmPA_SU_PERFCOUNTER3_HI ); - REG_OUTPUT( mmPA_SC_WINDOW_OFFSET ); REG_OUTPUT( mmPA_SC_AA_CONFIG ); REG_OUTPUT( mmPA_SC_AA_MASK ); - REG_OUTPUT( mmPA_SC_LINE_STIPPLE ); REG_OUTPUT( mmPA_SC_LINE_CNTL ); REG_OUTPUT( mmPA_SC_WINDOW_SCISSOR_TL ); - REG_OUTPUT( mmPA_SC_WINDOW_SCISSOR_BR ); REG_OUTPUT( mmPA_SC_SCREEN_SCISSOR_TL ); REG_OUTPUT( mmPA_SC_SCREEN_SCISSOR_BR ); - REG_OUTPUT( mmPA_SC_VIZ_QUERY ); REG_OUTPUT( mmPA_SC_VIZ_QUERY_STATUS ); REG_OUTPUT( mmPA_SC_LINE_STIPPLE_STATE ); - REG_OUTPUT( mmPA_SC_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmPA_SC_PERFCOUNTER0_LOW ); REG_OUTPUT( mmPA_SC_PERFCOUNTER0_HI ); - REG_OUTPUT( mmPA_CL_CNTL_STATUS ); REG_OUTPUT( mmPA_SU_CNTL_STATUS ); REG_OUTPUT( mmPA_SC_CNTL_STATUS ); - REG_OUTPUT( mmPA_SU_DEBUG_CNTL ); REG_OUTPUT( mmPA_SU_DEBUG_DATA ); REG_OUTPUT( mmPA_SC_DEBUG_CNTL ); - REG_OUTPUT( mmPA_SC_DEBUG_DATA ); REG_OUTPUT( mmGFX_COPY_STATE ); REG_OUTPUT( mmVGT_DRAW_INITIATOR ); - REG_OUTPUT( mmVGT_EVENT_INITIATOR ); REG_OUTPUT( mmVGT_DMA_BASE ); REG_OUTPUT( mmVGT_DMA_SIZE ); - REG_OUTPUT( mmVGT_BIN_BASE ); REG_OUTPUT( mmVGT_BIN_SIZE ); REG_OUTPUT( mmVGT_CURRENT_BIN_ID_MIN ); - REG_OUTPUT( mmVGT_CURRENT_BIN_ID_MAX ); REG_OUTPUT( mmVGT_IMMED_DATA ); REG_OUTPUT( mmVGT_MAX_VTX_INDX ); - REG_OUTPUT( mmVGT_MIN_VTX_INDX ); REG_OUTPUT( mmVGT_INDX_OFFSET ); REG_OUTPUT( mmVGT_VERTEX_REUSE_BLOCK_CNTL ); - REG_OUTPUT( mmVGT_OUT_DEALLOC_CNTL ); REG_OUTPUT( mmVGT_MULTI_PRIM_IB_RESET_INDX ); REG_OUTPUT( mmVGT_ENHANCE ); - REG_OUTPUT( mmVGT_VTX_VECT_EJECT_REG ); REG_OUTPUT( mmVGT_LAST_COPY_STATE ); REG_OUTPUT( mmVGT_DEBUG_CNTL ); - REG_OUTPUT( mmVGT_DEBUG_DATA ); REG_OUTPUT( mmVGT_CNTL_STATUS ); REG_OUTPUT( mmVGT_CRC_SQ_DATA ); - REG_OUTPUT( mmVGT_CRC_SQ_CTRL ); REG_OUTPUT( mmVGT_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmVGT_PERFCOUNTER1_SELECT ); - REG_OUTPUT( mmVGT_PERFCOUNTER2_SELECT ); REG_OUTPUT( mmVGT_PERFCOUNTER3_SELECT ); REG_OUTPUT( mmVGT_PERFCOUNTER0_LOW ); - REG_OUTPUT( mmVGT_PERFCOUNTER1_LOW ); REG_OUTPUT( mmVGT_PERFCOUNTER2_LOW ); REG_OUTPUT( mmVGT_PERFCOUNTER3_LOW ); - REG_OUTPUT( mmVGT_PERFCOUNTER0_HI ); REG_OUTPUT( mmVGT_PERFCOUNTER1_HI ); REG_OUTPUT( mmVGT_PERFCOUNTER2_HI ); - REG_OUTPUT( mmVGT_PERFCOUNTER3_HI ); REG_OUTPUT( mmTC_CNTL_STATUS ); REG_OUTPUT( mmTCR_CHICKEN ); - REG_OUTPUT( mmTCF_CHICKEN ); REG_OUTPUT( mmTCM_CHICKEN ); REG_OUTPUT( mmTCR_PERFCOUNTER0_SELECT ); - REG_OUTPUT( mmTCR_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmTCR_PERFCOUNTER0_HI ); REG_OUTPUT( mmTCR_PERFCOUNTER1_HI ); - REG_OUTPUT( mmTCR_PERFCOUNTER0_LOW ); REG_OUTPUT( mmTCR_PERFCOUNTER1_LOW ); REG_OUTPUT( mmTP_TC_CLKGATE_CNTL ); - REG_OUTPUT( mmTPC_CNTL_STATUS ); REG_OUTPUT( mmTPC_DEBUG0 ); REG_OUTPUT( mmTPC_DEBUG1 ); - REG_OUTPUT( mmTPC_CHICKEN ); REG_OUTPUT( mmTP0_CNTL_STATUS ); REG_OUTPUT( mmTP0_DEBUG ); - REG_OUTPUT( mmTP0_CHICKEN ); REG_OUTPUT( mmTP0_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmTP0_PERFCOUNTER0_HI ); - REG_OUTPUT( mmTP0_PERFCOUNTER0_LOW ); REG_OUTPUT( mmTP0_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmTP0_PERFCOUNTER1_HI ); - REG_OUTPUT( mmTP0_PERFCOUNTER1_LOW ); REG_OUTPUT( mmTCM_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmTCM_PERFCOUNTER1_SELECT ); - REG_OUTPUT( mmTCM_PERFCOUNTER0_HI ); REG_OUTPUT( mmTCM_PERFCOUNTER1_HI ); REG_OUTPUT( mmTCM_PERFCOUNTER0_LOW ); - REG_OUTPUT( mmTCM_PERFCOUNTER1_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER1_SELECT ); - REG_OUTPUT( mmTCF_PERFCOUNTER2_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER3_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER4_SELECT ); - REG_OUTPUT( mmTCF_PERFCOUNTER5_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER6_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER7_SELECT ); - REG_OUTPUT( mmTCF_PERFCOUNTER8_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER9_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER10_SELECT ); - REG_OUTPUT( mmTCF_PERFCOUNTER11_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER0_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER1_HI ); - REG_OUTPUT( mmTCF_PERFCOUNTER2_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER3_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER4_HI ); - REG_OUTPUT( mmTCF_PERFCOUNTER5_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER6_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER7_HI ); - REG_OUTPUT( mmTCF_PERFCOUNTER8_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER9_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER10_HI ); - REG_OUTPUT( mmTCF_PERFCOUNTER11_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER0_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER1_LOW ); - REG_OUTPUT( mmTCF_PERFCOUNTER2_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER3_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER4_LOW ); - REG_OUTPUT( mmTCF_PERFCOUNTER5_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER6_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER7_LOW ); - REG_OUTPUT( mmTCF_PERFCOUNTER8_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER9_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER10_LOW ); - REG_OUTPUT( mmTCF_PERFCOUNTER11_LOW ); REG_OUTPUT( mmTCF_DEBUG ); REG_OUTPUT( mmTCA_FIFO_DEBUG ); - REG_OUTPUT( mmTCA_PROBE_DEBUG ); REG_OUTPUT( mmTCA_TPC_DEBUG ); REG_OUTPUT( mmTCB_CORE_DEBUG ); - REG_OUTPUT( mmTCB_TAG0_DEBUG ); REG_OUTPUT( mmTCB_TAG1_DEBUG ); REG_OUTPUT( mmTCB_TAG2_DEBUG ); - REG_OUTPUT( mmTCB_TAG3_DEBUG ); REG_OUTPUT( mmTCB_FETCH_GEN_SECTOR_WALKER0_DEBUG ); REG_OUTPUT( mmTCB_FETCH_GEN_WALKER_DEBUG ); - REG_OUTPUT( mmTCB_FETCH_GEN_PIPE0_DEBUG ); REG_OUTPUT( mmTCD_INPUT0_DEBUG ); REG_OUTPUT( mmTCD_DEGAMMA_DEBUG ); - REG_OUTPUT( mmTCD_DXTMUX_SCTARB_DEBUG ); REG_OUTPUT( mmTCD_DXTC_ARB_DEBUG ); REG_OUTPUT( mmTCD_STALLS_DEBUG ); - REG_OUTPUT( mmTCO_STALLS_DEBUG ); REG_OUTPUT( mmTCO_QUAD0_DEBUG0 ); REG_OUTPUT( mmTCO_QUAD0_DEBUG1 ); - REG_OUTPUT( mmSQ_GPR_MANAGEMENT ); REG_OUTPUT( mmSQ_FLOW_CONTROL ); REG_OUTPUT( mmSQ_INST_STORE_MANAGMENT ); - REG_OUTPUT( mmSQ_RESOURCE_MANAGMENT ); REG_OUTPUT( mmSQ_EO_RT ); REG_OUTPUT( mmSQ_DEBUG_MISC ); - REG_OUTPUT( mmSQ_ACTIVITY_METER_CNTL ); REG_OUTPUT( mmSQ_ACTIVITY_METER_STATUS ); REG_OUTPUT( mmSQ_INPUT_ARB_PRIORITY ); - REG_OUTPUT( mmSQ_THREAD_ARB_PRIORITY ); REG_OUTPUT( mmSQ_VS_WATCHDOG_TIMER ); REG_OUTPUT( mmSQ_PS_WATCHDOG_TIMER ); - REG_OUTPUT( mmSQ_INT_CNTL ); REG_OUTPUT( mmSQ_INT_STATUS ); REG_OUTPUT( mmSQ_INT_ACK ); - REG_OUTPUT( mmSQ_DEBUG_INPUT_FSM ); REG_OUTPUT( mmSQ_DEBUG_CONST_MGR_FSM ); REG_OUTPUT( mmSQ_DEBUG_TP_FSM ); - REG_OUTPUT( mmSQ_DEBUG_FSM_ALU_0 ); REG_OUTPUT( mmSQ_DEBUG_FSM_ALU_1 ); REG_OUTPUT( mmSQ_DEBUG_EXP_ALLOC ); - REG_OUTPUT( mmSQ_DEBUG_PTR_BUFF ); REG_OUTPUT( mmSQ_DEBUG_GPR_VTX ); REG_OUTPUT( mmSQ_DEBUG_GPR_PIX ); - REG_OUTPUT( mmSQ_DEBUG_TB_STATUS_SEL ); REG_OUTPUT( mmSQ_DEBUG_VTX_TB_0 ); REG_OUTPUT( mmSQ_DEBUG_VTX_TB_1 ); - REG_OUTPUT( mmSQ_DEBUG_VTX_TB_STATUS_REG ); REG_OUTPUT( mmSQ_DEBUG_VTX_TB_STATE_MEM ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_0 ); - REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_0 ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_1 ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_2 ); - REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_3 ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATE_MEM ); REG_OUTPUT( mmSQ_PERFCOUNTER0_SELECT ); - REG_OUTPUT( mmSQ_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmSQ_PERFCOUNTER2_SELECT ); REG_OUTPUT( mmSQ_PERFCOUNTER3_SELECT ); - REG_OUTPUT( mmSQ_PERFCOUNTER0_LOW ); REG_OUTPUT( mmSQ_PERFCOUNTER0_HI ); REG_OUTPUT( mmSQ_PERFCOUNTER1_LOW ); - REG_OUTPUT( mmSQ_PERFCOUNTER1_HI ); REG_OUTPUT( mmSQ_PERFCOUNTER2_LOW ); REG_OUTPUT( mmSQ_PERFCOUNTER2_HI ); - REG_OUTPUT( mmSQ_PERFCOUNTER3_LOW ); REG_OUTPUT( mmSQ_PERFCOUNTER3_HI ); REG_OUTPUT( mmSX_PERFCOUNTER0_SELECT ); - REG_OUTPUT( mmSX_PERFCOUNTER0_LOW ); REG_OUTPUT( mmSX_PERFCOUNTER0_HI ); REG_OUTPUT( mmSQ_INSTRUCTION_ALU_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_ALU_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_ALU_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_EXEC_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_CF_EXEC_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_EXEC_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_LOOP_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_CF_LOOP_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_LOOP_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_JMP_CALL_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_CF_JMP_CALL_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_JMP_CALL_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_ALLOC_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_CF_ALLOC_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_ALLOC_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_TFETCH_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_TFETCH_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_TFETCH_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_VFETCH_0 ); - REG_OUTPUT( mmSQ_INSTRUCTION_VFETCH_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_VFETCH_2 ); REG_OUTPUT( mmSQ_CONSTANT_0 ); - REG_OUTPUT( mmSQ_CONSTANT_1 ); REG_OUTPUT( mmSQ_CONSTANT_2 ); REG_OUTPUT( mmSQ_CONSTANT_3 ); - REG_OUTPUT( mmSQ_FETCH_0 ); REG_OUTPUT( mmSQ_FETCH_1 ); REG_OUTPUT( mmSQ_FETCH_2 ); - REG_OUTPUT( mmSQ_FETCH_3 ); REG_OUTPUT( mmSQ_FETCH_4 ); REG_OUTPUT( mmSQ_FETCH_5 ); - REG_OUTPUT( mmSQ_CONSTANT_VFETCH_0 ); REG_OUTPUT( mmSQ_CONSTANT_VFETCH_1 ); REG_OUTPUT( mmSQ_CONSTANT_T2 ); - REG_OUTPUT( mmSQ_CONSTANT_T3 ); REG_OUTPUT( mmSQ_CF_BOOLEANS ); REG_OUTPUT( mmSQ_CF_LOOP ); - REG_OUTPUT( mmSQ_CONSTANT_RT_0 ); REG_OUTPUT( mmSQ_CONSTANT_RT_1 ); REG_OUTPUT( mmSQ_CONSTANT_RT_2 ); - REG_OUTPUT( mmSQ_CONSTANT_RT_3 ); REG_OUTPUT( mmSQ_FETCH_RT_0 ); REG_OUTPUT( mmSQ_FETCH_RT_1 ); - REG_OUTPUT( mmSQ_FETCH_RT_2 ); REG_OUTPUT( mmSQ_FETCH_RT_3 ); REG_OUTPUT( mmSQ_FETCH_RT_4 ); - REG_OUTPUT( mmSQ_FETCH_RT_5 ); REG_OUTPUT( mmSQ_CF_RT_BOOLEANS ); REG_OUTPUT( mmSQ_CF_RT_LOOP ); - REG_OUTPUT( mmSQ_VS_PROGRAM ); REG_OUTPUT( mmSQ_PS_PROGRAM ); REG_OUTPUT( mmSQ_CF_PROGRAM_SIZE ); - REG_OUTPUT( mmSQ_INTERPOLATOR_CNTL ); REG_OUTPUT( mmSQ_PROGRAM_CNTL ); REG_OUTPUT( mmSQ_WRAPPING_0 ); - REG_OUTPUT( mmSQ_WRAPPING_1 ); REG_OUTPUT( mmSQ_VS_CONST ); REG_OUTPUT( mmSQ_PS_CONST ); - REG_OUTPUT( mmSQ_CONTEXT_MISC ); REG_OUTPUT( mmSQ_CF_RD_BASE ); REG_OUTPUT( mmSQ_DEBUG_MISC_0 ); - REG_OUTPUT( mmSQ_DEBUG_MISC_1 ); REG_OUTPUT( mmMH_ARBITER_CONFIG ); REG_OUTPUT( mmMH_CLNT_AXI_ID_REUSE ); - REG_OUTPUT( mmMH_INTERRUPT_MASK ); REG_OUTPUT( mmMH_INTERRUPT_STATUS ); REG_OUTPUT( mmMH_INTERRUPT_CLEAR ); - REG_OUTPUT( mmMH_AXI_ERROR ); REG_OUTPUT( mmMH_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmMH_PERFCOUNTER1_SELECT ); - REG_OUTPUT( mmMH_PERFCOUNTER0_CONFIG ); REG_OUTPUT( mmMH_PERFCOUNTER1_CONFIG ); REG_OUTPUT( mmMH_PERFCOUNTER0_LOW ); - REG_OUTPUT( mmMH_PERFCOUNTER1_LOW ); REG_OUTPUT( mmMH_PERFCOUNTER0_HI ); REG_OUTPUT( mmMH_PERFCOUNTER1_HI ); - REG_OUTPUT( mmMH_DEBUG_CTRL ); REG_OUTPUT( mmMH_DEBUG_DATA ); REG_OUTPUT( mmMH_AXI_HALT_CONTROL ); - REG_OUTPUT( mmMH_MMU_CONFIG ); REG_OUTPUT( mmMH_MMU_VA_RANGE ); REG_OUTPUT( mmMH_MMU_PT_BASE ); - REG_OUTPUT( mmMH_MMU_PAGE_FAULT ); REG_OUTPUT( mmMH_MMU_TRAN_ERROR ); REG_OUTPUT( mmMH_MMU_INVALIDATE ); - REG_OUTPUT( mmMH_MMU_MPU_BASE ); REG_OUTPUT( mmMH_MMU_MPU_END ); REG_OUTPUT( mmWAIT_UNTIL ); - REG_OUTPUT( mmRBBM_ISYNC_CNTL ); REG_OUTPUT( mmRBBM_STATUS ); REG_OUTPUT( mmRBBM_DSPLY ); - REG_OUTPUT( mmRBBM_RENDER_LATEST ); REG_OUTPUT( mmRBBM_RTL_RELEASE ); REG_OUTPUT( mmRBBM_PATCH_RELEASE ); - REG_OUTPUT( mmRBBM_AUXILIARY_CONFIG ); REG_OUTPUT( mmRBBM_PERIPHID0 ); REG_OUTPUT( mmRBBM_PERIPHID1 ); - REG_OUTPUT( mmRBBM_PERIPHID2 ); REG_OUTPUT( mmRBBM_PERIPHID3 ); REG_OUTPUT( mmRBBM_CNTL ); - REG_OUTPUT( mmRBBM_SKEW_CNTL ); REG_OUTPUT( mmRBBM_SOFT_RESET ); REG_OUTPUT( mmRBBM_PM_OVERRIDE1 ); - REG_OUTPUT( mmRBBM_PM_OVERRIDE2 ); REG_OUTPUT( mmGC_SYS_IDLE ); REG_OUTPUT( mmNQWAIT_UNTIL ); - REG_OUTPUT( mmRBBM_DEBUG_OUT ); REG_OUTPUT( mmRBBM_DEBUG_CNTL ); REG_OUTPUT( mmRBBM_DEBUG ); - REG_OUTPUT( mmRBBM_READ_ERROR ); REG_OUTPUT( mmRBBM_WAIT_IDLE_CLOCKS ); REG_OUTPUT( mmRBBM_INT_CNTL ); - REG_OUTPUT( mmRBBM_INT_STATUS ); REG_OUTPUT( mmRBBM_INT_ACK ); REG_OUTPUT( mmMASTER_INT_SIGNAL ); - REG_OUTPUT( mmRBBM_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmRBBM_PERFCOUNTER1_LO ); REG_OUTPUT( mmRBBM_PERFCOUNTER1_HI ); - REG_OUTPUT( mmCP_RB_BASE ); REG_OUTPUT( mmCP_RB_CNTL ); REG_OUTPUT( mmCP_RB_RPTR_ADDR ); - REG_OUTPUT( mmCP_RB_RPTR ); REG_OUTPUT( mmCP_RB_RPTR_WR ); REG_OUTPUT( mmCP_RB_WPTR ); - REG_OUTPUT( mmCP_RB_WPTR_DELAY ); REG_OUTPUT( mmCP_RB_WPTR_BASE ); REG_OUTPUT( mmCP_IB1_BASE ); - REG_OUTPUT( mmCP_IB1_BUFSZ ); REG_OUTPUT( mmCP_IB2_BASE ); REG_OUTPUT( mmCP_IB2_BUFSZ ); - REG_OUTPUT( mmCP_ST_BASE ); REG_OUTPUT( mmCP_ST_BUFSZ ); REG_OUTPUT( mmCP_QUEUE_THRESHOLDS ); - REG_OUTPUT( mmCP_MEQ_THRESHOLDS ); REG_OUTPUT( mmCP_CSQ_AVAIL ); REG_OUTPUT( mmCP_STQ_AVAIL ); - REG_OUTPUT( mmCP_MEQ_AVAIL ); REG_OUTPUT( mmCP_CSQ_RB_STAT ); REG_OUTPUT( mmCP_CSQ_IB1_STAT ); - REG_OUTPUT( mmCP_CSQ_IB2_STAT ); REG_OUTPUT( mmCP_NON_PREFETCH_CNTRS ); REG_OUTPUT( mmCP_STQ_ST_STAT ); - REG_OUTPUT( mmCP_MEQ_STAT ); REG_OUTPUT( mmCP_MIU_TAG_STAT ); REG_OUTPUT( mmCP_CMD_INDEX ); - REG_OUTPUT( mmCP_CMD_DATA ); REG_OUTPUT( mmCP_ME_CNTL ); REG_OUTPUT( mmCP_ME_STATUS ); - REG_OUTPUT( mmCP_ME_RAM_WADDR ); REG_OUTPUT( mmCP_ME_RAM_RADDR ); REG_OUTPUT( mmCP_ME_RAM_DATA ); - REG_OUTPUT( mmCP_ME_RDADDR ); REG_OUTPUT( mmCP_DEBUG ); REG_OUTPUT( mmSCRATCH_REG0 ); - REG_OUTPUT( mmSCRATCH_REG1 ); REG_OUTPUT( mmSCRATCH_REG2 ); REG_OUTPUT( mmSCRATCH_REG3 ); - REG_OUTPUT( mmSCRATCH_REG4 ); REG_OUTPUT( mmSCRATCH_REG5 ); REG_OUTPUT( mmSCRATCH_REG6 ); - REG_OUTPUT( mmSCRATCH_REG7 ); - REG_OUTPUT( mmSCRATCH_UMSK ); REG_OUTPUT( mmSCRATCH_ADDR ); REG_OUTPUT( mmCP_ME_VS_EVENT_SRC ); - REG_OUTPUT( mmCP_ME_VS_EVENT_ADDR ); REG_OUTPUT( mmCP_ME_VS_EVENT_DATA ); REG_OUTPUT( mmCP_ME_VS_EVENT_ADDR_SWM ); - REG_OUTPUT( mmCP_ME_VS_EVENT_DATA_SWM ); REG_OUTPUT( mmCP_ME_PS_EVENT_SRC ); REG_OUTPUT( mmCP_ME_PS_EVENT_ADDR ); - REG_OUTPUT( mmCP_ME_PS_EVENT_DATA ); REG_OUTPUT( mmCP_ME_PS_EVENT_ADDR_SWM ); REG_OUTPUT( mmCP_ME_PS_EVENT_DATA_SWM ); - REG_OUTPUT( mmCP_ME_CF_EVENT_SRC ); REG_OUTPUT( mmCP_ME_CF_EVENT_ADDR ); REG_OUTPUT( mmCP_ME_CF_EVENT_DATA ); - REG_OUTPUT( mmCP_ME_NRT_ADDR ); REG_OUTPUT( mmCP_ME_NRT_DATA ); REG_OUTPUT( mmCP_ME_VS_FETCH_DONE_SRC ); - REG_OUTPUT( mmCP_ME_VS_FETCH_DONE_ADDR ); REG_OUTPUT( mmCP_ME_VS_FETCH_DONE_DATA ); REG_OUTPUT( mmCP_INT_CNTL ); - REG_OUTPUT( mmCP_INT_STATUS ); REG_OUTPUT( mmCP_INT_ACK ); REG_OUTPUT( mmCP_PFP_UCODE_ADDR ); - REG_OUTPUT( mmCP_PFP_UCODE_DATA ); REG_OUTPUT( mmCP_PERFMON_CNTL ); REG_OUTPUT( mmCP_PERFCOUNTER_SELECT ); - REG_OUTPUT( mmCP_PERFCOUNTER_LO ); REG_OUTPUT( mmCP_PERFCOUNTER_HI ); REG_OUTPUT( mmCP_BIN_MASK_LO ); - REG_OUTPUT( mmCP_BIN_MASK_HI ); REG_OUTPUT( mmCP_BIN_SELECT_LO ); REG_OUTPUT( mmCP_BIN_SELECT_HI ); - REG_OUTPUT( mmCP_NV_FLAGS_0 ); REG_OUTPUT( mmCP_NV_FLAGS_1 ); REG_OUTPUT( mmCP_NV_FLAGS_2 ); - REG_OUTPUT( mmCP_NV_FLAGS_3 ); REG_OUTPUT( mmCP_STATE_DEBUG_INDEX ); REG_OUTPUT( mmCP_STATE_DEBUG_DATA ); - REG_OUTPUT( mmCP_PROG_COUNTER ); REG_OUTPUT( mmCP_STAT ); REG_OUTPUT( mmBIOS_0_SCRATCH ); - REG_OUTPUT( mmBIOS_1_SCRATCH ); REG_OUTPUT( mmBIOS_2_SCRATCH ); REG_OUTPUT( mmBIOS_3_SCRATCH ); - REG_OUTPUT( mmBIOS_4_SCRATCH ); REG_OUTPUT( mmBIOS_5_SCRATCH ); REG_OUTPUT( mmBIOS_6_SCRATCH ); - REG_OUTPUT( mmBIOS_7_SCRATCH ); REG_OUTPUT( mmBIOS_8_SCRATCH ); REG_OUTPUT( mmBIOS_9_SCRATCH ); - REG_OUTPUT( mmBIOS_10_SCRATCH ); REG_OUTPUT( mmBIOS_11_SCRATCH ); REG_OUTPUT( mmBIOS_12_SCRATCH ); - REG_OUTPUT( mmBIOS_13_SCRATCH ); REG_OUTPUT( mmBIOS_14_SCRATCH ); REG_OUTPUT( mmBIOS_15_SCRATCH ); - REG_OUTPUT( mmCOHER_SIZE_PM4 ); REG_OUTPUT( mmCOHER_BASE_PM4 ); REG_OUTPUT( mmCOHER_STATUS_PM4 ); - REG_OUTPUT( mmCOHER_SIZE_HOST ); REG_OUTPUT( mmCOHER_BASE_HOST ); REG_OUTPUT( mmCOHER_STATUS_HOST ); - REG_OUTPUT( mmCOHER_DEST_BASE_0 ); REG_OUTPUT( mmCOHER_DEST_BASE_1 ); REG_OUTPUT( mmCOHER_DEST_BASE_2 ); - REG_OUTPUT( mmCOHER_DEST_BASE_3 ); REG_OUTPUT( mmCOHER_DEST_BASE_4 ); REG_OUTPUT( mmCOHER_DEST_BASE_5 ); - REG_OUTPUT( mmCOHER_DEST_BASE_6 ); REG_OUTPUT( mmCOHER_DEST_BASE_7 ); REG_OUTPUT( mmRB_SURFACE_INFO ); - REG_OUTPUT( mmRB_COLOR_INFO ); REG_OUTPUT( mmRB_DEPTH_INFO ); REG_OUTPUT( mmRB_STENCILREFMASK ); - REG_OUTPUT( mmRB_ALPHA_REF ); REG_OUTPUT( mmRB_COLOR_MASK ); REG_OUTPUT( mmRB_BLEND_RED ); - REG_OUTPUT( mmRB_BLEND_GREEN ); REG_OUTPUT( mmRB_BLEND_BLUE ); REG_OUTPUT( mmRB_BLEND_ALPHA ); - REG_OUTPUT( mmRB_FOG_COLOR ); REG_OUTPUT( mmRB_STENCILREFMASK_BF ); REG_OUTPUT( mmRB_DEPTHCONTROL ); - REG_OUTPUT( mmRB_BLENDCONTROL ); REG_OUTPUT( mmRB_COLORCONTROL ); REG_OUTPUT( mmRB_MODECONTROL ); - REG_OUTPUT( mmRB_COLOR_DEST_MASK ); REG_OUTPUT( mmRB_COPY_CONTROL ); REG_OUTPUT( mmRB_COPY_DEST_BASE ); - REG_OUTPUT( mmRB_COPY_DEST_PITCH ); REG_OUTPUT( mmRB_COPY_DEST_INFO ); REG_OUTPUT( mmRB_COPY_DEST_PIXEL_OFFSET ); - REG_OUTPUT( mmRB_DEPTH_CLEAR ); REG_OUTPUT( mmRB_SAMPLE_COUNT_CTL ); REG_OUTPUT( mmRB_SAMPLE_COUNT_ADDR ); - REG_OUTPUT( mmRB_BC_CONTROL ); REG_OUTPUT( mmRB_EDRAM_INFO ); REG_OUTPUT( mmRB_CRC_RD_PORT ); - REG_OUTPUT( mmRB_CRC_CONTROL ); REG_OUTPUT( mmRB_CRC_MASK ); REG_OUTPUT( mmRB_PERFCOUNTER0_SELECT ); - REG_OUTPUT( mmRB_PERFCOUNTER0_LOW ); REG_OUTPUT( mmRB_PERFCOUNTER0_HI ); REG_OUTPUT( mmRB_TOTAL_SAMPLES ); - REG_OUTPUT( mmRB_ZPASS_SAMPLES ); REG_OUTPUT( mmRB_ZFAIL_SAMPLES ); REG_OUTPUT( mmRB_SFAIL_SAMPLES ); - REG_OUTPUT( mmRB_DEBUG_0 ); REG_OUTPUT( mmRB_DEBUG_1 ); REG_OUTPUT( mmRB_DEBUG_2 ); - REG_OUTPUT( mmRB_DEBUG_3 ); REG_OUTPUT( mmRB_DEBUG_4 ); REG_OUTPUT( mmRB_FLAG_CONTROL ); - REG_OUTPUT( mmRB_BC_SPARES ); REG_OUTPUT( mmBC_DUMMY_CRAYRB_ENUMS ); REG_OUTPUT( mmBC_DUMMY_CRAYRB_MOREENUMS ); - - default: - b += sprintf( b, "%s", "UNKNOWN REGISTER OFFSET" ); - break; - } - // Handle string after %R - kos_memcpy( b, p1+2, p2-(p1+2) ); - b += (unsigned int)p2-(unsigned int)(p1+2); - *b = '\0'; - } - break; - - - default: - { - int val = va_arg( arguments, int ); - // Standard format. Use vsprintf. - b += sprintf( b, buffer2, val ); - } - break; - } - - - c = p2; - } - - // Add this string to all outputs - output = outputs; - - while( output != NULL ) - { - // Filter according to the flags - if( ( output->flags & log_flags ) == log_flags ) - { - // Passed the filter. Now commit this message. - switch( output->type ) - { - case KGSL_OUTPUT_TYPE_MEMBUF: - // TODO - break; - - case KGSL_OUTPUT_TYPE_STDOUT: - // Write timestamp if enabled - if( output->flags & KGSL_LOG_TIMESTAMP ) - printf( "[Timestamp: %d] ", kos_timestamp() ); - // Write process id if enabled - if( output->flags & KGSL_LOG_PROCESS_ID ) - printf( "[Process ID: %d] ", kos_process_getid() ); - // Write thread id if enabled - if( output->flags & KGSL_LOG_THREAD_ID ) - printf( "[Thread ID: %d] ", kos_thread_getid() ); - - // Write the message - printf( buffer ); - break; - - case KGSL_OUTPUT_TYPE_FILE: - // Write timestamp if enabled - if( output->flags & KGSL_LOG_TIMESTAMP ) - kos_fprintf( output->file, "[Timestamp: %d] ", kos_timestamp() ); - // Write process id if enabled - if( output->flags & KGSL_LOG_PROCESS_ID ) - kos_fprintf( output->file, "[Process ID: %d] ", kos_process_getid() ); - // Write thread id if enabled - if( output->flags & KGSL_LOG_THREAD_ID ) - kos_fprintf( output->file, "[Thread ID: %d] ", kos_thread_getid() ); - - // Write the message - kos_fprintf( output->file, buffer ); - break; - } - } - - output = output->next; - } - - va_end( arguments ); - - kos_mutex_unlock( log_mutex ); - - return GSL_SUCCESS; -} - -//---------------------------------------------------------------------------- -#endif diff --git a/drivers/mxc/amd-gpu/common/gsl_memmgr.c b/drivers/mxc/amd-gpu/common/gsl_memmgr.c deleted file mode 100644 index 75f250ae59b..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_memmgr.c +++ /dev/null @@ -1,949 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -#define GSL_MEMARENAPRIV_SIGNATURE_MASK 0x0000FFFF -#define GSL_MEMARENAPRIV_APERTUREID_MASK 0xF0000000 -#define GSL_MEMARENAPRIV_MMUVIRTUALIZED_MASK 0x0F000000 - -#define GSL_MEMARENAPRIV_SIGNATURE_SHIFT 0 -#define GSL_MEMARENAPRIV_MMUVIRTUALIZED_SHIFT 24 -#define GSL_MEMARENAPRIV_APERTUREID_SHIFT 28 - -#define GSL_MEMARENA_INSTANCE_SIGNATURE 0x0000CAFE - -#ifdef GSL_STATS_MEM -#define GSL_MEMARENA_STATS(x) x -#else -#define GSL_MEMARENA_STATS(x) -#endif // GSL_STATS_MEM - - -///////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#define GSL_MEMARENA_LOCK() kos_mutex_lock(memarena->mutex) -#define GSL_MEMARENA_UNLOCK() kos_mutex_unlock(memarena->mutex) - -#define GSL_MEMARENA_SET_SIGNATURE (memarena->priv |= ((GSL_MEMARENA_INSTANCE_SIGNATURE << GSL_MEMARENAPRIV_SIGNATURE_SHIFT) & GSL_MEMARENAPRIV_SIGNATURE_MASK)) -#define GSL_MEMARENA_SET_MMU_VIRTUALIZED (memarena->priv |= ((mmu_virtualized << GSL_MEMARENAPRIV_MMUVIRTUALIZED_SHIFT) & GSL_MEMARENAPRIV_MMUVIRTUALIZED_MASK)) -#define GSL_MEMARENA_SET_ID (memarena->priv |= ((aperture_id << GSL_MEMARENAPRIV_APERTUREID_SHIFT) & GSL_MEMARENAPRIV_APERTUREID_MASK)) - -#define GSL_MEMARENA_GET_SIGNATURE ((memarena->priv & GSL_MEMARENAPRIV_SIGNATURE_MASK) >> GSL_MEMARENAPRIV_SIGNATURE_SHIFT) -#define GSL_MEMARENA_IS_MMU_VIRTUALIZED ((memarena->priv & GSL_MEMARENAPRIV_MMUVIRTUALIZED_MASK) >> GSL_MEMARENAPRIV_MMUVIRTUALIZED_SHIFT) -#define GSL_MEMARENA_GET_ID ((memarena->priv & GSL_MEMARENAPRIV_APERTUREID_MASK) >> GSL_MEMARENAPRIV_APERTUREID_SHIFT) - - -////////////////////////////////////////////////////////////////////////////// -// validate -////////////////////////////////////////////////////////////////////////////// -#define GSL_MEMARENA_VALIDATE(memarena) \ - KOS_ASSERT(memarena); \ - if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) \ - { \ - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, \ - "ERROR: Memarena validation failed.\n" ); \ - return (GSL_FAILURE); \ - } - -////////////////////////////////////////////////////////////////////////////// -// block alignment shift count -////////////////////////////////////////////////////////////////////////////// -OSINLINE unsigned int -gsl_memarena_alignmentshift(gsl_flags_t flags) -{ - int alignshift = ((flags & GSL_MEMFLAGS_ALIGN_MASK) >> GSL_MEMFLAGS_ALIGN_SHIFT); - if (alignshift == 0) - alignshift = 5; // 32 bytes is the minimum alignment boundary - return (alignshift); -} - -////////////////////////////////////////////////////////////////////////////// -// address alignment -////////////////////////////////////////////////////////////////////////////// -OSINLINE unsigned int -gsl_memarena_alignaddr(unsigned int address, int shift) -{ - // - // the value of the returned address is guaranteed to be an even multiple - // of the block alignment shift specified. - // - unsigned int alignedbaseaddr = ((address) >> shift) << shift; - if (alignedbaseaddr < address) - { - alignedbaseaddr += (1 << shift); - } - return (alignedbaseaddr); -} - - -////////////////////////////////////////////////////////////////////////////// -// memory management API -////////////////////////////////////////////////////////////////////////////// - -OSINLINE memblk_t* -kgsl_memarena_getmemblknode(gsl_memarena_t *memarena) -{ -#ifdef GSL_MEMARENA_NODE_POOL_ENABLED - gsl_nodepool_t *nodepool = memarena->nodepool; - memblk_t *memblk = NULL; - int allocnewpool = 1; - int i; - - if (nodepool) - { - // walk through list of existing pools - for ( ; ; ) - { - // if there is a pool with a free memblk node - if (nodepool->priv != (1 << GSL_MEMARENA_NODE_POOL_MAX)-1) - { - // get index of the first free memblk node - for (i = 0; i < GSL_MEMARENA_NODE_POOL_MAX; i++) - { - if (((nodepool->priv >> i) & 0x1) == 0) - { - break; - } - } - - // mark memblk node as used - nodepool->priv |= 1 << i; - - memblk = &nodepool->memblk[i]; - memblk->nodepoolindex = i; - memblk->blkaddr = 0; - memblk->blksize = 0; - - allocnewpool = 0; - - break; - } - else - { - nodepool = nodepool->next; - - if (nodepool == memarena->nodepool) - { - // no free memblk node found - break; - } - } - } - } - - // if no existing pool has a free memblk node - if (allocnewpool) - { - // alloc new pool of memblk nodes - nodepool = ((gsl_nodepool_t *)kos_malloc(sizeof(gsl_nodepool_t))); - if (nodepool) - { - kos_memset(nodepool, 0, sizeof(gsl_nodepool_t)); - - if (memarena->nodepool) - { - nodepool->next = memarena->nodepool->next; - nodepool->prev = memarena->nodepool; - memarena->nodepool->next->prev = nodepool; - memarena->nodepool->next = nodepool; - } - else - { - nodepool->next = nodepool; - nodepool->prev = nodepool; - } - - // reposition pool head - memarena->nodepool = nodepool; - - // mark memblk node as used - nodepool->priv |= 0x1; - - memblk = &nodepool->memblk[0]; - memblk->nodepoolindex = 0; - } - } - - KOS_ASSERT(memblk); - - return (memblk); -#else - // unreferenced formal parameter - (void) memarena; - - return ((memblk_t *)kos_malloc(sizeof(memblk_t))); -#endif // GSL_MEMARENA_NODE_POOL_ENABLED -} - -//---------------------------------------------------------------------------- - -OSINLINE void -kgsl_memarena_releasememblknode(gsl_memarena_t *memarena, memblk_t *memblk) -{ -#ifdef GSL_MEMARENA_NODE_POOL_ENABLED - gsl_nodepool_t *nodepool = memarena->nodepool; - - KOS_ASSERT(memblk); - KOS_ASSERT(nodepool); - - // locate pool to which this memblk node belongs - while (((unsigned int) memblk) < ((unsigned int) nodepool) || - ((unsigned int) memblk) > ((unsigned int) nodepool) + sizeof(gsl_nodepool_t)) - { - nodepool = nodepool->prev; - - KOS_ASSERT(nodepool != memarena->nodepool); - } - - // mark memblk node as unused - nodepool->priv &= ~(1 << memblk->nodepoolindex); - - // free pool when all its memblk nodes are unused - if (nodepool->priv == 0) - { - if (nodepool != nodepool->prev) - { - // reposition pool head - if (nodepool == memarena->nodepool) - { - memarena->nodepool = nodepool->prev; - } - - nodepool->prev->next = nodepool->next; - nodepool->next->prev = nodepool->prev; - } - else - { - memarena->nodepool = NULL; - } - - kos_free((void *)nodepool); - } - else - { - // leave pool head in last pool a memblk node was released - memarena->nodepool = nodepool; - } -#else - // unreferenced formal parameter - (void) memarena; - - kos_free((void *)memblk); -#endif // GSL_MEMARENA_NODE_POOL_ENABLED -} - -//---------------------------------------------------------------------------- - -gsl_memarena_t* -kgsl_memarena_create(int aperture_id, int mmu_virtualized, unsigned int hostbaseaddr, gpuaddr_t gpubaseaddr, int sizebytes) -{ - static int count = 0; - char name[100], id_str[2]; - int len; - gsl_memarena_t *memarena; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> gsl_memarena_t* kgsl_memarena_create(int aperture_id=%d, gpuaddr_t gpubaseaddr=0x%08x, int sizebytes=%d)\n", aperture_id, gpubaseaddr, sizebytes ); - - memarena = (gsl_memarena_t *)kos_malloc(sizeof(gsl_memarena_t)); - - if (!memarena) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, - "ERROR: Memarena allocation failed.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "<-- kgsl_memarena_create. Return value: 0x%08x\n", NULL ); - return (NULL); - } - - kos_memset(memarena, 0, sizeof(gsl_memarena_t)); - - GSL_MEMARENA_SET_SIGNATURE; - GSL_MEMARENA_SET_MMU_VIRTUALIZED; - GSL_MEMARENA_SET_ID; - - // define unique mutex for each memory arena instance - id_str[0] = (char) (count + '0'); - id_str[1] = '\0'; - kos_strcpy(name, "GSL_memory_arena_"); - len = kos_strlen(name); - kos_strcpy(&name[len], id_str); - - memarena->mutex = kos_mutex_create(name); - - // set up the memory arena - memarena->hostbaseaddr = hostbaseaddr; - memarena->gpubaseaddr = gpubaseaddr; - memarena->sizebytes = sizebytes; - - // allocate a memory block in free list which represents all memory in arena - memarena->freelist.head = kgsl_memarena_getmemblknode(memarena); - memarena->freelist.head->blkaddr = 0; - memarena->freelist.head->blksize = memarena->sizebytes; - memarena->freelist.head->next = memarena->freelist.head; - memarena->freelist.head->prev = memarena->freelist.head; - memarena->freelist.allocrover = memarena->freelist.head; - memarena->freelist.freerover = memarena->freelist.head; - - count++; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_create. Return value: 0x%08x\n", memarena ); - - return (memarena); -} - -//---------------------------------------------------------------------------- - -int -kgsl_memarena_destroy(gsl_memarena_t *memarena) -{ - int status = GSL_SUCCESS; - memblk_t *p, *next; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_memarena_destroy(gsl_memarena_t *memarena=0x%08x)\n", memarena ); - - GSL_MEMARENA_VALIDATE(memarena); - - GSL_MEMARENA_LOCK(); - -#ifdef _DEBUG - // memory leak check - if (memarena->freelist.head->blksize != memarena->sizebytes) - { - if (GSL_MEMARENA_GET_ID == GSL_APERTURE_EMEM) - { - // external memory leak detected - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, - "ERROR: External memory leak detected.\n" ); - return (GSL_FAILURE); - } - } -#endif // _DEBUG - - p = memarena->freelist.head; - do - { - next = p->next; - kgsl_memarena_releasememblknode(memarena, p); - p = next; - } while (p != memarena->freelist.head); - - GSL_MEMARENA_UNLOCK(); - - if (memarena->mutex) - { - kos_mutex_free(memarena->mutex); - } - - kos_free((void *)memarena); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_destroy. Return value: %B\n", GSL_SUCCESS ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_memarena_isvirtualized(gsl_memarena_t *memarena) -{ - // mmu virtualization enabled - return (GSL_MEMARENA_IS_MMU_VIRTUALIZED); -} - -//---------------------------------------------------------------------------- - -int -kgsl_memarena_checkconsistency(gsl_memarena_t *memarena) -{ - memblk_t *p; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_memarena_checkconsistency(gsl_memarena_t *memarena=0x%08x)\n", memarena ); - - // go through list of free blocks and make sure there are no detectable errors - - p = memarena->freelist.head; - do - { - if (p->next->blkaddr != memarena->freelist.head->blkaddr) - { - if (p->prev->next->blkaddr != p->blkaddr || - p->next->prev->blkaddr != p->blkaddr || - p->blkaddr + p->blksize >= p->next->blkaddr) - { - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkconsistency. Return value: %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - } - p = p->next; - - } while (p != memarena->freelist.head); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkconsistency. Return value: %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_memarena_querystats(gsl_memarena_t *memarena, gsl_memarena_stats_t *stats) -{ -#ifdef GSL_STATS_MEM - KOS_ASSERT(stats); - GSL_MEMARENA_VALIDATE(memarena); - - kos_memcpy(stats, &memarena->stats, sizeof(gsl_memarena_stats_t)); - - return (GSL_SUCCESS); -#else - // unreferenced formal parameters - (void) memarena; - (void) stats; - - return (GSL_FAILURE_NOTSUPPORTED); -#endif // GSL_STATS_MEM -} - -//---------------------------------------------------------------------------- - -int -kgsl_memarena_checkfreeblock(gsl_memarena_t *memarena, int bytesneeded) -{ - memblk_t *p; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_memarena_checkfreeblock(gsl_memarena_t *memarena=0x%08x, int bytesneeded=%d)\n", memarena, bytesneeded ); - - GSL_MEMARENA_VALIDATE(memarena); - - if (bytesneeded < 1) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Illegal number of bytes needed.\n" ); - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkfreeblock. Return value: %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - GSL_MEMARENA_LOCK(); - - p = memarena->freelist.head; - do - { - if (p->blksize >= (unsigned int)bytesneeded) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkfreeblock. Return value: %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); - } - - p = p->next; - } while (p != memarena->freelist.head); - - GSL_MEMARENA_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkfreeblock. Return value: %B\n", GSL_FAILURE ); - - return (GSL_FAILURE); -} - -//---------------------------------------------------------------------------- - -int -kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_memdesc_t *memdesc) -{ - int result = GSL_FAILURE_OUTOFMEM; - memblk_t *ptrfree, *ptrlast, *p; - unsigned int blksize; - unsigned int baseaddr, alignedbaseaddr, alignfragment; - int freeblk, alignmentshift; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_memarena_alloc(gsl_memarena_t *memarena=0x%08x, gsl_flags_t flags=0x%08x, int size=%d, gsl_memdesc_t *memdesc=%M)\n", memarena, flags, size, memdesc ); - - GSL_MEMARENA_VALIDATE(memarena); - - if (size <= 0) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid size for memory allocation.\n" ); - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_alloc. Return value: %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // - // go through the list of free blocks. check to find block which can satisfy the alloc request - // - // if no block can satisfy the alloc request this implies that the memory is too fragmented - // and the requestor needs to free up other memory blocks and re-request the allocation - // - // if we do find a block that can satisfy the alloc request then reduce the size of free block - // by blksize and return the address after allocating the memory. if the free block size becomes - // 0 then remove this node from the free list - // - // there would be no node on the free list if all available memory were to be allocated. - // handling an empty list would require executing error checking code in the main branch which - // is not desired. instead, the free list will have at least one node at all times. This node - // could have a block size of zero - // - // we use a next fit allocation mechanism that uses a roving pointer on a circular free block list. - // the pointer is advanced along the chain when searching for a fit. Thus each allocation begins - // looking where the previous one finished. - // - - // when allocating from external memory aperture, round up size of requested block to multiple of page size if needed - if (GSL_MEMARENA_GET_ID == GSL_APERTURE_EMEM) - { - if ((flags & GSL_MEMFLAGS_FORCEPAGESIZE) || GSL_MEMARENA_IS_MMU_VIRTUALIZED) - { - if (size & (GSL_PAGESIZE-1)) - { - size = ((size >> GSL_PAGESIZE_SHIFT) + 1) << GSL_PAGESIZE_SHIFT; - } - } - } - - // determine shift count for alignment requested - alignmentshift = gsl_memarena_alignmentshift(flags); - - // adjust size of requested block to include alignment - blksize = (unsigned int)((size + ((1 << alignmentshift) - 1)) >> alignmentshift) << alignmentshift; - - GSL_MEMARENA_LOCK(); - - // check consistency, debug only - KGSL_DEBUG(GSL_DBGFLAGS_MEMMGR, kgsl_memarena_checkconsistency(memarena)); - - ptrfree = memarena->freelist.allocrover; - ptrlast = memarena->freelist.head->prev; - freeblk = 0; - - do - { - // align base address - baseaddr = ptrfree->blkaddr + memarena->gpubaseaddr; - alignedbaseaddr = gsl_memarena_alignaddr(baseaddr, alignmentshift); - - alignfragment = alignedbaseaddr - baseaddr; - - if (ptrfree->blksize >= blksize + alignfragment) - { - result = GSL_SUCCESS; - freeblk = 1; - - memdesc->gpuaddr = alignedbaseaddr; - memdesc->hostptr = kgsl_memarena_gethostptr(memarena, memdesc->gpuaddr); - memdesc->size = blksize; - - if (alignfragment > 0) - { - // insert new node to handle newly created (small) fragment - p = kgsl_memarena_getmemblknode(memarena); - p->blkaddr = ptrfree->blkaddr; - p->blksize = alignfragment; - - p->next = ptrfree; - p->prev = ptrfree->prev; - ptrfree->prev->next = p; - ptrfree->prev = p; - - if (ptrfree == memarena->freelist.head) - { - memarena->freelist.head = p; - } - } - - ptrfree->blkaddr += alignfragment + blksize; - ptrfree->blksize -= alignfragment + blksize; - - memarena->freelist.allocrover = ptrfree; - - if (ptrfree->blksize == 0 && ptrfree != ptrlast) - { - ptrfree->prev->next = ptrfree->next; - ptrfree->next->prev = ptrfree->prev; - if (ptrfree == memarena->freelist.head) - { - memarena->freelist.head = ptrfree->next; - } - if (ptrfree == memarena->freelist.allocrover) - { - memarena->freelist.allocrover = ptrfree->next; - } - if (ptrfree == memarena->freelist.freerover) - { - memarena->freelist.freerover = ptrfree->prev; - } - p = ptrfree; - ptrfree = ptrfree->prev; - kgsl_memarena_releasememblknode(memarena, p); - } - } - - ptrfree = ptrfree->next; - - } while (!freeblk && ptrfree != memarena->freelist.allocrover); - - GSL_MEMARENA_UNLOCK(); - - if (result == GSL_SUCCESS) - { - GSL_MEMARENA_STATS( - { - int i = 0; - while (memdesc->size >> (GSL_PAGESIZE_SHIFT + i)) - { - i++; - } - i = i > (GSL_MEMARENA_PAGE_DIST_MAX-1) ? (GSL_MEMARENA_PAGE_DIST_MAX-1) : i; - memarena->stats.allocs_pagedistribution[i]++; - }); - - GSL_MEMARENA_STATS(memarena->stats.allocs_success++); - } - else - { - GSL_MEMARENA_STATS(memarena->stats.allocs_fail++); - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_alloc. Return value: %B\n", result ); - - return (result); -} - -//---------------------------------------------------------------------------- - -void -kgsl_memarena_free(gsl_memarena_t *memarena, gsl_memdesc_t *memdesc) -{ - // - // request to free a malloc'ed block from the memory arena - // add this block to the free list - // adding a block to the free list requires the following: - // going through the list of free blocks to decide where to add this free block (based on address) - // coalesce free blocks - // - memblk_t *ptrfree, *ptrend, *p; - int mallocfreeblk, clockwise; - unsigned int addrtofree; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> void kgsl_memarena_free(gsl_memarena_t *memarena=0x%08x, gsl_memdesc_t *memdesc=%M)\n", memarena, memdesc ); - - KOS_ASSERT(memarena); - if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_free.\n" ); - return; - } - - // check size of malloc'ed block - if (memdesc->size <= 0) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Illegal size for the memdesc.\n" ); - KOS_ASSERT(0); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_free.\n" ); - return; - } - - // check address range - KOS_ASSERT( memarena->gpubaseaddr <= memdesc->gpuaddr); - KOS_ASSERT((memarena->gpubaseaddr + memarena->sizebytes) >= memdesc->gpuaddr + memdesc->size); - - GSL_MEMARENA_LOCK(); - - // check consistency of memory map, debug only - KGSL_DEBUG(GSL_DBGFLAGS_MEMMGR, kgsl_memarena_checkconsistency(memarena)); - - addrtofree = memdesc->gpuaddr - memarena->gpubaseaddr; - mallocfreeblk = 1; - - if (addrtofree < memarena->freelist.head->blkaddr) - { - // add node to head of free list - - if (addrtofree + memdesc->size == memarena->freelist.head->blkaddr) - { - memarena->freelist.head->blkaddr = addrtofree; - memarena->freelist.head->blksize += memdesc->size; - - mallocfreeblk = 0; - } - - ptrfree = memarena->freelist.head->prev; - } - else if (addrtofree >= memarena->freelist.head->prev->blkaddr) - { - // add node to tail of free list - - ptrfree = memarena->freelist.head->prev; - - if (ptrfree->blkaddr + ptrfree->blksize == addrtofree) - { - ptrfree->blksize += memdesc->size; - - mallocfreeblk = 0; - } - } - else - { - // determine range of free list nodes to traverse and orientation in which to traverse them - // keep this code segment unrolled for performance reasons! - if (addrtofree > memarena->freelist.freerover->blkaddr) - { - if (addrtofree - memarena->freelist.freerover->blkaddr < memarena->freelist.head->prev->blkaddr - addrtofree) - { - ptrfree = memarena->freelist.freerover; // rover - ptrend = memarena->freelist.head->prev; // tail - clockwise = 1; - } - else - { - ptrfree = memarena->freelist.head->prev->prev; // tail - ptrend = memarena->freelist.freerover->prev; // rover - clockwise = 0; - } - } - else - { - if (addrtofree - memarena->freelist.head->blkaddr < memarena->freelist.freerover->blkaddr - addrtofree) - { - ptrfree = memarena->freelist.head; // head - ptrend = memarena->freelist.freerover; // rover - clockwise = 1; - } - else - { - ptrfree = memarena->freelist.freerover->prev; // rover - ptrend = memarena->freelist.head->prev; // head - clockwise = 0; - } - } - - // traverse the nodes - do - { - if ((addrtofree >= ptrfree->blkaddr + ptrfree->blksize) && - (addrtofree + memdesc->size <= ptrfree->next->blkaddr)) - { - if (addrtofree == ptrfree->blkaddr + ptrfree->blksize) - { - memblk_t *next; - - ptrfree->blksize += memdesc->size; - next = ptrfree->next; - - if (ptrfree->blkaddr + ptrfree->blksize == next->blkaddr) - { - ptrfree->blksize += next->blksize; - ptrfree->next = next->next; - next->next->prev = ptrfree; - - if (next == memarena->freelist.allocrover) - { - memarena->freelist.allocrover = ptrfree; - } - - kgsl_memarena_releasememblknode(memarena, next); - } - - mallocfreeblk = 0; - } - else if (addrtofree + memdesc->size == ptrfree->next->blkaddr) - { - ptrfree->next->blkaddr = addrtofree; - ptrfree->next->blksize += memdesc->size; - - mallocfreeblk = 0; - } - - break; - } - - if (clockwise) - { - ptrfree = ptrfree->next; - } - else - { - ptrfree = ptrfree->prev; - } - - } while (ptrfree != ptrend); - } - - // this free block could not be coalesced, so create a new free block - // and add it to the free list in the memory arena - if (mallocfreeblk) - { - p = kgsl_memarena_getmemblknode(memarena); - p->blkaddr = addrtofree; - p->blksize = memdesc->size; - - p->next = ptrfree->next; - p->prev = ptrfree; - ptrfree->next->prev = p; - ptrfree->next = p; - - if (p->blkaddr < memarena->freelist.head->blkaddr) - { - memarena->freelist.head = p; - } - - memarena->freelist.freerover = p; - } - else - { - memarena->freelist.freerover = ptrfree; - } - - GSL_MEMARENA_UNLOCK(); - - GSL_MEMARENA_STATS( - { - int i = 0; - while (memdesc->size >> (GSL_PAGESIZE_SHIFT + i)) - { - i++; - } - i = i > (GSL_MEMARENA_PAGE_DIST_MAX-1) ? (GSL_MEMARENA_PAGE_DIST_MAX-1) : i; - memarena->stats.frees_pagedistribution[i]++; - }); - - GSL_MEMARENA_STATS(memarena->stats.frees++); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_free.\n" ); -} - -//---------------------------------------------------------------------------- - -void * -kgsl_memarena_gethostptr(gsl_memarena_t *memarena, gpuaddr_t gpuaddr) -{ - // - // get the host mapped address for a hardware device address - // - - void *hostptr = NULL; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> void* kgsl_memarena_gethostptr(gsl_memarena_t *memarena=0x%08x, gpuaddr_t gpuaddr=0x%08x)\n", memarena, gpuaddr ); - - KOS_ASSERT(memarena); - if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_gethostptr. Return value: 0x%08x\n", NULL ); - return (NULL); - } - - // check address range - KOS_ASSERT(gpuaddr >= memarena->gpubaseaddr); - KOS_ASSERT(gpuaddr < memarena->gpubaseaddr + memarena->sizebytes); - - hostptr = (void *)((gpuaddr - memarena->gpubaseaddr) + memarena->hostbaseaddr); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_gethostptr. Return value: 0x%08x\n", hostptr ); - - return (hostptr); -} - -//---------------------------------------------------------------------------- - -gpuaddr_t -kgsl_memarena_getgpuaddr(gsl_memarena_t *memarena, void *hostptr) -{ - // - // get the hardware device address for a host mapped address - // - - gpuaddr_t gpuaddr = 0; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_memarena_getgpuaddr(gsl_memarena_t *memarena=0x%08x, void *hostptr=0x%08x)\n", memarena, hostptr ); - - KOS_ASSERT(memarena); - if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getgpuaddr. Return value: 0x%08x\n", 0 ); - return (0); - } - - // check address range - KOS_ASSERT(hostptr >= (void *)memarena->hostbaseaddr); - KOS_ASSERT(hostptr < (void *)(memarena->hostbaseaddr + memarena->sizebytes)); - - gpuaddr = ((unsigned int)hostptr - memarena->hostbaseaddr) + memarena->gpubaseaddr; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getgpuaddr. Return value: 0x%08x\n", gpuaddr ); - - return (gpuaddr); -} - -//---------------------------------------------------------------------------- - -unsigned int -kgsl_memarena_getlargestfreeblock(gsl_memarena_t *memarena, gsl_flags_t flags) -{ - memblk_t *ptrfree; - unsigned int blocksize, largestblocksize = 0; - int alignmentshift; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> unsigned int kgsl_memarena_getlargestfreeblock(gsl_memarena_t *memarena=0x%08x, gsl_flags_t flags=0x%08x)\n", memarena, flags ); - - KOS_ASSERT(memarena); - if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getlargestfreeblock. Return value: %d\n", 0 ); - return (0); - } - - // determine shift count for alignment requested - alignmentshift = gsl_memarena_alignmentshift(flags); - - GSL_MEMARENA_LOCK(); - - ptrfree = memarena->freelist.head; - - do - { - blocksize = ptrfree->blksize - (ptrfree->blkaddr - ((ptrfree->blkaddr >> alignmentshift) << alignmentshift)); - - if (blocksize > largestblocksize) - { - largestblocksize = blocksize; - } - - ptrfree = ptrfree->next; - - } while (ptrfree != memarena->freelist.head); - - GSL_MEMARENA_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getlargestfreeblock. Return value: %d\n", largestblocksize ); - - return (largestblocksize); -} diff --git a/drivers/mxc/amd-gpu/common/gsl_mmu.c b/drivers/mxc/amd-gpu/common/gsl_mmu.c deleted file mode 100644 index 810a058a515..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_mmu.c +++ /dev/null @@ -1,1084 +0,0 @@ -/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" - - -////////////////////////////////////////////////////////////////////////////// -// types -////////////////////////////////////////////////////////////////////////////// - -// --------- -// pte debug -// --------- - -typedef struct _gsl_pte_debug_t -{ - unsigned int write :1; - unsigned int read :1; - unsigned int reserved :10; - unsigned int phyaddr :20; -} gsl_pte_debug_t; - - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -#define GSL_PT_ENTRY_SIZEBYTES 4 -#define GSL_PT_EXTRA_ENTRIES 16 - -#define GSL_PT_PAGE_WRITE 0x00000001 -#define GSL_PT_PAGE_READ 0x00000002 - -#define GSL_PT_PAGE_AP_MASK 0x00000003 -#define GSL_PT_PAGE_ADDR_MASK ~(GSL_PAGESIZE-1) - -#define GSL_MMUFLAGS_TLBFLUSH 0x80000000 - -#define GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS (sizeof(unsigned char) * 8) - - -////////////////////////////////////////////////////////////////////////////// -// constants -////////////////////////////////////////////////////////////////////////////// -const unsigned int GSL_PT_PAGE_AP[4] = {(GSL_PT_PAGE_READ | GSL_PT_PAGE_WRITE), GSL_PT_PAGE_READ, GSL_PT_PAGE_WRITE, 0}; - - -///////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#ifdef GSL_LOCKING_FINEGRAIN -#define GSL_MMU_MUTEX_CREATE() mmu->mutex = kos_mutex_create("gsl_mmu"); \ - if (!mmu->mutex) {return (GSL_FAILURE);} -#define GSL_MMU_LOCK() kos_mutex_lock(mmu->mutex) -#define GSL_MMU_UNLOCK() kos_mutex_unlock(mmu->mutex) -#define GSL_MMU_MUTEX_FREE() kos_mutex_free(mmu->mutex); mmu->mutex = 0; -#else -#define GSL_MMU_MUTEX_CREATE() -#define GSL_MMU_LOCK() -#define GSL_MMU_UNLOCK() -#define GSL_MMU_MUTEX_FREE() -#endif - -#define GSL_PT_ENTRY_GET(va) ((va - pagetable->va_base) >> GSL_PAGESIZE_SHIFT) -#define GSL_PT_VIRT_GET(pte) (pagetable->va_base + (pte * GSL_PAGESIZE)) - -#define GSL_PT_MAP_APDEFAULT GSL_PT_PAGE_AP[0] - -#define GSL_PT_MAP_GET(pte) *((unsigned int *)(((unsigned int)pagetable->base.hostptr) + ((pte) * GSL_PT_ENTRY_SIZEBYTES))) -#define GSL_PT_MAP_GETADDR(pte) (GSL_PT_MAP_GET(pte) & GSL_PT_PAGE_ADDR_MASK) - -#define GSL_PT_MAP_DEBUG(pte) ((gsl_pte_debug_t*) &GSL_PT_MAP_GET(pte)) - -#define GSL_PT_MAP_SETBITS(pte, bits) (GSL_PT_MAP_GET(pte) |= (((unsigned int) bits) & GSL_PT_PAGE_AP_MASK)) -#define GSL_PT_MAP_SETADDR(pte, pageaddr) (GSL_PT_MAP_GET(pte) = (GSL_PT_MAP_GET(pte) & ~GSL_PT_PAGE_ADDR_MASK) | (((unsigned int) pageaddr) & GSL_PT_PAGE_ADDR_MASK)) - -#define GSL_PT_MAP_RESET(pte) (GSL_PT_MAP_GET(pte) = 0) -#define GSL_PT_MAP_RESETBITS(pte, bits) (GSL_PT_MAP_GET(pte) &= ~(((unsigned int) bits) & GSL_PT_PAGE_AP_MASK)) - -#define GSL_MMU_VIRT_TO_PAGE(va) *((unsigned int *)(pagetable->base.gpuaddr + (GSL_PT_ENTRY_GET(va) * GSL_PT_ENTRY_SIZEBYTES))) -#define GSL_MMU_VIRT_TO_PHYS(va) ((GSL_MMU_VIRT_TO_PAGE(va) & GSL_PT_PAGE_ADDR_MASK) + (va & (GSL_PAGESIZE-1))) - -#define GSL_TLBFLUSH_FILTER_GET(superpte) *((unsigned char *)(((unsigned int)mmu->tlbflushfilter.base) + (superpte / GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS))) -#define GSL_TLBFLUSH_FILTER_SETDIRTY(superpte) (GSL_TLBFLUSH_FILTER_GET((superpte)) |= 1 << (superpte % GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS)) -#define GSL_TLBFLUSH_FILTER_ISDIRTY(superpte) (GSL_TLBFLUSH_FILTER_GET((superpte)) & (1 << (superpte % GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS))) -#define GSL_TLBFLUSH_FILTER_RESET() kos_memset(mmu->tlbflushfilter.base, 0, mmu->tlbflushfilter.size) - - -////////////////////////////////////////////////////////////////////////////// -// process index in pagetable object table -////////////////////////////////////////////////////////////////////////////// -OSINLINE int -kgsl_mmu_getprocessindex(unsigned int pid, int *pindex) -{ - int status = GSL_SUCCESS; -#ifdef GSL_MMU_PAGETABLE_PERPROCESS - if (kgsl_driver_getcallerprocessindex(pid, pindex) != GSL_SUCCESS) - { - status = GSL_FAILURE; - } -#else - (void) pid; // unreferenced formal parameter - *pindex = 0; -#endif // GSL_MMU_PAGETABLE_PERPROCESS - return (status); -} - -////////////////////////////////////////////////////////////////////////////// -// pagetable object for current caller process -////////////////////////////////////////////////////////////////////////////// -OSINLINE gsl_pagetable_t* -kgsl_mmu_getpagetableobject(gsl_mmu_t *mmu, unsigned int pid) -{ - int pindex = 0; - if (kgsl_mmu_getprocessindex(pid, &pindex) == GSL_SUCCESS) - { - return (mmu->pagetable[pindex]); - } - else - { - return (NULL); - } -} - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -void -kgsl_mh_intrcallback(gsl_intrid_t id, void *cookie) -{ - gsl_mmu_t *mmu = (gsl_mmu_t *) cookie; - unsigned int devindex = mmu->device->id-1; // device_id is 1 based - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> void kgsl_mh_ntrcallback(gsl_intrid_t id=%I, void *cookie=0x%08x)\n", id, cookie ); - - // error condition interrupt - if (id == gsl_cfg_mh_intr[devindex].AXI_READ_ERROR || - id == gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR || - id == gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT) - { - printk(KERN_ERR "GPU: AXI Read/Write Error or MMU page fault\n"); - schedule_work(&mmu->device->irq_err_work); - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mh_intrcallback.\n" ); -} - -//---------------------------------------------------------------------------- - -#ifdef _DEBUG -static void -kgsl_mmu_debug(gsl_mmu_t *mmu, gsl_mmu_debug_t *regs) -{ - unsigned int devindex = mmu->device->id-1; // device_id is 1 based - - kos_memset(regs, 0, sizeof(gsl_mmu_debug_t)); - - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].CONFIG, ®s->config); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].MPU_BASE, ®s->mpu_base); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].MPU_END, ®s->mpu_end); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].VA_RANGE, ®s->va_range); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].PT_BASE, ®s->pt_base); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].PAGE_FAULT, ®s->page_fault); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].TRAN_ERROR, ®s->trans_error); - mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].INVALIDATE, ®s->invalidate); -} -#endif - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_checkconsistency(gsl_pagetable_t *pagetable) -{ - unsigned int pte; - unsigned int data; - gsl_pte_debug_t *pte_debug; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_mmu_checkconsistency(gsl_pagetable_t *pagetable=0x%08x)\n", pagetable ); - - if (pagetable->last_superpte % GSL_PT_SUPER_PTE != 0) - { - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_checkconsistency. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // go through page table and make sure there are no detectable errors - pte = 0; - while (pte < pagetable->max_entries) - { - pte_debug = GSL_PT_MAP_DEBUG(pte); - - if (GSL_PT_MAP_GETADDR(pte) != 0) - { - // pte is in use - - // access first couple bytes of a page - data = *((unsigned int *)GSL_PT_VIRT_GET(pte)); - } - - pte++; - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_checkconsistency. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_destroypagetableobject(gsl_mmu_t *mmu, unsigned int pid) -{ - gsl_deviceid_t tmp_id; - gsl_device_t *tmp_device; - int pindex; - gsl_pagetable_t *pagetable; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> gsl_pagetable_t* kgsl_mmu_destroypagetableobject(gsl_mmu_t *mmu=0x%08x, unsigned int pid=0x%08x)\n", mmu, pid ); - - if (kgsl_mmu_getprocessindex(pid, &pindex) != GSL_SUCCESS) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_destroypagetableobject. Return value 0x%08x\n", GSL_SUCCESS ); - return (GSL_FAILURE); - } - - pagetable = mmu->pagetable[pindex]; - - // if pagetable object exists for current "current device mmu"/"current caller process" combination - if (pagetable) - { - // no more "device mmu"/"caller process" combinations attached to current pagetable object - if (pagetable->refcnt == 0) - { -#ifdef _DEBUG - // memory leak check - if (pagetable->last_superpte != 0 || GSL_PT_MAP_GETADDR(pagetable->last_superpte)) - { - /* many dumpx test cases forcefully exit, and thus trigger this assert. */ - /* Because it is an annoyance for HW guys, it is disabled for dumpx */ - if(!gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX) - { - KOS_ASSERT(0); - return (GSL_FAILURE); - } - } -#endif // _DEBUG - - if (pagetable->base.gpuaddr) - { - kgsl_sharedmem_free0(&pagetable->base, GSL_CALLER_PROCESSID_GET()); - } - - kos_free(pagetable); - - // clear pagetable object reference for all "device mmu"/"current caller process" combinations - for (tmp_id = GSL_DEVICE_ANY + 1; tmp_id <= GSL_DEVICE_MAX; tmp_id++) - { - tmp_device = &gsl_driver.device[tmp_id-1]; - - if (tmp_device->mmu.flags & GSL_FLAGS_STARTED) - { - tmp_device->mmu.pagetable[pindex] = NULL; - } - } - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_destroypagetableobject. Return value 0x%08x\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -gsl_pagetable_t* -kgsl_mmu_createpagetableobject(gsl_mmu_t *mmu, unsigned int pid) -{ - // - // create pagetable object for "current device mmu"/"current caller - // process" combination. If none exists, setup a new pagetable object. - // - int status = GSL_SUCCESS; - gsl_pagetable_t *tmp_pagetable = NULL; - gsl_deviceid_t tmp_id; - gsl_device_t *tmp_device; - int pindex; - gsl_flags_t flags; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> gsl_pagetable_t* kgsl_mmu_createpagetableobject(gsl_mmu_t *mmu=0x%08x, unsigned int pid=0x%08x)\n", mmu, pid ); - - status = kgsl_mmu_getprocessindex(pid, &pindex); - if (status != GSL_SUCCESS) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_createpagetableobject. Return value 0x%08x\n", NULL ); - return (NULL); - } - // if pagetable object does not already exists for "current device mmu"/"current caller process" combination - if (!mmu->pagetable[pindex]) - { - // then, check if pagetable object already exists for any "other device mmu"/"current caller process" combination - for (tmp_id = GSL_DEVICE_ANY + 1; tmp_id <= GSL_DEVICE_MAX; tmp_id++) - { - tmp_device = &gsl_driver.device[tmp_id-1]; - - if (tmp_device->mmu.flags & GSL_FLAGS_STARTED) - { - if (tmp_device->mmu.pagetable[pindex]) - { - tmp_pagetable = tmp_device->mmu.pagetable[pindex]; - break; - } - } - } - - // pagetable object exists - if (tmp_pagetable) - { - KOS_ASSERT(tmp_pagetable->va_base == mmu->va_base); - KOS_ASSERT(tmp_pagetable->va_range == mmu->va_range); - - // set pagetable object reference - mmu->pagetable[pindex] = tmp_pagetable; - } - // create new pagetable object - else - { - mmu->pagetable[pindex] = (void *)kos_malloc(sizeof(gsl_pagetable_t)); - if (!mmu->pagetable[pindex]) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to allocate pagetable object.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_createpagetableobject. Return value 0x%08x\n", NULL ); - return (NULL); - } - - kos_memset(mmu->pagetable[pindex], 0, sizeof(gsl_pagetable_t)); - - mmu->pagetable[pindex]->pid = pid; - mmu->pagetable[pindex]->refcnt = 0; - mmu->pagetable[pindex]->va_base = mmu->va_base; - mmu->pagetable[pindex]->va_range = mmu->va_range; - mmu->pagetable[pindex]->last_superpte = 0; - mmu->pagetable[pindex]->max_entries = (mmu->va_range >> GSL_PAGESIZE_SHIFT) + GSL_PT_EXTRA_ENTRIES; - - // allocate page table memory - flags = (GSL_MEMFLAGS_ALIGN4K | GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_STRICTREQUEST); - status = kgsl_sharedmem_alloc0(mmu->device->id, flags, mmu->pagetable[pindex]->max_entries * GSL_PT_ENTRY_SIZEBYTES, &mmu->pagetable[pindex]->base); - - if (status == GSL_SUCCESS) - { - // reset page table entries - kgsl_sharedmem_set0(&mmu->pagetable[pindex]->base, 0, 0, mmu->pagetable[pindex]->base.size); - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MMU_TBLADDR, mmu->pagetable[pindex]->base.gpuaddr, 0, mmu->pagetable[pindex]->base.size, "kgsl_mmu_init")); - } - else - { - kgsl_mmu_destroypagetableobject(mmu, pid); - } - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_createpagetableobject. Return value 0x%08x\n", mmu->pagetable[pindex] ); - - return (mmu->pagetable[pindex]); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_setpagetable(gsl_device_t *device, unsigned int pid) -{ - // - // set device mmu to use current caller process's page table - // - int status = GSL_SUCCESS; - unsigned int devindex = device->id-1; // device_id is 1 based - gsl_mmu_t *mmu = &device->mmu; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> gsl_pagetable_t* kgsl_mmu_setpagetable(gsl_device_t *device=0x%08x)\n", device ); - - GSL_MMU_LOCK(); - - if (mmu->flags & GSL_FLAGS_STARTED) - { -#ifdef GSL_MMU_PAGETABLE_PERPROCESS - // page table not current, then setup mmu to use new specified page table - if (mmu->hwpagetable->pid != pid) - { - gsl_pagetable_t *pagetable = kgsl_mmu_getpagetableobject(mmu, pid); - if (pagetable) - { - mmu->hwpagetable = pagetable; - - // flag tlb flush - mmu->flags |= GSL_MMUFLAGS_TLBFLUSH; - - status = mmu->device->ftbl.mmu_setpagetable(mmu->device, gsl_cfg_mmu_reg[devindex].PT_BASE, pagetable->base.gpuaddr, pid); - - GSL_MMU_STATS(mmu->stats.pt.switches++); - } - else - { - status = GSL_FAILURE; - } - } -#endif // GSL_MMU_PAGETABLE_PERPROCESS - - // if needed, invalidate device specific tlb - if ((mmu->flags & GSL_MMUFLAGS_TLBFLUSH) && status == GSL_SUCCESS) - { - mmu->flags &= ~GSL_MMUFLAGS_TLBFLUSH; - - GSL_TLBFLUSH_FILTER_RESET(); - - status = mmu->device->ftbl.mmu_tlbinvalidate(mmu->device, gsl_cfg_mmu_reg[devindex].INVALIDATE, pid); - - GSL_MMU_STATS(mmu->stats.tlbflushes++); - } - } - - GSL_MMU_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_setpagetable. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_init(gsl_device_t *device) -{ - // - // intialize device mmu - // - // call this with the global lock held - // - int status; - gsl_flags_t flags; - gsl_pagetable_t *pagetable; - unsigned int devindex = device->id-1; // device_id is 1 based - gsl_mmu_t *mmu = &device->mmu; -#ifdef _DEBUG - gsl_mmu_debug_t regs; -#endif // _DEBUG - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_mmu_init(gsl_device_t *device=0x%08x)\n", device ); - - if (device->ftbl.mmu_tlbinvalidate == NULL || device->ftbl.mmu_setpagetable == NULL || - !(device->flags & GSL_FLAGS_INITIALIZED)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - if (mmu->flags & GSL_FLAGS_INITIALIZED0) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_INFO, "MMU already initialized.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); - } - - // setup backward reference - mmu->device = device; - - // disable MMU when running in safe mode - if (device->flags & GSL_FLAGS_SAFEMODE) - { - mmu->config = 0x00000000; - } - - // setup MMU and sub-client behavior - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].CONFIG, mmu->config); - - // enable axi interrupts - kgsl_intr_attach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_READ_ERROR, kgsl_mh_intrcallback, (void *) mmu); - kgsl_intr_attach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR, kgsl_mh_intrcallback, (void *) mmu); - kgsl_intr_enable(&device->intr, gsl_cfg_mh_intr[devindex].AXI_READ_ERROR); - kgsl_intr_enable(&device->intr, gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR); - - mmu->refcnt = 0; - mmu->flags |= GSL_FLAGS_INITIALIZED0; - - // MMU enabled - if (mmu->config & 0x1) - { - // idle device - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - - // make sure aligned to pagesize - KOS_ASSERT((mmu->mpu_base & ((1 << GSL_PAGESIZE_SHIFT)-1)) == 0); - KOS_ASSERT(((mmu->mpu_base + mmu->mpu_range) & ((1 << GSL_PAGESIZE_SHIFT)-1)) == 0); - - // define physical memory range accessible by the core - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].MPU_BASE, mmu->mpu_base); - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].MPU_END, mmu->mpu_base + mmu->mpu_range); - - // enable page fault interrupt - kgsl_intr_attach(&device->intr, gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT, kgsl_mh_intrcallback, (void *) mmu); - kgsl_intr_enable(&device->intr, gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT); - - mmu->flags |= GSL_FLAGS_INITIALIZED; - - // sub-client MMU lookups require address translation - if ((mmu->config & ~0x1) > 0) - { - GSL_MMU_MUTEX_CREATE(); - - // make sure virtual address range is a multiple of 64Kb - KOS_ASSERT((mmu->va_range & ((1 << 16)-1)) == 0); - - // setup pagetable object - pagetable = kgsl_mmu_createpagetableobject(mmu, GSL_CALLER_PROCESSID_GET()); - if (!pagetable) - { - kgsl_mmu_close(device); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - mmu->hwpagetable = pagetable; - - // create tlb flush filter to track dirty superPTE's -- one bit per superPTE - mmu->tlbflushfilter.size = (mmu->va_range / (GSL_PAGESIZE * GSL_PT_SUPER_PTE * 8)) + 1; - mmu->tlbflushfilter.base = (unsigned int *)kos_malloc(mmu->tlbflushfilter.size); - if (!mmu->tlbflushfilter.base) - { - kgsl_mmu_close(device); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - GSL_TLBFLUSH_FILTER_RESET(); - - // set page table base - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].PT_BASE, mmu->hwpagetable->base.gpuaddr); - - // define virtual address range - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].VA_RANGE, (mmu->hwpagetable->va_base | (mmu->hwpagetable->va_range >> 16))); - - // allocate memory used for completing r/w operations that cannot be mapped by the MMU - flags = (GSL_MEMFLAGS_ALIGN32 | GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_STRICTREQUEST); - status = kgsl_sharedmem_alloc0(device->id, flags, 32, &mmu->dummyspace); - if (status != GSL_SUCCESS) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to allocate dummy space memory.\n" ); - kgsl_mmu_close(device); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", status ); - return (status); - } - - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].TRAN_ERROR, mmu->dummyspace.gpuaddr); - - // call device specific tlb invalidate - device->ftbl.mmu_tlbinvalidate(device, gsl_cfg_mmu_reg[devindex].INVALIDATE, mmu->hwpagetable->pid); - - GSL_MMU_STATS(mmu->stats.tlbflushes++); - - mmu->flags |= GSL_FLAGS_STARTED; - } - } - - KGSL_DEBUG(GSL_DBGFLAGS_MMU, kgsl_mmu_debug(&device->mmu, ®s)); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_map(gsl_mmu_t *mmu, gpuaddr_t gpubaseaddr, const gsl_scatterlist_t *scatterlist, gsl_flags_t flags, unsigned int pid) -{ - // - // map physical pages into the gpu page table - // - int status = GSL_SUCCESS; - unsigned int i, phyaddr, ap; - unsigned int pte, ptefirst, ptelast, superpte; - int flushtlb; - gsl_pagetable_t *pagetable; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_mmu_map(gsl_mmu_t *mmu=0x%08x, gpuaddr_t gpubaseaddr=0x%08x, gsl_scatterlist_t *scatterlist=%M, gsl_flags_t flags=%d, unsigned int pid=%d)\n", - mmu, gpubaseaddr, scatterlist, flags, pid ); - - KOS_ASSERT(scatterlist); - - if (scatterlist->num <= 0) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: num pages is too small.\n" ); - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_map. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // get gpu access permissions - ap = GSL_PT_PAGE_AP[((flags & GSL_MEMFLAGS_GPUAP_MASK) >> GSL_MEMFLAGS_GPUAP_SHIFT)]; - - GSL_MMU_LOCK(); - - pagetable = kgsl_mmu_getpagetableobject(mmu, pid); - if (!pagetable) - { - GSL_MMU_UNLOCK(); - return (GSL_FAILURE); - } - - // check consistency, debug only - KGSL_DEBUG(GSL_DBGFLAGS_MMU, kgsl_mmu_checkconsistency(pagetable)); - - ptefirst = GSL_PT_ENTRY_GET(gpubaseaddr); - ptelast = GSL_PT_ENTRY_GET(gpubaseaddr + (GSL_PAGESIZE * (scatterlist->num-1))); - flushtlb = 0; - - if (!GSL_PT_MAP_GETADDR(ptefirst)) - { - // tlb needs to be flushed when the first and last pte are not at superpte boundaries - if ((ptefirst & (GSL_PT_SUPER_PTE-1)) != 0 || ((ptelast+1) & (GSL_PT_SUPER_PTE-1)) != 0) - { - flushtlb = 1; - } - - // create page table entries - for (pte = ptefirst; pte <= ptelast; pte++) - { - if (scatterlist->contiguous) - { - phyaddr = scatterlist->pages[0] + ((pte-ptefirst) * GSL_PAGESIZE); - } - else - { - phyaddr = scatterlist->pages[pte-ptefirst]; - } - - GSL_PT_MAP_SETADDR(pte, phyaddr); - GSL_PT_MAP_SETBITS(pte, ap); - - // tlb needs to be flushed when a dirty superPTE gets backed - if ((pte & (GSL_PT_SUPER_PTE-1)) == 0) - { - if (GSL_TLBFLUSH_FILTER_ISDIRTY(pte / GSL_PT_SUPER_PTE)) - { - flushtlb = 1; - } - } - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_SET_MMUTBL, pte , *(unsigned int*)(((char*)pagetable->base.hostptr) + (pte * GSL_PT_ENTRY_SIZEBYTES)), 0, "kgsl_mmu_map")); - } - - if (flushtlb) - { - // every device's tlb needs to be flushed because the current page table is shared among all devices - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - if (gsl_driver.device[i].flags & GSL_FLAGS_INITIALIZED) - { - gsl_driver.device[i].mmu.flags |= GSL_MMUFLAGS_TLBFLUSH; - } - } - } - - // determine new last mapped superPTE - superpte = ptelast - (ptelast & (GSL_PT_SUPER_PTE-1)); - if (superpte > pagetable->last_superpte) - { - pagetable->last_superpte = superpte; - } - - GSL_MMU_STATS(mmu->stats.pt.maps++); - } - else - { - // this should never happen - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, "FATAL: This should never happen.\n" ); - KOS_ASSERT(0); - status = GSL_FAILURE; - } - - GSL_MMU_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_map. Return value %B\n", GSL_SUCCESS ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_unmap(gsl_mmu_t *mmu, gpuaddr_t gpubaseaddr, int range, unsigned int pid) -{ - // - // remove mappings in the specified address range from the gpu page table - // - int status = GSL_SUCCESS; - gsl_pagetable_t *pagetable; - unsigned int numpages; - unsigned int pte, ptefirst, ptelast, superpte; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_mmu_unmap(gsl_mmu_t *mmu=0x%08x, gpuaddr_t gpubaseaddr=0x%08x, int range=%d, unsigned int pid=%d)\n", - mmu, gpubaseaddr, range, pid ); - - if (range <= 0) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Range is too small.\n" ); - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_unmap. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - numpages = (range >> GSL_PAGESIZE_SHIFT); - if (range & (GSL_PAGESIZE-1)) - { - numpages++; - } - - GSL_MMU_LOCK(); - - pagetable = kgsl_mmu_getpagetableobject(mmu, pid); - if (!pagetable) - { - GSL_MMU_UNLOCK(); - return (GSL_FAILURE); - } - - // check consistency, debug only - KGSL_DEBUG(GSL_DBGFLAGS_MMU, kgsl_mmu_checkconsistency(pagetable)); - - ptefirst = GSL_PT_ENTRY_GET(gpubaseaddr); - ptelast = GSL_PT_ENTRY_GET(gpubaseaddr + (GSL_PAGESIZE * (numpages-1))); - - if (GSL_PT_MAP_GETADDR(ptefirst)) - { - superpte = ptefirst - (ptefirst & (GSL_PT_SUPER_PTE-1)); - GSL_TLBFLUSH_FILTER_SETDIRTY(superpte / GSL_PT_SUPER_PTE); - - // remove page table entries - for (pte = ptefirst; pte <= ptelast; pte++) - { - GSL_PT_MAP_RESET(pte); - - superpte = pte - (pte & (GSL_PT_SUPER_PTE-1)); - if (pte == superpte) - { - GSL_TLBFLUSH_FILTER_SETDIRTY(superpte / GSL_PT_SUPER_PTE); - } - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_SET_MMUTBL, pte, *(unsigned int*)(((char*)pagetable->base.hostptr) + (pte * GSL_PT_ENTRY_SIZEBYTES)), 0, "kgsl_mmu_unmap, reset superPTE")); - } - - // determine new last mapped superPTE - superpte = ptelast - (ptelast & (GSL_PT_SUPER_PTE-1)); - if (superpte == pagetable->last_superpte && pagetable->last_superpte >= GSL_PT_SUPER_PTE) - { - do - { - pagetable->last_superpte -= GSL_PT_SUPER_PTE; - } while (!GSL_PT_MAP_GETADDR(pagetable->last_superpte) && pagetable->last_superpte >= GSL_PT_SUPER_PTE); - } - - GSL_MMU_STATS(mmu->stats.pt.unmaps++); - } - else - { - // this should never happen - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, "FATAL: This should never happen.\n" ); - KOS_ASSERT(0); - status = GSL_FAILURE; - } - - // invalidate tlb, debug only - KGSL_DEBUG(GSL_DBGFLAGS_MMU, mmu->device->ftbl.mmu_tlbinvalidate(mmu->device, gsl_cfg_mmu_reg[mmu->device->id-1].INVALIDATE, pagetable->pid)); - - GSL_MMU_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_unmap. Return value %B\n", GSL_SUCCESS ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_getmap(gsl_mmu_t *mmu, gpuaddr_t gpubaseaddr, int range, gsl_scatterlist_t *scatterlist, unsigned int pid) -{ - // - // obtain scatter list of physical pages for the given gpu address range. - // if all pages are physically contiguous they are coalesced into a single - // scatterlist entry. - // - gsl_pagetable_t *pagetable; - unsigned int numpages; - unsigned int pte, ptefirst, ptelast; - unsigned int contiguous = 1; - - numpages = (range >> GSL_PAGESIZE_SHIFT); - if (range & (GSL_PAGESIZE-1)) - { - numpages++; - } - - if (range <= 0 || scatterlist->num != numpages) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Range is too small.\n" ); - KOS_ASSERT(0); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_getmap. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - GSL_MMU_LOCK(); - - pagetable = kgsl_mmu_getpagetableobject(mmu, pid); - if (!pagetable) - { - GSL_MMU_UNLOCK(); - return (GSL_FAILURE); - } - - ptefirst = GSL_PT_ENTRY_GET(gpubaseaddr); - ptelast = GSL_PT_ENTRY_GET(gpubaseaddr + (GSL_PAGESIZE * (numpages-1))); - - // determine whether pages are physically contiguous - if (numpages > 1) - { - for (pte = ptefirst; pte <= ptelast-1; pte++) - { - if (GSL_PT_MAP_GETADDR(pte) + GSL_PAGESIZE != GSL_PT_MAP_GETADDR(pte+1)) - { - contiguous = 0; - break; - } - } - } - - if (!contiguous) - { - // populate scatter list - for (pte = ptefirst; pte <= ptelast; pte++) - { - scatterlist->pages[pte-ptefirst] = GSL_PT_MAP_GETADDR(pte); - } - } - else - { - // coalesce physically contiguous pages into a single scatter list entry - scatterlist->pages[0] = GSL_PT_MAP_GETADDR(ptefirst); - } - - GSL_MMU_UNLOCK(); - - scatterlist->contiguous = contiguous; - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_close(gsl_device_t *device) -{ - // - // close device mmu - // - // call this with the global lock held - // - gsl_mmu_t *mmu = &device->mmu; - unsigned int devindex = mmu->device->id-1; // device_id is 1 based -#ifdef _DEBUG - int i; -#endif // _DEBUG - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_close(gsl_device_t *device=0x%08x)\n", device ); - - if (mmu->flags & GSL_FLAGS_INITIALIZED0) - { - if (mmu->flags & GSL_FLAGS_STARTED) - { - // terminate pagetable object - kgsl_mmu_destroypagetableobject(mmu, GSL_CALLER_PROCESSID_GET()); - } - - // no more processes attached to current device mmu - if (mmu->refcnt == 0) - { -#ifdef _DEBUG - // check if there are any orphaned pagetable objects lingering around - for (i = 0; i < GSL_MMU_PAGETABLE_MAX; i++) - { - if (mmu->pagetable[i]) - { - /* many dumpx test cases forcefully exit, and thus trigger this assert. */ - /* Because it is an annoyance for HW guys, it is disabled for dumpx */ - if(!gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX) - { - KOS_ASSERT(0); - return (GSL_FAILURE); - } - } - } -#endif // _DEBUG - - // disable mh interrupts - kgsl_intr_detach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_READ_ERROR); - kgsl_intr_detach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR); - kgsl_intr_detach(&device->intr, gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT); - - // disable MMU - device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].CONFIG, 0x00000000); - - if (mmu->tlbflushfilter.base) - { - kos_free(mmu->tlbflushfilter.base); - } - - if (mmu->dummyspace.gpuaddr) - { - kgsl_sharedmem_free0(&mmu->dummyspace, GSL_CALLER_PROCESSID_GET()); - } - - GSL_MMU_MUTEX_FREE(); - - mmu->flags &= ~GSL_FLAGS_STARTED; - mmu->flags &= ~GSL_FLAGS_INITIALIZED; - mmu->flags &= ~GSL_FLAGS_INITIALIZED0; - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_close. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_attachcallback(gsl_mmu_t *mmu, unsigned int pid) -{ - // - // attach process - // - // call this with the global lock held - // - int status = GSL_SUCCESS; - gsl_pagetable_t *pagetable; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_attachcallback(gsl_mmu_t *mmu=0x%08x, unsigned int pid=0x%08x)\n", mmu, pid ); - - GSL_MMU_LOCK(); - - if (mmu->flags & GSL_FLAGS_INITIALIZED0) - { - // attach to current device mmu - mmu->refcnt++; - - if (mmu->flags & GSL_FLAGS_STARTED) - { - // attach to pagetable object - pagetable = kgsl_mmu_createpagetableobject(mmu, pid); - if(pagetable) - { - pagetable->refcnt++; - } - else - { - status = GSL_FAILURE; - } - } - } - - GSL_MMU_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_attachcallback. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_detachcallback(gsl_mmu_t *mmu, unsigned int pid) -{ - // - // detach process - // - int status = GSL_SUCCESS; - gsl_pagetable_t *pagetable; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_detachcallback(gsl_mmu_t *mmu=0x%08x, unsigned int pid=0x%08x)\n", mmu, pid ); - - GSL_MMU_LOCK(); - - if (mmu->flags & GSL_FLAGS_INITIALIZED0) - { - // detach from current device mmu - mmu->refcnt--; - - if (mmu->flags & GSL_FLAGS_STARTED) - { - // detach from pagetable object - pagetable = kgsl_mmu_getpagetableobject(mmu, pid); - if(pagetable) - { - pagetable->refcnt--; - } - else - { - status = GSL_FAILURE; - } - } - } - - GSL_MMU_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_detachcallback. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_querystats(gsl_mmu_t *mmu, gsl_mmustats_t *stats) -{ -#ifdef GSL_STATS_MMU - int status = GSL_SUCCESS; - - KOS_ASSERT(stats); - - GSL_MMU_LOCK(); - - if (mmu->flags & GSL_FLAGS_STARTED) - { - kos_memcpy(stats, &mmu->stats, sizeof(gsl_mmustats_t)); - } - else - { - kos_memset(stats, 0, sizeof(gsl_mmustats_t)); - } - - GSL_MMU_UNLOCK(); - - return (status); -#else - // unreferenced formal parameters - (void) mmu; - (void) stats; - - return (GSL_FAILURE_NOTSUPPORTED); -#endif // GSL_STATS_MMU -} - -//---------------------------------------------------------------------------- - -int -kgsl_mmu_bist(gsl_mmu_t *mmu) -{ - // unreferenced formal parameter - (void) mmu; - - return (GSL_SUCCESS); -} diff --git a/drivers/mxc/amd-gpu/common/gsl_ringbuffer.c b/drivers/mxc/amd-gpu/common/gsl_ringbuffer.c deleted file mode 100644 index fb05ff3cbe1..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_ringbuffer.c +++ /dev/null @@ -1,1163 +0,0 @@ -/* Copyright (c) 2002,2007-2009, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#include "gsl_cmdstream.h" - -#ifdef GSL_BLD_YAMATO - -////////////////////////////////////////////////////////////////////////////// -// ucode -////////////////////////////////////////////////////////////////////////////// -#define uint32 unsigned int - -#include "pm4_microcode.inl" -#include "pfp_microcode_nrt.inl" - -#undef uint32 - - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -#define GSL_RB_NOP_SIZEDWORDS 2 // default is 2 -#define GSL_RB_PROTECTED_MODE_CONTROL 0x00000000 // protected mode error checking below register address 0x800 - // note: if CP_INTERRUPT packet is used then checking needs - // to change to below register address 0x7C8 - - -////////////////////////////////////////////////////////////////////////////// -// ringbuffer size log2 quadwords equivalent -////////////////////////////////////////////////////////////////////////////// -OSINLINE unsigned int -gsl_ringbuffer_sizelog2quadwords(unsigned int sizedwords) -{ - unsigned int sizelog2quadwords = 0; - int i = sizedwords >> 1; - while (i >>= 1) - { - sizelog2quadwords++; - } - return (sizelog2quadwords); -} - - -////////////////////////////////////////////////////////////////////////////// -// private prototypes -////////////////////////////////////////////////////////////////////////////// -#ifdef _DEBUG -static void kgsl_ringbuffer_debug(gsl_ringbuffer_t *rb, gsl_rb_debug_t *rb_debug); -#endif - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -void -kgsl_cp_intrcallback(gsl_intrid_t id, void *cookie) -{ - gsl_ringbuffer_t *rb = (gsl_ringbuffer_t *) cookie; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> void kgsl_cp_intrcallback(gsl_intrid_t id=%I, void *cookie=0x%08x)\n", id, cookie ); - - switch(id) - { - // error condition interrupt - case GSL_INTR_YDX_CP_T0_PACKET_IN_IB: - case GSL_INTR_YDX_CP_OPCODE_ERROR: - case GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR: - case GSL_INTR_YDX_CP_RESERVED_BIT_ERROR: - case GSL_INTR_YDX_CP_IB_ERROR: - printk(KERN_ERR "GPU: CP Error\n"); - schedule_work(&rb->device->irq_err_work); - break; - - // non-error condition interrupt - case GSL_INTR_YDX_CP_SW_INT: - case GSL_INTR_YDX_CP_IB2_INT: - case GSL_INTR_YDX_CP_IB1_INT: - case GSL_INTR_YDX_CP_RING_BUFFER: - - // signal intr completion event - kos_event_signal(rb->device->intr.evnt[id]); - break; - - default: - - break; - } - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cp_intrcallback.\n" ); -} - -//---------------------------------------------------------------------------- - -void -kgsl_ringbuffer_watchdog() -{ - gsl_ringbuffer_t *rb = &(gsl_driver.device[GSL_DEVICE_YAMATO-1]).ringbuffer; // device_id is 1 based - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> void kgsl_ringbuffer_watchdog()\n" ); - - if (rb->flags & GSL_FLAGS_STARTED) - { - GSL_RB_MUTEX_LOCK(); - - GSL_RB_GET_READPTR(rb, &rb->rptr); - - // ringbuffer is currently not empty - if (rb->rptr != rb->wptr) - { - // and a rptr sample was taken during interval n-1 - if (rb->watchdog.flags & GSL_FLAGS_ACTIVE) - { - // and the rptr did not advance between interval n-1 and n - if (rb->rptr == rb->watchdog.rptr_sample) - { - // then the core has hung - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_FATAL, - "ERROR: Watchdog detected core hung.\n" ); - - rb->device->ftbl.device_destroy(rb->device); - return; - } - } - - // save rptr sample for interval n - rb->watchdog.flags |= GSL_FLAGS_ACTIVE; - rb->watchdog.rptr_sample = rb->rptr; - } - else - { - // clear rptr sample for interval n - rb->watchdog.flags &= ~GSL_FLAGS_ACTIVE; - } - - GSL_RB_MUTEX_UNLOCK(); - } - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_watchdog.\n" ); -} - -//---------------------------------------------------------------------------- - -#ifdef _DEBUG - -OSINLINE void -kgsl_ringbuffer_checkregister(unsigned int reg, int pmodecheck) -{ - if (pmodecheck) - { - // check for register protection mode violation - if (reg <= (GSL_RB_PROTECTED_MODE_CONTROL & 0x3FFF)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Register protection mode violation.\n" ); - KOS_ASSERT(0); - } - } - - // range check register offset - if (reg > (gsl_driver.device[GSL_DEVICE_YAMATO-1].regspace.sizebytes >> 2)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Register out of range.\n" ); - KOS_ASSERT(0); - } -} - -//---------------------------------------------------------------------------- - -void -kgsl_ringbuffer_checkpm4type0(unsigned int header, unsigned int** cmds, int pmodeoff) -{ - pm4_type0 pm4header = *((pm4_type0*) &header); - unsigned int reg; - - if (pm4header.one_reg_wr) - { - reg = pm4header.base_index; - } - else - { - reg = pm4header.base_index + pm4header.count; - } - - kgsl_ringbuffer_checkregister(reg, !pmodeoff); - - *cmds += pm4header.count + 1; -} - -//---------------------------------------------------------------------------- - -void -kgsl_ringbuffer_checkpm4type3(unsigned int header, unsigned int** cmds, int indirection, int pmodeoff) -{ - pm4_type3 pm4header = *((pm4_type3*) &header); - unsigned int *ordinal2 = *cmds; - unsigned int *ibcmds, *end; - unsigned int reg, length; - - // check indirect buffer level - if (indirection > 2) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Only two levels of indirection supported.\n" ); - KOS_ASSERT(0); - } - - switch(pm4header.it_opcode) - { - case PM4_INDIRECT_BUFFER: - case PM4_INDIRECT_BUFFER_PFD: - - // determine ib host base and end address - ibcmds = (unsigned int*) kgsl_sharedmem_convertaddr(*ordinal2, 0); - end = ibcmds + *(ordinal2 + 1); - - // walk through the ib - while(ibcmds < end) - { - unsigned int tmpheader = *(ibcmds++); - - switch(tmpheader & PM4_PKT_MASK) - { - case PM4_TYPE0_PKT: - kgsl_ringbuffer_checkpm4type0(tmpheader, &ibcmds, pmodeoff); - break; - - case PM4_TYPE1_PKT: - case PM4_TYPE2_PKT: - break; - - case PM4_TYPE3_PKT: - kgsl_ringbuffer_checkpm4type3(tmpheader, &ibcmds, (indirection + 1), pmodeoff); - break; - } - } - break; - - case PM4_ME_INIT: - - if(indirection != 0) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: ME INIT packet cannot reside in an ib.\n" ); - KOS_ASSERT(0); - } - break; - - case PM4_REG_RMW: - - reg = (*ordinal2) & 0x1FFF; - - kgsl_ringbuffer_checkregister(reg, !pmodeoff); - - break; - - case PM4_SET_CONSTANT: - - if((((*ordinal2) >> 16) & 0xFF) == 0x4) // incremental register update - { - reg = 0x2000 + ((*ordinal2) & 0x3FF); // gfx decode space address starts at 0x2000 - length = pm4header.count - 1; - - kgsl_ringbuffer_checkregister(reg + length, 0); - } - break; - - case PM4_LOAD_CONSTANT_CONTEXT: - - if(((*(ordinal2 + 1) >> 16) & 0xFF) == 0x4) // incremental register update - { - reg = 0x2000 + (*(ordinal2 + 1) & 0x3FF); // gfx decode space address starts at 0x2000 - length = *(ordinal2 + 2); - - kgsl_ringbuffer_checkregister(reg + length, 0); - } - break; - - case PM4_COND_WRITE: - - if(((*ordinal2) & 0x00000100) == 0x0) // write to register - { - reg = *(ordinal2 + 4) & 0x3FFF; - - kgsl_ringbuffer_checkregister(reg, !pmodeoff); - } - break; - } - - *cmds += pm4header.count + 1; -} - -//---------------------------------------------------------------------------- - -void -kgsl_ringbuffer_checkpm4(unsigned int* cmds, unsigned int sizedwords, int pmodeoff) -{ - unsigned int *ringcmds = cmds; - unsigned int *end = cmds + sizedwords; - - while(ringcmds < end) - { - unsigned int header = *(ringcmds++); - - switch(header & PM4_PKT_MASK) - { - case PM4_TYPE0_PKT: - kgsl_ringbuffer_checkpm4type0(header, &ringcmds, pmodeoff); - break; - - case PM4_TYPE1_PKT: - case PM4_TYPE2_PKT: - break; - - case PM4_TYPE3_PKT: - kgsl_ringbuffer_checkpm4type3(header, &ringcmds, 0, pmodeoff); - break; - } - } -} - -#endif // _DEBUG - -//---------------------------------------------------------------------------- - -static void -kgsl_ringbuffer_submit(gsl_ringbuffer_t *rb) -{ - unsigned int value; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> static void kgsl_ringbuffer_submit(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); - - KOS_ASSERT(rb->wptr != 0); - - kgsl_device_active(rb->device); - - GSL_RB_UPDATE_WPTR_POLLING(rb); - - // send the wptr to the hw - rb->device->ftbl.device_regwrite(rb->device, mmCP_RB_WPTR, rb->wptr); - - rb->flags |= GSL_FLAGS_ACTIVE; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_submit.\n" ); -} - -//---------------------------------------------------------------------------- - -static int -kgsl_ringbuffer_waitspace(gsl_ringbuffer_t *rb, unsigned int numcmds, int wptr_ahead) -{ - int nopcount; - unsigned int freecmds; - unsigned int *cmds; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> static int kgsl_ringbuffer_waitspace(gsl_ringbuffer_t *rb=0x%08x, unsigned int numcmds=%d, int wptr_ahead=%d)\n", - rb, numcmds, wptr_ahead ); - - - // if wptr ahead, fill the remaining with NOPs - if (wptr_ahead) - { - nopcount = rb->sizedwords - rb->wptr - 1; // -1 for header - - cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; - GSL_RB_WRITE(cmds, pm4_nop_packet(nopcount)); - rb->wptr++; - - kgsl_ringbuffer_submit(rb); - - rb->wptr = 0; - - GSL_RB_STATS(rb->stats.wraps++); - } - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_RBWAIT, GSL_DEVICE_YAMATO, rb->wptr, numcmds, "kgsl_ringbuffer_waitspace")); - - // wait for space in ringbuffer - for( ; ; ) - { - GSL_RB_GET_READPTR(rb, &rb->rptr); - - freecmds = rb->rptr - rb->wptr; - - if ((freecmds == 0) || (freecmds > numcmds)) - { - break; - } - - } - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_waitspace. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -static unsigned int * -kgsl_ringbuffer_addcmds(gsl_ringbuffer_t *rb, unsigned int numcmds) -{ - unsigned int *ptr; - int status = GSL_SUCCESS; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> static unsigned int* kgsl_ringbuffer_addcmds(gsl_ringbuffer_t *rb=0x%08x, unsigned int numcmds=%d)\n", - rb, numcmds ); - - KOS_ASSERT(numcmds < rb->sizedwords); - - // update host copy of read pointer when running in safe mode - if (rb->device->flags & GSL_FLAGS_SAFEMODE) - { - GSL_RB_GET_READPTR(rb, &rb->rptr); - } - - // check for available space - if (rb->wptr >= rb->rptr) - { - // wptr ahead or equal to rptr - if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) // reserve dwords for nop packet - { - status = kgsl_ringbuffer_waitspace(rb, numcmds, 1); - } - } - else - { - // wptr behind rptr - if ((rb->wptr + numcmds) >= rb->rptr) - { - status = kgsl_ringbuffer_waitspace(rb, numcmds, 0); - } - - // check for remaining space - if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) // reserve dwords for nop packet - { - status = kgsl_ringbuffer_waitspace(rb, numcmds, 1); - } - } - - ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; - rb->wptr += numcmds; - - if (status == GSL_SUCCESS) - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_waitspace. Return value 0x%08x\n", ptr ); - return (ptr); - } - else - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_waitspace. Return value 0x%08x\n", NULL ); - return (NULL); - } -} - -//---------------------------------------------------------------------------- -int -kgsl_ringbuffer_start(gsl_ringbuffer_t *rb) -{ - int status; - cp_rb_cntl_u cp_rb_cntl; - int i; - unsigned int *cmds; - gsl_device_t *device = rb->device; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> static int kgsl_ringbuffer_start(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); - - if (rb->flags & GSL_FLAGS_STARTED) - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_start. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); - } - - // clear memptrs values - kgsl_sharedmem_set0(&rb->memptrs_desc, 0, 0, sizeof(gsl_rbmemptrs_t)); - - // clear ringbuffer - kgsl_sharedmem_set0(&rb->buffer_desc, 0, 0x12341234, (rb->sizedwords << 2)); - - // setup WPTR polling address - device->ftbl.device_regwrite(device, mmCP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); - - // setup WPTR delay - device->ftbl.device_regwrite(device, mmCP_RB_WPTR_DELAY, 0/*0x70000010*/); - - // setup RB_CNTL - device->ftbl.device_regread(device, mmCP_RB_CNTL, (unsigned int *)&cp_rb_cntl); - - cp_rb_cntl.f.rb_bufsz = gsl_ringbuffer_sizelog2quadwords(rb->sizedwords); // size of ringbuffer - cp_rb_cntl.f.rb_blksz = rb->blksizequadwords; // quadwords to read before updating mem RPTR - cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; // WPTR polling - cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; // mem RPTR writebacks - - device->ftbl.device_regwrite(device, mmCP_RB_CNTL, cp_rb_cntl.val); - - // setup RB_BASE - device->ftbl.device_regwrite(device, mmCP_RB_BASE, rb->buffer_desc.gpuaddr); - - // setup RPTR_ADDR - device->ftbl.device_regwrite(device, mmCP_RB_RPTR_ADDR, rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_RPTR_OFFSET); - - // explicitly clear all cp interrupts when running in safe mode - if (rb->device->flags & GSL_FLAGS_SAFEMODE) - { - device->ftbl.device_regwrite(device, mmCP_INT_ACK, 0xFFFFFFFF); - } - - // setup scratch/timestamp addr - device->ftbl.device_regwrite(device, mmSCRATCH_ADDR, device->memstore.gpuaddr + GSL_DEVICE_MEMSTORE_OFFSET(soptimestamp)); - - // setup scratch/timestamp mask - device->ftbl.device_regwrite(device, mmSCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); - - // load the CP ucode - device->ftbl.device_regwrite(device, mmCP_DEBUG, 0x02000000); - device->ftbl.device_regwrite(device, mmCP_ME_RAM_WADDR, 0); - - for (i = 0; i < PM4_MICROCODE_SIZE; i++ ) - { - device->ftbl.device_regwrite(device, mmCP_ME_RAM_DATA, aPM4_Microcode[i][0]); - device->ftbl.device_regwrite(device, mmCP_ME_RAM_DATA, aPM4_Microcode[i][1]); - device->ftbl.device_regwrite(device, mmCP_ME_RAM_DATA, aPM4_Microcode[i][2]); - } - - // load the prefetch parser ucode - device->ftbl.device_regwrite(device, mmCP_PFP_UCODE_ADDR, 0); - - for ( i = 0; i < PFP_MICROCODE_SIZE_NRT; i++ ) - { - device->ftbl.device_regwrite(device, mmCP_PFP_UCODE_DATA, aPFP_Microcode_nrt[i]); - } - - // queue thresholds ??? - device->ftbl.device_regwrite(device, mmCP_QUEUE_THRESHOLDS, 0x000C0804); - - // reset pointers - rb->rptr = 0; - rb->wptr = 0; - - // init timestamp - rb->timestamp = 0; - GSL_RB_INIT_TIMESTAMP(rb); - - // clear ME_HALT to start micro engine - device->ftbl.device_regwrite(device, mmCP_ME_CNTL, 0); - - // ME_INIT - cmds = kgsl_ringbuffer_addcmds(rb, 19); - - GSL_RB_WRITE(cmds, PM4_HDR_ME_INIT); - GSL_RB_WRITE(cmds, 0x000003ff); // All fields present (bits 9:0) - GSL_RB_WRITE(cmds, 0x00000000); // Disable/Enable Real-Time Stream processing (present but ignored) - GSL_RB_WRITE(cmds, 0x00000000); // Enable (2D to 3D) and (3D to 2D) implicit synchronization (present but ignored) - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmRB_SURFACE_INFO)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SC_WINDOW_OFFSET)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmVGT_MAX_VTX_INDX)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmSQ_PROGRAM_CNTL)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmRB_DEPTHCONTROL)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SU_POINT_SIZE)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SC_LINE_CNTL)); - GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SU_POLY_OFFSET_FRONT_SCALE)); - GSL_RB_WRITE(cmds, 0x80000180); // Vertex and Pixel Shader Start Addresses in instructions (3 DWORDS per instruction) - GSL_RB_WRITE(cmds, 0x00000001); // Maximum Contexts - GSL_RB_WRITE(cmds, 0x00000000); // Write Confirm Interval and The CP will wait the wait_interval * 16 clocks between polling - GSL_RB_WRITE(cmds, 0x00000000); // NQ and External Memory Swap - GSL_RB_WRITE(cmds, GSL_RB_PROTECTED_MODE_CONTROL); // Protected mode error checking - GSL_RB_WRITE(cmds, 0x00000000); // Disable header dumping and Header dump address - GSL_RB_WRITE(cmds, 0x00000000); // Header dump size - - KGSL_DEBUG(GSL_DBGFLAGS_PM4CHECK, kgsl_ringbuffer_checkpm4((unsigned int *)rb->buffer_desc.hostptr, 19, 1)); - KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPPM4((unsigned int *)rb->buffer_desc.hostptr, 19)); - - kgsl_ringbuffer_submit(rb); - - // idle device to validate ME INIT - status = device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - - if (status == GSL_SUCCESS) - { - rb->flags |= GSL_FLAGS_STARTED; - } - - // enable cp interrupts - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_SW_INT, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_T0_PACKET_IN_IB, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_OPCODE_ERROR, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_RESERVED_BIT_ERROR, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_IB_ERROR, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_IB2_INT, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_IB1_INT, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER, kgsl_cp_intrcallback, (void *) rb); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_SW_INT); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_T0_PACKET_IN_IB); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_OPCODE_ERROR); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_RESERVED_BIT_ERROR); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_IB_ERROR); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_IB2_INT); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_IB1_INT); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER); - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_start. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_ringbuffer_stop(gsl_ringbuffer_t *rb) -{ - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> static int kgsl_ringbuffer_stop(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); - - if (rb->flags & GSL_FLAGS_STARTED) - { - // disable cp interrupts - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_SW_INT); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_T0_PACKET_IN_IB); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_OPCODE_ERROR); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_RESERVED_BIT_ERROR); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_IB_ERROR); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_IB2_INT); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_IB1_INT); - kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_RING_BUFFER); - - // ME_HALT - rb->device->ftbl.device_regwrite(rb->device, mmCP_ME_CNTL, 0x10000000); - - rb->flags &= ~GSL_FLAGS_STARTED; - } - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_stop. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_ringbuffer_init(gsl_device_t *device) -{ - int status; - gsl_flags_t flags; - gsl_ringbuffer_t *rb = &device->ringbuffer; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_ringbuffer_init(gsl_device_t *device=0x%08x)\n", device ); - - rb->device = device; - rb->sizedwords = (2 << gsl_cfg_rb_sizelog2quadwords); - rb->blksizequadwords = gsl_cfg_rb_blksizequadwords; - - GSL_RB_MUTEX_CREATE(); - - // allocate memory for ringbuffer, needs to be double octword aligned - // align on page from contiguous physical memory - flags = (GSL_MEMFLAGS_ALIGNPAGE | GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_STRICTREQUEST); - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, flags = (GSL_MEMFLAGS_ALIGNPAGE | GSL_MEMFLAGS_STRICTREQUEST)); /* set MMU table for ringbuffer */ - - status = kgsl_sharedmem_alloc0(device->id, flags, (rb->sizedwords << 2), &rb->buffer_desc); - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_RINGBUF_SET, (unsigned int)rb->buffer_desc.gpuaddr, (unsigned int)rb->buffer_desc.hostptr, 0, "kgsl_ringbuffer_init")); - - if (status != GSL_SUCCESS) - { - kgsl_ringbuffer_close(rb); - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", status ); - return (status); - } - - // allocate memory for polling and timestamps - flags = (GSL_MEMFLAGS_ALIGN32 | GSL_MEMFLAGS_CONPHYS); - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, flags = GSL_MEMFLAGS_ALIGN32); - - status = kgsl_sharedmem_alloc0(device->id, flags, sizeof(gsl_rbmemptrs_t), &rb->memptrs_desc); - - if (status != GSL_SUCCESS) - { - kgsl_ringbuffer_close(rb); - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", status ); - return (status); - } - - // overlay structure on memptrs memory - rb->memptrs = (gsl_rbmemptrs_t *)rb->memptrs_desc.hostptr; - - rb->flags |= GSL_FLAGS_INITIALIZED; - - // validate command stream data when running in safe mode - if (device->flags & GSL_FLAGS_SAFEMODE) - { - gsl_driver.flags_debug |= GSL_DBGFLAGS_PM4CHECK; - } - - // start ringbuffer - status = kgsl_ringbuffer_start(rb); - - if (status != GSL_SUCCESS) - { - kgsl_ringbuffer_close(rb); - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", status ); - return (status); - } - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_ringbuffer_close(gsl_ringbuffer_t *rb) -{ - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_ringbuffer_close(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); - - GSL_RB_MUTEX_LOCK(); - - // stop ringbuffer - kgsl_ringbuffer_stop(rb); - - // free buffer - if (rb->buffer_desc.hostptr) - { - kgsl_sharedmem_free0(&rb->buffer_desc, GSL_CALLER_PROCESSID_GET()); - } - - // free memory pointers - if (rb->memptrs_desc.hostptr) - { - kgsl_sharedmem_free0(&rb->memptrs_desc, GSL_CALLER_PROCESSID_GET()); - } - - rb->flags &= ~GSL_FLAGS_INITIALIZED; - - GSL_RB_MUTEX_UNLOCK(); - - GSL_RB_MUTEX_FREE(); - - kos_memset(rb, 0, sizeof(gsl_ringbuffer_t)); - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_close. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -gsl_timestamp_t -kgsl_ringbuffer_issuecmds(gsl_device_t *device, int pmodeoff, unsigned int *cmds, int sizedwords, unsigned int pid) -{ - gsl_ringbuffer_t *rb = &device->ringbuffer; - unsigned int pmodesizedwords; - unsigned int *ringcmds; - unsigned int timestamp; - - pmodeoff = 0; - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> gsl_timestamp_t kgsl_ringbuffer_issuecmds(gsl_device_t *device=0x%08x, int pmodeoff=%d, unsigned int *cmds=0x%08x, int sizedwords=%d, unsigned int pid=0x%08x)\n", - device, pmodeoff, cmds, sizedwords, pid ); - - if (!(device->ringbuffer.flags & GSL_FLAGS_STARTED)) - { - return (0); - } - - // set mmu pagetable - kgsl_mmu_setpagetable(device, pid); - - KGSL_DEBUG(GSL_DBGFLAGS_PM4CHECK, kgsl_ringbuffer_checkpm4(cmds, sizedwords, pmodeoff)); - KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPPM4(cmds, sizedwords)); - - // reserve space to temporarily turn off protected mode error checking if needed - pmodesizedwords = pmodeoff ? 8 : 0; - -#if defined GSL_RB_TIMESTAMP_INTERUPT - pmodesizedwords += 2; -#endif - // allocate space in ringbuffer - ringcmds = kgsl_ringbuffer_addcmds(rb, pmodesizedwords + sizedwords + 6); - - if (pmodeoff) - { - // disable protected mode error checking - *ringcmds++ = pm4_type3_packet(PM4_ME_INIT, 2); - *ringcmds++ = 0x00000080; - *ringcmds++ = 0x00000000; - } - - // copy the cmds to the ringbuffer - kos_memcpy(ringcmds, cmds, (sizedwords << 2)); - - ringcmds += sizedwords; - - if (pmodeoff) - { - *ringcmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - *ringcmds++ = 0; - - // re-enable protected mode error checking - *ringcmds++ = pm4_type3_packet(PM4_ME_INIT, 2); - *ringcmds++ = 0x00000080; - *ringcmds++ = GSL_RB_PROTECTED_MODE_CONTROL; - } - - // increment timestamp - rb->timestamp++; - timestamp = rb->timestamp; - - // start-of-pipeline and end-of-pipeline timestamps - *ringcmds++ = pm4_type0_packet(mmCP_TIMESTAMP, 1); - *ringcmds++ = rb->timestamp; - *ringcmds++ = pm4_type3_packet(PM4_EVENT_WRITE, 3); - *ringcmds++ = CACHE_FLUSH_TS; - *ringcmds++ = device->memstore.gpuaddr + GSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp); - *ringcmds++ = rb->timestamp; - -#if defined GSL_RB_TIMESTAMP_INTERUPT - *ringcmds++ = pm4_type3_packet(PM4_INTERRUPT, 1); - *ringcmds++ = 0x80000000; -#endif - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MEMWRITE, (unsigned int)((char*)ringcmds - ((pmodesizedwords + sizedwords + 6) << 2)), (unsigned int)((char*)ringcmds - ((pmodesizedwords + sizedwords + 6) << 2)), (pmodesizedwords + sizedwords + 6) << 2, "kgsl_ringbuffer_issuecmds")); - - // issue the commands - kgsl_ringbuffer_submit(rb); - - // stats - GSL_RB_STATS(rb->stats.wordstotal += sizedwords); - GSL_RB_STATS(rb->stats.issues++); - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_issuecmds. Return value %d\n", timestamp ); - - // return timestamp of issued commands - return (timestamp); -} - -//---------------------------------------------------------------------------- -int -kgsl_ringbuffer_issueibcmds(gsl_device_t *device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, gsl_flags_t flags) -{ - unsigned int link[3]; - int dumpx_swap; - (void)dumpx_swap; // used only when BB_DUMPX is defined - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> gsl_timestamp_t kgsl_ringbuffer_issueibcmds(gsl_device_t device=%0x%08x, int drawctxt_index=%d, gpuaddr_t ibaddr=0x%08x, int sizedwords=%d, gsl_timestamp_t *timestamp=0x%08x)\n", - device, drawctxt_index, ibaddr, sizedwords, timestamp ); - - if (!(device->ringbuffer.flags & GSL_FLAGS_STARTED)) - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_issueibcmds. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - KOS_ASSERT(ibaddr); - KOS_ASSERT(sizedwords); - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, dumpx_swap = kgsl_dumpx_parse_ibs(ibaddr, sizedwords)); - - GSL_RB_MUTEX_LOCK(); - - // context switch if needed - kgsl_drawctxt_switch(device, &device->drawctxt[drawctxt_index], flags); - - link[0] = PM4_HDR_INDIRECT_BUFFER_PFD; - link[1] = ibaddr; - link[2] = sizedwords; - - *timestamp = kgsl_ringbuffer_issuecmds(device, 0, &link[0], 3, GSL_CALLER_PROCESSID_GET()); - - GSL_RB_MUTEX_UNLOCK(); - - // idle device when running in safe mode - if (device->flags & GSL_FLAGS_SAFEMODE) - { - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - } - else - { - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, - { - // insert wait for idle after every IB1 - // this is conservative but works reliably and is ok even for performance simulations - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - }); - } - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, - { - if(dumpx_swap) - { - KGSL_DEBUG_DUMPX( BB_DUMP_EXPORT_CBUF, 0, 0, 0, "resolve"); - KGSL_DEBUG_DUMPX( BB_DUMP_FLUSH,0,0,0," "); - } - }); - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_issueibcmds. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -#ifdef _DEBUG -static void -kgsl_ringbuffer_debug(gsl_ringbuffer_t *rb, gsl_rb_debug_t *rb_debug) -{ - kos_memset(rb_debug, 0, sizeof(gsl_rb_debug_t)); - - rb_debug->pm4_ucode_rel = PM4_MICROCODE_VERSION; - rb_debug->pfp_ucode_rel = PFP_MICROCODE_VERSION; - - rb->device->ftbl.device_regread(rb->device, mmCP_RB_BASE, (unsigned int *)&rb_debug->cp_rb_base); - rb->device->ftbl.device_regread(rb->device, mmCP_RB_CNTL, (unsigned int *)&rb_debug->cp_rb_cntl); - rb->device->ftbl.device_regread(rb->device, mmCP_RB_RPTR_ADDR, (unsigned int *)&rb_debug->cp_rb_rptr_addr); - rb->device->ftbl.device_regread(rb->device, mmCP_RB_RPTR, (unsigned int *)&rb_debug->cp_rb_rptr); - rb->device->ftbl.device_regread(rb->device, mmCP_RB_WPTR, (unsigned int *)&rb_debug->cp_rb_wptr); - rb->device->ftbl.device_regread(rb->device, mmCP_RB_WPTR_BASE, (unsigned int *)&rb_debug->cp_rb_wptr_base); - rb->device->ftbl.device_regread(rb->device, mmSCRATCH_UMSK, (unsigned int *)&rb_debug->scratch_umsk); - rb->device->ftbl.device_regread(rb->device, mmSCRATCH_ADDR, (unsigned int *)&rb_debug->scratch_addr); - rb->device->ftbl.device_regread(rb->device, mmCP_ME_CNTL, (unsigned int *)&rb_debug->cp_me_cntl); - rb->device->ftbl.device_regread(rb->device, mmCP_ME_STATUS, (unsigned int *)&rb_debug->cp_me_status); - rb->device->ftbl.device_regread(rb->device, mmCP_DEBUG, (unsigned int *)&rb_debug->cp_debug); - rb->device->ftbl.device_regread(rb->device, mmCP_STAT, (unsigned int *)&rb_debug->cp_stat); - rb->device->ftbl.device_regread(rb->device, mmRBBM_STATUS, (unsigned int *)&rb_debug->rbbm_status); - rb_debug->sop_timestamp = kgsl_cmdstream_readtimestamp(rb->device->id, GSL_TIMESTAMP_CONSUMED); - rb_debug->eop_timestamp = kgsl_cmdstream_readtimestamp(rb->device->id, GSL_TIMESTAMP_RETIRED); -} -#endif - - -//---------------------------------------------------------------------------- - -int -kgsl_ringbuffer_querystats(gsl_ringbuffer_t *rb, gsl_rbstats_t *stats) -{ -#ifdef GSL_STATS_RINGBUFFER - KOS_ASSERT(stats); - - if (!(rb->flags & GSL_FLAGS_STARTED)) - { - return (GSL_FAILURE); - } - - kos_memcpy(stats, &rb->stats, sizeof(gsl_rbstats_t)); - - return (GSL_SUCCESS); -#else - // unreferenced formal parameters - (void) rb; - (void) stats; - - return (GSL_FAILURE_NOTSUPPORTED); -#endif // GSL_STATS_RINGBUFFER -} - -//---------------------------------------------------------------------------- - -int -kgsl_ringbuffer_bist(gsl_ringbuffer_t *rb) -{ - unsigned int *cmds; - unsigned int temp, k, j; - int status; - int i; -#ifdef _DEBUG - gsl_rb_debug_t rb_debug; -#endif - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_ringbuffer_bist(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); - - if (!(rb->flags & GSL_FLAGS_STARTED)) - { - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // simple nop submit - cmds = kgsl_ringbuffer_addcmds(rb, 2); - if (!cmds) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - GSL_RB_WRITE(cmds, pm4_nop_packet(1)); - GSL_RB_WRITE(cmds, 0xDEADBEEF); - - kgsl_ringbuffer_submit(rb); - - status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); - - if (status != GSL_SUCCESS) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); - return (status); - } - - // simple scratch submit - cmds = kgsl_ringbuffer_addcmds(rb, 2); - if (!cmds) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - GSL_RB_WRITE(cmds, pm4_type0_packet(mmSCRATCH_REG7, 1)); - GSL_RB_WRITE(cmds, 0xFEEDF00D); - - kgsl_ringbuffer_submit(rb); - - status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); - - if (status != GSL_SUCCESS) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); - return (status); - } - - rb->device->ftbl.device_regread(rb->device, mmSCRATCH_REG7, &temp); - - if (temp != 0xFEEDF00D) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // simple wraps - for (i = 0; i < 256; i+=2) - { - j = ((rb->sizedwords >> 2) - 256) + i; - - cmds = kgsl_ringbuffer_addcmds(rb, j); - if (!cmds) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - k = 0; - - while (k < j) - { - k+=2; - GSL_RB_WRITE(cmds, pm4_type0_packet(mmSCRATCH_REG7, 1)); - GSL_RB_WRITE(cmds, k); - } - - kgsl_ringbuffer_submit(rb); - - status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); - - if (status != GSL_SUCCESS) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); - return (status); - } - - rb->device->ftbl.device_regread(rb->device, mmSCRATCH_REG7, &temp); - - if (temp != k) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - } - - // max size submits, TODO do this at least with regreads - for (i = 0; i < 256; i++) - { - cmds = kgsl_ringbuffer_addcmds(rb, (rb->sizedwords >> 2)); - if (!cmds) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - GSL_RB_WRITE(cmds, pm4_nop_packet((rb->sizedwords >> 2) - 1)); - - kgsl_ringbuffer_submit(rb); - - status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); - - if (status != GSL_SUCCESS) - { -#ifdef _DEBUG - kgsl_ringbuffer_debug(rb, &rb_debug); -#endif - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); - return (status); - } - } - - // submit load with randomness - -#ifdef GSL_RB_USE_MEM_TIMESTAMP - // scratch memptr validate -#endif // GSL_RB_USE_MEM_TIMESTAMP - -#ifdef GSL_RB_USE_MEM_RPTR - // rptr memptr validate -#endif // GSL_RB_USE_MEM_RPTR - -#ifdef GSL_RB_USE_WPTR_POLLING - // wptr memptr validate -#endif // GSL_RB_USE_WPTR_POLLING - - kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -#endif - diff --git a/drivers/mxc/amd-gpu/common/gsl_sharedmem.c b/drivers/mxc/amd-gpu/common/gsl_sharedmem.c deleted file mode 100644 index 51e66f97c52..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_sharedmem.c +++ /dev/null @@ -1,937 +0,0 @@ -/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" - -///////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#define GSL_SHMEM_APERTURE_MARK(aperture_id) \ - (shmem->priv |= (((aperture_id + 1) << GSL_APERTURE_SHIFT) & GSL_APERTURE_MASK)) - -#define GSL_SHMEM_APERTURE_ISMARKED(aperture_id) \ - (((shmem->priv & GSL_APERTURE_MASK) >> GSL_APERTURE_SHIFT) & (aperture_id + 1)) - -#define GSL_MEMFLAGS_APERTURE_GET(flags, aperture_id) \ - aperture_id = (gsl_apertureid_t)((flags & GSL_MEMFLAGS_APERTURE_MASK) >> GSL_MEMFLAGS_APERTURE_SHIFT); \ - KOS_ASSERT(aperture_id < GSL_APERTURE_MAX); - -#define GSL_MEMFLAGS_CHANNEL_GET(flags, channel_id) \ - channel_id = (gsl_channelid_t)((flags & GSL_MEMFLAGS_CHANNEL_MASK) >> GSL_MEMFLAGS_CHANNEL_SHIFT); \ - KOS_ASSERT(channel_id < GSL_CHANNEL_MAX); - -#define GSL_MEMDESC_APERTURE_SET(memdesc, aperture_index) \ - memdesc->priv = (memdesc->priv & ~GSL_APERTURE_MASK) | ((aperture_index << GSL_APERTURE_SHIFT) & GSL_APERTURE_MASK); - -#define GSL_MEMDESC_DEVICE_SET(memdesc, device_id) \ - memdesc->priv = (memdesc->priv & ~GSL_DEVICEID_MASK) | ((device_id << GSL_DEVICEID_SHIFT) & GSL_DEVICEID_MASK); - -#define GSL_MEMDESC_EXTALLOC_SET(memdesc, flag) \ - memdesc->priv = (memdesc->priv & ~GSL_EXTALLOC_MASK) | ((flag << GSL_EXTALLOC_SHIFT) & GSL_EXTALLOC_MASK); - -#define GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index) \ - KOS_ASSERT(memdesc); \ - aperture_index = ((memdesc->priv & GSL_APERTURE_MASK) >> GSL_APERTURE_SHIFT); \ - KOS_ASSERT(aperture_index < GSL_SHMEM_MAX_APERTURES); - -#define GSL_MEMDESC_DEVICE_GET(memdesc, device_id) \ - KOS_ASSERT(memdesc); \ - device_id = (gsl_deviceid_t)((memdesc->priv & GSL_DEVICEID_MASK) >> GSL_DEVICEID_SHIFT); \ - KOS_ASSERT(device_id <= GSL_DEVICE_MAX); - -#define GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc) \ - ((memdesc->priv & GSL_EXTALLOC_MASK) >> GSL_EXTALLOC_SHIFT) - - -////////////////////////////////////////////////////////////////////////////// -// aperture index in shared memory object -////////////////////////////////////////////////////////////////////////////// -OSINLINE int -kgsl_sharedmem_getapertureindex(gsl_sharedmem_t *shmem, gsl_apertureid_t aperture_id, gsl_channelid_t channel_id) -{ - KOS_ASSERT(shmem->aperturelookup[aperture_id][channel_id] < shmem->numapertures); - - return (shmem->aperturelookup[aperture_id][channel_id]); -} - - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -int -kgsl_sharedmem_init(gsl_sharedmem_t *shmem) -{ - int i; - int status; - gsl_shmemconfig_t config; - int mmu_virtualized; - gsl_apertureid_t aperture_id; - gsl_channelid_t channel_id; - unsigned int hostbaseaddr; - gpuaddr_t gpubaseaddr; - int sizebytes; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_sharedmem_init(gsl_sharedmem_t *shmem=0x%08x)\n", shmem ); - - if (shmem->flags & GSL_FLAGS_INITIALIZED) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", GSL_SUCCESS ); - return (GSL_SUCCESS); - } - - status = kgsl_hal_getshmemconfig(&config); - if (status != GSL_SUCCESS) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to get sharedmem config.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", status ); - return (status); - } - - shmem->numapertures = config.numapertures; - - for (i = 0; i < shmem->numapertures; i++) - { - aperture_id = config.apertures[i].id; - channel_id = config.apertures[i].channel; - hostbaseaddr = config.apertures[i].hostbase; - gpubaseaddr = config.apertures[i].gpubase; - sizebytes = config.apertures[i].sizebytes; - mmu_virtualized = 0; - - // handle mmu virtualized aperture - if (aperture_id == GSL_APERTURE_MMU) - { - mmu_virtualized = 1; - aperture_id = GSL_APERTURE_EMEM; - } - - // make sure aligned to page size - KOS_ASSERT((gpubaseaddr & ((1 << GSL_PAGESIZE_SHIFT) - 1)) == 0); - - // make a multiple of page size - sizebytes = (sizebytes & ~((1 << GSL_PAGESIZE_SHIFT) - 1)); - - if (sizebytes > 0) - { - shmem->apertures[i].memarena = kgsl_memarena_create(aperture_id, mmu_virtualized, hostbaseaddr, gpubaseaddr, sizebytes); - - if (!shmem->apertures[i].memarena) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to allocate memarena.\n" ); - kgsl_sharedmem_close(shmem); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - shmem->apertures[i].id = aperture_id; - shmem->apertures[i].channel = channel_id; - shmem->apertures[i].numbanks = 1; - - // create aperture lookup table - if (GSL_SHMEM_APERTURE_ISMARKED(aperture_id)) - { - // update "current aperture_id"/"current channel_id" index - shmem->aperturelookup[aperture_id][channel_id] = i; - } - else - { - // initialize "current aperture_id"/"channel_id" indexes - for (channel_id = GSL_CHANNEL_1; channel_id < GSL_CHANNEL_MAX; channel_id++) - { - shmem->aperturelookup[aperture_id][channel_id] = i; - } - - GSL_SHMEM_APERTURE_MARK(aperture_id); - } - } - } - - shmem->flags |= GSL_FLAGS_INITIALIZED; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_close(gsl_sharedmem_t *shmem) -{ - int i; - int result = GSL_SUCCESS; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_sharedmem_close(gsl_sharedmem_t *shmem=0x%08x)\n", shmem ); - - if (shmem->flags & GSL_FLAGS_INITIALIZED) - { - for (i = 0; i < shmem->numapertures; i++) - { - if (shmem->apertures[i].memarena) - { - result = kgsl_memarena_destroy(shmem->apertures[i].memarena); - } - } - - kos_memset(shmem, 0, sizeof(gsl_sharedmem_t)); - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_close. Return value %B\n", result ); - - return (result); -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_alloc0(gsl_deviceid_t device_id, gsl_flags_t flags, int sizebytes, gsl_memdesc_t *memdesc) -{ - gsl_apertureid_t aperture_id; - gsl_channelid_t channel_id; - gsl_deviceid_t tmp_id; - int aperture_index, org_index; - int result = GSL_FAILURE; - gsl_mmu_t *mmu = NULL; - gsl_sharedmem_t *shmem = &gsl_driver.shmem; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_alloc(gsl_deviceid_t device_id=%D, gsl_flags_t flags=0x%08x, int sizebytes=%d, gsl_memdesc_t *memdesc=%M)\n", - device_id, flags, sizebytes, memdesc ); - - KOS_ASSERT(sizebytes); - KOS_ASSERT(memdesc); - - GSL_MEMFLAGS_APERTURE_GET(flags, aperture_id); - GSL_MEMFLAGS_CHANNEL_GET(flags, channel_id); - - kos_memset(memdesc, 0, sizeof(gsl_memdesc_t)); - - if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_alloc. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - // execute pending device action - tmp_id = (device_id != GSL_DEVICE_ANY) ? device_id : device_id+1; - for ( ; tmp_id <= GSL_DEVICE_MAX; tmp_id++) - { - if (gsl_driver.device[tmp_id-1].flags & GSL_FLAGS_INITIALIZED) - { - kgsl_device_runpending(&gsl_driver.device[tmp_id-1]); - - if (tmp_id == device_id) - { - break; - } - } - } - - // convert any device to an actual existing device - if (device_id == GSL_DEVICE_ANY) - { - for ( ; ; ) - { - device_id++; - - if (device_id <= GSL_DEVICE_MAX) - { - if (gsl_driver.device[device_id-1].flags & GSL_FLAGS_INITIALIZED) - { - break; - } - } - else - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid device.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_alloc. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - } - } - - KOS_ASSERT(device_id > GSL_DEVICE_ANY && device_id <= GSL_DEVICE_MAX); - - // get mmu reference - mmu = &gsl_driver.device[device_id-1].mmu; - - aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); - - //do not proceed if it is a strict request, the aperture requested is not present, and the MMU is enabled - if (!((flags & GSL_MEMFLAGS_STRICTREQUEST) && aperture_id != shmem->apertures[aperture_index].id && kgsl_mmu_isenabled(mmu))) - { - // do allocation - result = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, sizebytes, memdesc); - - // if allocation failed - if (result != GSL_SUCCESS) - { - org_index = aperture_index; - - // then failover to other channels within the current aperture - for (channel_id = GSL_CHANNEL_1; channel_id < GSL_CHANNEL_MAX; channel_id++) - { - aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); - - if (aperture_index != org_index) - { - // do allocation - result = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, sizebytes, memdesc); - - if (result == GSL_SUCCESS) - { - break; - } - } - } - - // if allocation still has not succeeded, then failover to EMEM/MMU aperture, but - // not if it's a strict request and the MMU is enabled - if (result != GSL_SUCCESS && aperture_id != GSL_APERTURE_EMEM - && !((flags & GSL_MEMFLAGS_STRICTREQUEST) && kgsl_mmu_isenabled(mmu))) - { - aperture_id = GSL_APERTURE_EMEM; - - // try every channel - for (channel_id = GSL_CHANNEL_1; channel_id < GSL_CHANNEL_MAX; channel_id++) - { - aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); - - if (aperture_index != org_index) - { - // do allocation - result = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, sizebytes, memdesc); - - if (result == GSL_SUCCESS) - { - break; - } - } - } - } - } - } - - if (result == GSL_SUCCESS) - { - GSL_MEMDESC_APERTURE_SET(memdesc, aperture_index); - GSL_MEMDESC_DEVICE_SET(memdesc, device_id); - - if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) - { - gsl_scatterlist_t scatterlist; - - scatterlist.contiguous = 0; - scatterlist.num = memdesc->size / GSL_PAGESIZE; - - if (memdesc->size & (GSL_PAGESIZE-1)) - { - scatterlist.num++; - } - - scatterlist.pages = kos_malloc(sizeof(unsigned int) * scatterlist.num); - if (scatterlist.pages) - { - // allocate physical pages - result = kgsl_hal_allocphysical(memdesc->gpuaddr, scatterlist.num, scatterlist.pages); - if (result == GSL_SUCCESS) - { - result = kgsl_mmu_map(mmu, memdesc->gpuaddr, &scatterlist, flags, GSL_CALLER_PROCESSID_GET()); - if (result != GSL_SUCCESS) - { - kgsl_hal_freephysical(memdesc->gpuaddr, scatterlist.num, scatterlist.pages); - } - } - - kos_free(scatterlist.pages); - } - else - { - result = GSL_FAILURE; - } - - if (result != GSL_SUCCESS) - { - kgsl_memarena_free(shmem->apertures[aperture_index].memarena, memdesc); - } - } - } - - KGSL_DEBUG_TBDUMP_SETMEM( memdesc->gpuaddr, 0, memdesc->size ); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_alloc. Return value %B\n", result ); - - return (result); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_alloc(gsl_deviceid_t device_id, gsl_flags_t flags, int sizebytes, gsl_memdesc_t *memdesc) -{ - int status = GSL_SUCCESS; - GSL_API_MUTEX_LOCK(); - status = kgsl_sharedmem_alloc0(device_id, flags, sizebytes, memdesc); - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_free0(gsl_memdesc_t *memdesc, unsigned int pid) -{ - int status = GSL_SUCCESS; - int aperture_index; - gsl_deviceid_t device_id; - gsl_sharedmem_t *shmem; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_sharedmem_free(gsl_memdesc_t *memdesc=%M)\n", memdesc ); - - GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); - GSL_MEMDESC_DEVICE_GET(memdesc, device_id); - - shmem = &gsl_driver.shmem; - - if (shmem->flags & GSL_FLAGS_INITIALIZED) - { - if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) - { - status |= kgsl_mmu_unmap(&gsl_driver.device[device_id-1].mmu, memdesc->gpuaddr, memdesc->size, pid); - - if (!GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) - { - status |= kgsl_hal_freephysical(memdesc->gpuaddr, memdesc->size / GSL_PAGESIZE, NULL); - } - } - - kgsl_memarena_free(shmem->apertures[aperture_index].memarena, memdesc); - - // clear descriptor - kos_memset(memdesc, 0, sizeof(gsl_memdesc_t)); - } - else - { - status = GSL_FAILURE; - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_free. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_free(gsl_memdesc_t *memdesc) -{ - int status = GSL_SUCCESS; - GSL_API_MUTEX_LOCK(); - status = kgsl_sharedmem_free0(memdesc, GSL_CALLER_PROCESSID_GET()); - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_read0(const gsl_memdesc_t *memdesc, void *dst, unsigned int offsetbytes, unsigned int sizebytes, unsigned int touserspace) -{ - int aperture_index; - gsl_sharedmem_t *shmem; - unsigned int gpuoffsetbytes; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_read(gsl_memdesc_t *memdesc=%M, void *dst=0x%08x, unsigned int offsetbytes=%d, unsigned int sizebytes=%d)\n", - memdesc, dst, offsetbytes, sizebytes ); - - GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); - - if (GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_read. Return value %B\n", GSL_FAILURE_BADPARAM ); - return (GSL_FAILURE_BADPARAM); - } - - shmem = &gsl_driver.shmem; - - if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_read. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - KOS_ASSERT(dst); - KOS_ASSERT(sizebytes); - - if (memdesc->gpuaddr < shmem->apertures[aperture_index].memarena->gpubaseaddr) - { - return (GSL_FAILURE_BADPARAM); - } - - if (memdesc->gpuaddr + sizebytes > shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes) - { - return (GSL_FAILURE_BADPARAM); - } - - gpuoffsetbytes = (memdesc->gpuaddr - shmem->apertures[aperture_index].memarena->gpubaseaddr) + offsetbytes; - - GSL_HAL_MEM_READ(dst, shmem->apertures[aperture_index].memarena->hostbaseaddr, gpuoffsetbytes, sizebytes, touserspace); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_read. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_read(const gsl_memdesc_t *memdesc, void *dst, unsigned int offsetbytes, unsigned int sizebytes, unsigned int touserspace) -{ - int status = GSL_SUCCESS; - GSL_API_MUTEX_LOCK(); - status = kgsl_sharedmem_read0(memdesc, dst, offsetbytes, sizebytes, touserspace); - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_write0(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, void *src, unsigned int sizebytes, unsigned int fromuserspace) -{ - int aperture_index; - gsl_sharedmem_t *shmem; - unsigned int gpuoffsetbytes; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_write(gsl_memdesc_t *memdesc=%M, unsigned int offsetbytes=%d, void *src=0x%08x, unsigned int sizebytes=%d)\n", - memdesc, offsetbytes, src, sizebytes ); - - GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); - - if (GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_write. Return value %B\n", GSL_FAILURE_BADPARAM ); - return (GSL_FAILURE_BADPARAM); - } - - shmem = &gsl_driver.shmem; - - if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_write. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - KOS_ASSERT(src); - KOS_ASSERT(sizebytes); - KOS_ASSERT(memdesc->gpuaddr >= shmem->apertures[aperture_index].memarena->gpubaseaddr); - KOS_ASSERT((memdesc->gpuaddr + sizebytes) <= (shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes)); - - gpuoffsetbytes = (memdesc->gpuaddr - shmem->apertures[aperture_index].memarena->gpubaseaddr) + offsetbytes; - - GSL_HAL_MEM_WRITE(shmem->apertures[aperture_index].memarena->hostbaseaddr, gpuoffsetbytes, src, sizebytes, fromuserspace); - - KGSL_DEBUG(GSL_DBGFLAGS_PM4MEM, KGSL_DEBUG_DUMPMEMWRITE((memdesc->gpuaddr + offsetbytes), sizebytes, src)); - - KGSL_DEBUG_TBDUMP_SYNCMEM( (memdesc->gpuaddr + offsetbytes), src, sizebytes ); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_write. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_write(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, void *src, unsigned int sizebytes, unsigned int fromuserspace) -{ - int status = GSL_SUCCESS; - GSL_API_MUTEX_LOCK(); - status = kgsl_sharedmem_write0(memdesc, offsetbytes, src, sizebytes, fromuserspace); - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_set0(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes) -{ - int aperture_index; - gsl_sharedmem_t *shmem; - unsigned int gpuoffsetbytes; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_set(gsl_memdesc_t *memdesc=%M, unsigned int offsetbytes=%d, unsigned int value=0x%08x, unsigned int sizebytes=%d)\n", - memdesc, offsetbytes, value, sizebytes ); - - GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); - - if (GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_set. Return value %B\n", GSL_FAILURE_BADPARAM ); - return (GSL_FAILURE_BADPARAM); - } - - shmem = &gsl_driver.shmem; - - if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_set. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - - KOS_ASSERT(sizebytes); - KOS_ASSERT(memdesc->gpuaddr >= shmem->apertures[aperture_index].memarena->gpubaseaddr); - KOS_ASSERT((memdesc->gpuaddr + sizebytes) <= (shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes)); - - gpuoffsetbytes = (memdesc->gpuaddr - shmem->apertures[aperture_index].memarena->gpubaseaddr) + offsetbytes; - - GSL_HAL_MEM_SET(shmem->apertures[aperture_index].memarena->hostbaseaddr, gpuoffsetbytes, value, sizebytes); - - KGSL_DEBUG(GSL_DBGFLAGS_PM4MEM, KGSL_DEBUG_DUMPMEMSET((memdesc->gpuaddr + offsetbytes), sizebytes, value)); - - KGSL_DEBUG_TBDUMP_SETMEM( (memdesc->gpuaddr + offsetbytes), value, sizebytes ); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_set. Return value %B\n", GSL_SUCCESS ); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_set(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes) -{ - int status = GSL_SUCCESS; - GSL_API_MUTEX_LOCK(); - status = kgsl_sharedmem_set0(memdesc, offsetbytes, value, sizebytes); - GSL_API_MUTEX_UNLOCK(); - return status; -} - -//---------------------------------------------------------------------------- - -KGSL_API unsigned int -kgsl_sharedmem_largestfreeblock(gsl_deviceid_t device_id, gsl_flags_t flags) -{ - gsl_apertureid_t aperture_id; - gsl_channelid_t channel_id; - int aperture_index; - unsigned int result = 0; - gsl_sharedmem_t *shmem; - - // device_id is ignored at this level, it would be used with per-device memarena's - - // unreferenced formal parameter - (void) device_id; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_largestfreeblock(gsl_deviceid_t device_id=%D, gsl_flags_t flags=0x%08x)\n", - device_id, flags ); - - GSL_MEMFLAGS_APERTURE_GET(flags, aperture_id); - GSL_MEMFLAGS_CHANNEL_GET(flags, channel_id); - - GSL_API_MUTEX_LOCK(); - - shmem = &gsl_driver.shmem; - - if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); - GSL_API_MUTEX_UNLOCK(); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_largestfreeblock. Return value %d\n", 0 ); - return (0); - } - - aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); - - if (aperture_id == shmem->apertures[aperture_index].id) - { - result = kgsl_memarena_getlargestfreeblock(shmem->apertures[aperture_index].memarena, flags); - } - - GSL_API_MUTEX_UNLOCK(); - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_largestfreeblock. Return value %d\n", result ); - - return (result); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_map(gsl_deviceid_t device_id, gsl_flags_t flags, const gsl_scatterlist_t *scatterlist, gsl_memdesc_t *memdesc) -{ - int status = GSL_FAILURE; - gsl_sharedmem_t *shmem = &gsl_driver.shmem; - int aperture_index; - gsl_deviceid_t tmp_id; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_map(gsl_deviceid_t device_id=%D, gsl_flags_t flags=0x%08x, gsl_scatterlist_t scatterlist=%M, gsl_memdesc_t *memdesc=%M)\n", - device_id, flags, memdesc, scatterlist ); - - // execute pending device action - tmp_id = (device_id != GSL_DEVICE_ANY) ? device_id : device_id+1; - for ( ; tmp_id <= GSL_DEVICE_MAX; tmp_id++) - { - if (gsl_driver.device[tmp_id-1].flags & GSL_FLAGS_INITIALIZED) - { - kgsl_device_runpending(&gsl_driver.device[tmp_id-1]); - - if (tmp_id == device_id) - { - break; - } - } - } - - // convert any device to an actual existing device - if (device_id == GSL_DEVICE_ANY) - { - for ( ; ; ) - { - device_id++; - - if (device_id <= GSL_DEVICE_MAX) - { - if (gsl_driver.device[device_id-1].flags & GSL_FLAGS_INITIALIZED) - { - break; - } - } - else - { - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid device.\n" ); - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_map. Return value %B\n", GSL_FAILURE ); - return (GSL_FAILURE); - } - } - } - - KOS_ASSERT(device_id > GSL_DEVICE_ANY && device_id <= GSL_DEVICE_MAX); - - if (shmem->flags & GSL_FLAGS_INITIALIZED) - { - aperture_index = kgsl_sharedmem_getapertureindex(shmem, GSL_APERTURE_EMEM, GSL_CHANNEL_1); - - if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) - { - KOS_ASSERT(scatterlist->num); - KOS_ASSERT(scatterlist->pages); - - status = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, scatterlist->num *GSL_PAGESIZE, memdesc); - if (status == GSL_SUCCESS) - { - GSL_MEMDESC_APERTURE_SET(memdesc, aperture_index); - GSL_MEMDESC_DEVICE_SET(memdesc, device_id); - - // mark descriptor's memory as externally allocated -- i.e. outside GSL - GSL_MEMDESC_EXTALLOC_SET(memdesc, 1); - - status = kgsl_mmu_map(&gsl_driver.device[device_id-1].mmu, memdesc->gpuaddr, scatterlist, flags, GSL_CALLER_PROCESSID_GET()); - if (status != GSL_SUCCESS) - { - kgsl_memarena_free(shmem->apertures[aperture_index].memarena, memdesc); - } - } - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_map. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_unmap(gsl_memdesc_t *memdesc) -{ - return (kgsl_sharedmem_free0(memdesc, GSL_CALLER_PROCESSID_GET())); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_getmap(const gsl_memdesc_t *memdesc, gsl_scatterlist_t *scatterlist) -{ - int status = GSL_SUCCESS; - int aperture_index; - gsl_deviceid_t device_id; - gsl_sharedmem_t *shmem; - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, - "--> int kgsl_sharedmem_getmap(gsl_memdesc_t *memdesc=%M, gsl_scatterlist_t scatterlist=%M)\n", - memdesc, scatterlist ); - - GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); - GSL_MEMDESC_DEVICE_GET(memdesc, device_id); - - shmem = &gsl_driver.shmem; - - if (shmem->flags & GSL_FLAGS_INITIALIZED) - { - KOS_ASSERT(scatterlist->num); - KOS_ASSERT(scatterlist->pages); - KOS_ASSERT(memdesc->gpuaddr >= shmem->apertures[aperture_index].memarena->gpubaseaddr); - KOS_ASSERT((memdesc->gpuaddr + memdesc->size) <= (shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes)); - - kos_memset(scatterlist->pages, 0, sizeof(unsigned int) * scatterlist->num); - - if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) - { - status = kgsl_mmu_getmap(&gsl_driver.device[device_id-1].mmu, memdesc->gpuaddr, memdesc->size, scatterlist, GSL_CALLER_PROCESSID_GET()); - } - else - { - // coalesce physically contiguous pages into a single scatter list entry - scatterlist->pages[0] = memdesc->gpuaddr; - scatterlist->contiguous = 1; - } - } - - kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_getmap. Return value %B\n", status ); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_sharedmem_querystats(gsl_sharedmem_t *shmem, gsl_sharedmem_stats_t *stats) -{ -#ifdef GSL_STATS_MEM - int status = GSL_SUCCESS; - int i; - - KOS_ASSERT(stats); - - if (shmem->flags & GSL_FLAGS_INITIALIZED) - { - for (i = 0; i < shmem->numapertures; i++) - { - if (shmem->apertures[i].memarena) - { - stats->apertures[i].id = shmem->apertures[i].id; - stats->apertures[i].channel = shmem->apertures[i].channel; - - status |= kgsl_memarena_querystats(shmem->apertures[i].memarena, &stats->apertures[i].memarena); - } - } - } - else - { - kos_memset(stats, 0, sizeof(gsl_sharedmem_stats_t)); - } - - return (status); -#else - // unreferenced formal parameters - (void) shmem; - (void) stats; - - return (GSL_FAILURE_NOTSUPPORTED); -#endif // GSL_STATS_MEM -} - -//---------------------------------------------------------------------------- - -unsigned int -kgsl_sharedmem_convertaddr(unsigned int addr, int type) -{ - gsl_sharedmem_t *shmem = &gsl_driver.shmem; - unsigned int cvtaddr = 0; - unsigned int gpubaseaddr, hostbaseaddr, sizebytes; - int i; - - if ((shmem->flags & GSL_FLAGS_INITIALIZED)) - { - for (i = 0; i < shmem->numapertures; i++) - { - hostbaseaddr = shmem->apertures[i].memarena->hostbaseaddr; - gpubaseaddr = shmem->apertures[i].memarena->gpubaseaddr; - sizebytes = shmem->apertures[i].memarena->sizebytes; - - // convert from gpu to host - if (type == 0) - { - if (addr >= gpubaseaddr && addr < (gpubaseaddr + sizebytes)) - { - cvtaddr = hostbaseaddr + (addr - gpubaseaddr); - break; - } - } - // convert from host to gpu - else if (type == 1) - { - if (addr >= hostbaseaddr && addr < (hostbaseaddr + sizebytes)) - { - cvtaddr = gpubaseaddr + (addr - hostbaseaddr); - break; - } - } - } - } - - return (cvtaddr); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_cacheoperation(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int sizebytes, unsigned int operation) -{ - int status = GSL_FAILURE; - - /* unreferenced formal parameter */ - (void)memdesc; - (void)offsetbytes; - (void)sizebytes; - (void)operation; - - /* do cache operation */ - - return (status); -} - -//---------------------------------------------------------------------------- - -KGSL_API int -kgsl_sharedmem_fromhostpointer(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, void* hostptr) -{ - int status = GSL_FAILURE; - - memdesc->gpuaddr = (gpuaddr_t)hostptr; /* map physical address with hostptr */ - memdesc->hostptr = hostptr; /* set virtual address also in memdesc */ - - /* unreferenced formal parameter */ - (void)device_id; - - return (status); -} diff --git a/drivers/mxc/amd-gpu/common/gsl_tbdump.c b/drivers/mxc/amd-gpu/common/gsl_tbdump.c deleted file mode 100644 index e22cf894f7b..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_tbdump.c +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#ifdef WIN32 -#include -#endif -#include "gsl.h" -#include "gsl_tbdump.h" -#include "kos_libapi.h" - -#ifdef TBDUMP - -typedef struct TBDump_ -{ - void* file; -} TBDump; - - -static TBDump g_tb; -static oshandle_t tbdump_mutex = 0; -#define TBDUMP_MUTEX_LOCK() if( tbdump_mutex ) kos_mutex_lock( tbdump_mutex ) -#define TBDUMP_MUTEX_UNLOCK() if( tbdump_mutex ) kos_mutex_unlock( tbdump_mutex ) - -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ - -static void tbdump_printline(const char* format, ...) -{ - if(g_tb.file) - { - va_list va; - va_start(va, format); - vfprintf((FILE*)g_tb.file, format, va); - va_end(va); - fprintf((FILE*)g_tb.file, "\n"); - } -} - -static void tbdump_printinfo(const char* message ) -{ - tbdump_printline("15 %s", message); -} - -static void tbdump_getmemhex(char* buffer, unsigned int addr, unsigned int sizewords) -{ - unsigned int i = 0; - static const char* hexChars = "0123456789abcdef"; - unsigned char* ptr = (unsigned char*)addr; - - for (i = 0; i < sizewords; i++) - { - buffer[(sizewords - i) * 2 - 1] = hexChars[ptr[i] & 0x0f]; - buffer[(sizewords - i) * 2 - 2] = hexChars[ptr[i] >> 4]; - } - buffer[sizewords * 2] = '\0'; -} - -/* ------------------------------------------------------------------------ */ - -void tbdump_open(char* filename) -{ - if( !tbdump_mutex ) tbdump_mutex = kos_mutex_create( "TBDUMP_MUTEX" ); - - kos_memset( &g_tb, 0, sizeof( g_tb ) ); - - g_tb.file = kos_fopen( filename, "wt" ); - - tbdump_printinfo("reset"); - tbdump_printline("0"); - tbdump_printline("1 00000000 00000eff"); - - /* Enable interrupts */ - tbdump_printline("1 00000000 00000003"); -} - -void tbdump_close() -{ - TBDUMP_MUTEX_LOCK(); - - kos_fclose( g_tb.file ); - g_tb.file = 0; - - TBDUMP_MUTEX_UNLOCK(); - - if( tbdump_mutex ) kos_mutex_free( tbdump_mutex ); -} - -/* ------------------------------------------------------------------------ */ - -void tbdump_syncmem(unsigned int addr, unsigned int src, unsigned int sizebytes) -{ - /* Align starting address and size */ - unsigned int beg = addr; - unsigned int end = addr+sizebytes; - char buffer[65]; - - TBDUMP_MUTEX_LOCK(); - - beg = (beg+15) & ~15; - end &= ~15; - - if( sizebytes <= 16 ) - { - tbdump_getmemhex(buffer, src, 16); - - tbdump_printline("19 %08x %i 1 %s", addr, sizebytes, buffer); - - TBDUMP_MUTEX_UNLOCK(); - return; - } - - /* Handle unaligned start */ - if( beg != addr ) - { - tbdump_getmemhex(buffer, src, 16); - - tbdump_printline("19 %08x %i 1 %s", addr, beg-addr, buffer); - - src += beg-addr; - } - - /* Dump the memory writes */ - while( beg < end ) - { - tbdump_getmemhex(buffer, src, 16); - - tbdump_printline("2 %08x %s", beg, buffer); - - beg += 16; - src += 16; - } - - /* Handle unaligned end */ - if( end != addr+sizebytes ) - { - tbdump_getmemhex(buffer, src, 16); - - tbdump_printline("19 %08x %i 1 %s", end, (addr+sizebytes)-end, buffer); - } - - TBDUMP_MUTEX_UNLOCK(); -} - -/* ------------------------------------------------------------------------ */ - -void tbdump_setmem(unsigned int addr, unsigned int value, unsigned int sizebytes) -{ - TBDUMP_MUTEX_LOCK(); - - tbdump_printline("19 %08x 4 %i %032x", addr, (sizebytes+3)/4, value ); - - TBDUMP_MUTEX_UNLOCK(); -} - -/* ------------------------------------------------------------------------ */ - -void tbdump_slavewrite(unsigned int addr, unsigned int value) -{ - TBDUMP_MUTEX_LOCK(); - - tbdump_printline("1 %08x %08x", addr, value); - - TBDUMP_MUTEX_UNLOCK(); -} - -/* ------------------------------------------------------------------------ */ - - -KGSL_API int -kgsl_tbdump_waitirq() -{ - if(!g_tb.file) return GSL_FAILURE; - - TBDUMP_MUTEX_LOCK(); - - tbdump_printinfo("wait irq"); - tbdump_printline("10"); - - /* ACK IRQ */ - tbdump_printline("1 00000418 00000003"); - tbdump_printline("18 00000018 00000000 # slave read & assert"); - - TBDUMP_MUTEX_UNLOCK(); - - return GSL_SUCCESS; -} - -/* ------------------------------------------------------------------------ */ - -KGSL_API int -kgsl_tbdump_exportbmp(const void* addr, unsigned int format, unsigned int stride, unsigned int width, unsigned int height) -{ - static char filename[20]; - static int numframe = 0; - - if(!g_tb.file) return GSL_FAILURE; - - TBDUMP_MUTEX_LOCK(); - #pragma warning(disable:4996) - sprintf( filename, "tbdump_%08d.bmp", numframe++ ); - - tbdump_printline("13 %s %d %08x %d %d %d 0", filename, format, (unsigned int)addr, stride, width, height); - - TBDUMP_MUTEX_UNLOCK(); - - return GSL_SUCCESS; -} - -/* ------------------------------------------------------------------------ */ - -#endif /* TBDUMP */ diff --git a/drivers/mxc/amd-gpu/common/gsl_yamato.c b/drivers/mxc/amd-gpu/common/gsl_yamato.c deleted file mode 100644 index 07c651f57f4..00000000000 --- a/drivers/mxc/amd-gpu/common/gsl_yamato.c +++ /dev/null @@ -1,924 +0,0 @@ -/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_hal.h" -#ifdef _LINUX -#include -#include -#endif - -#ifdef GSL_BLD_YAMATO - -#include "gsl_ringbuffer.h" -#include "gsl_drawctxt.h" - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -static int -kgsl_yamato_gmeminit(gsl_device_t *device) -{ - rb_edram_info_u rb_edram_info = {0}; - unsigned int gmem_size; - unsigned int edram_value = 0; - - // make sure edram range is aligned to size - KOS_ASSERT((device->gmemspace.gpu_base & (device->gmemspace.sizebytes - 1)) == 0); - - // get edram_size value equivalent - gmem_size = (device->gmemspace.sizebytes >> 14); - while (gmem_size >>= 1) - { - edram_value++; - } - - rb_edram_info.f.edram_size = edram_value; - rb_edram_info.f.edram_mapping_mode = 0; // EDRAM_MAP_UPPER - rb_edram_info.f.edram_range = (device->gmemspace.gpu_base >> 14); // must be aligned to size - - device->ftbl.device_regwrite(device, mmRB_EDRAM_INFO, (unsigned int)rb_edram_info.val); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -static int -kgsl_yamato_gmemclose(gsl_device_t *device) -{ - device->ftbl.device_regwrite(device, mmRB_EDRAM_INFO, 0x00000000); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -void -kgsl_yamato_rbbmintrcallback(gsl_intrid_t id, void *cookie) -{ - gsl_device_t *device = (gsl_device_t *) cookie; - - switch(id) - { - // error condition interrupt - case GSL_INTR_YDX_RBBM_READ_ERROR: - printk(KERN_ERR "GPU: Z430 RBBM Read Error\n"); - schedule_work(&device->irq_err_work); - break; - - // non-error condition interrupt - case GSL_INTR_YDX_RBBM_DISPLAY_UPDATE: - case GSL_INTR_YDX_RBBM_GUI_IDLE: - - kos_event_signal(device->intr.evnt[id]); - break; - - default: - - break; - } -} - -//---------------------------------------------------------------------------- - -void -kgsl_yamato_cpintrcallback(gsl_intrid_t id, void *cookie) -{ - gsl_device_t *device = (gsl_device_t *) cookie; - - switch(id) - { - case GSL_INTR_YDX_CP_RING_BUFFER: -#ifndef _LINUX - kos_event_signal(device->timestamp_event); -#else - wake_up_interruptible_all(&(device->timestamp_waitq)); -#endif - break; - default: - break; - } -} -//---------------------------------------------------------------------------- - -void -kgsl_yamato_sqintrcallback(gsl_intrid_t id, void *cookie) -{ - (void) cookie; // unreferenced formal parameter - /*gsl_device_t *device = (gsl_device_t *) cookie;*/ - - switch(id) - { - // error condition interrupt - case GSL_INTR_YDX_SQ_PS_WATCHDOG: - case GSL_INTR_YDX_SQ_VS_WATCHDOG: - - // todo: take appropriate action - - break; - - default: - - break; - } -} - -//---------------------------------------------------------------------------- - -#ifdef _DEBUG - -static int -kgsl_yamato_bist(gsl_device_t *device) -{ - int status = GSL_FAILURE; - unsigned int link[2]; - - if (!(device->flags & GSL_FLAGS_STARTED)) - { - return (GSL_FAILURE); - } - - status = kgsl_ringbuffer_bist(&device->ringbuffer); - if (status != GSL_SUCCESS) - { - return (status); - } - - // interrupt bist - link[0] = pm4_type3_packet(PM4_INTERRUPT, 1); - link[1] = CP_INT_CNTL__RB_INT_MASK; - kgsl_ringbuffer_issuecmds(device, 1, &link[0], 2, GSL_CALLER_PROCESSID_GET()); - - status = kgsl_mmu_bist(&device->mmu); - if (status != GSL_SUCCESS) - { - return (status); - } - - return (status); -} -#endif - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_isr(gsl_device_t *device) -{ - unsigned int status; -#ifdef _DEBUG - mh_mmu_page_fault_u page_fault = {0}; - mh_axi_error_u axi_error = {0}; - mh_clnt_axi_id_reuse_u clnt_axi_id_reuse = {0}; - rbbm_read_error_u read_error = {0}; -#endif // DEBUG - - // determine if yamato is interrupting, and if so, which block - device->ftbl.device_regread(device, mmMASTER_INT_SIGNAL, &status); - - if (status & MASTER_INT_SIGNAL__MH_INT_STAT) - { -#ifdef _DEBUG - // obtain mh error information - device->ftbl.device_regread(device, mmMH_MMU_PAGE_FAULT, (unsigned int *)&page_fault); - device->ftbl.device_regread(device, mmMH_AXI_ERROR, (unsigned int *)&axi_error); - device->ftbl.device_regread(device, mmMH_CLNT_AXI_ID_REUSE, (unsigned int *)&clnt_axi_id_reuse); -#endif // DEBUG - - kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_MH); - } - - if (status & MASTER_INT_SIGNAL__CP_INT_STAT) - { - kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_CP); - } - - if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) - { -#ifdef _DEBUG - // obtain rbbm error information - device->ftbl.device_regread(device, mmRBBM_READ_ERROR, (unsigned int *)&read_error); -#endif // DEBUG - - kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_RBBM); - } - - if (status & MASTER_INT_SIGNAL__SQ_INT_STAT) - { - kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_SQ); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_tlbinvalidate(gsl_device_t *device, unsigned int reg_invalidate, unsigned int pid) -{ - unsigned int link[2]; - mh_mmu_invalidate_u mh_mmu_invalidate = {0}; - - mh_mmu_invalidate.f.invalidate_all = 1; - mh_mmu_invalidate.f.invalidate_tc = 1; - - // if possible, invalidate via command stream, otherwise via direct register writes - if (device->flags & GSL_FLAGS_STARTED) - { - link[0] = pm4_type0_packet(reg_invalidate, 1); - link[1] = mh_mmu_invalidate.val; - - kgsl_ringbuffer_issuecmds(device, 1, &link[0], 2, pid); - } - else - { - - device->ftbl.device_regwrite(device, reg_invalidate, mh_mmu_invalidate.val); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_setpagetable(gsl_device_t *device, unsigned int reg_ptbase, gpuaddr_t ptbase, unsigned int pid) -{ - unsigned int link[25]; - - // if there is an active draw context, set via command stream, - if (device->flags & GSL_FLAGS_STARTED) - { - // wait for graphics pipe to be idle - link[0] = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - link[1] = 0x00000000; - - // set page table base - link[2] = pm4_type0_packet(reg_ptbase, 1); - link[3] = ptbase; - - // HW workaround: to resolve MMU page fault interrupts caused by the VGT. It prevents - // the CP PFP from filling the VGT DMA request fifo too early, thereby ensuring that - // the VGT will not fetch vertex/bin data until after the page table base register - // has been updated. - // - // Two null DRAW_INDX_BIN packets are inserted right after the page table base update, - // followed by a wait for idle. The null packets will fill up the VGT DMA request - // fifo and prevent any further vertex/bin updates from occurring until the wait - // has finished. - link[4] = pm4_type3_packet(PM4_SET_CONSTANT, 2); - link[5] = (0x4 << 16) | (mmPA_SU_SC_MODE_CNTL - 0x2000); - link[6] = 0; // disable faceness generation - link[7] = pm4_type3_packet(PM4_SET_BIN_BASE_OFFSET, 1); - link[8] = device->mmu.dummyspace.gpuaddr; - link[9] = pm4_type3_packet(PM4_DRAW_INDX_BIN, 6); - link[10] = 0; // viz query info - link[11] = 0x0003C004; // draw indicator - link[12] = 0; // bin base - link[13] = 3; // bin size - link[14] = device->mmu.dummyspace.gpuaddr; // dma base - link[15] = 6; // dma size - link[16] = pm4_type3_packet(PM4_DRAW_INDX_BIN, 6); - link[17] = 0; // viz query info - link[18] = 0x0003C004; // draw indicator - link[19] = 0; // bin base - link[20] = 3; // bin size - link[21] = device->mmu.dummyspace.gpuaddr; // dma base - link[22] = 6; // dma size - link[23] = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - link[24] = 0x00000000; - - kgsl_ringbuffer_issuecmds(device, 1, &link[0], 25, pid); - } - else - { - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - device->ftbl.device_regwrite(device, reg_ptbase, ptbase); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -static void kgsl_yamato_irqerr(struct work_struct *work) -{ - gsl_device_t *device = &gsl_driver.device[GSL_DEVICE_YAMATO-1]; - device->ftbl.device_destroy(device); -} - -int -kgsl_yamato_init(gsl_device_t *device) -{ - int status = GSL_FAILURE; - - device->flags |= GSL_FLAGS_INITIALIZED; - - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_ON, 100); - - //We need to make sure all blocks are powered up and clocked before - //issuing a soft reset. The overrides will be turned off (set to 0) - //later in kgsl_yamato_start. - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, 0xfffffffe); - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, 0xffffffff); - - // soft reset - device->ftbl.device_regwrite(device, mmRBBM_SOFT_RESET, 0xFFFFFFFF); - kos_sleep(50); - device->ftbl.device_regwrite(device, mmRBBM_SOFT_RESET, 0x00000000); - - // RBBM control - device->ftbl.device_regwrite(device, mmRBBM_CNTL, 0x00004442); - - // setup MH arbiter - device->ftbl.device_regwrite(device, mmMH_ARBITER_CONFIG, *(unsigned int *) &gsl_cfg_yamato_mharb); - - // SQ_*_PROGRAM - device->ftbl.device_regwrite(device, mmSQ_VS_PROGRAM, 0x00000000); - device->ftbl.device_regwrite(device, mmSQ_PS_PROGRAM, 0x00000000); - - // init interrupt - status = kgsl_intr_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } - - // init mmu - status = kgsl_mmu_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } - - /* handle error condition */ - INIT_WORK(&device->irq_err_work, kgsl_yamato_irqerr); - - return(status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_close(gsl_device_t *device) -{ - if (device->refcnt == 0) - { - // shutdown mmu - kgsl_mmu_close(device); - - // shutdown interrupt - kgsl_intr_close(device); - - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_OFF, 0); - - device->flags &= ~GSL_FLAGS_INITIALIZED; - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_destroy(gsl_device_t *device) -{ - int i; - unsigned int pid; - -#ifdef _DEBUG - // for now, signal catastrophic failure in a brute force way - KOS_ASSERT(0); -#endif // _DEBUG - - // todo: - hard reset core? - - kgsl_drawctxt_destroyall(device); - - for (i = 0; i < GSL_CALLER_PROCESS_MAX; i++) - { - pid = device->callerprocess[i]; - if (pid) - { - device->ftbl.device_stop(device); - kgsl_driver_destroy(pid); - - // todo: terminate client process? - } - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_start(gsl_device_t *device, gsl_flags_t flags) -{ - int status = GSL_FAILURE; - unsigned int pm1, pm2; - - KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPFBSTART(device)); - - (void) flags; // unreferenced formal parameter - - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_ON, 100); - - // default power management override when running in safe mode - pm1 = (device->flags & GSL_FLAGS_SAFEMODE) ? 0xFFFFFFFE : 0x00000000; - pm2 = (device->flags & GSL_FLAGS_SAFEMODE) ? 0x000000FF : 0x00000000; - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, pm1); - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, pm2); - - // enable rbbm interrupts - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_RBBM_READ_ERROR, kgsl_yamato_rbbmintrcallback, (void *) device); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_RBBM_DISPLAY_UPDATE, kgsl_yamato_rbbmintrcallback, (void *) device); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_RBBM_GUI_IDLE, kgsl_yamato_rbbmintrcallback, (void *) device); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_RBBM_READ_ERROR); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_RBBM_DISPLAY_UPDATE); -#if defined GSL_RB_TIMESTAMP_INTERUPT - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER, kgsl_yamato_cpintrcallback, (void *) device); - kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER); -#endif - - //kgsl_intr_enable(&device->intr, GSL_INTR_YDX_RBBM_GUI_IDLE); - - // enable sq interrupts - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_SQ_PS_WATCHDOG, kgsl_yamato_sqintrcallback, (void *) device); - kgsl_intr_attach(&device->intr, GSL_INTR_YDX_SQ_VS_WATCHDOG, kgsl_yamato_sqintrcallback, (void *) device); - //kgsl_intr_enable(&device->intr, GSL_INTR_YDX_SQ_PS_WATCHDOG); - //kgsl_intr_enable(&device->intr, GSL_INTR_YDX_SQ_VS_WATCHDOG); - - // init gmem - kgsl_yamato_gmeminit(device); - - // init ring buffer - status = kgsl_ringbuffer_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } - - // init draw context - status = kgsl_drawctxt_init(device); - if (status != GSL_SUCCESS) - { - device->ftbl.device_stop(device); - return (status); - } - - device->flags |= GSL_FLAGS_STARTED; - - KGSL_DEBUG(GSL_DBGFLAGS_BIST, kgsl_yamato_bist(device)); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_stop(gsl_device_t *device) -{ - // HW WORKAROUND: Ringbuffer hangs during next start if it is stopped without any - // commands ever being submitted. To avoid this, submit a dummy wait packet. - unsigned int cmds[2]; - cmds[0] = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); - cmds[0] = 0; - kgsl_ringbuffer_issuecmds(device, 0, cmds, 2, GSL_CALLER_PROCESSID_GET()); - - // disable rbbm interrupts - kgsl_intr_detach(&device->intr, GSL_INTR_YDX_RBBM_READ_ERROR); - kgsl_intr_detach(&device->intr, GSL_INTR_YDX_RBBM_DISPLAY_UPDATE); - kgsl_intr_detach(&device->intr, GSL_INTR_YDX_RBBM_GUI_IDLE); -#if defined GSL_RB_TIMESTAMP_INTERUPT - kgsl_intr_detach(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER); -#endif - - // disable sq interrupts - kgsl_intr_detach(&device->intr, GSL_INTR_YDX_SQ_PS_WATCHDOG); - kgsl_intr_detach(&device->intr, GSL_INTR_YDX_SQ_VS_WATCHDOG); - - kgsl_drawctxt_close(device); - - // shutdown ringbuffer - kgsl_ringbuffer_close(&device->ringbuffer); - - // shutdown gmem - kgsl_yamato_gmemclose(device); - - if(device->refcnt == 0) - { - kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_OFF, 0); - } - - device->flags &= ~GSL_FLAGS_STARTED; - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_getproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) -{ - int status = GSL_FAILURE; - -#ifndef _DEBUG - (void) sizebytes; // unreferenced formal parameter -#endif - - if (type == GSL_PROP_DEVICE_INFO) - { - gsl_devinfo_t *devinfo = (gsl_devinfo_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_devinfo_t)); - - devinfo->device_id = device->id; - devinfo->chip_id = (gsl_chipid_t)device->chip_id; - devinfo->mmu_enabled = kgsl_mmu_isenabled(&device->mmu); - devinfo->gmem_hostbaseaddr = device->gmemspace.mmio_virt_base; - devinfo->gmem_gpubaseaddr = device->gmemspace.gpu_base; - devinfo->gmem_sizebytes = device->gmemspace.sizebytes; - devinfo->high_precision = 0; - - status = GSL_SUCCESS; - } - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_setproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) -{ - int status = GSL_FAILURE; - -#ifndef _DEBUG - (void) sizebytes; // unreferenced formal parameter -#endif - - if (type == GSL_PROP_DEVICE_POWER) - { - gsl_powerprop_t *power = (gsl_powerprop_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_powerprop_t)); - - if (!(device->flags & GSL_FLAGS_SAFEMODE)) - { - if (power->flags & GSL_PWRFLAGS_OVERRIDE_ON) - { - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, 0xfffffffe); - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, 0xffffffff); - } - else if (power->flags & GSL_PWRFLAGS_OVERRIDE_OFF) - { - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, 0x00000000); - device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, 0x00000000); - } - else - { - kgsl_hal_setpowerstate(device->id, power->flags, power->value); - } - } - - status = GSL_SUCCESS; - } - else if (type == GSL_PROP_DEVICE_DMI) - { - gsl_dmiprop_t *dmi = (gsl_dmiprop_t *) value; - - KOS_ASSERT(sizebytes == sizeof(gsl_dmiprop_t)); - - // - // In order to enable DMI, it must not already be enabled. - // - switch (dmi->flags) - { - case GSL_DMIFLAGS_ENABLE_SINGLE: - case GSL_DMIFLAGS_ENABLE_DOUBLE: - if (!gsl_driver.dmi_state) - { - gsl_driver.dmi_state = OS_TRUE; - gsl_driver.dmi_mode = dmi->flags; - gsl_driver.dmi_frame = -1; - status = GSL_SUCCESS; - } - break; - case GSL_DMIFLAGS_DISABLE: - // - // To disable, we must be enabled. - // - if (gsl_driver.dmi_state) - { - gsl_driver.dmi_state = OS_FALSE; - gsl_driver.dmi_mode = -1; - gsl_driver.dmi_frame = -2; - status = GSL_SUCCESS; - } - break; - case GSL_DMIFLAGS_NEXT_BUFFER: - // - // Going to the next buffer is dependent upon what mod we are in with respect to single, double, or triple buffering. - // DMI must also be enabled. - // - if (gsl_driver.dmi_state) - { - unsigned int cmdbuf[10]; - unsigned int *cmds = &cmdbuf[0]; - int size; - - if (gsl_driver.dmi_frame == -1) - { - size = 8; - - *cmds++ = pm4_type0_packet(mmRBBM_DSPLY, 1); - switch (gsl_driver.dmi_mode) - { - case GSL_DMIFLAGS_ENABLE_SINGLE: - gsl_driver.dmi_max_frame = 1; - *cmds++ = 0x041000410; - break; - case GSL_DMIFLAGS_ENABLE_DOUBLE: - gsl_driver.dmi_max_frame = 2; - *cmds++ = 0x041000510; - break; - case GSL_DMIFLAGS_ENABLE_TRIPLE: - gsl_driver.dmi_max_frame = 3; - *cmds++ = 0x041000610; - break; - } - } - else - { - size = 6; - } - - - // - // Wait for 3D core to be idle and wait for vsync - // - *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); - *cmds++ = 0x00008000; // 3d idle - // *cmds++ = 0x00008008; // 3d idle & vsync - - // - // Update the render latest register. - // - *cmds++ = pm4_type0_packet(mmRBBM_RENDER_LATEST, 1); - switch (gsl_driver.dmi_frame) - { - case 0: - // - // Render frame 0 - // - *cmds++ = 0; - // - // Wait for our max frame # indicator to be de-asserted - // - *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); - *cmds++ = 0x00000008 << gsl_driver.dmi_max_frame; - gsl_driver.dmi_frame = 1; - break; - case -1: - case 1: - // - // Render frame 1 - // - *cmds++ = 1; - *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); - *cmds++ = 0x00000010; // Wait for frame 0 to be deasserted - gsl_driver.dmi_frame = 2; - break; - case 2: - // - // Render frame 2 - // - *cmds++ = 2; - *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); - *cmds++ = 0x00000020; // Wait for frame 1 to be deasserted - gsl_driver.dmi_frame = 0; - break; - } - - // issue the commands - kgsl_ringbuffer_issuecmds(device, 1, &cmdbuf[0], size, GSL_CALLER_PROCESSID_GET()); - - gsl_driver.dmi_frame %= gsl_driver.dmi_max_frame; - status = GSL_SUCCESS; - } - break; - default: - status = GSL_FAILURE; - break; - } - } - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_idle(gsl_device_t *device, unsigned int timeout) -{ - int status = GSL_FAILURE; - gsl_ringbuffer_t *rb = &device->ringbuffer; - rbbm_status_u rbbm_status; - - (void) timeout; // unreferenced formal parameter - - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_REGPOLL, device->id, mmRBBM_STATUS, 0x80000000, "kgsl_yamato_idle")); - - GSL_RB_MUTEX_LOCK(); - - // first, wait until the CP has consumed all the commands in the ring buffer - if (rb->flags & GSL_FLAGS_STARTED) - { - do - { - GSL_RB_GET_READPTR(rb, &rb->rptr); - - } while (rb->rptr != rb->wptr); - } - - // now, wait for the GPU to finish its operations - for ( ; ; ) - { - device->ftbl.device_regread(device, mmRBBM_STATUS, (unsigned int *)&rbbm_status); - - if (!(rbbm_status.val & 0x80000000)) - { - status = GSL_SUCCESS; - break; - } - - } - - GSL_RB_MUTEX_UNLOCK(); - - return (status); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_regread(gsl_device_t *device, unsigned int offsetwords, unsigned int *value) -{ - KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, - { - if (!(gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX_WITHOUT_IFH)) - { - if(offsetwords == mmCP_RB_RPTR || offsetwords == mmCP_RB_WPTR) - { - *value = device->ringbuffer.wptr; - return (GSL_SUCCESS); - } - } - }); - - GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_regwrite(gsl_device_t *device, unsigned int offsetwords, unsigned int value) -{ - KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPREGWRITE(offsetwords, value)); - - GSL_HAL_REG_WRITE(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); - - // idle device when running in safe mode - if (device->flags & GSL_FLAGS_SAFEMODE) - { - device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); - } - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_waitirq(gsl_device_t *device, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout) -{ - int status = GSL_FAILURE_NOTSUPPORTED; - - if (intr_id == GSL_INTR_YDX_CP_IB1_INT || intr_id == GSL_INTR_YDX_CP_IB2_INT || - intr_id == GSL_INTR_YDX_CP_SW_INT || intr_id == GSL_INTR_YDX_RBBM_DISPLAY_UPDATE) - { - if (kgsl_intr_isenabled(&device->intr, intr_id) == GSL_SUCCESS) - { - // wait until intr completion event is received - if (kos_event_wait(device->intr.evnt[intr_id], timeout) == OS_SUCCESS) - { - *count = 1; - status = GSL_SUCCESS; - } - else - { - status = GSL_FAILURE_TIMEOUT; - } - } - } - - return (status); -} - -int kgsl_yamato_check_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp) -{ - int i; - /* Reason to use a wait loop: - * When bus is busy, for example vpu is working too, the timestamp is - * possiblly not yet refreshed to memory by yamato. For most cases, it - * will hit on first loop cycle. So it don't effect performance. - */ - for (i = 0; i < 10; i++) { - if (kgsl_cmdstream_check_timestamp(device_id, timestamp)) - return 1; - udelay(10); - } - return 0; -} - -int -kgsl_yamato_waittimestamp(gsl_device_t *device, gsl_timestamp_t timestamp, unsigned int timeout) -{ -#if defined GSL_RB_TIMESTAMP_INTERUPT -#ifndef _LINUX - return kos_event_wait( device->timestamp_event, timeout ); -#else - int status = wait_event_interruptible_timeout(device->timestamp_waitq, - kgsl_yamato_check_timestamp(device->id, timestamp), - msecs_to_jiffies(timeout)); - if (status > 0) - return GSL_SUCCESS; - else - return GSL_FAILURE; -#endif -#else - return (GSL_SUCCESS); -#endif -} -//---------------------------------------------------------------------------- - -int -kgsl_yamato_runpending(gsl_device_t *device) -{ - (void) device; - - return (GSL_SUCCESS); -} - -//---------------------------------------------------------------------------- - -int -kgsl_yamato_getfunctable(gsl_functable_t *ftbl) -{ - ftbl->device_init = kgsl_yamato_init; - ftbl->device_close = kgsl_yamato_close; - ftbl->device_destroy = kgsl_yamato_destroy; - ftbl->device_start = kgsl_yamato_start; - ftbl->device_stop = kgsl_yamato_stop; - ftbl->device_getproperty = kgsl_yamato_getproperty; - ftbl->device_setproperty = kgsl_yamato_setproperty; - ftbl->device_idle = kgsl_yamato_idle; - ftbl->device_waittimestamp = kgsl_yamato_waittimestamp; - ftbl->device_regread = kgsl_yamato_regread; - ftbl->device_regwrite = kgsl_yamato_regwrite; - ftbl->device_waitirq = kgsl_yamato_waitirq; - ftbl->device_runpending = kgsl_yamato_runpending; - ftbl->intr_isr = kgsl_yamato_isr; - ftbl->mmu_tlbinvalidate = kgsl_yamato_tlbinvalidate; - ftbl->mmu_setpagetable = kgsl_yamato_setpagetable; - ftbl->cmdstream_issueibcmds = kgsl_ringbuffer_issueibcmds; - ftbl->context_create = kgsl_drawctxt_create; - ftbl->context_destroy = kgsl_drawctxt_destroy; - - return (GSL_SUCCESS); -} - -#endif - diff --git a/drivers/mxc/amd-gpu/common/pfp_microcode_nrt.inl b/drivers/mxc/amd-gpu/common/pfp_microcode_nrt.inl deleted file mode 100644 index dfe61295e9e..00000000000 --- a/drivers/mxc/amd-gpu/common/pfp_microcode_nrt.inl +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright (c) 2008-2010, QUALCOMM Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of QUALCOMM Incorporated nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef PFP_MICROCODE_NRT_H -#define PFP_MICROCODE_NRT_H - -#define PFP_MICROCODE_VERSION 308308 - -#define PFP_MICROCODE_SIZE_NRT 288 - -uint32 aPFP_Microcode_nrt[PFP_MICROCODE_SIZE_NRT]={ -0xc60400, -0x7e424b, -0xa00000, -0x7e828b, -0x800001, -0xc60400, -0xcc4003, -0x800000, -0xd60003, -0x800000, -0xc62c00, -0xc80c35, -0x98c000, -0xc80c35, -0x880000, -0xc80c1d, -0x84000b, -0xc60800, -0x98c007, -0xc61000, -0x978003, -0xcc4003, -0xd60004, -0x800000, -0xcd0003, -0x9783e8, -0xc60400, -0x800000, -0xc60400, -0x84000b, -0xc60800, -0x98c00c, -0xc61000, -0xcc4003, -0xc61400, -0xc61800, -0x7d6d40, -0xcd401e, -0x978003, -0xcd801e, -0xd60004, -0x800000, -0xcd0003, -0x800000, -0xd6001f, -0x84000b, -0xc60800, -0x98c007, -0xc60c00, -0xcc4003, -0xcc8003, -0xccc003, -0x800000, -0xd60003, -0x800000, -0xd6001f, -0xc60800, -0x348c08, -0x98c006, -0xc80c1e, -0x98c000, -0xc80c1e, -0x800041, -0xcc8007, -0xcc8008, -0xcc4003, -0x800000, -0xcc8003, -0xc60400, -0x1a9c07, -0xca8821, -0x95c3b9, -0xc8102c, -0x98800a, -0x329418, -0x9a4004, -0xcc6810, -0x042401, -0xd00143, -0xd00162, -0xcd0002, -0x7d514c, -0xcd4003, -0x9b8007, -0x06a801, -0x964003, -0xc28000, -0xcf4003, -0x800001, -0xc60400, -0x800045, -0xc60400, -0x800001, -0xc60400, -0xc60800, -0xc60c00, -0xc8102d, -0x349402, -0x99000b, -0xc8182e, -0xcd4002, -0xcd8002, -0xd001e3, -0xd001c3, -0xccc003, -0xcc801c, -0xcd801d, -0x800001, -0xc60400, -0xd00203, -0x800000, -0xd001c3, -0xc8081f, -0xc60c00, -0xc80c20, -0x988000, -0xc8081f, -0xcc4003, -0xccc003, -0xd60003, -0xccc022, -0xcc001f, -0x800000, -0xcc001f, -0xc81c2f, -0xc60400, -0xc60800, -0xc60c00, -0xc81030, -0x99c000, -0xc81c2f, -0xcc8021, -0xcc4020, -0x990011, -0xc107ff, -0xd00223, -0xd00243, -0x345402, -0x7cb18b, -0x7d95cc, -0xcdc002, -0xccc002, -0xd00263, -0x978005, -0xccc003, -0xc60800, -0x80008a, -0xc60c00, -0x800000, -0xd00283, -0x97836b, -0xc60400, -0xd6001f, -0x800001, -0xc60400, -0xd2000d, -0xcc000d, -0x800000, -0xcc000d, -0xc60800, -0xc60c00, -0xca1433, -0xd022a0, -0xcce000, -0x99435c, -0xcce005, -0x800000, -0x062001, -0xc60800, -0xc60c00, -0xd202c3, -0xcc8003, -0xccc003, -0xcce027, -0x800000, -0x062001, -0xca0831, -0x9883ff, -0xca0831, -0xd6001f, -0x800001, -0xc60400, -0x0a2001, -0x800001, -0xc60400, -0xd20009, -0xd2000a, -0xcc001f, -0x800000, -0xcc001f, -0xd2000b, -0xd2000c, -0xcc001f, -0x800000, -0xcc001f, -0xcc0023, -0xcc4003, -0xce0003, -0x800000, -0xd60003, -0xd00303, -0xcc0024, -0xcc4003, -0x800000, -0xd60003, -0xd00323, -0xcc0025, -0xcc4003, -0x800000, -0xd60003, -0xd00343, -0xcc0026, -0xcc4003, -0x800000, -0xd60003, -0x800000, -0xd6001f, -0x280401, -0xd20001, -0xcc4001, -0xcc4006, -0x8400e7, -0xc40802, -0xc40c02, -0xcc402b, -0x98831f, -0xc63800, -0x8400e7, -0xcf802b, -0x800000, -0xd6001f, -0xcc001f, -0x880000, -0xcc001f, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x000000, -0x0100c8, -0x0200cd, -0x0300d2, -0x050004, -0x1000d7, -0x1700b6, -0x220010, -0x230038, -0x250044, -0x27005e, -0x2d0070, -0x2e007c, -0x4b0009, -0x34001d, -0x36002d, -0x3700a8, -0x3b009b, -0x3f009f, -0x4400d9, -0x4800c3, -0x5000b9, -0x5100be, -0x5500c9, -0x5600ce, -0x5700d3, -0x5d00b0, -0x000006, -0x000006, -0x000006, -0x000006, -0x000006, -0x000006, -}; - -#endif diff --git a/drivers/mxc/amd-gpu/common/pm4_microcode.inl b/drivers/mxc/amd-gpu/common/pm4_microcode.inl deleted file mode 100644 index 03f6f4cd35e..00000000000 --- a/drivers/mxc/amd-gpu/common/pm4_microcode.inl +++ /dev/null @@ -1,815 +0,0 @@ -/* Copyright (c) 2008-2010, QUALCOMM Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of QUALCOMM Incorporated nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef PM4_MICROCODE_H -#define PM4_MICROCODE_H - -#define PM4_MICROCODE_VERSION 300684 - -#define PM4_MICROCODE_SIZE 768 - - -#ifdef _PRIMLIB_INCLUDE -extern uint32 aPM4_Microcode[PM4_MICROCODE_SIZE][3]; -#else -uint32 aPM4_Microcode[PM4_MICROCODE_SIZE][3]={ - { 0x00000000, 0xc0200400, 0x000 }, - { 0x00000000, 0x00a0000a, 0x000 }, - { 0x000001f3, 0x00204411, 0x000 }, - { 0x01000000, 0x00204811, 0x000 }, - { 0x00000000, 0x00400000, 0x004 }, - { 0x0000ffff, 0x00284621, 0x000 }, - { 0x00000000, 0xd9004800, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0x34e00000, 0x000 }, - { 0x00000000, 0x00600000, 0x28c }, - { 0x0000ffff, 0xc0280a20, 0x000 }, - { 0x00000000, 0x00294582, 0x000 }, - { 0x00000000, 0xd9004800, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0x00600000, 0x28c }, - { 0x0000ffff, 0xc0284620, 0x000 }, - { 0x00000000, 0xd9004800, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0x00600000, 0x2a8 }, - { 0x00000000, 0xc0200c00, 0x000 }, - { 0x000021fc, 0x0029462c, 0x000 }, - { 0x00000000, 0x00404803, 0x021 }, - { 0x00000000, 0x00600000, 0x2a8 }, - { 0x00000000, 0xc0200000, 0x000 }, - { 0x00000000, 0xc0200c00, 0x000 }, - { 0x000021fc, 0x0029462c, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00003fff, 0x002f022f, 0x000 }, - { 0x00000000, 0x0ce00000, 0x000 }, - { 0x0000a1fd, 0x0029462c, 0x000 }, - { 0x00000000, 0xd9004800, 0x000 }, - { 0x00000000, 0x00400000, 0x021 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00001000, 0x00281223, 0x000 }, - { 0x00001000, 0x002f0224, 0x000 }, - { 0x00000000, 0x0ce00000, 0x000 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x0000000e, 0x00404811, 0x000 }, - { 0x00000394, 0x00204411, 0x000 }, - { 0x00000001, 0xc0404811, 0x000 }, - { 0x00000000, 0x00600000, 0x2a8 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000008, 0xc0210a20, 0x000 }, - { 0x00000000, 0x14e00000, 0x02d }, - { 0x00000007, 0x00404811, 0x000 }, - { 0x00000008, 0x00404811, 0x000 }, - { 0x0000001f, 0x40280a20, 0x000 }, - { 0x0000001b, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x043 }, - { 0x00000002, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x04a }, - { 0x00000003, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x051 }, - { 0x00000004, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x058 }, - { 0x00000014, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x058 }, - { 0x00000015, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x060 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000000, 0xc0404802, 0x000 }, - { 0x0000001f, 0x40280a20, 0x000 }, - { 0x0000001b, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x043 }, - { 0x00000002, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x04a }, - { 0x00000000, 0x00400000, 0x051 }, - { 0x0000001f, 0xc0210e20, 0x000 }, - { 0x00000612, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000000, 0x00404802, 0x000 }, - { 0x0000001e, 0xc0210e20, 0x000 }, - { 0x00000600, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000000, 0x00404802, 0x000 }, - { 0x0000001e, 0xc0210e20, 0x000 }, - { 0x00000605, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000000, 0x00404802, 0x000 }, - { 0x0000001f, 0x40280a20, 0x000 }, - { 0x0000001f, 0xc0210e20, 0x000 }, - { 0x0000060a, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000000, 0x00404802, 0x000 }, - { 0x0000001f, 0xc0680a20, 0x2a8 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000000, 0x00404802, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00001fff, 0x40280a20, 0x000 }, - { 0x80000000, 0x40280e20, 0x000 }, - { 0x40000000, 0xc0281220, 0x000 }, - { 0x00040000, 0x00694622, 0x2b2 }, - { 0x00000000, 0x00201410, 0x000 }, - { 0x00000000, 0x002f0223, 0x000 }, - { 0x00000000, 0x0ae00000, 0x06d }, - { 0x00000000, 0xc0401800, 0x070 }, - { 0x00001fff, 0xc0281a20, 0x000 }, - { 0x00040000, 0x00694626, 0x2b2 }, - { 0x00000000, 0x00201810, 0x000 }, - { 0x00000000, 0x002f0224, 0x000 }, - { 0x00000000, 0x0ae00000, 0x073 }, - { 0x00000000, 0xc0401c00, 0x076 }, - { 0x00001fff, 0xc0281e20, 0x000 }, - { 0x00040000, 0x00694627, 0x2b2 }, - { 0x00000000, 0x00201c10, 0x000 }, - { 0x00000000, 0x00204402, 0x000 }, - { 0x00000000, 0x002820c5, 0x000 }, - { 0x00000000, 0x004948e8, 0x000 }, - { 0x00000000, 0x00600000, 0x28c }, - { 0x00000010, 0x40210a20, 0x000 }, - { 0x000000ff, 0x00280a22, 0x000 }, - { 0x000007ff, 0x40280e20, 0x000 }, - { 0x00000002, 0x00221e23, 0x000 }, - { 0x00000005, 0xc0211220, 0x000 }, - { 0x00080000, 0x00281224, 0x000 }, - { 0x00000013, 0x00210224, 0x000 }, - { 0x00000000, 0x14c00000, 0x084 }, - { 0xa100ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204811, 0x000 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x088 }, - { 0x00000000, 0x0020162d, 0x000 }, - { 0x00004000, 0x00500e23, 0x097 }, - { 0x00000001, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x08c }, - { 0x00000001, 0x0020162d, 0x000 }, - { 0x00004800, 0x00500e23, 0x097 }, - { 0x00000002, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x090 }, - { 0x00000003, 0x0020162d, 0x000 }, - { 0x00004900, 0x00500e23, 0x097 }, - { 0x00000003, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x094 }, - { 0x00000002, 0x0020162d, 0x000 }, - { 0x00004908, 0x00500e23, 0x097 }, - { 0x00000012, 0x0020162d, 0x000 }, - { 0x00002000, 0x00300e23, 0x000 }, - { 0x00000000, 0x00290d83, 0x000 }, - { 0x9400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x002948e5, 0x000 }, - { 0x00000000, 0x00294483, 0x000 }, - { 0x00000000, 0x40201800, 0x000 }, - { 0x00000000, 0xd9004800, 0x000 }, - { 0x00000013, 0x00210224, 0x000 }, - { 0x00000000, 0x14c00000, 0x000 }, - { 0x9400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x002948e5, 0x000 }, - { 0x9300ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00404806, 0x000 }, - { 0x00000000, 0x00600000, 0x28c }, - { 0x00000000, 0xc0200800, 0x000 }, - { 0x00000000, 0xc0201400, 0x000 }, - { 0x0000001f, 0x00211a25, 0x000 }, - { 0x00000000, 0x14e00000, 0x000 }, - { 0x000007ff, 0x00280e25, 0x000 }, - { 0x00000010, 0x00211225, 0x000 }, - { 0x8300ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x002f0224, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0ae }, - { 0x00000000, 0x00203622, 0x000 }, - { 0x00004000, 0x00504a23, 0x0bd }, - { 0x00000001, 0x002f0224, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0b2 }, - { 0x00000001, 0x00203622, 0x000 }, - { 0x00004800, 0x00504a23, 0x0bd }, - { 0x00000002, 0x002f0224, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0b6 }, - { 0x00000003, 0x00203622, 0x000 }, - { 0x00004900, 0x00504a23, 0x0bd }, - { 0x00000003, 0x002f0224, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0ba }, - { 0x00000002, 0x00203622, 0x000 }, - { 0x00004908, 0x00504a23, 0x0bd }, - { 0x00000012, 0x00203622, 0x000 }, - { 0x00000000, 0x00290d83, 0x000 }, - { 0x00002000, 0x00304a23, 0x000 }, - { 0x8400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0x21000000, 0x000 }, - { 0x00000000, 0x00400000, 0x0a4 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00040578, 0x00604411, 0x2b2 }, - { 0x00000000, 0xc0400000, 0x000 }, - { 0x00000000, 0xc0200c00, 0x000 }, - { 0x00000000, 0xc0201000, 0x000 }, - { 0x00000000, 0xc0201400, 0x000 }, - { 0x00000000, 0xc0201800, 0x000 }, - { 0x00007f00, 0x00280a21, 0x000 }, - { 0x00004500, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x0cd }, - { 0x00000000, 0xc0201c00, 0x000 }, - { 0x00000000, 0x17000000, 0x000 }, - { 0x00000010, 0x00280a23, 0x000 }, - { 0x00000010, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x0d5 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00040000, 0x00694624, 0x2b2 }, - { 0x00000000, 0x00400000, 0x0d6 }, - { 0x00000000, 0x00600000, 0x135 }, - { 0x00000000, 0x002820d0, 0x000 }, - { 0x00000007, 0x00280a23, 0x000 }, - { 0x00000001, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0dd }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x04e00000, 0x0f6 }, - { 0x00000000, 0x00400000, 0x0fd }, - { 0x00000002, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0e2 }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x02e00000, 0x0f6 }, - { 0x00000000, 0x00400000, 0x0fd }, - { 0x00000003, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0e7 }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x0ce00000, 0x0f6 }, - { 0x00000000, 0x00400000, 0x0fd }, - { 0x00000004, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0ec }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0f6 }, - { 0x00000000, 0x00400000, 0x0fd }, - { 0x00000005, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0f1 }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x06e00000, 0x0f6 }, - { 0x00000000, 0x00400000, 0x0fd }, - { 0x00000006, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x0f6 }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x08e00000, 0x0f6 }, - { 0x00000000, 0x00400000, 0x0fd }, - { 0x00007f00, 0x00280a21, 0x000 }, - { 0x00004500, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x000 }, - { 0x00000008, 0x00210a23, 0x000 }, - { 0x00000000, 0x14e00000, 0x11b }, - { 0x00000000, 0xc0204400, 0x000 }, - { 0x00000000, 0xc0404800, 0x000 }, - { 0x00007f00, 0x00280a21, 0x000 }, - { 0x00004500, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x102 }, - { 0x00000000, 0xc0200000, 0x000 }, - { 0x00000000, 0xc0400000, 0x000 }, - { 0x00000000, 0x00404c07, 0x0cd }, - { 0x00000000, 0xc0201000, 0x000 }, - { 0x00000000, 0xc0201400, 0x000 }, - { 0x00000000, 0xc0201800, 0x000 }, - { 0x00000000, 0xc0201c00, 0x000 }, - { 0x00000000, 0x17000000, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00040000, 0x00694624, 0x2b2 }, - { 0x00000000, 0x002820d0, 0x000 }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x0ce00000, 0x000 }, - { 0x00000000, 0x00404c07, 0x107 }, - { 0x00000000, 0xc0201000, 0x000 }, - { 0x00000000, 0xc0201400, 0x000 }, - { 0x00000000, 0xc0201800, 0x000 }, - { 0x00000000, 0xc0201c00, 0x000 }, - { 0x00000000, 0x17000000, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00040000, 0x00694624, 0x2b2 }, - { 0x00000000, 0x002820d0, 0x000 }, - { 0x00000000, 0x002f00a8, 0x000 }, - { 0x00000000, 0x06e00000, 0x000 }, - { 0x00000000, 0x00404c07, 0x113 }, - { 0x0000060d, 0x00204411, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x0000860e, 0x00204411, 0x000 }, - { 0x00000000, 0xd9004800, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000009, 0x00204811, 0x000 }, - { 0x0000060d, 0x00204411, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0x00404810, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00000000, 0xc0200800, 0x000 }, - { 0x00007fff, 0x00281a22, 0x000 }, - { 0x00040000, 0x00694626, 0x2b2 }, - { 0x00000000, 0x00200c10, 0x000 }, - { 0x00000000, 0xc0201000, 0x000 }, - { 0x80000000, 0x00281a22, 0x000 }, - { 0x00000000, 0x002f0226, 0x000 }, - { 0x00000000, 0x0ce00000, 0x132 }, - { 0x00000000, 0x00600000, 0x135 }, - { 0x00000000, 0x00201c10, 0x000 }, - { 0x00000000, 0x00300c67, 0x000 }, - { 0x0000060d, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000000, 0x00404803, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204811, 0x000 }, - { 0xa400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204811, 0x000 }, - { 0x000001ea, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000000, 0x1ac00000, 0x13b }, - { 0x9e00ffff, 0x00204411, 0x000 }, - { 0xdeadbeef, 0x00204811, 0x000 }, - { 0x00000000, 0x1ae00000, 0x13e }, - { 0xa400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x0080480b, 0x000 }, - { 0x000001f3, 0x00204411, 0x000 }, - { 0xe0000000, 0xc0484a20, 0x000 }, - { 0x00000000, 0xd9000000, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0xc0200c00, 0x000 }, - { 0x8c00ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000fff, 0x00281223, 0x000 }, - { 0x0000000f, 0x00203624, 0x000 }, - { 0x00000003, 0x00381224, 0x000 }, - { 0x00005000, 0x00301224, 0x000 }, - { 0x0000000e, 0x00203624, 0x000 }, - { 0x8700ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000001, 0x00331224, 0x000 }, - { 0x8600ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x0000001d, 0x00211223, 0x000 }, - { 0x00000020, 0x00222091, 0x000 }, - { 0x00000003, 0x00381228, 0x000 }, - { 0x8800ffff, 0x00204411, 0x000 }, - { 0x00004fff, 0x00304a24, 0x000 }, - { 0x00000010, 0x00211623, 0x000 }, - { 0x00000fff, 0x00281625, 0x000 }, - { 0x00000fff, 0x00281a23, 0x000 }, - { 0x00000000, 0x00331ca6, 0x000 }, - { 0x8f00ffff, 0x00204411, 0x000 }, - { 0x00000003, 0x00384a27, 0x000 }, - { 0x00000010, 0x00211223, 0x000 }, - { 0x00000fff, 0x00281224, 0x000 }, - { 0x0000000d, 0x00203624, 0x000 }, - { 0x8b00ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000003, 0x00381224, 0x000 }, - { 0x00005000, 0x00301224, 0x000 }, - { 0x0000000c, 0x00203624, 0x000 }, - { 0x8500ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000000, 0x00331cc8, 0x000 }, - { 0x9000ffff, 0x00204411, 0x000 }, - { 0x00000003, 0x00384a27, 0x000 }, - { 0x00300000, 0x00493a2e, 0x000 }, - { 0x00000000, 0x00202c11, 0x000 }, - { 0x00000001, 0x00303e2f, 0x000 }, - { 0x00000000, 0xc0200800, 0x000 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x172 }, - { 0x00000000, 0xd9000000, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0x00600000, 0x28c }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000002, 0x00204811, 0x000 }, - { 0x00000000, 0x002f0230, 0x000 }, - { 0x00000000, 0x0ae00000, 0x175 }, - { 0x00000000, 0xc0200800, 0x000 }, - { 0x00000009, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x17d }, - { 0x00000000, 0x00600000, 0x2af }, - { 0x00000000, 0x00200c11, 0x000 }, - { 0x00000016, 0x00203623, 0x000 }, - { 0x00000000, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x180 }, - { 0x00000000, 0xc0200000, 0x000 }, - { 0x00000001, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x183 }, - { 0x00000000, 0xc0200000, 0x000 }, - { 0x00000002, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x18d }, - { 0x00000004, 0xc0203620, 0x000 }, - { 0x00000005, 0xc0203620, 0x000 }, - { 0x00000006, 0xc0203620, 0x000 }, - { 0x00000007, 0xc0203620, 0x000 }, - { 0x00000008, 0xc0203620, 0x000 }, - { 0x00000009, 0xc0203620, 0x000 }, - { 0x0000000a, 0xc0203620, 0x000 }, - { 0x0000000b, 0xc0203620, 0x000 }, - { 0x00000003, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x1b5 }, - { 0x00000000, 0xc0200c00, 0x000 }, - { 0x8c00ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000fff, 0x00281223, 0x000 }, - { 0x0000000f, 0x00203624, 0x000 }, - { 0x00000003, 0x00381224, 0x000 }, - { 0x00005000, 0x00301224, 0x000 }, - { 0x0000000e, 0x00203624, 0x000 }, - { 0x8700ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000001, 0x00331224, 0x000 }, - { 0x8600ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x0000001d, 0x00211223, 0x000 }, - { 0x00000020, 0x00222091, 0x000 }, - { 0x00000003, 0x00381228, 0x000 }, - { 0x8800ffff, 0x00204411, 0x000 }, - { 0x00004fff, 0x00304a24, 0x000 }, - { 0x00000010, 0x00211623, 0x000 }, - { 0x00000fff, 0x00281625, 0x000 }, - { 0x00000fff, 0x00281a23, 0x000 }, - { 0x00000000, 0x00331ca6, 0x000 }, - { 0x8f00ffff, 0x00204411, 0x000 }, - { 0x00000003, 0x00384a27, 0x000 }, - { 0x00000010, 0x00211223, 0x000 }, - { 0x00000fff, 0x00281224, 0x000 }, - { 0x0000000d, 0x00203624, 0x000 }, - { 0x8b00ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000003, 0x00381224, 0x000 }, - { 0x00005000, 0x00301224, 0x000 }, - { 0x0000000c, 0x00203624, 0x000 }, - { 0x8500ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204804, 0x000 }, - { 0x00000000, 0x00331cc8, 0x000 }, - { 0x9000ffff, 0x00204411, 0x000 }, - { 0x00000003, 0x00384a27, 0x000 }, - { 0x00300000, 0x00293a2e, 0x000 }, - { 0x00000004, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x1bd }, - { 0xa300ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x40204800, 0x000 }, - { 0x0000000a, 0xc0220e20, 0x000 }, - { 0x00000011, 0x00203623, 0x000 }, - { 0x000021f4, 0x00204411, 0x000 }, - { 0x0000000a, 0x00614a2c, 0x2af }, - { 0x00000005, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x1c0 }, - { 0x00000000, 0xc0200000, 0x000 }, - { 0x00000006, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x1c6 }, - { 0x9c00ffff, 0x00204411, 0x000 }, - { 0x0000001f, 0x40214a20, 0x000 }, - { 0x9600ffff, 0x00204411, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000007, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x1d0 }, - { 0x3fffffff, 0x00283a2e, 0x000 }, - { 0xc0000000, 0x40280e20, 0x000 }, - { 0x00000000, 0x0029386e, 0x000 }, - { 0x18000000, 0x40280e20, 0x000 }, - { 0x00000016, 0x00203623, 0x000 }, - { 0xa400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0xc0202c00, 0x000 }, - { 0x00000000, 0x0020480b, 0x000 }, - { 0x00000008, 0x00210222, 0x000 }, - { 0x00000000, 0x14c00000, 0x1dc }, - { 0x00000000, 0xc0200c00, 0x000 }, - { 0x00000013, 0x00203623, 0x000 }, - { 0x00000015, 0x00203623, 0x000 }, - { 0x00000002, 0x40221220, 0x000 }, - { 0x00000000, 0x00301083, 0x000 }, - { 0x00000014, 0x00203624, 0x000 }, - { 0x00000003, 0xc0210e20, 0x000 }, - { 0x10000000, 0x00280e23, 0x000 }, - { 0xefffffff, 0x00283a2e, 0x000 }, - { 0x00000000, 0x0029386e, 0x000 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0x00600000, 0x28c }, - { 0x00000000, 0xc0200800, 0x000 }, - { 0x0000001f, 0x00210e22, 0x000 }, - { 0x00000000, 0x14e00000, 0x000 }, - { 0x000003ff, 0x00280e22, 0x000 }, - { 0x00000018, 0x00211222, 0x000 }, - { 0x00000004, 0x00301224, 0x000 }, - { 0x00000000, 0x0020108d, 0x000 }, - { 0x00002000, 0x00291224, 0x000 }, - { 0x8300ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00294984, 0x000 }, - { 0x8400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0x21000000, 0x000 }, - { 0x00000000, 0x00400000, 0x1de }, - { 0x8200ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00000000, 0xc0200800, 0x000 }, - { 0x00003fff, 0x40280e20, 0x000 }, - { 0x00000010, 0xc0211220, 0x000 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x1fb }, - { 0x00000000, 0x2ae00000, 0x205 }, - { 0x20000080, 0x00281e2e, 0x000 }, - { 0x00000080, 0x002f0227, 0x000 }, - { 0x00000000, 0x0ce00000, 0x1f8 }, - { 0x00000000, 0x00401c0c, 0x1f9 }, - { 0x00000010, 0x00201e2d, 0x000 }, - { 0x000021f9, 0x00294627, 0x000 }, - { 0x00000000, 0x00404811, 0x205 }, - { 0x00000001, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x23a }, - { 0x00000000, 0x28e00000, 0x205 }, - { 0x00800080, 0x00281e2e, 0x000 }, - { 0x00000080, 0x002f0227, 0x000 }, - { 0x00000000, 0x0ce00000, 0x202 }, - { 0x00000000, 0x00401c0c, 0x203 }, - { 0x00000010, 0x00201e2d, 0x000 }, - { 0x000021f9, 0x00294627, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x20c }, - { 0x00000003, 0x00204811, 0x000 }, - { 0x0000000c, 0x0020162d, 0x000 }, - { 0x0000000d, 0x00201a2d, 0x000 }, - { 0xffdfffff, 0x00483a2e, 0x210 }, - { 0x00000004, 0x00204811, 0x000 }, - { 0x0000000e, 0x0020162d, 0x000 }, - { 0x0000000f, 0x00201a2d, 0x000 }, - { 0xffefffff, 0x00283a2e, 0x000 }, - { 0x00000000, 0x00201c10, 0x000 }, - { 0x00000000, 0x002f0067, 0x000 }, - { 0x00000000, 0x04e00000, 0x205 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000006, 0x00204811, 0x000 }, - { 0x8300ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204805, 0x000 }, - { 0x8900ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204806, 0x000 }, - { 0x8400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0x21000000, 0x000 }, - { 0x00000000, 0x00601010, 0x28c }, - { 0x0000000c, 0x00221e24, 0x000 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x22d }, - { 0x20000000, 0x00293a2e, 0x000 }, - { 0x000021f7, 0x0029462c, 0x000 }, - { 0x00000000, 0x002948c7, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000005, 0x00204811, 0x000 }, - { 0x0000000c, 0x00203630, 0x000 }, - { 0x00000007, 0x00204811, 0x000 }, - { 0x0000000d, 0x00203630, 0x000 }, - { 0x9100ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0x23000000, 0x000 }, - { 0x8d00ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00404803, 0x240 }, - { 0x00800000, 0x00293a2e, 0x000 }, - { 0x000021f6, 0x0029462c, 0x000 }, - { 0x00000000, 0x002948c7, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000005, 0x00204811, 0x000 }, - { 0x0000000e, 0x00203630, 0x000 }, - { 0x00000007, 0x00204811, 0x000 }, - { 0x0000000f, 0x00203630, 0x000 }, - { 0x9200ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0x25000000, 0x000 }, - { 0x8e00ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00404803, 0x240 }, - { 0x8300ffff, 0x00204411, 0x000 }, - { 0x00000003, 0x00381224, 0x000 }, - { 0x00005000, 0x00304a24, 0x000 }, - { 0x8400ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x00000000, 0x21000000, 0x000 }, - { 0x8200ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00404811, 0x000 }, - { 0x00000003, 0x40280a20, 0x000 }, - { 0xffffffe0, 0xc0280e20, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x00000001, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x24a }, - { 0x000021f6, 0x0029122c, 0x000 }, - { 0x00040000, 0x00494624, 0x24c }, - { 0x000021f7, 0x0029122c, 0x000 }, - { 0x00040000, 0x00294624, 0x000 }, - { 0x00000000, 0x00600000, 0x2b2 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x252 }, - { 0x00000001, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ce00000, 0x252 }, - { 0x00000000, 0x00481630, 0x258 }, - { 0x00000fff, 0x00281630, 0x000 }, - { 0x0000000c, 0x00211a30, 0x000 }, - { 0x00000fff, 0x00281a26, 0x000 }, - { 0x00000000, 0x002f0226, 0x000 }, - { 0x00000000, 0x0ae00000, 0x258 }, - { 0x00000000, 0xc0400000, 0x000 }, - { 0x00040d02, 0x00604411, 0x2b2 }, - { 0x00000000, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x25d }, - { 0x00000010, 0x00211e30, 0x000 }, - { 0x00000fff, 0x00482630, 0x267 }, - { 0x00000001, 0x002f0222, 0x000 }, - { 0x00000000, 0x0ae00000, 0x261 }, - { 0x00000fff, 0x00281e30, 0x000 }, - { 0x00000200, 0x00402411, 0x267 }, - { 0x00000000, 0x00281e30, 0x000 }, - { 0x00000010, 0x00212630, 0x000 }, - { 0x00000010, 0x00211a30, 0x000 }, - { 0x00000000, 0x002f0226, 0x000 }, - { 0x00000000, 0x0ae00000, 0x258 }, - { 0x00000000, 0xc0400000, 0x000 }, - { 0x00000003, 0x00381625, 0x000 }, - { 0x00000003, 0x00381a26, 0x000 }, - { 0x00000003, 0x00381e27, 0x000 }, - { 0x00000003, 0x00382629, 0x000 }, - { 0x00005000, 0x00302629, 0x000 }, - { 0x0000060d, 0x00204411, 0x000 }, - { 0x00000000, 0xc0204800, 0x000 }, - { 0x00000000, 0x00204806, 0x000 }, - { 0x00005000, 0x00302225, 0x000 }, - { 0x00040000, 0x00694628, 0x2b2 }, - { 0x00000001, 0x00302228, 0x000 }, - { 0x00000000, 0x00202810, 0x000 }, - { 0x00040000, 0x00694628, 0x2b2 }, - { 0x00000001, 0x00302228, 0x000 }, - { 0x00000000, 0x00200810, 0x000 }, - { 0x00040000, 0x00694628, 0x2b2 }, - { 0x00000001, 0x00302228, 0x000 }, - { 0x00000000, 0x00201410, 0x000 }, - { 0x0000060d, 0x00204411, 0x000 }, - { 0x00000000, 0x00204803, 0x000 }, - { 0x0000860e, 0x00204411, 0x000 }, - { 0x00000000, 0x0020480a, 0x000 }, - { 0x00000000, 0x00204802, 0x000 }, - { 0x00000000, 0x00204805, 0x000 }, - { 0x00000000, 0x002f0128, 0x000 }, - { 0x00000000, 0x0ae00000, 0x282 }, - { 0x00005000, 0x00302227, 0x000 }, - { 0x0000000c, 0x00300e23, 0x000 }, - { 0x00000003, 0x00331a26, 0x000 }, - { 0x00000000, 0x002f0226, 0x000 }, - { 0x00000000, 0x0ae00000, 0x270 }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x000001f3, 0x00204411, 0x000 }, - { 0x04000000, 0x00204811, 0x000 }, - { 0x00000000, 0x00400000, 0x289 }, - { 0x00000000, 0xc0600000, 0x28c }, - { 0x00000000, 0x00400000, 0x000 }, - { 0x00000000, 0x0ec00000, 0x28e }, - { 0x00000000, 0x00800000, 0x000 }, - { 0x000021f9, 0x0029462c, 0x000 }, - { 0x00000005, 0x00204811, 0x000 }, - { 0x00000000, 0x0020280c, 0x000 }, - { 0x00000011, 0x0020262d, 0x000 }, - { 0x00000000, 0x002f012c, 0x000 }, - { 0x00000000, 0x0ae00000, 0x295 }, - { 0x00000000, 0x00403011, 0x296 }, - { 0x00000400, 0x0030322c, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000002, 0x00204811, 0x000 }, - { 0x0000000a, 0x0021262c, 0x000 }, - { 0x00000000, 0x00210130, 0x000 }, - { 0x00000000, 0x14c00000, 0x29d }, - { 0xa500ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00404811, 0x299 }, - { 0xa500ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204811, 0x000 }, - { 0x000021f4, 0x0029462c, 0x000 }, - { 0x0000000a, 0x00214a2a, 0x000 }, - { 0xa200ffff, 0x00204411, 0x000 }, - { 0x00000001, 0x00204811, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000002, 0x00204811, 0x000 }, - { 0x00000000, 0x00210130, 0x000 }, - { 0xdf7fffff, 0x00283a2e, 0x000 }, - { 0x00000010, 0x0080362a, 0x000 }, - { 0x9700ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x0020480c, 0x000 }, - { 0xa200ffff, 0x00204411, 0x000 }, - { 0x00000000, 0x00204811, 0x000 }, - { 0x8100ffff, 0x00204411, 0x000 }, - { 0x00000002, 0x00204811, 0x000 }, - { 0x00000000, 0x00810130, 0x000 }, - { 0x00000000, 0x00203011, 0x000 }, - { 0x00000010, 0x0080362c, 0x000 }, - { 0x00000000, 0xc0400000, 0x000 }, - { 0x00000000, 0x1ac00000, 0x2b2 }, - { 0x9f00ffff, 0x00204411, 0x000 }, - { 0xdeadbeef, 0x00204811, 0x000 }, - { 0x00000000, 0x1ae00000, 0x2b5 }, - { 0x00000000, 0x00800000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00000000, 0x00000000, 0x000 }, - { 0x00020143, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x01dd0002, 0x000 }, - { 0x006301ee, 0x00280012, 0x000 }, - { 0x00020002, 0x00020026, 0x000 }, - { 0x00020002, 0x01ec0002, 0x000 }, - { 0x00790242, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00200012, 0x00020016, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x011b00c5, 0x00020125, 0x000 }, - { 0x00020141, 0x00020002, 0x000 }, - { 0x00c50002, 0x0143002e, 0x000 }, - { 0x00a2016b, 0x00020145, 0x000 }, - { 0x00020002, 0x01200002, 0x000 }, - { 0x00020002, 0x010f0103, 0x000 }, - { 0x00090002, 0x000e000e, 0x000 }, - { 0x0058003d, 0x00600002, 0x000 }, - { 0x000200c1, 0x0002028a, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x00020002, 0x00020002, 0x000 }, - { 0x000502b1, 0x00020008, 0x000 }, -}; - -#endif -static const uint32 ME_JUMP_TABLE_START = 740; -static const uint32 ME_JUMP_TABLE_END = 768; - -#endif diff --git a/drivers/mxc/amd-gpu/include/gsl_context.h b/drivers/mxc/amd-gpu/include/gsl_context.h deleted file mode 100644 index 6e83bdb3403..00000000000 --- a/drivers/mxc/amd-gpu/include/gsl_context.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Advanced Micro Devices nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GSL_CONTEXT_H -#define __GSL_CONTEXT_H - - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// types -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// - -#endif // __GSL_CONTEXT_H diff --git a/drivers/mxc/amd-gpu/os/include/os_types.h b/drivers/mxc/amd-gpu/os/include/os_types.h deleted file mode 100644 index e7ecd90f895..00000000000 --- a/drivers/mxc/amd-gpu/os/include/os_types.h +++ /dev/null @@ -1,138 +0,0 @@ - /* Copyright (c) 2008-2010, QUALCOMM Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of QUALCOMM Incorporated nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __OSTYPES_H -#define __OSTYPES_H - -////////////////////////////////////////////////////////////////////////////// -// status -////////////////////////////////////////////////////////////////////////////// -#define OS_SUCCESS 0 -#define OS_FAILURE -1 -#define OS_FAILURE_SYSTEMERROR -2 -#define OS_FAILURE_DEVICEERROR -3 -#define OS_FAILURE_OUTOFMEM -4 -#define OS_FAILURE_BADPARAM -5 -#define OS_FAILURE_NOTSUPPORTED -6 -#define OS_FAILURE_NOMOREAVAILABLE -7 -#define OS_FAILURE_NOTINITIALIZED -8 -#define OS_FAILURE_ALREADYINITIALIZED -9 -#define OS_FAILURE_TIMEOUT -10 - - -////////////////////////////////////////////////////////////////////////////// -// inline -////////////////////////////////////////////////////////////////////////////// -#ifndef OSINLINE -#ifdef _LINUX -#define OSINLINE static __inline -#else -#define OSINLINE __inline -#endif -#endif // OSINLINE - - -////////////////////////////////////////////////////////////////////////////// -// values -////////////////////////////////////////////////////////////////////////////// -#define OS_INFINITE 0xFFFFFFFF -#define OS_TLS_OUTOFINDEXES 0xFFFFFFFF -#define OS_TRUE 1 -#define OS_FALSE 0 - -#ifndef NULL -#define NULL (void *)0x0 -#endif // !NULL - -////////////////////////////////////////////////////////////////////////////// -// types -////////////////////////////////////////////////////////////////////////////// - - -// -// oshandle_t -// -typedef void * oshandle_t; -#define OS_HANDLE_NULL (oshandle_t)0x0 - -// -// os_sysinfo_t -// -typedef struct _os_sysinfo_t { - int cpu_mhz; - int cpu_type; - int cpu_version; - int os_type; - int os_version; - int sysmem_size; - int page_size; - int max_path; - int tls_slots; - int endianness; // 0 == little_endian, 1 == big_endian -} os_sysinfo_t; - - -// -// os_stats_t -// -#ifdef _LINUX -typedef long long __int64; -typedef unsigned long long __uint64; -#else -typedef unsigned __int64 __uint64; -#endif - -typedef struct _os_stats_t { - __int64 heap_allocs; - __int64 heap_frees; - __int64 heap_alloc_bytes; - __int64 shared_heap_allocs; - __int64 shared_heap_frees; - __int64 shared_heap_alloc_bytes; - __int64 objects_alloc; - __int64 objects_free; -} os_stats_t; - - -typedef enum { - OS_PROTECTION_GLOBAL, // inter process - OS_PROTECTION_LOCAL, // process local - OS_PROTECTION_NONE, // none -} os_protection_t; - -typedef struct _os_cputimer_t { - int refcount; // Reference count - int enabled; // Counter is enabled - int size; // Number of counters - __int64 start_time; // start time in cpu ticks - __int64 end_time; // end time in cpu ticks - __int64 timer_frequency; // cpu ticks per second - __int64 *counter_array; // number of ticks for each counter -} os_cputimer_t; - -#endif // __OSTYPES_H diff --git a/drivers/mxc/amd-gpu/os/kernel/include/kos_libapi.h b/drivers/mxc/amd-gpu/os/kernel/include/kos_libapi.h deleted file mode 100644 index a02c396c22a..00000000000 --- a/drivers/mxc/amd-gpu/os/kernel/include/kos_libapi.h +++ /dev/null @@ -1,813 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Advanced Micro Devices nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __KOSAPI_H -#define __KOSAPI_H - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#include "os_types.h" - - -////////////////////////////////////////////////////////////////////////////// -// entrypoint abstraction -////////////////////////////////////////////////////////////////////////////// - - -#if defined(_WIN32) && !defined (_WIN32_WCE) && !defined(__SYMBIAN32__) -#define KOS_DLLEXPORT __declspec(dllexport) -#define KOS_DLLIMPORT __declspec(dllimport) -#elif defined(_WIN32) && defined (_WIN32_WCE) -#define KOS_DLLEXPORT __declspec(dllexport) -#define KOS_DLLIMPORT -#else -#define KOS_DLLEXPORT extern -#define KOS_DLLIMPORT -#endif // _WIN32 - - -////////////////////////////////////////////////////////////////////////////// -// KOS lib entrypoints -////////////////////////////////////////////////////////////////////////////// -#ifdef __KOSLIB_EXPORTS -#define KOS_API KOS_DLLEXPORT -#else -#define KOS_API KOS_DLLIMPORT -#endif // __KOSLIB_EXPORTS - -////////////////////////////////////////////////////////////////////////////// -// assert API -////////////////////////////////////////////////////////////////////////////// -KOS_API void kos_assert_hook(const char* file, int line, int expression); - -#if defined(DEBUG) || defined(DBG) || defined (_DBG) || defined (_DEBUG) - -#if defined(_WIN32) && !defined(__SYMBIAN32__) || defined(_WIN32_WCE) -#include -#define KOS_ASSERT(expression) assert(expression) -#elif defined(_BREW) -#include -#define KOS_ASSERT(expression) kos_assert_hook(__FILE__, __LINE__, expression) -#elif defined(__SYMBIAN32__) -//#include -//#define KOS_ASSERT(expression) assert(expression) -#define KOS_ASSERT(expression) /**/ -#elif defined(__ARM__) -#define KOS_ASSERT(expression) -#elif defined(_LINUX) -#define KOS_ASSERT(expression) //kos_assert_hook(__FILE__, __LINE__, (int)(expression)) -#endif - -#else - -#define KOS_ASSERT(expression) - -#endif // DEBUG || DBG || _DBG - -#if defined(_WIN32) && defined(_DEBUG) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) -#pragma warning ( push, 3 ) -#include -#pragma warning (pop) -#define KOS_MALLOC_DBG(size) _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__) -#else -#define KOS_MALLOC_DBG(size) kos_malloc(int size) -#endif // _WIN32 _DEBUG - -#define kos_assert(expression) KOS_ASSERT(expression) -#define kos_malloc_dbg(size) KOS_MALLOC_DBG(size) - -#ifdef UNDER_CE -#define KOS_PAGE_SIZE 0x1000 -#endif - -typedef enum mutexIndex mutexIndex_t; -////////////////////////////////////////////////////////////////////////////// -// Interprocess shared memory initialization -////////////////////////////////////////////////////////////////////////////// -// TODO: still valid? -KOS_API int kos_sharedmem_create(unsigned int map_addr, unsigned int size); -KOS_API int kos_sharedmem_destroy(void); - -////////////////////////////////////////////////////////////////////////////// -// heap API (per process) -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Allocate memory for a kernel side process. - * - * - * \param int size Amount of bytes to be allocated. - * \return Pointer to the reserved memory, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_malloc(int size); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Allocate memory for a kernel side process. Clears the reserved memory. - * - * - * \param int num Number of elements to allocate. - * \param int size Element size in bytes. - * \return Pointer to the reserved memory, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_calloc(int num, int size); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Re-allocate an existing memory for a kernel side process. - * Contents of the old block will be copied to the new block - * taking the sizes of both blocks into account. - * - * - * \param void* memblock Pointer to the old memory block. - * \param int size Size of the new block in bytes. - * \return Pointer to the new memory block, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_realloc(void* memblock, int size); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Free a reserved memory block from the kernel side process. - * - * - * \param void* memblock Pointer to the memory block. - *//*-------------------------------------------------------------------*/ -KOS_API void kos_free(void* memblock); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Enable automatic memory leak checking performed at program exit. - * - * - *//*-------------------------------------------------------------------*/ -KOS_API void kos_enable_memoryleakcheck(void); - - -////////////////////////////////////////////////////////////////////////////// -// shared heap API (cross process) -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Allocate memory that can be shared between user and kernel - * side processes. - * - * - * \param int size Amount of bytes to be allocated. - * \return Pointer to the new memory block, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_shared_malloc(int size); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Allocate memory that can be shared between user and kernel - * side processes. Clears the reserved memory. - * - * - * \param int num Number of elements to allocate. - * \param int size Element size in bytes. - * \return Pointer to the reserved memory, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_shared_calloc(int num, int size); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Re-allocate an existing user/kernel shared memory block. - * Contents of the old block will be copied to the new block - * taking the sizes of both blocks into account. - * - * - * \param void* ptr Pointer to the old memory block. - * \param int size Size of the new block in bytes. - * \return Pointer to the new memory block, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_shared_realloc(void* ptr, int size); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Free a reserved shared memory block. - * - * - * \param void* ptr Pointer to the memory block. - *//*-------------------------------------------------------------------*/ - KOS_API void kos_shared_free(void* ptr); - - -////////////////////////////////////////////////////////////////////////////// -// memory API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Copies the values of num bytes from the location pointed by src - * directly to the memory block pointed by dst. - * - * - * \param void* dst Pointer to the destination memory block. - * \param void* src Pointer to the source memory block. - * \param void* count Amount of bytes to copy. - * \return Returns the dst pointer, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_memcpy(void* dst, const void* src, int count); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Fills the destination memory block with the given value. - * - * - * \param void* dst Pointer to the destination memory block. - * \param int value Value to be written to each destination address. - * \param void* count Number of bytes to be set to the value. - * \return Returns the dst pointer, NULL if any error. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_memset(void* dst, int value, int count); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Compares two memory blocks. - * - * - * \param void* dst Pointer to the destination memory block. - * \param void* src Pointer to the source memory block. - * \param void* count Number of bytes to compare. - * \return Zero if identical, >0 if first nonmatching byte is greater in dst. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_memcmp(void* dst, void* src, int count); - - -////////////////////////////////////////////////////////////////////////////// -// physical memory API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Allocates a physically contiguous memory block. - * - * - * \param void** virt_addr Pointer where to store the virtual address of the reserved block. - * \param void** phys_addr Pointer where to store the physical address of the reserved block. - * \param int pages Number of pages to reserve (default page size = 4096 bytes). - * \return Zero if ok, othervise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_alloc_physical(void** virt_addr, void** phys_addr, int pages); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Free a physically contiguous allocated memory block. - * - * - * \param void* virt_addr Virtual address of the memory block. - * \param int pages Number of pages. - * \return Zero if ok, othervise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_free_physical(void* virt_addr, int pages); - -KOS_API void kos_memoryfence(void); - - -////////////////////////////////////////////////////////////////////////////// -// string API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Perform a string copy. - * - * - * \param void* strdestination Pointer to destination memory. - * \param void* strsource Pointer to the source string. - * \return Zero if ok, othervise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API char* kos_strcpy(char* strdestination, const char* strsource); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Perform a string copy with given length. - * - * - * \param void* destination Pointer to destination memory. - * \param void* source Pointer to the source string. - * \param int length Amount of bytes to copy. - * \return Returns the destination pointer. - *//*-------------------------------------------------------------------*/ -KOS_API char* kos_strncpy(char* destination, const char* source, int length); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Append source string to destination string. - * - * - * \param void* strdestination Pointer to destination string. - * \param void* strsource Pointer to the source string. - * \return Returns the destination pointer. - *//*-------------------------------------------------------------------*/ -KOS_API char* kos_strcat(char* strdestination, const char* strsource); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Compare two strings. - * - * - * \param void* string1 Pointer to first string. - * \param void* string2 Pointer to second string. - * \param void* length Number of bytes to compare. - * \return Zero if identical, >0 if first string is lexically greater <0 if not. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_strcmp(const char* string1, const char* string2); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Compares two strings of given length. - * - * - * \param void* string1 Pointer to first string. - * \param void* string2 Pointer to second string. - * \param void* length Number of bytes to compare. - * \return Zero if identical, >0 if first string is lexically greater <0 if not. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_strncmp(const char* string1, const char* string2, int length); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Calculates the length of a string.. - * - * - * \param void* string Pointer to the string. - * \return Lenght of the string in bytes. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_strlen(const char* string); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Convert an numeric ascii string to integer value. - * - * - * \param void* string Pointer to the string. - * \return Integer value extracted from the string. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_atoi(const char* string); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Convert string to unsigned long integer. - * - * - * \param void* nptr Pointer to the string. - * \param char** endptr If not null, will be set to point to the next character after the number. - * \param int base Base defining the type of the numeric string. - * \return Unsigned integer value extracted from the string. - *//*-------------------------------------------------------------------*/ -KOS_API unsigned int kos_strtoul(const char* nptr, char** endptr, int base); - - -////////////////////////////////////////////////////////////////////////////// -// sync API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Create a mutex instance. - * - * - * \param void* name Name string for the new mutex. - * \return Returns a handle to the mutex. - *//*-------------------------------------------------------------------*/ -KOS_API oshandle_t kos_mutex_create(const char* name); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get a handle to an already existing mutex. - * - * - * \param void* name Name string for the new mutex. - * \return Returns a handle to the mutex. - *//*-------------------------------------------------------------------*/ -KOS_API oshandle_t kos_mutex_open(const char* name); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Free the given mutex. - * - * - * \param oshandle_t mutexhandle Handle to the mutex. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_mutex_free(oshandle_t mutexhandle); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Lock the given mutex. - * - * - * \param oshandle_t mutexhandle Handle to the mutex. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_mutex_lock(oshandle_t mutexhandle); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Try to lock the given mutex, if already locked returns immediately. - * - * - * \param oshandle_t mutexhandle Handle to the mutex. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_mutex_locktry(oshandle_t mutexhandle); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Try to lock the given mutex by waiting for its release. Returns without locking if the - * mutex is already locked and cannot be acquired within the given period. - * - * - * \param oshandle_t mutexhandle Handle to the mutex. - * \param int millisecondstowait Time to wait for the mutex to be available. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_mutex_lockwait(oshandle_t mutexhandle, int millisecondstowait); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Unlock the given mutex. - * - * - * \param oshandle_t mutexhandle Handle to the mutex. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_mutex_unlock(oshandle_t mutexhandle); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Increments (increases by one) the value of the specified 32-bit variable as an atomic operation. - * - * - * \param int* ptr Pointer to the value to be incremented. - * \return Returns the new incremented value. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interlock_incr(int* ptr); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Decrements (decreases by one) the value of the specified 32-bit variable as an atomic operation. - * - * - * \param int* ptr Pointer to the value to be decremented. - * \return Returns the new decremented value. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interlock_decr(int* ptr); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Atomic replacement of a value. - * - * - * \param int* ptr Pointer to the value to be replaced. - * \param int value The new value. - * \return Returns the old value. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interlock_xchg(int* ptr, int value); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Perform an atomic compare-and-exchange operation on the specified values. Compares the two specified 32-bit values and exchanges -* with another 32-bit value based on the outcome of the comparison. - * - * - * \param int* ptr Pointer to the value to be replaced. - * \param int value The new value. - * \param int compvalue Value to be compared with. - * \return Returns the initial value of the first given parameter. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interlock_compxchg(int* ptr, int value, int compvalue); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Atomic addition of two 32-bit values. - * - * - * \param int* ptr Pointer to the target value. - * \param int value Value to be added to the target. - * \return Returns the initial value of the target. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interlock_xchgadd(int* ptr, int value); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Create an event semaphore. - * - * - * \param int a_manualReset Selection for performing reset manually (or by the system). - * \return Returns an handle to the created semaphore. - *//*-------------------------------------------------------------------*/ -KOS_API oshandle_t kos_event_create(int a_manualReset); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Destroy an event semaphore. - * - * - * \param oshandle_t a_event Handle to the semaphore. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_event_destroy(oshandle_t a_event); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Signal an event semaphore. - * - * - * \param oshandle_t a_event Handle to the semaphore. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_event_signal(oshandle_t a_event); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Reset an event semaphore. - * - * - * \param oshandle_t a_event Handle to the semaphore. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_event_reset(oshandle_t a_event); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Wait for an event semaphore to be freed and acquire it. - * - * - * \param oshandle_t a_event Handle to the semaphore. - * \param int a_milliSeconds Time to wait. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_event_wait(oshandle_t a_event, int a_milliSeconds); - - -////////////////////////////////////////////////////////////////////////////// -// interrupt handler API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Enable an interrupt with specified id. - * - * - * \param int interrupt Identification number for the interrupt. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interrupt_enable(int interrupt); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Disable an interrupt with specified id. - * - * - * \param int interrupt Identification number for the interrupt. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interrupt_disable(int interrupt); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Set the callback function for an interrupt. - * - * - * \param int interrupt Identification number for the interrupt. - * \param void* handler Pointer to the callback function. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interrupt_setcallback(int interrupt, void* handler); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Remove a callback function from an interrupt. - * - * - * \param int interrupt Identification number for the interrupt. - * \param void* handler Pointer to the callback function. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_interrupt_clearcallback(int interrupt, void* handler); - - -////////////////////////////////////////////////////////////////////////////// -// thread and process API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Allocate an entry from the thread local storage table. - * - * - * \return Index of the reserved entry. - *//*-------------------------------------------------------------------*/ -KOS_API unsigned int kos_tls_alloc(void); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Free an entry from the thread local storage table. - * - * - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_tls_free(unsigned int tlsindex); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Read the value of an entry in the thread local storage table. - * - * - * \param unsigned int tlsindex Index of the entry. - * \return Returns the value of the entry. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_tls_read(unsigned int tlsindex); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Write a value to an entry in the thread local storage table. - * - * - * \param unsigned int tlsindex Index of the entry. - * \param void* tlsvalue Value to be written. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_tls_write(unsigned int tlsindex, void* tlsvalue); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Put the thread to sleep for the given time period. - * - * - * \param unsigned int milliseconds Time in milliseconds. - *//*-------------------------------------------------------------------*/ -KOS_API void kos_sleep(unsigned int milliseconds); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get the id of the current process. - * - * - * \return Returns the process id. - *//*-------------------------------------------------------------------*/ -KOS_API unsigned int kos_process_getid(void); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get the id of the current caller process. - * - * - * \return Returns the caller process id. - *//*-------------------------------------------------------------------*/ -KOS_API unsigned int kos_callerprocess_getid(void); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get the id of the current thread. - * - * - * \return Returns the thread id. - *//*-------------------------------------------------------------------*/ -KOS_API unsigned int kos_thread_getid(void); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Create a new thread. - * - * - * \param oshandle_t a_function Handle to the function to be executed in the thread. - * \param unsigned int* a_threadId Pointer to a value where to store the ID of the new thread. - * \return Returns an handle to the created thread. - *//*-------------------------------------------------------------------*/ -KOS_API oshandle_t kos_thread_create(oshandle_t a_function, unsigned int* a_threadId); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Destroy the given thread. - * - * - * \param oshandle_t a_task Handle to the thread to be destroyed. - *//*-------------------------------------------------------------------*/ -KOS_API void kos_thread_destroy( oshandle_t a_task ); - -////////////////////////////////////////////////////////////////////////////// -// timing API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get the current time as a timestamp. - * - * - * \return Returns the timestamp. - *//*-------------------------------------------------------------------*/ -KOS_API unsigned int kos_timestamp(void); - - -////////////////////////////////////////////////////////////////////////////// -// libary API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Map the given library (not required an all OS'es). - * - * - * \param char* libraryname The name string of the lib. - * \return Returns a handle for the lib. - *//*-------------------------------------------------------------------*/ -KOS_API oshandle_t kos_lib_map(char* libraryname); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Unmap the given library. - * - * \param oshandle_t libhandle Handle to the lib. - * \return Returns an error code incase of an error. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_lib_unmap(oshandle_t libhandle); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get the address of a lib. - * - * \param oshandle_t libhandle Handle to the lib. - * \return Returns a pointer to the lib. - *//*-------------------------------------------------------------------*/ -KOS_API void* kos_lib_getaddr(oshandle_t libhandle, char* procname); - - -////////////////////////////////////////////////////////////////////////////// -// query API -////////////////////////////////////////////////////////////////////////////// -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get device system info. - * - * \param os_sysinfo_t* sysinfo Pointer to the destination sysinfo structure. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_get_sysinfo(os_sysinfo_t* sysinfo); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Get system status info. - * - * \param os_stats_t* stats Pointer to the destination stats structure. - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_get_stats(os_stats_t* stats); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Sync block start - * - * \param void - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_syncblock_start(void); -/*-------------------------------------------------------------------*//*! - * \external - * \brief Sync block end - * - * \param void - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_syncblock_end(void); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Sync block start with argument - * - * \param void - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_syncblock_start_ex( mutexIndex_t a_index ); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Sync block start with argument - * - * \param void - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_syncblock_end_ex( mutexIndex_t a_index ); - -////////////////////////////////////////////////////////////////////////////// -// file API -////////////////////////////////////////////////////////////////////////////// - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Opens a file - * - * \param const char* filename Name of the file to open. - * \param const char* mode Mode used for file opening. See fopen. - * \return Returns file handle or NULL if error. - *//*-------------------------------------------------------------------*/ -KOS_API oshandle_t kos_fopen(const char* filename, const char* mode); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Writes to a file - * - * \param oshandle_t file Handle of the file to write to. - * \param const char* format Format string. See fprintf. - * \return Returns the number of bytes written - *//*-------------------------------------------------------------------*/ -KOS_API int kos_fprintf(oshandle_t file, const char* format, ...); - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Closes a file - * - * \param oshandle_t file Handle of the file to close. - * \return Returns zero if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_fclose(oshandle_t file); - -#ifdef __SYMBIAN32__ -KOS_API void kos_create_dfc(void); -KOS_API void kos_signal_dfc(void); -KOS_API void kos_enter_critical_section(); -KOS_API void kos_leave_critical_section(); -#endif // __SYMBIAN32__ - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // __KOSAPI_H diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hal.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hal.c deleted file mode 100644 index 8d452830cc0..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hal.c +++ /dev/null @@ -1,579 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -#include "gsl_hal.h" -#include "gsl_halconfig.h" -#include "gsl_linux_map.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#define GSL_HAL_MEM1 0 -#define GSL_HAL_MEM2 1 -#define GSL_HAL_MEM3 2 - -/* #define GSL_HAL_DEBUG */ - -extern phys_addr_t gpu_2d_regbase; -extern int gpu_2d_regsize; -extern phys_addr_t gpu_3d_regbase; -extern int gpu_3d_regsize; -extern int gmem_size; -extern phys_addr_t gpu_reserved_mem; -extern int gpu_reserved_mem_size; -extern int gpu_2d_irq, gpu_3d_irq; - - -KGSLHAL_API int -kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[]) -{ - /* allocate physically contiguous memory */ - - int i; - void *va; - - va = gsl_linux_map_alloc(virtaddr, numpages*PAGE_SIZE); - - if (!va) - return GSL_FAILURE_OUTOFMEM; - - for (i = 0; i < numpages; i++) { - scattergatterlist[i] = page_to_phys(vmalloc_to_page(va)); - va += PAGE_SIZE; - } - - return GSL_SUCCESS; -} - -/* --------------------------------------------------------------------------- */ - -KGSLHAL_API int -kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[]) -{ - /* free physical memory */ - - gsl_linux_map_free(virtaddr); - - return GSL_SUCCESS; -} - -/* ---------------------------------------------------------------------------- */ - -KGSLHAL_API int -kgsl_hal_init(void) -{ - gsl_hal_t *hal; - unsigned long totalsize, mem1size; - unsigned int va, pa; - - if (gsl_driver.hal) { - return GSL_FAILURE_ALREADYINITIALIZED; - } - - gsl_driver.hal = (void *)kos_malloc(sizeof(gsl_hal_t)); - - if (!gsl_driver.hal) { - return GSL_FAILURE_OUTOFMEM; - } - - kos_memset(gsl_driver.hal, 0, sizeof(gsl_hal_t)); - - - /* overlay structure on hal memory */ - hal = (gsl_hal_t *) gsl_driver.hal; - - if (gpu_3d_regbase && gpu_3d_regsize && gpu_3d_irq) { - hal->has_z430 = 1; - } else { - hal->has_z430 = 0; - } - - if (gpu_2d_regbase && gpu_2d_regsize && gpu_2d_irq) { - hal->has_z160 = 1; - } else { - hal->has_z160 = 0; - } - - /* there is still some problem to enable mmu currently */ - gsl_driver.enable_mmu = 0; - - /* setup register space */ - if (hal->has_z430) { - hal->z430_regspace.mmio_phys_base = gpu_3d_regbase; - hal->z430_regspace.sizebytes = gpu_3d_regsize; - hal->z430_regspace.mmio_virt_base = (unsigned char *)ioremap(hal->z430_regspace.mmio_phys_base, hal->z430_regspace.sizebytes); - - if (hal->z430_regspace.mmio_virt_base == NULL) { - return GSL_FAILURE_SYSTEMERROR; - } - -#ifdef GSL_HAL_DEBUG - printk(KERN_INFO "%s: hal->z430_regspace.mmio_phys_base = 0x%p\n", __func__, (void *)hal->z430_regspace.mmio_phys_base); - printk(KERN_INFO "%s: hal->z430_regspace.mmio_virt_base = 0x%p\n", __func__, (void *)hal->z430_regspace.mmio_virt_base); - printk(KERN_INFO "%s: hal->z430_regspace.sizebytes = 0x%08x\n", __func__, hal->z430_regspace.sizebytes); -#endif - } - - if (hal->has_z160) { - hal->z160_regspace.mmio_phys_base = gpu_2d_regbase; - hal->z160_regspace.sizebytes = gpu_2d_regsize; - hal->z160_regspace.mmio_virt_base = (unsigned char *)ioremap(hal->z160_regspace.mmio_phys_base, hal->z160_regspace.sizebytes); - - if (hal->z160_regspace.mmio_virt_base == NULL) { - return GSL_FAILURE_SYSTEMERROR; - } - -#ifdef GSL_HAL_DEBUG - printk(KERN_INFO "%s: hal->z160_regspace.mmio_phys_base = 0x%p\n", __func__, (void *)hal->z160_regspace.mmio_phys_base); - printk(KERN_INFO "%s: hal->z160_regspace.mmio_virt_base = 0x%p\n", __func__, (void *)hal->z160_regspace.mmio_virt_base); - printk(KERN_INFO "%s: hal->z160_regspace.sizebytes = 0x%08x\n", __func__, hal->z160_regspace.sizebytes); -#endif - } - - if (gsl_driver.enable_mmu) { - totalsize = GSL_HAL_SHMEM_SIZE_EMEM2_MMU + GSL_HAL_SHMEM_SIZE_PHYS_MMU; - mem1size = GSL_HAL_SHMEM_SIZE_EMEM1_MMU; - if (gpu_reserved_mem && gpu_reserved_mem_size >= totalsize) { - pa = gpu_reserved_mem; - va = (unsigned int)ioremap(gpu_reserved_mem, totalsize); - } else { - va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL); - } - } else { - if (gpu_reserved_mem && gpu_reserved_mem_size >= SZ_8M) { - totalsize = gpu_reserved_mem_size; - pa = gpu_reserved_mem; - va = (unsigned int)ioremap(gpu_reserved_mem, gpu_reserved_mem_size); - } else { - gpu_reserved_mem = 0; - totalsize = GSL_HAL_SHMEM_SIZE_EMEM1_NOMMU + GSL_HAL_SHMEM_SIZE_EMEM2_NOMMU + GSL_HAL_SHMEM_SIZE_PHYS_NOMMU; - va = (unsigned int)dma_alloc_coherent(0, totalsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL); - } - mem1size = totalsize - (GSL_HAL_SHMEM_SIZE_EMEM2_NOMMU + GSL_HAL_SHMEM_SIZE_PHYS_NOMMU); - } - - if (va) { - kos_memset((void *)va, 0, totalsize); - - hal->memchunk.mmio_virt_base = (void *)va; - hal->memchunk.mmio_phys_base = pa; - hal->memchunk.sizebytes = totalsize; - -#ifdef GSL_HAL_DEBUG - printk(KERN_INFO "%s: hal->memchunk.mmio_phys_base = 0x%p\n", __func__, (void *)hal->memchunk.mmio_phys_base); - printk(KERN_INFO "%s: hal->memchunk.mmio_virt_base = 0x%p\n", __func__, (void *)hal->memchunk.mmio_virt_base); - printk(KERN_INFO "%s: hal->memchunk.sizebytes = 0x%08x\n", __func__, hal->memchunk.sizebytes); -#endif - - hal->memspace[GSL_HAL_MEM2].mmio_virt_base = (void *) va; - hal->memspace[GSL_HAL_MEM2].gpu_base = pa; - if (gsl_driver.enable_mmu) { - hal->memspace[GSL_HAL_MEM2].sizebytes = GSL_HAL_SHMEM_SIZE_EMEM2_MMU; - va += GSL_HAL_SHMEM_SIZE_EMEM2_MMU; - pa += GSL_HAL_SHMEM_SIZE_EMEM2_MMU; - } else { - hal->memspace[GSL_HAL_MEM2].sizebytes = GSL_HAL_SHMEM_SIZE_EMEM2_NOMMU; - va += GSL_HAL_SHMEM_SIZE_EMEM2_NOMMU; - pa += GSL_HAL_SHMEM_SIZE_EMEM2_NOMMU; - } - -#ifdef GSL_HAL_DEBUG - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].gpu_base = 0x%p\n", __func__, (void *)hal->memspace[GSL_HAL_MEM2].gpu_base); - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].mmio_virt_base = 0x%p\n", __func__, (void *)hal->memspace[GSL_HAL_MEM2].mmio_virt_base); - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM2].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM2].sizebytes); -#endif - - hal->memspace[GSL_HAL_MEM3].mmio_virt_base = (void *) va; - hal->memspace[GSL_HAL_MEM3].gpu_base = pa; - if (gsl_driver.enable_mmu) { - hal->memspace[GSL_HAL_MEM3].sizebytes = GSL_HAL_SHMEM_SIZE_PHYS_MMU; - va += GSL_HAL_SHMEM_SIZE_PHYS_MMU; - pa += GSL_HAL_SHMEM_SIZE_PHYS_MMU; - } else { - hal->memspace[GSL_HAL_MEM3].sizebytes = GSL_HAL_SHMEM_SIZE_PHYS_NOMMU; - va += GSL_HAL_SHMEM_SIZE_PHYS_NOMMU; - pa += GSL_HAL_SHMEM_SIZE_PHYS_NOMMU; - } - -#ifdef GSL_HAL_DEBUG - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].gpu_base = 0x%p\n", __func__, (void *)hal->memspace[GSL_HAL_MEM3].gpu_base); - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].mmio_virt_base = 0x%p\n", __func__, (void *)hal->memspace[GSL_HAL_MEM3].mmio_virt_base); - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM3].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM3].sizebytes); -#endif - - if (gsl_driver.enable_mmu) { - gsl_linux_map_init(); - hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *)GSL_LINUX_MAP_RANGE_START; - hal->memspace[GSL_HAL_MEM1].gpu_base = GSL_LINUX_MAP_RANGE_START; - hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size; - } else { - hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *) va; - hal->memspace[GSL_HAL_MEM1].gpu_base = pa; - hal->memspace[GSL_HAL_MEM1].sizebytes = mem1size; - } - -#ifdef GSL_HAL_DEBUG - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].gpu_base = 0x%p\n", __func__, (void *)hal->memspace[GSL_HAL_MEM1].gpu_base); - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].mmio_virt_base = 0x%p\n", __func__, (void *)hal->memspace[GSL_HAL_MEM1].mmio_virt_base); - printk(KERN_INFO "%s: hal->memspace[GSL_HAL_MEM1].sizebytes = 0x%08x\n", __func__, hal->memspace[GSL_HAL_MEM1].sizebytes); -#endif - } else { - kgsl_hal_close(); - return GSL_FAILURE_SYSTEMERROR; - } - - return GSL_SUCCESS; -} - -/* ---------------------------------------------------------------------------- */ - -KGSLHAL_API int -kgsl_hal_close(void) -{ - gsl_hal_t *hal; - - if (gsl_driver.hal) { - /* overlay structure on hal memory */ - hal = (gsl_hal_t *) gsl_driver.hal; - - /* unmap registers */ - if (hal->has_z430 && hal->z430_regspace.mmio_virt_base) { - iounmap(hal->z430_regspace.mmio_virt_base); - } - - if (hal->has_z160 && hal->z160_regspace.mmio_virt_base) { - iounmap(hal->z160_regspace.mmio_virt_base); - } - - /* free physical block */ - if (hal->memchunk.mmio_virt_base && gpu_reserved_mem) { - iounmap(hal->memchunk.mmio_virt_base); - } else { - dma_free_coherent(0, hal->memchunk.sizebytes, hal->memchunk.mmio_virt_base, hal->memchunk.mmio_phys_base); - } - - if (gsl_driver.enable_mmu) { - gsl_linux_map_destroy(); - } - - /* release hal struct */ - kos_memset(hal, 0, sizeof(gsl_hal_t)); - kos_free(gsl_driver.hal); - gsl_driver.hal = NULL; - } - - return GSL_SUCCESS; -} - -/* ---------------------------------------------------------------------------- */ - -KGSLHAL_API int -kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config) -{ - int status = GSL_FAILURE_DEVICEERROR; - gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal; - - kos_memset(config, 0, sizeof(gsl_shmemconfig_t)); - - if (hal) { - config->numapertures = GSL_SHMEM_MAX_APERTURES; - - if (gsl_driver.enable_mmu) { - config->apertures[0].id = GSL_APERTURE_MMU; - } else { - config->apertures[0].id = GSL_APERTURE_EMEM; - } - config->apertures[0].channel = GSL_CHANNEL_1; - config->apertures[0].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM1].mmio_virt_base; - config->apertures[0].gpubase = hal->memspace[GSL_HAL_MEM1].gpu_base; - config->apertures[0].sizebytes = hal->memspace[GSL_HAL_MEM1].sizebytes; - - config->apertures[1].id = GSL_APERTURE_EMEM; - config->apertures[1].channel = GSL_CHANNEL_2; - config->apertures[1].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM2].mmio_virt_base; - config->apertures[1].gpubase = hal->memspace[GSL_HAL_MEM2].gpu_base; - config->apertures[1].sizebytes = hal->memspace[GSL_HAL_MEM2].sizebytes; - - config->apertures[2].id = GSL_APERTURE_PHYS; - config->apertures[2].channel = GSL_CHANNEL_1; - config->apertures[2].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM3].mmio_virt_base; - config->apertures[2].gpubase = hal->memspace[GSL_HAL_MEM3].gpu_base; - config->apertures[2].sizebytes = hal->memspace[GSL_HAL_MEM3].sizebytes; - - status = GSL_SUCCESS; - } - - return status; -} - -/* ---------------------------------------------------------------------------- */ - -KGSLHAL_API int -kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config) -{ - int status = GSL_FAILURE_DEVICEERROR; - gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal; - - kos_memset(config, 0, sizeof(gsl_devconfig_t)); - - if (hal) { - switch (device_id) { - case GSL_DEVICE_YAMATO: - { - if (hal->has_z430) { - mh_mmu_config_u mmu_config = {0}; - - config->gmemspace.gpu_base = 0; - config->gmemspace.mmio_virt_base = 0; - config->gmemspace.mmio_phys_base = 0; - if (gmem_size) { - config->gmemspace.sizebytes = gmem_size; - } else { - config->gmemspace.sizebytes = 0; - } - - config->regspace.gpu_base = 0; - config->regspace.mmio_virt_base = (unsigned char *)hal->z430_regspace.mmio_virt_base; - config->regspace.mmio_phys_base = (unsigned int) hal->z430_regspace.mmio_phys_base; - config->regspace.sizebytes = GSL_HAL_SIZE_REG_YDX; - - mmu_config.f.mmu_enable = 1; - - if (gsl_driver.enable_mmu) { - mmu_config.f.split_mode_enable = 0; - mmu_config.f.rb_w_clnt_behavior = 1; - mmu_config.f.cp_w_clnt_behavior = 1; - mmu_config.f.cp_r0_clnt_behavior = 1; - mmu_config.f.cp_r1_clnt_behavior = 1; - mmu_config.f.cp_r2_clnt_behavior = 1; - mmu_config.f.cp_r3_clnt_behavior = 1; - mmu_config.f.cp_r4_clnt_behavior = 1; - mmu_config.f.vgt_r0_clnt_behavior = 1; - mmu_config.f.vgt_r1_clnt_behavior = 1; - mmu_config.f.tc_r_clnt_behavior = 1; - mmu_config.f.pa_w_clnt_behavior = 1; - } - - config->mmu_config = mmu_config.val; - - if (gsl_driver.enable_mmu) { - config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base; - config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes; - } else { - config->va_base = 0x00000000; - config->va_range = 0x00000000; - } - - /* turn off memory protection unit by setting acceptable physical address range to include all pages */ - config->mpu_base = 0x00000000; /* hal->memchunk.mmio_virt_base; */ - config->mpu_range = 0xFFFFF000; /* hal->memchunk.sizebytes; */ - status = GSL_SUCCESS; - } - break; - } - - case GSL_DEVICE_G12: - { - mh_mmu_config_u mmu_config = {0}; - - config->regspace.gpu_base = 0; - config->regspace.mmio_virt_base = (unsigned char *)hal->z160_regspace.mmio_virt_base; - config->regspace.mmio_phys_base = (unsigned int) hal->z160_regspace.mmio_phys_base; - config->regspace.sizebytes = GSL_HAL_SIZE_REG_G12; - - mmu_config.f.mmu_enable = 1; - - if (gsl_driver.enable_mmu) { - config->mmu_config = 0x00555551; - config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base; - config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes; - } else { - config->mmu_config = mmu_config.val; - config->va_base = 0x00000000; - config->va_range = 0x00000000; - } - - config->mpu_base = 0x00000000; /* (unsigned int) hal->memchunk.mmio_virt_base; */ - config->mpu_range = 0xFFFFF000; /* hal->memchunk.sizebytes; */ - - status = GSL_SUCCESS; - break; - } - - default: - break; - } - } - - return status; -} - -/*---------------------------------------------------------------------------- - * kgsl_hal_getchipid - * - * The proper platform method, build from RBBM_PERIPHIDx and RBBM_PATCH_RELEASE - *---------------------------------------------------------------------------- - */ -KGSLHAL_API gsl_chipid_t -kgsl_hal_getchipid(gsl_deviceid_t device_id) -{ - gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal; - gsl_device_t *device = &gsl_driver.device[device_id-1]; - gsl_chipid_t chipid = 0; - unsigned int coreid, majorid, minorid, patchid, revid; - - if (hal->has_z430 && (device_id == GSL_DEVICE_YAMATO)) { - device->ftbl.device_regread(device, mmRBBM_PERIPHID1, &coreid); - coreid &= 0xF; - - device->ftbl.device_regread(device, mmRBBM_PERIPHID2, &majorid); - majorid = (majorid >> 4) & 0xF; - - device->ftbl.device_regread(device, mmRBBM_PATCH_RELEASE, &revid); - - minorid = ((revid >> 0) & 0xFF); /* this is a 16bit field, but extremely unlikely it would ever get this high */ - - patchid = ((revid >> 16) & 0xFF); - - chipid = ((coreid << 24) | (majorid << 16) | (minorid << 8) | (patchid << 0)); - } - - return chipid; -} - -/* --------------------------------------------------------------------------- */ - -KGSLHAL_API int -kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value) -{ - gsl_device_t *device = &gsl_driver.device[device_id-1]; - struct clk *gpu_clk = NULL; - struct clk *garb_clk = NULL; - struct clk *emi_garb_clk = NULL; - - /* unreferenced formal parameters */ - (void) value; - - switch (device_id) { - case GSL_DEVICE_G12: - gpu_clk = clk_get(0, "gpu2d_clk"); - break; - case GSL_DEVICE_YAMATO: - gpu_clk = clk_get(0, "gpu3d_clk"); - garb_clk = clk_get(0, "garb_clk"); - emi_garb_clk = clk_get(0, "emi_garb_clk"); - break; - default: - return GSL_FAILURE_DEVICEERROR; - } - - if (!gpu_clk) { - return GSL_FAILURE_DEVICEERROR; - } - - switch (state) { - case GSL_PWRFLAGS_CLK_ON: - break; - case GSL_PWRFLAGS_POWER_ON: - clk_enable(gpu_clk); - if (garb_clk) { - clk_enable(garb_clk); - } - if (emi_garb_clk) { - clk_enable(emi_garb_clk); - } - kgsl_device_autogate_init(&gsl_driver.device[device_id-1]); - break; - case GSL_PWRFLAGS_CLK_OFF: - break; - case GSL_PWRFLAGS_POWER_OFF: - if (device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT) != GSL_SUCCESS) { - return GSL_FAILURE_DEVICEERROR; - } - kgsl_device_autogate_exit(&gsl_driver.device[device_id-1]); - clk_disable(gpu_clk); - if (garb_clk) { - clk_disable(garb_clk); - } - if (emi_garb_clk) { - clk_disable(emi_garb_clk); - } - break; - default: - break; - } - - return GSL_SUCCESS; -} - -KGSLHAL_API int kgsl_clock(gsl_deviceid_t dev, int enable) -{ - struct clk *gpu_clk = NULL; - struct clk *garb_clk = NULL; - struct clk *emi_garb_clk = NULL; - - switch (dev) { - case GSL_DEVICE_G12: - gpu_clk = clk_get(0, "gpu2d_clk"); - break; - case GSL_DEVICE_YAMATO: - gpu_clk = clk_get(0, "gpu3d_clk"); - garb_clk = clk_get(0, "garb_clk"); - emi_garb_clk = clk_get(0, "emi_garb_clk"); - break; - default: - printk(KERN_ERR "GPU device %d is invalid!\n", dev); - return GSL_FAILURE_DEVICEERROR; - } - - if (IS_ERR(gpu_clk)) { - printk(KERN_ERR "%s: GPU clock get failed!\n", __func__); - return GSL_FAILURE_DEVICEERROR; - } - - if (enable) { - clk_enable(gpu_clk); - if (garb_clk) { - clk_enable(garb_clk); - } - if (emi_garb_clk) { - clk_enable(emi_garb_clk); - } - } else { - clk_disable(gpu_clk); - if (garb_clk) { - clk_disable(garb_clk); - } - if (emi_garb_clk) { - clk_disable(emi_garb_clk); - } - } - - return GSL_SUCCESS; -} diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h deleted file mode 100644 index 305b2ee9066..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_hwaccess.h +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Advanced Micro Devices nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GSL_HWACCESS_LINUX_H -#define __GSL_HWACCESS_LINUX_H - -#ifdef _LINUX -#include "gsl_linux_map.h" -#endif - -#include -#include -#include - -OSINLINE void -kgsl_hwaccess_memread(void *dst, unsigned int gpubase, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace) -{ - if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) { - gsl_linux_map_read(dst, gpubase+gpuoffset, sizebytes, touserspace); - } else { - mb(); - dsb(); - if (touserspace) - { - if (copy_to_user(dst, (void *)(gpubase + gpuoffset), sizebytes)) - { - return; - } - } - else - { - kos_memcpy(dst, (void *) (gpubase + gpuoffset), sizebytes); - } - mb(); - dsb(); - } -} - -//---------------------------------------------------------------------------- - -OSINLINE void -kgsl_hwaccess_memwrite(unsigned int gpubase, unsigned int gpuoffset, void *src, unsigned int sizebytes, unsigned int fromuserspace) -{ - if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) { - gsl_linux_map_write(src, gpubase+gpuoffset, sizebytes, fromuserspace); - } else { - mb(); - dsb(); - if (fromuserspace) - { - if (copy_from_user((void *)(gpubase + gpuoffset), src, sizebytes)) - { - return; - } - } - else - { - kos_memcpy((void *)(gpubase + gpuoffset), src, sizebytes); - } - mb(); - dsb(); - } -} - -//---------------------------------------------------------------------------- - -OSINLINE void -kgsl_hwaccess_memset(unsigned int gpubase, unsigned int gpuoffset, unsigned int value, unsigned int sizebytes) -{ - if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) { - gsl_linux_map_set(gpuoffset+gpubase, value, sizebytes); - } else { - mb(); - dsb(); - kos_memset((void *)(gpubase + gpuoffset), value, sizebytes); - mb(); - dsb(); - } -} - -//---------------------------------------------------------------------------- - -OSINLINE void -kgsl_hwaccess_regread(gsl_deviceid_t device_id, unsigned int gpubase, unsigned int offsetwords, unsigned int *data) -{ - unsigned int *reg; - - // unreferenced formal parameter - (void) device_id; - - reg = (unsigned int *)(gpubase + (offsetwords << 2)); - - mb(); - dsb(); - *data = __raw_readl(reg); - mb(); - dsb(); -} - -//---------------------------------------------------------------------------- - -OSINLINE void -kgsl_hwaccess_regwrite(gsl_deviceid_t device_id, unsigned int gpubase, unsigned int offsetwords, unsigned int data) -{ - unsigned int *reg; - - // unreferenced formal parameter - (void) device_id; - - reg = (unsigned int *)(gpubase + (offsetwords << 2)); - mb(); - dsb(); - __raw_writel(data, reg); - mb(); - dsb(); -} -#endif // __GSL_HWACCESS_WINCE_MX51_H diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c deleted file mode 100644 index 94667d04668..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod.c +++ /dev/null @@ -1,977 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl_types.h" -#include "gsl.h" -#include "gsl_buildconfig.h" -#include "gsl_halconfig.h" -#include "gsl_ioctl.h" -#include "gsl_kmod_cleanup.h" -#include "gsl_linux_map.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -int gpu_2d_irq, gpu_3d_irq; - -phys_addr_t gpu_2d_regbase; -int gpu_2d_regsize; -phys_addr_t gpu_3d_regbase; -int gpu_3d_regsize; -int gmem_size; -phys_addr_t gpu_reserved_mem; -int gpu_reserved_mem_size; -int z160_version; - -static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr); -static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr); -static long gsl_kmod_ioctl(struct file *fd, unsigned int cmd, unsigned long arg); -static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma); -static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf); -static int gsl_kmod_open(struct inode *inode, struct file *fd); -static int gsl_kmod_release(struct inode *inode, struct file *fd); -static irqreturn_t z160_irq_handler(int irq, void *dev_id); -static irqreturn_t z430_irq_handler(int irq, void *dev_id); - -static int gsl_kmod_major; -static struct class *gsl_kmod_class; -DEFINE_MUTEX(gsl_mutex); - -static const struct file_operations gsl_kmod_fops = -{ - .owner = THIS_MODULE, - .read = gsl_kmod_read, - .write = gsl_kmod_write, - .unlocked_ioctl = gsl_kmod_ioctl, - .mmap = gsl_kmod_mmap, - .open = gsl_kmod_open, - .release = gsl_kmod_release -}; - -static struct vm_operations_struct gsl_kmod_vmops = -{ - .fault = gsl_kmod_fault, -}; - -static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) -{ - return 0; -} - -static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) -{ - return 0; -} - -static long gsl_kmod_ioctl(struct file *fd, unsigned int cmd, unsigned long arg) -{ - int kgslStatus = GSL_FAILURE; - - switch (cmd) { - case IOCTL_KGSL_DEVICE_START: - { - kgsl_device_start_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_start_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_start(param.device_id, param.flags); - break; - } - case IOCTL_KGSL_DEVICE_STOP: - { - kgsl_device_stop_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_stop_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_stop(param.device_id); - break; - } - case IOCTL_KGSL_DEVICE_IDLE: - { - kgsl_device_idle_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_idle_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_idle(param.device_id, param.timeout); - break; - } - case IOCTL_KGSL_DEVICE_ISIDLE: - { - kgsl_device_isidle_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_isidle_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_isidle(param.device_id); - break; - } - case IOCTL_KGSL_DEVICE_GETPROPERTY: - { - kgsl_device_getproperty_t param; - void *tmp; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_getproperty_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - tmp = kmalloc(param.sizebytes, GFP_KERNEL); - if (!tmp) - { - printk(KERN_ERR "%s:kmalloc error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_getproperty(param.device_id, param.type, tmp, param.sizebytes); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.value, tmp, param.sizebytes)) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - kfree(tmp); - break; - } - } - else - { - printk(KERN_ERR "%s: kgsl_device_getproperty error\n", __func__); - } - kfree(tmp); - break; - } - case IOCTL_KGSL_DEVICE_SETPROPERTY: - { - kgsl_device_setproperty_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_setproperty_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_setproperty(param.device_id, param.type, param.value, param.sizebytes); - if (kgslStatus != GSL_SUCCESS) - { - printk(KERN_ERR "%s: kgsl_device_setproperty error\n", __func__); - } - break; - } - case IOCTL_KGSL_DEVICE_REGREAD: - { - kgsl_device_regread_t param; - unsigned int tmp; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_regread_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_regread(param.device_id, param.offsetwords, &tmp); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.value, &tmp, sizeof(unsigned int))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - } - break; - } - case IOCTL_KGSL_DEVICE_REGWRITE: - { - kgsl_device_regwrite_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_regwrite_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_regwrite(param.device_id, param.offsetwords, param.value); - break; - } - case IOCTL_KGSL_DEVICE_WAITIRQ: - { - kgsl_device_waitirq_t param; - unsigned int count; - - printk(KERN_ERR "IOCTL_KGSL_DEVICE_WAITIRQ obsoleted!\n"); -// kgslStatus = -ENOTTY; break; - - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_waitirq_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_waitirq(param.device_id, param.intr_id, &count, param.timeout); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.count, &count, sizeof(unsigned int))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - } - break; - } - case IOCTL_KGSL_CMDSTREAM_ISSUEIBCMDS: - { - kgsl_cmdstream_issueibcmds_t param; - gsl_timestamp_t tmp; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_issueibcmds_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_cmdstream_issueibcmds(param.device_id, param.drawctxt_index, param.ibaddr, param.sizedwords, &tmp, param.flags); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - } - break; - } - case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP: - { - kgsl_cmdstream_readtimestamp_t param; - gsl_timestamp_t tmp; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_readtimestamp_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - tmp = kgsl_cmdstream_readtimestamp(param.device_id, param.type); - if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = GSL_SUCCESS; - break; - } - case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP: - { - int err; - kgsl_cmdstream_freememontimestamp_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_freememontimestamp_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - err = del_memblock_from_allocated_list(fd, param.memdesc); - if(err) - { - /* tried to remove a block of memory that is not allocated! - * NOTE that -EINVAL is Linux kernel's error codes! - * the drivers error codes COULD mix up with kernel's. */ - kgslStatus = -EINVAL; - } - else - { - kgslStatus = kgsl_cmdstream_freememontimestamp(param.device_id, - param.memdesc, - param.timestamp, - param.type); - } - break; - } - case IOCTL_KGSL_CMDSTREAM_WAITTIMESTAMP: - { - kgsl_cmdstream_waittimestamp_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_waittimestamp_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_cmdstream_waittimestamp(param.device_id, param.timestamp, param.timeout); - break; - } - case IOCTL_KGSL_CMDWINDOW_WRITE: - { - kgsl_cmdwindow_write_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdwindow_write_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_cmdwindow_write(param.device_id, param.target, param.addr, param.data); - break; - } - case IOCTL_KGSL_CONTEXT_CREATE: - { - kgsl_context_create_t param; - unsigned int tmp; - int tmpStatus; - - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_context_create_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_context_create(param.device_id, param.type, &tmp, param.flags); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.drawctxt_id, &tmp, sizeof(unsigned int))) - { - tmpStatus = kgsl_context_destroy(param.device_id, tmp); - /* is asserting ok? Basicly we should return the error from copy_to_user - * but will the user space interpret it correctly? Will the user space - * always check against GSL_SUCCESS or GSL_FAILURE as they are not the only - * return values. - */ - KOS_ASSERT(tmpStatus == GSL_SUCCESS); - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - else - { - add_device_context_to_array(fd, param.device_id, tmp); - } - } - break; - } - case IOCTL_KGSL_CONTEXT_DESTROY: - { - kgsl_context_destroy_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_context_destroy_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_context_destroy(param.device_id, param.drawctxt_id); - del_device_context_from_array(fd, param.device_id, param.drawctxt_id); - break; - } - case IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW: - { - kgsl_drawctxt_bind_gmem_shadow_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_drawctxt_bind_gmem_shadow_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_drawctxt_bind_gmem_shadow(param.device_id, param.drawctxt_id, param.gmem_rect, param.shadow_x, param.shadow_y, param.shadow_buffer, param.buffer_id); - break; - } - case IOCTL_KGSL_SHAREDMEM_ALLOC: - { - kgsl_sharedmem_alloc_t param; - gsl_memdesc_t tmp; - int tmpStatus; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_alloc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_sharedmem_alloc(param.device_id, param.flags, param.sizebytes, &tmp); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t))) - { - tmpStatus = kgsl_sharedmem_free(&tmp); - KOS_ASSERT(tmpStatus == GSL_SUCCESS); - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - else - { - add_memblock_to_allocated_list(fd, &tmp); - } - } - break; - } - case IOCTL_KGSL_SHAREDMEM_FREE: - { - kgsl_sharedmem_free_t param; - gsl_memdesc_t tmp; - int err; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_free_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - if (copy_from_user(&tmp, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - err = del_memblock_from_allocated_list(fd, &tmp); - if(err) - { - printk(KERN_ERR "%s: tried to free memdesc that was not allocated!\n", __func__); - kgslStatus = err; - break; - } - kgslStatus = kgsl_sharedmem_free(&tmp); - if (kgslStatus == GSL_SUCCESS) - { - if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - } - break; - } - case IOCTL_KGSL_SHAREDMEM_READ: - { - kgsl_sharedmem_read_t param; - gsl_memdesc_t memdesc; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_read_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_sharedmem_read(&memdesc, param.dst, param.offsetbytes, param.sizebytes, true); - if (kgslStatus != GSL_SUCCESS) - { - printk(KERN_ERR "%s: kgsl_sharedmem_read failed\n", __func__); - } - break; - } - case IOCTL_KGSL_SHAREDMEM_WRITE: - { - kgsl_sharedmem_write_t param; - gsl_memdesc_t memdesc; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_write_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_sharedmem_write(&memdesc, param.offsetbytes, param.src, param.sizebytes, true); - if (kgslStatus != GSL_SUCCESS) - { - printk(KERN_ERR "%s: kgsl_sharedmem_write failed\n", __func__); - } - - break; - } - case IOCTL_KGSL_SHAREDMEM_SET: - { - kgsl_sharedmem_set_t param; - gsl_memdesc_t memdesc; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_set_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_sharedmem_set(&memdesc, param.offsetbytes, param.value, param.sizebytes); - break; - } - case IOCTL_KGSL_SHAREDMEM_LARGESTFREEBLOCK: - { - kgsl_sharedmem_largestfreeblock_t param; - unsigned int largestfreeblock; - - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_largestfreeblock_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - largestfreeblock = kgsl_sharedmem_largestfreeblock(param.device_id, param.flags); - if (copy_to_user(param.largestfreeblock, &largestfreeblock, sizeof(unsigned int))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = GSL_SUCCESS; - break; - } - case IOCTL_KGSL_SHAREDMEM_CACHEOPERATION: - { - kgsl_sharedmem_cacheoperation_t param; - gsl_memdesc_t memdesc; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_cacheoperation_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_sharedmem_cacheoperation(&memdesc, param.offsetbytes, param.sizebytes, param.operation); - break; - } - case IOCTL_KGSL_SHAREDMEM_FROMHOSTPOINTER: - { - kgsl_sharedmem_fromhostpointer_t param; - gsl_memdesc_t memdesc; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_fromhostpointer_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_sharedmem_fromhostpointer(param.device_id, &memdesc, param.hostptr); - break; - } - case IOCTL_KGSL_ADD_TIMESTAMP: - { - kgsl_add_timestamp_t param; - gsl_timestamp_t tmp; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_add_timestamp_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - tmp = kgsl_add_timestamp(param.device_id, &tmp); - if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) - { - printk(KERN_ERR "%s: copy_to_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = GSL_SUCCESS; - break; - } - - case IOCTL_KGSL_DEVICE_CLOCK: - { - kgsl_device_clock_t param; - if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_clock_t))) - { - printk(KERN_ERR "%s: copy_from_user error\n", __func__); - kgslStatus = GSL_FAILURE; - break; - } - kgslStatus = kgsl_device_clock(param.device, param.enable); - break; - } - default: - kgslStatus = -ENOTTY; - break; - } - - return kgslStatus; -} - -static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma) -{ - int status = 0; - unsigned long start = vma->vm_start; - unsigned long pfn = vma->vm_pgoff; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long prot = pgprot_writecombine(vma->vm_page_prot); - unsigned long addr = vma->vm_pgoff << PAGE_SHIFT; - void *va = NULL; - - if (gsl_driver.enable_mmu && (addr < GSL_LINUX_MAP_RANGE_END) && (addr >= GSL_LINUX_MAP_RANGE_START)) { - va = gsl_linux_map_find(addr); - while (size > 0) { - if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot)) { - return -EAGAIN; - } - start += PAGE_SIZE; - va += PAGE_SIZE; - size -= PAGE_SIZE; - } - } else { - if (remap_pfn_range(vma, start, pfn, size, prot)) { - status = -EAGAIN; - } - } - - vma->vm_ops = &gsl_kmod_vmops; - - return status; -} - -static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - return VM_FAULT_SIGBUS; -} - -static int gsl_kmod_open(struct inode *inode, struct file *fd) -{ - gsl_flags_t flags = 0; - struct gsl_kmod_per_fd_data *datp; - int err = 0; - - if(mutex_lock_interruptible(&gsl_mutex)) - { - return -EINTR; - } - - if (kgsl_driver_entry(flags) != GSL_SUCCESS) - { - printk(KERN_INFO "%s: kgsl_driver_entry error\n", __func__); - err = -EIO; // TODO: not sure why did it fail? - } - else - { - /* allocate per file descriptor data structure */ - datp = (struct gsl_kmod_per_fd_data *)kzalloc( - sizeof(struct gsl_kmod_per_fd_data), - GFP_KERNEL); - if(datp) - { - init_created_contexts_array(datp->created_contexts_array[0]); - INIT_LIST_HEAD(&datp->allocated_blocks_head); - - fd->private_data = (void *)datp; - } - else - { - err = -ENOMEM; - } - } - - mutex_unlock(&gsl_mutex); - - return err; -} - -static int gsl_kmod_release(struct inode *inode, struct file *fd) -{ - struct gsl_kmod_per_fd_data *datp; - int err = 0; - - if(mutex_lock_interruptible(&gsl_mutex)) - { - return -EINTR; - } - - /* make sure contexts are destroyed */ - del_all_devices_contexts(fd); - - if (kgsl_driver_exit() != GSL_SUCCESS) - { - printk(KERN_INFO "%s: kgsl_driver_exit error\n", __func__); - err = -EIO; // TODO: find better error code - } - else - { - /* release per file descriptor data structure */ - datp = (struct gsl_kmod_per_fd_data *)fd->private_data; - del_all_memblocks_from_allocated_list(fd); - kfree(datp); - fd->private_data = 0; - } - - mutex_unlock(&gsl_mutex); - - return err; -} - -static struct class *gsl_kmod_class; - -static irqreturn_t z160_irq_handler(int irq, void *dev_id) -{ - kgsl_intr_isr(&gsl_driver.device[GSL_DEVICE_G12-1]); - return IRQ_HANDLED; -} - -static irqreturn_t z430_irq_handler(int irq, void *dev_id) -{ - kgsl_intr_isr(&gsl_driver.device[GSL_DEVICE_YAMATO-1]); - return IRQ_HANDLED; -} - -static int gpu_probe(struct platform_device *pdev) -{ - int i; - struct resource *res; - struct device *dev; - struct mxc_gpu_platform_data *pdata; - - pdata = pdev->dev.platform_data; - if (pdata) { - z160_version = pdata->z160_revision; - gpu_reserved_mem = pdata->reserved_mem_base; - gpu_reserved_mem_size = pdata->reserved_mem_size; - } - - for(i = 0; i < 2; i++){ - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!res) { - if (i == 0) { - printk(KERN_ERR "gpu: unable to get gpu irq\n"); - return -ENODEV; - } else { - break; - } - } - if(strcmp(res->name, "gpu_2d_irq") == 0){ - gpu_2d_irq = res->start; - }else if(strcmp(res->name, "gpu_3d_irq") == 0){ - gpu_3d_irq = res->start; - } - } - - for (i = 0; i < 3; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) { - gpu_2d_regbase = 0; - gpu_2d_regsize = 0; - gpu_3d_regbase = 0; - gpu_2d_regsize = 0; - gmem_size = 0; - gpu_reserved_mem = 0; - gpu_reserved_mem_size = 0; - break; - }else{ - if(strcmp(res->name, "gpu_2d_registers") == 0){ - gpu_2d_regbase = res->start; - gpu_2d_regsize = res->end - res->start + 1; - }else if(strcmp(res->name, "gpu_3d_registers") == 0){ - gpu_3d_regbase = res->start; - gpu_3d_regsize = res->end - res->start + 1; - }else if(strcmp(res->name, "gpu_graphics_mem") == 0){ - gmem_size = res->end - res->start + 1; - } - } - } - - if (gpu_3d_irq > 0) - { - if (request_irq(gpu_3d_irq, z430_irq_handler, 0, "ydx", NULL) < 0) { - printk(KERN_ERR "%s: request_irq error\n", __func__); - gpu_3d_irq = 0; - goto request_irq_error; - } - } - - if (gpu_2d_irq > 0) - { - if (request_irq(gpu_2d_irq, z160_irq_handler, 0, "g12", NULL) < 0) { - printk(KERN_ERR "DO NOT use uio_pdrv_genirq kernel module for X acceleration!\n"); - gpu_2d_irq = 0; - } - } - - if (kgsl_driver_init() != GSL_SUCCESS) { - printk(KERN_ERR "%s: kgsl_driver_init error\n", __func__); - goto kgsl_driver_init_error; - } - - gsl_kmod_major = register_chrdev(0, "gsl_kmod", &gsl_kmod_fops); - gsl_kmod_vmops.fault = gsl_kmod_fault; - - if (gsl_kmod_major <= 0) - { - pr_err("%s: register_chrdev error\n", __func__); - goto register_chrdev_error; - } - - gsl_kmod_class = class_create(THIS_MODULE, "gsl_kmod"); - - if (IS_ERR(gsl_kmod_class)) - { - pr_err("%s: class_create error\n", __func__); - goto class_create_error; - } - - #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) - dev = device_create(gsl_kmod_class, NULL, MKDEV(gsl_kmod_major, 0), "gsl_kmod"); - #else - dev = device_create(gsl_kmod_class, NULL, MKDEV(gsl_kmod_major, 0), NULL,"gsl_kmod"); - #endif - - if (!IS_ERR(dev)) - { - // gsl_kmod_data.device = dev; - return 0; - } - - pr_err("%s: device_create error\n", __func__); - -class_create_error: - class_destroy(gsl_kmod_class); - -register_chrdev_error: - unregister_chrdev(gsl_kmod_major, "gsl_kmod"); - -kgsl_driver_init_error: - kgsl_driver_close(); - if (gpu_2d_irq > 0) { - free_irq(gpu_2d_irq, NULL); - } - if (gpu_3d_irq > 0) { - free_irq(gpu_3d_irq, NULL); - } -request_irq_error: - return 0; // TODO: return proper error code -} - -static int gpu_remove(struct platform_device *pdev) -{ - device_destroy(gsl_kmod_class, MKDEV(gsl_kmod_major, 0)); - class_destroy(gsl_kmod_class); - unregister_chrdev(gsl_kmod_major, "gsl_kmod"); - - if (gpu_3d_irq) - { - free_irq(gpu_3d_irq, NULL); - } - - if (gpu_2d_irq) - { - free_irq(gpu_2d_irq, NULL); - } - - kgsl_driver_close(); - return 0; -} - -#ifdef CONFIG_PM -static int gpu_suspend(struct platform_device *pdev, pm_message_t state) -{ - int i; - gsl_powerprop_t power; - - power.flags = GSL_PWRFLAGS_POWER_OFF; - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - kgsl_device_setproperty( - (gsl_deviceid_t) (i+1), - GSL_PROP_DEVICE_POWER, - &power, - sizeof(gsl_powerprop_t)); - } - - return 0; -} - -static int gpu_resume(struct platform_device *pdev) -{ - int i; - gsl_powerprop_t power; - - power.flags = GSL_PWRFLAGS_POWER_ON; - for (i = 0; i < GSL_DEVICE_MAX; i++) - { - kgsl_device_setproperty( - (gsl_deviceid_t) (i+1), - GSL_PROP_DEVICE_POWER, - &power, - sizeof(gsl_powerprop_t)); - } - - return 0; -} -#else -#define gpu_suspend NULL -#define gpu_resume NULL -#endif /* !CONFIG_PM */ - -/*! Driver definition - */ -static struct platform_driver gpu_driver = { - .driver = { - .name = "mxc_gpu", - }, - .probe = gpu_probe, - .remove = gpu_remove, - .suspend = gpu_suspend, - .resume = gpu_resume, -}; - -static int __init gsl_kmod_init(void) -{ - return platform_driver_register(&gpu_driver); -} - -static void __exit gsl_kmod_exit(void) -{ - platform_driver_unregister(&gpu_driver); -} - -module_init(gsl_kmod_init); -module_exit(gsl_kmod_exit); -MODULE_AUTHOR("Advanced Micro Devices"); -MODULE_DESCRIPTION("AMD graphics core driver for i.MX"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c deleted file mode 100644 index 3685a5756ba..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.c +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include "gsl.h" -#include "gsl_kmod_cleanup.h" - -#include -#include - -/* - * Local helper functions to check and convert device/context id's (1 based) - * to index (0 based). - */ -static u32 device_id_to_device_index(gsl_deviceid_t device_id) -{ - KOS_ASSERT((GSL_DEVICE_ANY < device_id) && - (device_id <= GSL_DEVICE_MAX)); - return (u32)(device_id - 1); -} - -/* - * Local helper function to check and get pointer to per file descriptor data - */ -static struct gsl_kmod_per_fd_data *get_fd_private_data(struct file *fd) -{ - struct gsl_kmod_per_fd_data *datp; - - KOS_ASSERT(fd); - datp = (struct gsl_kmod_per_fd_data *)fd->private_data; - KOS_ASSERT(datp); - return datp; -} - -static s8 *find_first_entry_with(s8 *subarray, s8 context_id) -{ - s8 *entry = NULL; - int i; - -//printk(KERN_DEBUG "At %s, ctx_id = %d\n", __func__, context_id); - - KOS_ASSERT(context_id >= EMPTY_ENTRY); - KOS_ASSERT(context_id <= GSL_CONTEXT_MAX); // TODO: check the bound. - - for(i = 0; i < GSL_CONTEXT_MAX; i++) // TODO: check the bound. - { - if(subarray[i] == (s8)context_id) - { - entry = &subarray[i]; - break; - } - } - - return entry; -} - - -/* - * Add a memdesc into a list of allocated memory blocks for this file - * descriptor. The list is build in such a way that it implements FIFO (i.e. - * list). Traces of tiger, tiger_ri and VG11 CTs should be analysed to make - * informed choice. - * - * NOTE! gsl_memdesc_ts are COPIED so user space should NOT change them. - */ -int add_memblock_to_allocated_list(struct file *fd, - gsl_memdesc_t *allocated_block) -{ - int err = 0; - struct gsl_kmod_per_fd_data *datp; - struct gsl_kmod_alloc_list *lisp; - struct list_head *head; - - KOS_ASSERT(allocated_block); - - datp = get_fd_private_data(fd); - - head = &datp->allocated_blocks_head; - KOS_ASSERT(head); - - /* allocate and put new entry in the list of allocated memory descriptors */ - lisp = (struct gsl_kmod_alloc_list *)kzalloc(sizeof(struct gsl_kmod_alloc_list), GFP_KERNEL); - if(lisp) - { - INIT_LIST_HEAD(&lisp->node); - - /* builds FIFO (list_add() would build LIFO) */ - list_add_tail(&lisp->node, head); - memcpy(&lisp->allocated_block, allocated_block, sizeof(gsl_memdesc_t)); - lisp->allocation_number = datp->maximum_number_of_blocks; -// printk(KERN_DEBUG "List entry #%u allocated\n", lisp->allocation_number); - - datp->maximum_number_of_blocks++; - datp->number_of_allocated_blocks++; - - err = 0; - } - else - { - printk(KERN_ERR "%s: Could not allocate new list element\n", __func__); - err = -ENOMEM; - } - - return err; -} - -/* Delete a previously allocated memdesc from a list of allocated memory blocks */ -int del_memblock_from_allocated_list(struct file *fd, - gsl_memdesc_t *freed_block) -{ - struct gsl_kmod_per_fd_data *datp; - struct gsl_kmod_alloc_list *cursor, *next; - struct list_head *head; -// int is_different; - - KOS_ASSERT(freed_block); - - datp = get_fd_private_data(fd); - - head = &datp->allocated_blocks_head; - KOS_ASSERT(head); - - KOS_ASSERT(datp->number_of_allocated_blocks > 0); - - if(!list_empty(head)) - { - list_for_each_entry_safe(cursor, next, head, node) - { - if(cursor->allocated_block.gpuaddr == freed_block->gpuaddr) - { -// is_different = memcmp(&cursor->allocated_block, freed_block, sizeof(gsl_memdesc_t)); -// KOS_ASSERT(!is_different); - - list_del(&cursor->node); -// printk(KERN_DEBUG "List entry #%u freed\n", cursor->allocation_number); - kfree(cursor); - datp->number_of_allocated_blocks--; - return 0; - } - } - } - return -EINVAL; // tried to free entry not existing or from empty list. -} - -/* Delete all previously allocated memdescs from a list */ -int del_all_memblocks_from_allocated_list(struct file *fd) -{ - struct gsl_kmod_per_fd_data *datp; - struct gsl_kmod_alloc_list *cursor, *next; - struct list_head *head; - - datp = get_fd_private_data(fd); - - head = &datp->allocated_blocks_head; - KOS_ASSERT(head); - - if(!list_empty(head)) - { - printk(KERN_INFO "Not all allocated memory blocks were freed. Doing it now.\n"); - list_for_each_entry_safe(cursor, next, head, node) - { - printk(KERN_INFO "Freeing list entry #%u, gpuaddr=%x\n", (u32)cursor->allocation_number, cursor->allocated_block.gpuaddr); - kgsl_sharedmem_free(&cursor->allocated_block); - list_del(&cursor->node); - kfree(cursor); - } - } - - KOS_ASSERT(list_empty(head)); - datp->number_of_allocated_blocks = 0; - - return 0; -} - -void init_created_contexts_array(s8 *array) -{ - memset((void*)array, EMPTY_ENTRY, GSL_DEVICE_MAX * GSL_CONTEXT_MAX); -} - - -void add_device_context_to_array(struct file *fd, - gsl_deviceid_t device_id, - unsigned int context_id) -{ - struct gsl_kmod_per_fd_data *datp; - s8 *entry; - s8 *subarray; - u32 device_index = device_id_to_device_index(device_id); - - datp = get_fd_private_data(fd); - - subarray = datp->created_contexts_array[device_index]; - entry = find_first_entry_with(subarray, EMPTY_ENTRY); - - KOS_ASSERT(entry); - KOS_ASSERT((datp->created_contexts_array[device_index] <= entry) && - (entry < datp->created_contexts_array[device_index] + GSL_CONTEXT_MAX)); - KOS_ASSERT(context_id < 127); - *entry = (s8)context_id; -} - -void del_device_context_from_array(struct file *fd, - gsl_deviceid_t device_id, - unsigned int context_id) -{ - struct gsl_kmod_per_fd_data *datp; - u32 device_index = device_id_to_device_index(device_id); - s8 *entry; - s8 *subarray; - - datp = get_fd_private_data(fd); - - KOS_ASSERT(context_id < 127); - subarray = &(datp->created_contexts_array[device_index][0]); - entry = find_first_entry_with(subarray, context_id); - KOS_ASSERT(entry); - KOS_ASSERT((datp->created_contexts_array[device_index] <= entry) && - (entry < datp->created_contexts_array[device_index] + GSL_CONTEXT_MAX)); - *entry = EMPTY_ENTRY; -} - -void del_all_devices_contexts(struct file *fd) -{ - struct gsl_kmod_per_fd_data *datp; - gsl_deviceid_t id; - u32 device_index; - u32 ctx_array_index; - s8 ctx; - int err; - - datp = get_fd_private_data(fd); - - /* device_id is 1 based */ - for(id = GSL_DEVICE_ANY + 1; id <= GSL_DEVICE_MAX; id++) - { - device_index = device_id_to_device_index(id); - for(ctx_array_index = 0; ctx_array_index < GSL_CONTEXT_MAX; ctx_array_index++) - { - ctx = datp->created_contexts_array[device_index][ctx_array_index]; - if(ctx != EMPTY_ENTRY) - { - err = kgsl_context_destroy(id, ctx); - if(err != GSL_SUCCESS) - { - printk(KERN_ERR "%s: could not destroy context %d on device id = %u\n", __func__, ctx, id); - } - else - { - printk(KERN_DEBUG "%s: Destroyed context %d on device id = %u\n", __func__, ctx, id); - } - } - } - } -} - diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h deleted file mode 100644 index 475ee3be2e5..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_kmod_cleanup.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Advanced Micro Devices nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GSL_KMOD_CLEANUP_H -#define __GSL_KMOD_CLEANUP_H -#include "gsl_types.h" - -#include -#include -#include -#include - -#if (GSL_CONTEXT_MAX > 127) - #error created_contexts_array supports context numbers only 127 or less. -#endif - -static const s8 EMPTY_ENTRY = -1; - -/* A structure to make list of allocated memory blocks. List per fd. */ -/* should probably be allocated from slab cache to minimise fragmentation */ -struct gsl_kmod_alloc_list -{ - struct list_head node; - gsl_memdesc_t allocated_block; - u32 allocation_number; -}; - -/* A structure to hold abovementioned list of blocks. Contain per fd data. */ -struct gsl_kmod_per_fd_data -{ - struct list_head allocated_blocks_head; // list head - u32 maximum_number_of_blocks; - u32 number_of_allocated_blocks; - s8 created_contexts_array[GSL_DEVICE_MAX][GSL_CONTEXT_MAX]; -}; - - -/* - * prototypes - */ - -/* allocated memory block tracking */ -int add_memblock_to_allocated_list(struct file *fd, - gsl_memdesc_t *allocated_block); - -int del_memblock_from_allocated_list(struct file *fd, - gsl_memdesc_t *freed_block); - -int del_all_memblocks_from_allocated_list(struct file *fd); - -/* created contexts tracking */ -void init_created_contexts_array(s8 *array); - -void add_device_context_to_array(struct file *fd, - gsl_deviceid_t device_id, - unsigned int context_id); - -void del_device_context_from_array(struct file *fd, - gsl_deviceid_t device_id, - unsigned int context_id); - -void del_all_devices_contexts(struct file *fd); - -#endif // __GSL_KMOD_CLEANUP_H - diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c deleted file mode 100644 index 7fee7b81441..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "gsl_linux_map.h" - -struct gsl_linux_map -{ - struct list_head list; - unsigned int gpu_addr; - void *kernel_virtual_addr; - unsigned int size; -}; - -static LIST_HEAD(gsl_linux_map_list); -static DEFINE_MUTEX(gsl_linux_map_mutex); - -int gsl_linux_map_init() -{ - mutex_lock(&gsl_linux_map_mutex); - INIT_LIST_HEAD(&gsl_linux_map_list); - mutex_unlock(&gsl_linux_map_mutex); - - return 0; -} - -void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size) -{ - struct gsl_linux_map * map; - struct list_head *p; - void *va; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each(p, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - if(map->gpu_addr == gpu_addr){ - mutex_unlock(&gsl_linux_map_mutex); - return map->kernel_virtual_addr; - } - } - - va = __vmalloc(size, GFP_KERNEL, pgprot_noncached(pgprot_kernel)); - if(va == NULL){ - mutex_unlock(&gsl_linux_map_mutex); - return NULL; - } - - map = (struct gsl_linux_map *)kmalloc(sizeof(*map), GFP_KERNEL); - map->gpu_addr = gpu_addr; - map->kernel_virtual_addr = va; - map->size = size; - - INIT_LIST_HEAD(&map->list); - list_add_tail(&map->list, &gsl_linux_map_list); - - mutex_unlock(&gsl_linux_map_mutex); - return va; -} - -void gsl_linux_map_free(unsigned int gpu_addr) -{ - int found = 0; - struct gsl_linux_map * map; - struct list_head *p; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each(p, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - if(map->gpu_addr == gpu_addr){ - found = 1; - break; - } - } - - if(found){ - vfree(map->kernel_virtual_addr); - list_del(&map->list); - kfree(map); - } - - mutex_unlock(&gsl_linux_map_mutex); -} - -void *gsl_linux_map_find(unsigned int gpu_addr) -{ - struct gsl_linux_map * map; - struct list_head *p; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each(p, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - if(map->gpu_addr == gpu_addr){ - mutex_unlock(&gsl_linux_map_mutex); - return map->kernel_virtual_addr; - } - } - - mutex_unlock(&gsl_linux_map_mutex); - return NULL; -} - -void *gsl_linux_map_read(void *dst, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace) -{ - struct gsl_linux_map * map; - struct list_head *p; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each(p, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - if(map->gpu_addr <= gpuoffset && - (map->gpu_addr + map->size) > gpuoffset){ - void *src = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr); - mutex_unlock(&gsl_linux_map_mutex); - if (touserspace) - { - return (void *)copy_to_user(dst, map->kernel_virtual_addr + gpuoffset - map->gpu_addr, sizebytes); - } - else - { - return memcpy(dst, src, sizebytes); - } - } - } - - mutex_unlock(&gsl_linux_map_mutex); - return NULL; -} - -void *gsl_linux_map_write(void *src, unsigned int gpuoffset, unsigned int sizebytes, unsigned int fromuserspace) -{ - struct gsl_linux_map * map; - struct list_head *p; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each(p, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - if(map->gpu_addr <= gpuoffset && - (map->gpu_addr + map->size) > gpuoffset){ - void *dst = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr); - mutex_unlock(&gsl_linux_map_mutex); - if (fromuserspace) - { - return (void *)copy_from_user(map->kernel_virtual_addr + gpuoffset - map->gpu_addr, src, sizebytes); - } - else - { - return memcpy(dst, src, sizebytes); - } - } - } - - mutex_unlock(&gsl_linux_map_mutex); - return NULL; -} - -void *gsl_linux_map_set(unsigned int gpuoffset, unsigned int value, unsigned int sizebytes) -{ - struct gsl_linux_map * map; - struct list_head *p; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each(p, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - if(map->gpu_addr <= gpuoffset && - (map->gpu_addr + map->size) > gpuoffset){ - void *ptr = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr); - mutex_unlock(&gsl_linux_map_mutex); - return memset(ptr, value, sizebytes); - } - } - - mutex_unlock(&gsl_linux_map_mutex); - return NULL; -} - -int gsl_linux_map_destroy() -{ - struct gsl_linux_map * map; - struct list_head *p, *tmp; - - mutex_lock(&gsl_linux_map_mutex); - - list_for_each_safe(p, tmp, &gsl_linux_map_list){ - map = list_entry(p, struct gsl_linux_map, list); - vfree(map->kernel_virtual_addr); - list_del(&map->list); - kfree(map); - } - - INIT_LIST_HEAD(&gsl_linux_map_list); - - mutex_unlock(&gsl_linux_map_mutex); - return 0; -} diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h b/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h deleted file mode 100644 index ebbe94a75e1..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/gsl_linux_map.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Advanced Micro Devices nor - * the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GSL_LINUX_MAP_H__ -#define __GSL_LINUX_MAP_H__ - -#include "gsl_halconfig.h" - -#define GSL_LINUX_MAP_RANGE_START (1024*1024) -#define GSL_LINUX_MAP_RANGE_END (GSL_LINUX_MAP_RANGE_START+GSL_HAL_SHMEM_SIZE_EMEM1_MMU) - -int gsl_linux_map_init(void); -void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size); -void gsl_linux_map_free(unsigned int gpu_addr); -void *gsl_linux_map_find(unsigned int gpu_addr); -void *gsl_linux_map_read(void *dst, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace); -void *gsl_linux_map_write(void *src, unsigned int gpuoffset, unsigned int sizebytes, unsigned int fromuserspace); -void *gsl_linux_map_set(unsigned int gpuoffset, unsigned int value, unsigned int sizebytes); -int gsl_linux_map_destroy(void); - -#endif diff --git a/drivers/mxc/amd-gpu/platform/hal/linux/misc.c b/drivers/mxc/amd-gpu/platform/hal/linux/misc.c deleted file mode 100644 index b3a4582bb15..00000000000 --- a/drivers/mxc/amd-gpu/platform/hal/linux/misc.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -#include -#include -#include -#include -#include - -typedef struct _gsl_autogate_t { - struct timer_list timer; - spinlock_t lock; - int active; - /* pending indicate the timer has been fired but clock not yet disabled. */ - int pending; - int timeout; - gsl_device_t *dev; - struct work_struct dis_task; -} gsl_autogate_t; - -static gsl_autogate_t *g_autogate[2]; -static DEFINE_SEMAPHORE(sem_dev); - -#define KGSL_DEVICE_IDLE_TIMEOUT 5000 /* unit ms */ - -static void clk_disable_task(struct work_struct *work) -{ - gsl_autogate_t *autogate; - autogate = container_of(work, gsl_autogate_t, dis_task); - if (autogate->dev->ftbl.device_idle) - autogate->dev->ftbl.device_idle(autogate->dev, GSL_TIMEOUT_DEFAULT); - kgsl_clock(autogate->dev->id, 0); - autogate->pending = 0; -} - -static int _kgsl_device_active(gsl_device_t *dev, int all) -{ - unsigned long flags; - int to_active = 0; - gsl_autogate_t *autogate = dev->autogate; - if (!autogate) { - printk(KERN_ERR "%s: autogate has exited!\n", __func__); - return 0; - } -// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, dev->id, autogate->active); - - spin_lock_irqsave(&autogate->lock, flags); - if (in_interrupt()) { - if (!autogate->active && !autogate->pending) - BUG(); - } else { - to_active = !autogate->active; - autogate->active = 1; - } - mod_timer(&autogate->timer, jiffies + msecs_to_jiffies(autogate->timeout)); - spin_unlock_irqrestore(&autogate->lock, flags); - if (to_active) - kgsl_clock(autogate->dev->id, 1); - if (to_active && all) { - int index; - index = autogate->dev->id == GSL_DEVICE_G12 ? GSL_DEVICE_YAMATO - 1 : - GSL_DEVICE_G12 - 1; - down(&sem_dev); - if (g_autogate[index]) - _kgsl_device_active(g_autogate[index]->dev, 0); - up(&sem_dev); - } - return 0; -} -int kgsl_device_active(gsl_device_t *dev) -{ - return _kgsl_device_active(dev, 0); -} - -static void kgsl_device_inactive(unsigned long data) -{ - gsl_autogate_t *autogate = (gsl_autogate_t *)data; - unsigned long flags; - -// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, autogate->dev->id, autogate->active); - del_timer(&autogate->timer); - spin_lock_irqsave(&autogate->lock, flags); - WARN(!autogate->active, "GPU Device %d is already inactive\n", autogate->dev->id); - if (autogate->active) { - autogate->active = 0; - autogate->pending = 1; - schedule_work(&autogate->dis_task); - } - spin_unlock_irqrestore(&autogate->lock, flags); -} - -int kgsl_device_clock(gsl_deviceid_t id, int enable) -{ - int ret = GSL_SUCCESS; - gsl_device_t *device; - - device = &gsl_driver.device[id-1]; // device_id is 1 based - if (device->flags & GSL_FLAGS_INITIALIZED) { - if (enable) - kgsl_device_active(device); - else - kgsl_device_inactive((unsigned long)device); - } else { - printk(KERN_ERR "%s: Dev %d clock is already off!\n", __func__, id); - ret = GSL_FAILURE; - } - - return ret; -} - -int kgsl_device_autogate_init(gsl_device_t *dev) -{ - gsl_autogate_t *autogate; - -// printk(KERN_ERR "%s:%d id %d\n", __func__, __LINE__, dev->id); - autogate = kzalloc(sizeof(gsl_autogate_t), GFP_KERNEL); - if (!autogate) { - printk(KERN_ERR "%s: out of memory!\n", __func__); - return -ENOMEM; - } - down(&sem_dev); - autogate->dev = dev; - autogate->active = 1; - spin_lock_init(&autogate->lock); - autogate->timeout = KGSL_DEVICE_IDLE_TIMEOUT; - init_timer(&autogate->timer); - autogate->timer.expires = jiffies + msecs_to_jiffies(autogate->timeout); - autogate->timer.function = kgsl_device_inactive; - autogate->timer.data = (unsigned long)autogate; - add_timer(&autogate->timer); - INIT_WORK(&autogate->dis_task, clk_disable_task); - dev->autogate = autogate; - g_autogate[dev->id - 1] = autogate; - up(&sem_dev); - return 0; -} - -void kgsl_device_autogate_exit(gsl_device_t *dev) -{ - gsl_autogate_t *autogate = dev->autogate; - -// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, dev->id, autogate->active); - down(&sem_dev); - del_timer_sync(&autogate->timer); - if (!autogate->active) - kgsl_clock(autogate->dev->id, 1); - flush_work(&autogate->dis_task); - g_autogate[dev->id - 1] = NULL; - up(&sem_dev); - kfree(autogate); - dev->autogate = NULL; -} From 45d30cd17e215a53914da758ed220f59bc9c2061 Mon Sep 17 00:00:00 2001 From: Matt Sealey Date: Tue, 27 Sep 2011 15:55:05 -0500 Subject: [PATCH 15/32] gpu: remove one last file --- .../mxc/amd-gpu/os/kernel/src/linux/kos_lib.c | 661 ------------------ 1 file changed, 661 deletions(-) delete mode 100644 drivers/mxc/amd-gpu/os/kernel/src/linux/kos_lib.c diff --git a/drivers/mxc/amd-gpu/os/kernel/src/linux/kos_lib.c b/drivers/mxc/amd-gpu/os/kernel/src/linux/kos_lib.c deleted file mode 100644 index 4ead84ffe0d..00000000000 --- a/drivers/mxc/amd-gpu/os/kernel/src/linux/kos_lib.c +++ /dev/null @@ -1,661 +0,0 @@ -/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kos_libapi.h" - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// -//#define KOS_STATS_ENABLE - -////////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#define KOS_MALLOC(s) kmalloc(s, GFP_KERNEL) -#define KOS_CALLOC(num, size) kcalloc(num, size, GFP_KERNEL) -#define KOS_REALLOC(p, s) krealloc(p, s, GFP_KERNEL) -#define KOS_FREE(p) kfree(p); p = 0 -#define KOS_DBGFLAGS_SET(flag) - -////////////////////////////////////////////////////////////////////////////// -// stats -////////////////////////////////////////////////////////////////////////////// -#ifdef KOS_STATS_ENABLE -os_stats_t kos_stats = {0, 0, 0, 0, 0, 0, 0, 0}; -#define KOS_STATS(x) x -#else -#define KOS_STATS(x) -#endif - -////////////////////////////////////////////////////////////////////////////// -// assert API -////////////////////////////////////////////////////////////////////////////// -KOS_API void -kos_assert_hook(const char* file, int line, int expression) -{ - if (expression) - { - return; - } - else - { - printk(KERN_ERR "Assertion failed at %s:%d!\n", file, line); - //BUG(); - } - - // put breakpoint here -} - - -////////////////////////////////////////////////////////////////////////////// -// heap API (per process) -////////////////////////////////////////////////////////////////////////////// -KOS_API void* -kos_malloc(int size) -{ - void* ptr = KOS_MALLOC(size); - - KOS_ASSERT(ptr); - KOS_STATS(kos_stats.heap_allocs++); - KOS_STATS(kos_stats.heap_alloc_bytes += size); - - return (ptr); -} - - -//---------------------------------------------------------------------------- - -KOS_API void* -kos_calloc(int num, int size) -{ - void* ptr = KOS_CALLOC(num, size); - - KOS_ASSERT(ptr); - KOS_STATS(kos_stats.heap_allocs++); - KOS_STATS(kos_stats.heap_alloc_bytes += (size * num)); - - return (ptr); -} - -//---------------------------------------------------------------------------- - -KOS_API void* -kos_realloc(void* ptr, int size) -{ - void* newptr; - - KOS_ASSERT(ptr); - newptr = KOS_REALLOC(ptr, size); - - KOS_ASSERT(newptr); - - return (newptr); -} - -//---------------------------------------------------------------------------- - -KOS_API void -kos_free(void* ptr) -{ - KOS_STATS(kos_stats.heap_frees++); - - KOS_FREE(ptr); -} - - -////////////////////////////////////////////////////////////////////////////// -// shared heap API (cross process) -////////////////////////////////////////////////////////////////////////////// -KOS_API void* -kos_shared_malloc(int size) -{ - void* ptr; - - ptr = NULL; // shared alloc - - KOS_ASSERT(ptr); - KOS_STATS(kos_stats.shared_heap_allocs++); - KOS_STATS(kos_stats.shared_heap_alloc_bytes += size); - - return (ptr); -} - -//---------------------------------------------------------------------------- - -KOS_API void* -kos_shared_calloc(int num, int size) -{ - void* ptr; - - ptr = NULL; // shared calloc - - KOS_ASSERT(ptr); - KOS_STATS(kos_stats.shared_heap_allocs++); - KOS_STATS(kos_stats.shared_heap_alloc_bytes += (size * num)); - return (ptr); -} - -//---------------------------------------------------------------------------- - -KOS_API void* -kos_shared_realloc(void* ptr, int size) -{ - void* newptr; - (void) ptr; // unreferenced formal parameter - (void) size; // unreferenced formal parameter - - newptr = NULL; // shared realloc - - KOS_ASSERT(newptr); - - return (newptr); -} - -//---------------------------------------------------------------------------- - -KOS_API void -kos_shared_free(void* ptr) -{ - (void) ptr; // unreferenced formal parameter - KOS_ASSERT(0); // not implemented - - KOS_STATS(kos_stats.shared_heap_frees++); - - // shared free -} - -////////////////////////////////////////////////////////////////////////////// -// memory access API -////////////////////////////////////////////////////////////////////////////// -KOS_API void* -kos_memcpy(void* dst, const void* src, int count) -{ - KOS_ASSERT(src); - KOS_ASSERT(dst); - return memcpy(dst, src, count); -} - -//---------------------------------------------------------------------------- - -KOS_API void* -kos_memset(void* dst, int value, int count) -{ - KOS_ASSERT(dst); - return memset(dst, value, count); -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_memcmp(void* dst, void* src, int count) -{ - KOS_ASSERT(src); - KOS_ASSERT(dst); - return memcmp(dst, src, count); -} - -////////////////////////////////////////////////////////////////////////////// -// physical memory API -////////////////////////////////////////////////////////////////////////////// -KOS_API int -kos_alloc_physical(void** virt_addr, void** phys_addr, int pages) -{ - *virt_addr = dma_alloc_coherent(NULL, pages*PAGE_SIZE, (dma_addr_t*)*phys_addr, GFP_DMA | GFP_KERNEL); - return *virt_addr ? OS_SUCCESS : OS_FAILURE; -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_free_physical(void* virt_addr, int pages) -{ - (void) virt_addr; // unreferenced formal parameter - (void) pages; // unreferenced formal parameter - - return (OS_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_map_physical(void** virt_addr, void** phys_addr, int pages) -{ - (void) virt_addr; // unreferenced formal parameter - (void) phys_addr; // unreferenced formal parameter - (void) pages; // unreferenced formal parameter - - return (OS_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_unmap_physical(void* virt_addr, int pages) -{ - (void) virt_addr; // unreferenced formal parameter - (void) pages; // unreferenced formal parameter - - return (OS_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KOS_API void -kos_memoryfence(void) -{ -} - -//---------------------------------------------------------------------------- - -KOS_API void -kos_enable_memoryleakcheck(void) -{ - // perform automatic leak checking at program exit - KOS_DBGFLAGS_SET(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); -} - -////////////////////////////////////////////////////////////////////////////// -// string API -////////////////////////////////////////////////////////////////////////////// - -KOS_API char* -kos_strcpy(char* strdestination, const char* strsource) -{ - KOS_ASSERT(strdestination); - KOS_ASSERT(strsource); - return strcpy(strdestination, strsource); -} - -//---------------------------------------------------------------------------- - -KOS_API char* -kos_strncpy(char* destination, const char* source, int length) -{ - KOS_ASSERT(destination); - KOS_ASSERT(source); - return strncpy(destination, source, length); -} - -//---------------------------------------------------------------------------- - -KOS_API char* -kos_strcat(char* strdestination, const char* strsource) -{ - KOS_ASSERT(strdestination); - KOS_ASSERT(strsource); - return strcat(strdestination, strsource); -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_strcmp(const char* string1, const char* string2) -{ - KOS_ASSERT(string1); - KOS_ASSERT(string2); - return strcmp(string1, string2); -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_strncmp(const char* string1, const char* string2, int length) -{ - KOS_ASSERT(string1); - KOS_ASSERT(string2); - return strncmp(string1, string2, length); -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_strlen(const char* string) -{ - KOS_ASSERT(string); - return strlen(string); -} - -////////////////////////////////////////////////////////////////////////////// -// sync API -////////////////////////////////////////////////////////////////////////////// - -KOS_API oshandle_t -kos_mutex_create(const char *name) -{ - struct mutex *mutex = KOS_MALLOC(sizeof(struct mutex)); - if (!mutex) - return 0; - mutex_init(mutex); - return mutex; -} - -//---------------------------------------------------------------------------- - -KOS_API oshandle_t -kos_mutex_open(const char *name) -{ - // not implemented - return 0; -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_mutex_free(oshandle_t mutexhandle) -{ - struct mutex *mutex = (struct mutex *)mutexhandle; - if (!mutex) - return OS_FAILURE; - KOS_FREE(mutex); - return OS_SUCCESS; -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_mutex_lock(oshandle_t mutexhandle) -{ - struct mutex *mutex = (struct mutex *)mutexhandle; - if (!mutex) - return OS_FAILURE; - if (mutex_lock_interruptible(mutex) == -EINTR) - return OS_FAILURE; - return OS_SUCCESS; -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_mutex_locktry(oshandle_t mutexhandle) -{ - struct mutex *mutex = (struct mutex *)mutexhandle; - if (!mutex) - return OS_FAILURE; - if (!mutex_trylock(mutex)) - return OS_FAILURE; - return OS_SUCCESS; -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_mutex_unlock(oshandle_t mutexhandle) -{ - struct mutex *mutex = (struct mutex *)mutexhandle; - if (!mutex) - return OS_FAILURE; - KOS_ASSERT(mutex_is_locked(mutex)); - mutex_unlock(mutex); - return OS_SUCCESS; -} - -//---------------------------------------------------------------------------- - -KOS_API unsigned int -kos_process_getid(void) -{ - return current->tgid; -} - -//---------------------------------------------------------------------------- - -/* ------------------------------------------------------------------- *//* - * \brief Creates new event semaphore - * \param uint32 a_manualReset - * When this param is zero, system automatically resets the - * event state to nonsignaled after waiting thread has been - * released - * \return oshandle_t -*//* ------------------------------------------------------------------- */ -KOS_API oshandle_t -kos_event_create(int a_manualReset) -{ - struct completion *comp = KOS_MALLOC(sizeof(struct completion)); - - KOS_ASSERT(comp); - if(!comp) - { - return (oshandle_t)NULL; - } - - init_completion(comp); - - return (oshandle_t)comp; -} - -/* ------------------------------------------------------------------- *//* - * \brief Frees event semaphore - * \param oshandle_t a_event, event semaphore - * \return int -*//* ------------------------------------------------------------------- */ -KOS_API int -kos_event_destroy(oshandle_t a_event) -{ - struct completion *comp = (struct completion *)a_event; - - KOS_ASSERT(comp); -// KOS_ASSERT(completion_done(comp)); - - KOS_FREE(comp); - return (OS_SUCCESS); -} - -/* ------------------------------------------------------------------- *//* - * \brief Signals event semaphore - * \param oshandle_t a_event, event semaphore - * \return int -*//* ------------------------------------------------------------------- */ -KOS_API int -kos_event_signal(oshandle_t a_event) -{ - struct completion *comp = (struct completion *)a_event; - - KOS_ASSERT(comp); - complete_all(comp); // perhaps complete_all? - return (OS_SUCCESS); -} - -/* ------------------------------------------------------------------- *//* - * \brief Resets event semaphore state to nonsignaled - * \param oshandle_t a_event, event semaphore - * \return int -*//* ------------------------------------------------------------------- */ -KOS_API int -kos_event_reset(oshandle_t a_event) -{ - struct completion *comp = (struct completion *)a_event; - - KOS_ASSERT(comp); - INIT_COMPLETION(*comp); - return (OS_SUCCESS); -} - -/* ------------------------------------------------------------------- *//* - * \brief Waits event semaphore to be signaled - * \param oshandle_t a_event, event semaphore - * \return int -*//* ------------------------------------------------------------------- */ -KOS_API int -kos_event_wait(oshandle_t a_event, int a_milliSeconds) -{ - struct completion *comp = (struct completion *)a_event; - - KOS_ASSERT(comp); - if(a_milliSeconds == OS_INFINITE) - { - wait_for_completion_killable(comp); - } - else - { - // should interpret milliseconds really to jiffies? - if(!wait_for_completion_timeout(comp, msecs_to_jiffies(a_milliSeconds))) - { - return (OS_FAILURE); - } - } - return (OS_SUCCESS); -} - -//---------------------------------------------------------------------------- - -KOS_API void -kos_sleep(unsigned int milliseconds) -{ - msleep(milliseconds); -} - -////////////////////////////////////////////////////////////////////////////// -// query API -////////////////////////////////////////////////////////////////////////////// - -static int -kos_get_endianness(void) -{ - int value; - char* ptr; - - value = 0x01FFFF00; - - ptr = (char*)&value; - - KOS_ASSERT((*ptr == 0x00) || (*ptr == 0x01)); - - return (int)*ptr; -} - -//---------------------------------------------------------------------------- - -KOS_API int -kos_get_sysinfo(os_sysinfo_t* sysinfo) -{ - KOS_ASSERT(sysinfo); - if (!sysinfo) return (OS_FAILURE); - - sysinfo->cpu_mhz = 0; - sysinfo->cpu_type = 0; - sysinfo->cpu_version = 0; - sysinfo->os_type = 0; - sysinfo->os_version = 0; - sysinfo->sysmem_size = 0; - sysinfo->page_size = 0x1000; - sysinfo->max_path = PATH_MAX; -// sysinfo->tls_slots = TLS_MINIMUM_AVAILABLE - 1; - sysinfo->endianness = kos_get_endianness(); - - return (OS_SUCCESS); -} - -//---------------------------------------------------------------------------- - -#ifdef KOS_STATS_ENABLE -KOS_API int -kos_get_stats(os_stats_t* stats) -{ - kos_memcpy(stats, &kos_stats, sizeof(os_stats_t)); - return (OS_SUCCESS); -} -#else -KOS_API int -kos_get_stats(os_stats_t* stats) -{ - return (OS_FAILURE); -} -#endif // KOS_STATS - -/*-------------------------------------------------------------------*//*! - * \brief Sync block API - * Same mutex needed from different blocks of driver - *//*-------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------*//*! - * \external - * \brief Sync block start - * - * \param void - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ - -static struct mutex* syncblock_mutex = 0; - -KOS_API int kos_syncblock_start(void) -{ - int return_value; - - if(!syncblock_mutex) - { - syncblock_mutex = kos_mutex_create("syncblock"); - } - - if(syncblock_mutex) - { - return_value = kos_mutex_lock(syncblock_mutex); - } - else - { - return_value = -1; - } - - return return_value; -} -/*-------------------------------------------------------------------*//*! - * \external - * \brief Sync block end - * - * \param void - * \return Returns NULL if no error, otherwise an error code. - *//*-------------------------------------------------------------------*/ -KOS_API int kos_syncblock_end(void) -{ - int return_value; - - if(syncblock_mutex) - { - return_value = kos_mutex_unlock(syncblock_mutex); - } - else - { - return_value = -1; - } - - return return_value; -} - -KOS_API oshandle_t kos_thread_create(oshandle_t a_function, unsigned int* a_threadId) -{ - struct task_struct *task = kthread_run(a_function, 0, "kos_thread_%p", a_threadId); - *a_threadId = (unsigned int)task; - return (oshandle_t)task; -} - -KOS_API void kos_thread_destroy( oshandle_t a_task ) -{ - kthread_stop((struct task_struct *)a_task); -} From 691ac5299982f2eb7bc8621df8ab4e1e78b3f10e Mon Sep 17 00:00:00 2001 From: Matt Sealey Date: Tue, 27 Sep 2011 15:55:32 -0500 Subject: [PATCH 16/32] gpu: update platform data to match BSP --- arch/arm/plat-mxc/include/mach/mxc_gpu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-mxc/include/mach/mxc_gpu.h b/arch/arm/plat-mxc/include/mach/mxc_gpu.h index a43d6ec99bf..4861d2677fa 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_gpu.h +++ b/arch/arm/plat-mxc/include/mach/mxc_gpu.h @@ -17,6 +17,7 @@ struct mxc_gpu_platform_data { int z160_revision; + int enable_mmu; resource_size_t reserved_mem_base; resource_size_t reserved_mem_size; }; From 63d77d0861fb6d2ae52f0321d18d2613bf1f04d0 Mon Sep 17 00:00:00 2001 From: Matt Sealey Date: Tue, 27 Sep 2011 13:52:22 -0500 Subject: [PATCH 17/32] Sync GPU to production kernel --- drivers/mxc/amd-gpu/Kconfig | 6 + drivers/mxc/amd-gpu/Makefile | 51 +- drivers/mxc/amd-gpu/gsl_cmdstream.c | 243 +++ drivers/mxc/amd-gpu/gsl_cmdwindow.c | 132 ++ drivers/mxc/amd-gpu/gsl_context.c | 73 + drivers/mxc/amd-gpu/gsl_debug_pm4.c | 942 +++++++++ drivers/mxc/amd-gpu/gsl_device.c | 673 ++++++ drivers/mxc/amd-gpu/gsl_drawctxt.c | 1796 +++++++++++++++++ drivers/mxc/amd-gpu/gsl_driver.c | 322 +++ drivers/mxc/amd-gpu/gsl_g12.c | 909 +++++++++ drivers/mxc/amd-gpu/gsl_hal.c | 570 ++++++ drivers/mxc/amd-gpu/gsl_intrmgr.c | 301 +++ drivers/mxc/amd-gpu/gsl_kmod.c | 983 +++++++++ drivers/mxc/amd-gpu/gsl_kmod_cleanup.c | 269 +++ drivers/mxc/amd-gpu/gsl_kmod_cleanup.h | 90 + drivers/mxc/amd-gpu/gsl_linux_map.c | 221 ++ drivers/mxc/amd-gpu/gsl_log.c | 557 +++++ drivers/mxc/amd-gpu/gsl_memmgr.c | 970 +++++++++ drivers/mxc/amd-gpu/gsl_mmu.c | 1054 ++++++++++ drivers/mxc/amd-gpu/gsl_ringbuffer.c | 1148 +++++++++++ drivers/mxc/amd-gpu/gsl_sharedmem.c | 940 +++++++++ drivers/mxc/amd-gpu/gsl_tbdump.c | 241 +++ drivers/mxc/amd-gpu/gsl_yamato.c | 918 +++++++++ .../mxc/amd-gpu/include/api/gsl_displayapi.h | 32 +- drivers/mxc/amd-gpu/include/api/gsl_klibapi.h | 93 +- drivers/mxc/amd-gpu/include/api/gsl_libapi.h | 113 +- drivers/mxc/amd-gpu/include/api/gsl_types.h | 42 + drivers/mxc/amd-gpu/include/gsl.h | 6 +- drivers/mxc/amd-gpu/include/gsl_buildconfig.h | 2 +- drivers/mxc/amd-gpu/include/gsl_cmdstream.h | 22 - drivers/mxc/amd-gpu/include/gsl_config.h | 2 +- drivers/mxc/amd-gpu/include/gsl_debug.h | 3 - drivers/mxc/amd-gpu/include/gsl_device.h | 108 +- drivers/mxc/amd-gpu/include/gsl_driver.h | 32 +- drivers/mxc/amd-gpu/include/gsl_hal.h | 15 +- drivers/mxc/amd-gpu/include/gsl_halconfig.h | 15 +- drivers/mxc/amd-gpu/include/gsl_hwaccess.h | 140 ++ drivers/mxc/amd-gpu/include/gsl_intrmgr.h | 3 +- drivers/mxc/amd-gpu/include/gsl_linux_map.h | 46 + drivers/mxc/amd-gpu/include/gsl_log.h | 18 +- drivers/mxc/amd-gpu/include/gsl_memmgr.h | 18 +- drivers/mxc/amd-gpu/include/gsl_mmu.h | 13 +- drivers/mxc/amd-gpu/include/gsl_ringbuffer.h | 26 +- .../mxc/amd-gpu/include/reg/vgc/vgregs_z160.h | 6 +- drivers/mxc/amd-gpu/include/reg/yamato.h | 6 - .../include/reg/yamato/22/yamato_genreg.h | 2 +- .../include/reg/yamato/22/yamato_registers.h | 4 +- drivers/mxc/amd-gpu/misc.c | 171 ++ drivers/mxc/amd-gpu/pfp_microcode_nrt.inl | 327 +++ drivers/mxc/amd-gpu/pm4_microcode.inl | 816 ++++++++ 50 files changed, 15099 insertions(+), 391 deletions(-) create mode 100644 drivers/mxc/amd-gpu/gsl_cmdstream.c create mode 100644 drivers/mxc/amd-gpu/gsl_cmdwindow.c create mode 100644 drivers/mxc/amd-gpu/gsl_context.c create mode 100644 drivers/mxc/amd-gpu/gsl_debug_pm4.c create mode 100644 drivers/mxc/amd-gpu/gsl_device.c create mode 100644 drivers/mxc/amd-gpu/gsl_drawctxt.c create mode 100644 drivers/mxc/amd-gpu/gsl_driver.c create mode 100644 drivers/mxc/amd-gpu/gsl_g12.c create mode 100644 drivers/mxc/amd-gpu/gsl_hal.c create mode 100644 drivers/mxc/amd-gpu/gsl_intrmgr.c create mode 100644 drivers/mxc/amd-gpu/gsl_kmod.c create mode 100644 drivers/mxc/amd-gpu/gsl_kmod_cleanup.c create mode 100644 drivers/mxc/amd-gpu/gsl_kmod_cleanup.h create mode 100644 drivers/mxc/amd-gpu/gsl_linux_map.c create mode 100644 drivers/mxc/amd-gpu/gsl_log.c create mode 100644 drivers/mxc/amd-gpu/gsl_memmgr.c create mode 100644 drivers/mxc/amd-gpu/gsl_mmu.c create mode 100644 drivers/mxc/amd-gpu/gsl_ringbuffer.c create mode 100644 drivers/mxc/amd-gpu/gsl_sharedmem.c create mode 100644 drivers/mxc/amd-gpu/gsl_tbdump.c create mode 100644 drivers/mxc/amd-gpu/gsl_yamato.c mode change 100644 => 100755 drivers/mxc/amd-gpu/include/gsl_halconfig.h create mode 100644 drivers/mxc/amd-gpu/include/gsl_hwaccess.h create mode 100644 drivers/mxc/amd-gpu/include/gsl_linux_map.h create mode 100644 drivers/mxc/amd-gpu/misc.c create mode 100644 drivers/mxc/amd-gpu/pfp_microcode_nrt.inl create mode 100644 drivers/mxc/amd-gpu/pm4_microcode.inl diff --git a/drivers/mxc/amd-gpu/Kconfig b/drivers/mxc/amd-gpu/Kconfig index 629d8cbbc98..1cbc89cac2a 100644 --- a/drivers/mxc/amd-gpu/Kconfig +++ b/drivers/mxc/amd-gpu/Kconfig @@ -10,4 +10,10 @@ config MXC_AMD_GPU ---help--- Say Y to get the GPU driver support. +config MXC_AMD_GPU_LOGGING + bool "Enable Logging" + depends on MXC_AMD_GPU + ---help--- + Enable logging to kernel messages for GPU kernel module + endmenu diff --git a/drivers/mxc/amd-gpu/Makefile b/drivers/mxc/amd-gpu/Makefile index 84cf02e5b3a..981d2599a93 100644 --- a/drivers/mxc/amd-gpu/Makefile +++ b/drivers/mxc/amd-gpu/Makefile @@ -1,31 +1,28 @@ EXTRA_CFLAGS := \ - -D_LINUX \ -I$(obj)/include \ - -I$(obj)/include/api \ - -I$(obj)/include/ucode \ - -I$(obj)/platform/hal/linux \ - -I$(obj)/os/include \ - -I$(obj)/os/kernel/include \ - -I$(obj)/os/user/include + -I$(obj)/include/api obj-$(CONFIG_MXC_AMD_GPU) += gpu.o -gpu-objs += common/gsl_cmdstream.o \ - common/gsl_cmdwindow.o \ - common/gsl_context.o \ - common/gsl_debug_pm4.o \ - common/gsl_device.o \ - common/gsl_drawctxt.o \ - common/gsl_driver.o \ - common/gsl_g12.o \ - common/gsl_intrmgr.o \ - common/gsl_memmgr.o \ - common/gsl_mmu.o \ - common/gsl_ringbuffer.o \ - common/gsl_sharedmem.o \ - common/gsl_yamato.o \ - platform/hal/linux/gsl_linux_map.o \ - platform/hal/linux/gsl_kmod.o \ - platform/hal/linux/gsl_hal.o \ - platform/hal/linux/gsl_kmod_cleanup.o \ - platform/hal/linux/misc.o \ - os/kernel/src/linux/kos_lib.o +gpu-objs += gsl_cmdstream.o \ + gsl_cmdwindow.o \ + gsl_context.o \ + gsl_device.o \ + gsl_drawctxt.o \ + gsl_driver.o \ + gsl_g12.o \ + gsl_intrmgr.o \ + gsl_memmgr.o \ + gsl_mmu.o \ + gsl_ringbuffer.o \ + gsl_sharedmem.o \ + gsl_yamato.o \ + gsl_linux_map.o \ + gsl_kmod.o \ + gsl_hal.o \ + gsl_kmod_cleanup.o \ + misc.o + +ifdef CONFIG_MXC_AMD_GPU_LOGGING +gpu-objs += gsl_log.o +EXTRA_CFLAGS += -DGSL_LOG +endif diff --git a/drivers/mxc/amd-gpu/gsl_cmdstream.c b/drivers/mxc/amd-gpu/gsl_cmdstream.c new file mode 100644 index 00000000000..8ab90950c09 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_cmdstream.c @@ -0,0 +1,243 @@ +/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" +#include "gsl_hal.h" +#include "gsl_cmdstream.h" + +// functions + +int kgsl_cmdstream_init(gsl_device_t *device) +{ + return GSL_SUCCESS; +} + +int kgsl_cmdstream_close(gsl_device_t *device) +{ + return GSL_SUCCESS; +} + +gsl_timestamp_t kgsl_cmdstream_readtimestamp0(gsl_deviceid_t device_id, gsl_timestamp_type_t type) +{ + gsl_timestamp_t timestamp = -1; + gsl_device_t* device = &gsl_driver.device[device_id-1]; + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> gsl_timestamp_t kgsl_cmdstream_readtimestamp(gsl_deviceid_t device_id=%D gsl_timestamp_type_t type=%d)\n", device_id, type ); +#if (defined(GSL_BLD_G12) && defined(IRQTHREAD_POLL)) + complete_all(&device->irqthread_event); +#endif + if (type == GSL_TIMESTAMP_CONSUMED) + { + // start-of-pipeline timestamp + GSL_CMDSTREAM_GET_SOP_TIMESTAMP(device, (unsigned int*)×tamp); + } + else if (type == GSL_TIMESTAMP_RETIRED) + { + // end-of-pipeline timestamp + GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (unsigned int*)×tamp); + } + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_readtimestamp. Return value %d\n", timestamp ); + return (timestamp); +} + +//---------------------------------------------------------------------------- + +gsl_timestamp_t +kgsl_cmdstream_readtimestamp(gsl_deviceid_t device_id, gsl_timestamp_type_t type) +{ + gsl_timestamp_t timestamp = -1; + + mutex_lock(&gsl_driver.lock); + + timestamp = kgsl_cmdstream_readtimestamp0(device_id, type); + + mutex_unlock(&gsl_driver.lock); + + return timestamp; +} + +//---------------------------------------------------------------------------- + +int +kgsl_cmdstream_issueibcmds(gsl_deviceid_t device_id, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, unsigned int flags) +{ + gsl_device_t* device = &gsl_driver.device[device_id-1]; + int status = GSL_FAILURE; + + mutex_lock(&gsl_driver.lock); + + kgsl_device_active(device); + + if (device->ftbl.cmdstream_issueibcmds) + { + status = device->ftbl.cmdstream_issueibcmds(device, drawctxt_index, ibaddr, sizedwords, timestamp, flags); + } + + mutex_unlock(&gsl_driver.lock); + + return status; +} + +//---------------------------------------------------------------------------- + +int +kgsl_add_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t *timestamp) +{ + gsl_device_t* device = &gsl_driver.device[device_id-1]; + int status = GSL_FAILURE; + + mutex_lock(&gsl_driver.lock); + + if (device->ftbl.device_addtimestamp) + { + status = device->ftbl.device_addtimestamp(device, timestamp); + } + + mutex_unlock(&gsl_driver.lock); + return status; +} + +//---------------------------------------------------------------------------- + +int kgsl_cmdstream_waittimestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp, unsigned int timeout) +{ + gsl_device_t* device = &gsl_driver.device[device_id-1]; + int status = GSL_FAILURE; + if (device->ftbl.device_waittimestamp) + { + status = device->ftbl.device_waittimestamp(device, timestamp, timeout); + } + return status; +} + +//---------------------------------------------------------------------------- + +void +kgsl_cmdstream_memqueue_drain(gsl_device_t *device) +{ + gsl_memnode_t *memnode, *nextnode, *freehead; + gsl_timestamp_t timestamp, ts_processed; + gsl_memqueue_t *memqueue = &device->memqueue; + + // check head + if (memqueue->head == NULL) + { + return; + } + // get current EOP timestamp + ts_processed = kgsl_cmdstream_readtimestamp0(device->id, GSL_TIMESTAMP_RETIRED); + timestamp = memqueue->head->timestamp; + // check head timestamp + if (!(((ts_processed - timestamp) >= 0) || ((ts_processed - timestamp) < -GSL_TIMESTAMP_EPSILON))) + { + return; + } + memnode = memqueue->head; + freehead = memqueue->head; + // get node list to free + for(;;) + { + nextnode = memnode->next; + if (nextnode == NULL) + { + // entire queue drained + memqueue->head = NULL; + memqueue->tail = NULL; + break; + } + timestamp = nextnode->timestamp; + if (!(((ts_processed - timestamp) >= 0) || ((ts_processed - timestamp) < -GSL_TIMESTAMP_EPSILON))) + { + // drained up to a point + memqueue->head = nextnode; + memnode->next = NULL; + break; + } + memnode = nextnode; + } + // free nodes + while (freehead) + { + memnode = freehead; + freehead = memnode->next; + kgsl_sharedmem_free0(&memnode->memdesc, memnode->pid); + kfree(memnode); + } + +} + +//---------------------------------------------------------------------------- + +int +kgsl_cmdstream_freememontimestamp(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, gsl_timestamp_t timestamp, gsl_timestamp_type_t type) +{ + gsl_memnode_t *memnode; + gsl_device_t *device = &gsl_driver.device[device_id-1]; + gsl_memqueue_t *memqueue; + (void)type; // unref. For now just use EOP timestamp + + mutex_lock(&gsl_driver.lock); + + memqueue = &device->memqueue; + memnode = kmalloc(sizeof(gsl_memnode_t), GFP_KERNEL); + + if (!memnode) + { + // other solution is to idle and free which given that the upper level driver probably wont check, probably a better idea + mutex_unlock(&gsl_driver.lock); + return (GSL_FAILURE); + } + + memnode->timestamp = timestamp; + memnode->pid = current->tgid; + memnode->next = NULL; + memcpy(&memnode->memdesc, memdesc, sizeof(gsl_memdesc_t)); + + // add to end of queue + if (memqueue->tail != NULL) + { + memqueue->tail->next = memnode; + memqueue->tail = memnode; + } + else + { + DEBUG_ASSERT(memqueue->head == NULL); + memqueue->head = memnode; + memqueue->tail = memnode; + } + + mutex_unlock(&gsl_driver.lock); + + return (GSL_SUCCESS); +} + +static int kgsl_cmdstream_timestamp_cmp(gsl_timestamp_t ts_new, gsl_timestamp_t ts_old) +{ + gsl_timestamp_t ts_diff = ts_new - ts_old; + return (ts_diff >= 0) || (ts_diff < -GSL_TIMESTAMP_EPSILON); +} + +int kgsl_cmdstream_check_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp) +{ + gsl_timestamp_t ts_processed; + ts_processed = kgsl_cmdstream_readtimestamp0(device_id, GSL_TIMESTAMP_RETIRED); + return kgsl_cmdstream_timestamp_cmp(ts_processed, timestamp); +} diff --git a/drivers/mxc/amd-gpu/gsl_cmdwindow.c b/drivers/mxc/amd-gpu/gsl_cmdwindow.c new file mode 100644 index 00000000000..7cec78490c4 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_cmdwindow.c @@ -0,0 +1,132 @@ +/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include + +#include "gsl.h" +#include "gsl_hal.h" + +#ifdef GSL_BLD_G12 + +// defines +#define GSL_CMDWINDOW_TARGET_MASK 0x000000FF +#define GSL_CMDWINDOW_ADDR_MASK 0x00FFFF00 +#define GSL_CMDWINDOW_TARGET_SHIFT 0 +#define GSL_CMDWINDOW_ADDR_SHIFT 8 + +// functions +int +kgsl_cmdwindow_init(gsl_device_t *device) +{ + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_cmdwindow_close(gsl_device_t *device) +{ + return (GSL_SUCCESS); +} + +#endif // GSL_BLD_G12 + +//---------------------------------------------------------------------------- + +int +kgsl_cmdwindow_write0(gsl_deviceid_t device_id, gsl_cmdwindow_t target, unsigned int addr, unsigned int data) +{ +#ifdef GSL_BLD_G12 + gsl_device_t *device; + unsigned int cmdwinaddr; + unsigned int cmdstream; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_cmdwindow_write( gsl_device_id_t device_id=%D, gsl_cmdwindow_t target=%d, uint addr=0x%08x, uint data=0x%08x)\n", device_id, target, addr, data ); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + if (target < GSL_CMDWINDOW_MIN || target > GSL_CMDWINDOW_MAX) + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid target.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + if ((!(device->flags & GSL_FLAGS_INITIALIZED) && target == GSL_CMDWINDOW_MMU) || + (!(device->flags & GSL_FLAGS_STARTED) && target != GSL_CMDWINDOW_MMU)) + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid device state to write to selected targer.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // set command stream + if (target == GSL_CMDWINDOW_MMU) + { +#ifdef GSL_NO_MMU + return (GSL_SUCCESS); +#endif + cmdstream = ADDR_VGC_MMUCOMMANDSTREAM; + } + else + { + cmdstream = ADDR_VGC_COMMANDSTREAM; + } + + + // set command window address + cmdwinaddr = ((target << GSL_CMDWINDOW_TARGET_SHIFT) & GSL_CMDWINDOW_TARGET_MASK); + cmdwinaddr |= ((addr << GSL_CMDWINDOW_ADDR_SHIFT) & GSL_CMDWINDOW_ADDR_MASK); + +#ifndef GSL_NO_MMU + // set mmu pagetable + kgsl_mmu_setpagetable(device, current->tgid); +#endif + + // write command window address + device->ftbl.device_regwrite(device, (cmdstream)>>2, cmdwinaddr); + + // write data + device->ftbl.device_regwrite(device, (cmdstream)>>2, data); + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +#else + // unreferenced formal parameter + (void) device_id; + (void) target; + (void) addr; + (void) data; + + return (GSL_FAILURE); +#endif // GSL_BLD_G12 +} + +//---------------------------------------------------------------------------- + +int +kgsl_cmdwindow_write(gsl_deviceid_t device_id, gsl_cmdwindow_t target, unsigned int addr, unsigned int data) +{ + int status = GSL_SUCCESS; + mutex_lock(&gsl_driver.lock); + status = kgsl_cmdwindow_write0(device_id, target, addr, data); + mutex_unlock(&gsl_driver.lock); + return status; +} diff --git a/drivers/mxc/amd-gpu/gsl_context.c b/drivers/mxc/amd-gpu/gsl_context.c new file mode 100644 index 00000000000..984cea66381 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_context.c @@ -0,0 +1,73 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include "gsl.h" +#include "gsl_hal.h" + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_context_create(gsl_deviceid_t device_id, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags) +{ + gsl_device_t* device = &gsl_driver.device[device_id-1]; + int status; + + mutex_lock(&gsl_driver.lock); + + if (device->ftbl.context_create) + { + status = device->ftbl.context_create(device, type, drawctxt_id, flags); + } + else + { + status = GSL_FAILURE; + } + + mutex_unlock(&gsl_driver.lock); + + return status; +} + +//---------------------------------------------------------------------------- + +int +kgsl_context_destroy(gsl_deviceid_t device_id, unsigned int drawctxt_id) +{ + gsl_device_t* device = &gsl_driver.device[device_id-1]; + int status; + + mutex_lock(&gsl_driver.lock); + + if (device->ftbl.context_destroy) + { + status = device->ftbl.context_destroy(device, drawctxt_id); + } + else + { + status = GSL_FAILURE; + } + + mutex_unlock(&gsl_driver.lock); + + return status; +} + +//---------------------------------------------------------------------------- + diff --git a/drivers/mxc/amd-gpu/gsl_debug_pm4.c b/drivers/mxc/amd-gpu/gsl_debug_pm4.c new file mode 100644 index 00000000000..f712bb402ff --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_debug_pm4.c @@ -0,0 +1,942 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include "gsl.h" +#include "gsl_hal.h" + +#if 0//defined(GSL_BLD_YAMATO) + +#include + +//#define PM4_DEBUG_USE_MEMBUF + +#ifdef PM4_DEBUG_USE_MEMBUF + +#define MEMBUF_SIZE 100000 +#define BUFFER_END_MARGIN 1000 +char memBuf[MEMBUF_SIZE]; +static int writePtr = 0; +static unsigned int lineNumber = 0; + +int printString(const char * _Format, ...) +{ + int ret; + va_list ap; + + va_start(ap, _Format); + if( writePtr > 0 && memBuf[writePtr-1] == '\n' ) + { + // Add line number if last written character was newline + writePtr += sprintf( memBuf+writePtr, "%d: ", lineNumber++ ); + } + ret = vsprintf(memBuf+writePtr, _Format, ap); + writePtr += ret; + sprintf( memBuf+writePtr, "###" ); + if( writePtr > MEMBUF_SIZE-BUFFER_END_MARGIN ) + { + memset(memBuf+writePtr, '#', MEMBUF_SIZE-writePtr); + writePtr = 0; + } + + va_end(ap); + + return ret; +} + +#else + +int printString(const char * _Format, ...) +{ + int ret; + va_list ap; + va_start(ap, _Format); + ret = printk(_Format, ap); + va_end(ap); + return ret; +} + +#endif + +////////////////////////////////////////////////////////////////////////////// +// defines +////////////////////////////////////////////////////////////////////////////// +#define EXPAND_OPCODE(opcode) ((opcode << 8) | PM4_PKT_MASK) + +#define GetString_uint GetString_int +#define GetString_fixed12_4(val, szValue) GetString_fixed(val, 12, 4, szValue) +#define GetString_signedint15(val, szValue) GetString_signedint(val, 15, szValue) + +// Need a prototype for this function +void WritePM4Packet_Type3(unsigned int dwHeader, unsigned int** ppBuffer); + +static int indirectionLevel = 0; + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +void WriteDWORD(unsigned int dwValue) +{ + printString( " 0x%08x", dwValue); +} + +void WriteDWORD2(unsigned int dwValue) +{ + printString( " 0x%08x\n", dwValue); +} + +//---------------------------------------------------------------------------- + +// Generate the GetString_## functions for enumerated types +#define START_ENUMTYPE(__type) \ +void GetString_##__type(unsigned int val, char* szValue) \ +{ \ + switch(val) \ + { + +#define GENERATE_ENUM(__enumname, __val) \ + case __val: \ + strcpy(szValue, #__enumname); \ + break; + +#define END_ENUMTYPE(__type) \ + default: \ + sprintf(szValue, "Unknown: %d", val); \ + break; \ + } \ +} + +#include _YAMATO_GENENUM_H + +//---------------------------------------------------------------------------- + +void +GetString_hex(unsigned int val, char* szValue) +{ + sprintf(szValue, "0x%x", val); +} + +//---------------------------------------------------------------------------- + +void +GetString_float(unsigned int val, char* szValue) +{ + float fval = *((float*) &val); + sprintf(szValue, "%.4f", fval); +} + +//---------------------------------------------------------------------------- + +void +GetString_bool(unsigned int val, char* szValue) +{ + strcpy(szValue, val ? "TRUE" : "FALSE"); +} + +//---------------------------------------------------------------------------- + +void GetString_int(unsigned int val, char* szValue) +{ + sprintf(szValue, "%d", val); +} + +//---------------------------------------------------------------------------- + +void +GetString_intMinusOne(unsigned int val, char* szValue) +{ + sprintf(szValue, "%d+1", val); +} + +//---------------------------------------------------------------------------- + +void +GetString_signedint(unsigned int val, unsigned int dwNumBits, char* szValue) +{ + int nValue = val; + + if (val & (1<<(dwNumBits-1))) + { + nValue |= 0xffffffff << dwNumBits; + } + + sprintf(szValue, "%d", nValue); +} + +//---------------------------------------------------------------------------- + +void +GetString_fixed(unsigned int val, unsigned int dwNumInt, unsigned int dwNumFrac, char* szValue) +{ + + (void) dwNumInt; // unreferenced formal parameter + + if (val>>dwNumFrac == 0) + { + // Integer part is 0 - just print out the fractional part + sprintf(szValue, "%d/%d", + val&((1<>dwNumFrac, + val&((1<> 16) == 0x4)) + registerAddr = (*pBuffer) & 0xffff; + + // Write unsigned int + WriteDWORD(*pBuffer); + + // Starting at Ordinal 2 is actual register values + if((dwIndex > 0) && (registerAddr != 0xffffffff)) + { + // Write register string based on address + GetString_Register(registerAddr + 0x2000, *pBuffer, szRegister); + printString( " // %s\n", szRegister); + registerAddr++; + } + else + { + // Write out newline if we aren't augmenting with register fields + printString( "\n"); + } + + pBuffer++; + } + } + *ppBuffer = pBuffer; +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpInitParams(unsigned int dwEDRAMBase, unsigned int dwEDRAMSize) +{ + printString( "InitParams, edrambase=0x%x, edramsize=%d\n", + dwEDRAMBase, dwEDRAMSize); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpSwapBuffers(unsigned int dwAddress, unsigned int dwWidth, + unsigned int dwHeight, unsigned int dwPitch, unsigned int dwAlignedHeight, unsigned int dwBitsPerPixel) +{ + printString( "SwapBuffers, address=0x%08x, width=%d, height=%d, pitch=%d, alignedheight=%d, bpp=%d\n", + dwAddress, dwWidth, dwHeight, dwPitch, dwAlignedHeight, dwBitsPerPixel); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpRegSpace(gsl_device_t *device) +{ + int regsPerLine = 0x20; + unsigned int dwOffset; + unsigned int value; + + printString( "Start_RegisterSpace\n"); + + for (dwOffset = 0; dwOffset < device->regspace.sizebytes; dwOffset += 4) + { + if (dwOffset % regsPerLine == 0) + { + printString( " 0x%08x ", dwOffset); + } + + GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, (dwOffset >> 2), &value); + + printString( " 0x%08x", value); + + if (((dwOffset + 4) % regsPerLine == 0) && ((dwOffset + 4) < device->regspace.sizebytes)) + { + printString( "\n"); + } + } + + printString( "\nEnd_RegisterSpace\n"); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpAllocateMemory(unsigned int dwSize, unsigned int dwFlags, unsigned int dwAddress, + unsigned int dwActualSize) +{ + printString( "AllocateMemory, size=%d, flags=0x%x, address=0x%x, actualSize=%d\n", + dwSize, dwFlags, dwAddress, dwActualSize); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpFreeMemory(unsigned int dwAddress) +{ + printString( "FreeMemory, address=0x%x\n", dwAddress); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpWriteMemory(unsigned int dwAddress, unsigned int dwSize, void* pData) +{ + // Open file + unsigned int dwNumDWORDs; + unsigned int dwIndex; + unsigned int *pDataPtr; + + printString( "StartWriteMemory, address=0x%x, size=%d\n", dwAddress, dwSize); + + // Now write the data, in dwNumDWORDs + dwNumDWORDs = dwSize >> 2; + + // If there are spillover bytes into the next dword, increment the amount dumped out here. + // The reader needs to take care of not overwriting the nonvalid bytes + if((dwSize % 4) != 0) + dwNumDWORDs++; + + for (dwIndex = 0, pDataPtr = (unsigned int *)pData; dwIndex < dwNumDWORDs; dwIndex++, pDataPtr++) + { + WriteDWORD2(*pDataPtr); + } + + printString( "EndWriteMemory\n"); +} + +void +Yamato_DumpSetMemory(unsigned int dwAddress, unsigned int dwSize, unsigned int pData) +{ +// unsigned int* pDataPtr; + + printString( "SetMemory, address=0x%x, size=%d, value=0x%x\n", + dwAddress, dwSize, pData); +} + +//---------------------------------------------------------------------------- +void +Yamato_ConvertIBAddr(unsigned int dwHeader, unsigned int *pBuffer, int gpuToHost) +{ + unsigned int hostaddr; + unsigned int *ibend; + unsigned int *addr; + unsigned int *ib = pBuffer; + pm4_type3 header = *((pm4_type3*) &dwHeader); + + // convert ib1 base address + if((EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER) || + (EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER_PFD)) + { + if (gpuToHost) + { + // from gpu to host + *ib = kgsl_sharedmem_convertaddr(*ib, 0); + + hostaddr = *ib; + } + else + { + // from host to gpu + hostaddr = *ib; + *ib = kgsl_sharedmem_convertaddr(*ib, 1); + } + + // walk through ib1 and convert any ib2 base address + + ib = (unsigned int *) hostaddr; + ibend = (unsigned int *) (ib + *(++pBuffer)); + + while (ib < ibend) + { + dwHeader = *(ib); + header = *((pm4_type3*) (&dwHeader)); + + switch(dwHeader & PM4_PKT_MASK) + { + case PM4_TYPE0_PKT: + ib += header.count + 2; + break; + + case PM4_TYPE1_PKT: + break; + + case PM4_TYPE2_PKT: + ib++; + break; + + case PM4_TYPE3_PKT: + if((EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER) || + (EXPAND_OPCODE(header.it_opcode) == PM4_PACKET3_INDIRECT_BUFFER_PFD)) + { + addr = ib + 1; + if (gpuToHost) + { + // from gpu to host + *addr = kgsl_sharedmem_convertaddr(*addr, 0); + } + else + { + // from host to gpu + *addr = kgsl_sharedmem_convertaddr(*addr, 1); + } + } + ib += header.count + 2; + break; + } + } + } +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpPM4(unsigned int* pBuffer, unsigned int sizeDWords) +{ + unsigned int *pBufferEnd = pBuffer + sizeDWords; + unsigned int *tmp; + + printString( "Start_PM4Buffer\n");//, count=%d\n", sizeDWords); + + // So look at the first unsigned int - should be a header + while(pBuffer < pBufferEnd) + { + unsigned int dwHeader = *(pBuffer++); + + //printString( " Start_Packet\n"); + switch(dwHeader & PM4_PKT_MASK) + { + case PM4_TYPE0_PKT: + WritePM4Packet_Type0(dwHeader, &pBuffer); + break; + + case PM4_TYPE1_PKT: + break; + + case PM4_TYPE2_PKT: + WritePM4Packet_Type2(dwHeader, &pBuffer); + break; + + case PM4_TYPE3_PKT: + indirectionLevel = 0; + tmp = pBuffer; + Yamato_ConvertIBAddr(dwHeader, tmp, 1); + WritePM4Packet_Type3(dwHeader, &pBuffer); + Yamato_ConvertIBAddr(dwHeader, tmp, 0); + break; + } + //printString( " End_Packet\n"); + } + + printString( "End_PM4Buffer\n"); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpRegisterWrite(unsigned int dwAddress, unsigned int value) +{ + // Build a Type-0 packet that maps to this register write + unsigned int pBuffer[100], *pBuf = &pBuffer[1]; + + // Don't dump CP_RB_WPTR (switch statement may be necessary here for future additions) + if(dwAddress == mmCP_RB_WPTR) + return; + + pBuffer[0] = dwAddress; + pBuffer[1] = value; + + printString( "StartRegisterWrite\n"); + WritePM4Packet_Type0(pBuffer[0], &pBuf); + printString( "EndRegisterWrite\n"); +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpFbStart(gsl_device_t *device) +{ + static int firstCall = 0; + + // We only want to call this once + if(firstCall) + return; + + printString( "FbStart, value=0x%x\n", device->mmu.mpu_base); + printString( "FbSize, value=0x%x\n", device->mmu.mpu_range); + + firstCall = 1; +} + +//---------------------------------------------------------------------------- + +void +Yamato_DumpWindow(unsigned int addr, unsigned int width, unsigned int height) +{ + printString( "DumpWindow, addr=0x%x, width=0x%x, height=0x%x\n", addr, width, height); +} + +//---------------------------------------------------------------------------- +#ifdef _DEBUG + +#define ADDRESS_STACK_SIZE 256 +#define GET_PM4_TYPE3_OPCODE(x) ((*(x) >> 8) & 0xFF) +#define IF_REGISTER_IN_RANGE(reg, base, count) \ + offset = (reg) - (base); \ + if(offset >= 0 && offset <= (count) - 2) +#define GET_CP_CONSTANT_DATA(x) (*((x) + offset + 2)) + +static const char format2bpp[] = +{ + 2, // COLORX_4_4_4_4 + 2, // COLORX_1_5_5_5 + 2, // COLORX_5_6_5 + 1, // COLORX_8 + 2, // COLORX_8_8 + 4, // COLORX_8_8_8_8 + 4, // COLORX_S8_8_8_8 + 2, // COLORX_16_FLOAT + 4, // COLORX_16_16_FLOAT + 8, // COLORX_16_16_16_16_FLOAT + 4, // COLORX_32_FLOAT + 8, // COLORX_32_32_FLOAT + 16, // COLORX_32_32_32_32_FLOAT , + 1, // COLORX_2_3_3 + 3, // COLORX_8_8_8 +}; + +static unsigned int kgsl_dumpx_addr_count = 0; //unique command buffer addresses encountered +static int kgsl_dumpx_handle_type3(unsigned int* hostaddr, int count) +{ + // For swap detection we need to find the below declared static values, and detect DI during EDRAM copy + static unsigned int width = 0, height = 0, format = 0, baseaddr = 0, iscopy = 0; + + static unsigned int addr_stack[ADDRESS_STACK_SIZE]; + static unsigned int size_stack[ADDRESS_STACK_SIZE]; + int swap = 0; // have we encountered a swap during recursion (return value) + + switch(GET_PM4_TYPE3_OPCODE(hostaddr)) + { + case PM4_INDIRECT_BUFFER_PFD: + case PM4_INDIRECT_BUFFER: + { + // traverse indirect buffers + unsigned int i; + unsigned int ibaddr = *(hostaddr+1); + unsigned int ibsize = *(hostaddr+2); + + // is this address already in encountered? + for(i = 0; i < kgsl_dumpx_addr_count && addr_stack[i] != ibaddr; i++); + + if(kgsl_dumpx_addr_count == i) + { + // yes it was, store the address so we don't dump this buffer twice + addr_stack[kgsl_dumpx_addr_count] = ibaddr; + // just for sanity checking + size_stack[kgsl_dumpx_addr_count++] = ibsize; + DEBUG_ASSERT(kgsl_dumpx_addr_count < ADDRESS_STACK_SIZE); + + // recursively follow the indirect link and update swap if indirect buffer had resolve + swap |= kgsl_dumpx_parse_ibs(ibaddr, ibsize); + } + else + { + DEBUG_ASSERT(size_stack[i] == ibsize); + } + } + break; + + case PM4_SET_CONSTANT: + if((*(hostaddr+1) >> 16) == 0x4) + { + // parse register writes, and figure out framebuffer configuration + + unsigned int regaddr = (*(hostaddr + 1) & 0xFFFF) + 0x2000; //dword address in register space + int offset; // used by the macros + + IF_REGISTER_IN_RANGE(mmPA_SC_WINDOW_SCISSOR_BR, regaddr, count) + { + // found write to PA_SC_WINDOW_SCISSOR_BR, we use this to detect current + // width and height of the framebuffer (TODO: find more reliable way of achieving this) + unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); + width = data & 0xFFFF; + height = data >> 16; + } + + IF_REGISTER_IN_RANGE(mmRB_MODECONTROL, regaddr, count) + { + // found write to RB_MODECONTROL, we use this to find out if next DI is resolve + unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); + iscopy = (data & RB_MODECONTROL__EDRAM_MODE_MASK) == (EDRAM_COPY << RB_MODECONTROL__EDRAM_MODE__SHIFT); + } + + IF_REGISTER_IN_RANGE(mmRB_COPY_DEST_BASE, regaddr, count) + { + // found write to RB_COPY_DEST_BASE, we use this to find out the framebuffer base address + unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); + baseaddr = (data & RB_COPY_DEST_BASE__COPY_DEST_BASE_MASK); + } + + IF_REGISTER_IN_RANGE(mmRB_COPY_DEST_INFO, regaddr, count) + { + // found write to RB_COPY_DEST_INFO, we use this to find out the framebuffer format + unsigned int data = GET_CP_CONSTANT_DATA(hostaddr); + format = (data & RB_COPY_DEST_INFO__COPY_DEST_FORMAT_MASK) >> RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT; + } + } + break; + + case PM4_DRAW_INDX: + case PM4_DRAW_INDX_2: + { + // DI found + // check if it is resolve + if(iscopy && !swap) + { + // printf("resolve: %ix%i @ 0x%08x, format = 0x%08x\n", width, height, baseaddr, format); + DEBUG_ASSERT(format < 15); + + // yes it was and we need to update color buffer config because this is the first bin + // dumpx framebuffer base address, and dimensions + KGSL_DEBUG_DUMPX( BB_DUMP_CBUF_AWH, (unsigned int)baseaddr, width, height, " "); + + // find aligned width + width = (width + 31) & ~31; + + //dump bytes-per-pixel and aligned width + KGSL_DEBUG_DUMPX( BB_DUMP_CBUF_FS, format2bpp[format], width, 0, " "); + swap = 1; + } + + } + break; + + default: + break; + } + return swap; +} + +// Traverse IBs and dump them to test vector. Detect swap by inspecting register +// writes, keeping note of the current state, and dump framebuffer config to test vector +int kgsl_dumpx_parse_ibs(gpuaddr_t gpuaddr, int sizedwords) +{ + static unsigned int level = 0; //recursion level + + int swap = 0; // have we encountered a swap during recursion (return value) + unsigned int *hostaddr; + int dwords_left = sizedwords; //dwords left in the current command buffer + + level++; + + DEBUG_ASSERT(sizeof(unsigned int *) == sizeof(unsigned int)); + DEBUG_ASSERT(level <= 2); + hostaddr = (unsigned int *)kgsl_sharedmem_convertaddr(gpuaddr, 0); + + // dump the IB to test vector + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MEMWRITE, gpuaddr, (unsigned int)hostaddr, sizedwords*4, "kgsl_dumpx_write_ibs")); + + while(dwords_left) + { + int count = 0; //dword count including packet header + + switch(*hostaddr >> 30) + { + case 0x0: // type-0 + count = (*hostaddr >> 16)+2; + break; + case 0x1: // type-1 + count = 2; + break; + case 0x3: // type-3 + count = ((*hostaddr >> 16) & 0x3fff) + 2; + swap |= kgsl_dumpx_handle_type3(hostaddr, count); + break; // type-3 + default: + DEBUG_ASSERT(!"unknown packet type"); + } + + // jump to next packet + dwords_left -= count; + hostaddr += count; + DEBUG_ASSERT(dwords_left >= 0 && "PM4 parsing error"); + } + + level--; + + // if this is the starting level of recursion, we are done. clean-up + if(level == 0) kgsl_dumpx_addr_count = 0; + + return swap; +} +#endif + +#endif // WIN32 + diff --git a/drivers/mxc/amd-gpu/gsl_device.c b/drivers/mxc/amd-gpu/gsl_device.c new file mode 100644 index 00000000000..04c8f099458 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_device.c @@ -0,0 +1,673 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include + +#include "gsl.h" +#include "gsl_hal.h" + +////////////////////////////////////////////////////////////////////////////// +// inline functions +////////////////////////////////////////////////////////////////////////////// +static __inline void +kgsl_device_getfunctable(gsl_deviceid_t device_id, gsl_functable_t *ftbl) +{ + switch (device_id) + { +#ifdef GSL_BLD_YAMATO + case GSL_DEVICE_YAMATO: + kgsl_yamato_getfunctable(ftbl); + break; +#endif // GSL_BLD_YAMATO +#ifdef GSL_BLD_G12 + case GSL_DEVICE_G12: + kgsl_g12_getfunctable(ftbl); + break; +#endif // GSL_BLD_G12 + default: + break; + } +} + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_device_init(gsl_device_t *device, gsl_deviceid_t device_id) +{ + int status = GSL_SUCCESS; + gsl_devconfig_t config; + gsl_hal_t *hal = (gsl_hal_t *)gsl_driver.hal; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_init(gsl_device_t *device=0x%08x, gsl_deviceid_t device_id=%D )\n", device, device_id ); + + if ((GSL_DEVICE_YAMATO == device_id) && !(hal->has_z430)) { + return GSL_FAILURE_NOTSUPPORTED; + } + + if ((GSL_DEVICE_G12 == device_id) && !(hal->has_z160)) { + return GSL_FAILURE_NOTSUPPORTED; + } + + if (device->flags & GSL_FLAGS_INITIALIZED) + { + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_init. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); + } + + memset(device, 0, sizeof(gsl_device_t)); + + // if device configuration is present + if (kgsl_hal_getdevconfig(device_id, &config) == GSL_SUCCESS) + { + kgsl_device_getfunctable(device_id, &device->ftbl); + + memcpy(&device->regspace, &config.regspace, sizeof(gsl_memregion_t)); +#ifdef GSL_BLD_YAMATO + memcpy(&device->gmemspace, &config.gmemspace, sizeof(gsl_memregion_t)); +#endif // GSL_BLD_YAMATO + + device->refcnt = 0; + device->id = device_id; + +#ifndef GSL_NO_MMU + device->mmu.config = config.mmu_config; + device->mmu.mpu_base = config.mpu_base; + device->mmu.mpu_range = config.mpu_range; + device->mmu.va_base = config.va_base; + device->mmu.va_range = config.va_range; +#endif + + if (device->ftbl.device_init) + { + status = device->ftbl.device_init(device); + } + else + { + status = GSL_FAILURE_NOTINITIALIZED; + } + + // allocate memory store + status = kgsl_sharedmem_alloc0(device->id, GSL_MEMFLAGS_ALIGNPAGE | GSL_MEMFLAGS_CONPHYS, sizeof(gsl_devmemstore_t), &device->memstore); + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + // dumpx needs this to be in EMEM0 aperture + kgsl_sharedmem_free0(&device->memstore, current->tgid); + status = kgsl_sharedmem_alloc0(device->id, GSL_MEMFLAGS_ALIGNPAGE, sizeof(gsl_devmemstore_t), &device->memstore); + }); + + if (status != GSL_SUCCESS) + { + kgsl_device_stop(device->id); + return (status); + } + kgsl_sharedmem_set0(&device->memstore, 0, 0, device->memstore.size); + + // init memqueue + device->memqueue.head = NULL; + device->memqueue.tail = NULL; + + // init cmdstream + status = kgsl_cmdstream_init(device); + if (status != GSL_SUCCESS) + { + kgsl_device_stop(device->id); + return (status); + } + + // Create timestamp wait queue + init_waitqueue_head(&device->timestamp_waitq); + + // + // Read the chip ID after the device has been initialized. + // + device->chip_id = kgsl_hal_getchipid(device->id); + } + + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_init. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_close(gsl_device_t *device) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_close(gsl_device_t *device=0x%08x )\n", device ); + + if (!(device->flags & GSL_FLAGS_INITIALIZED)) { + return status; + } + + /* make sure the device is stopped before close + kgsl_device_close is only called for last running caller process + */ + while (device->refcnt > 0) { + mutex_unlock(&gsl_driver.lock); + kgsl_device_stop(device->id); + mutex_lock(&gsl_driver.lock); + } + + // close cmdstream + status = kgsl_cmdstream_close(device); + if( status != GSL_SUCCESS ) return status; + + if (device->ftbl.device_close) { + status = device->ftbl.device_close(device); + } + + // DumpX allocates memstore from MMU aperture + if ((device->refcnt == 0) && device->memstore.hostptr + && !(gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX)) + { + kgsl_sharedmem_free0(&device->memstore, current->tgid); + } + + wake_up_interruptible_all(&(device->timestamp_waitq)); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_close. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_destroy(gsl_device_t *device) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_destroy(gsl_device_t *device=0x%08x )\n", device ); + + if (device->flags & GSL_FLAGS_INITIALIZED) + { + if (device->ftbl.device_destroy) + { + status = device->ftbl.device_destroy(device); + } + } + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_destroy. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_attachcallback(gsl_device_t *device, unsigned int pid) +{ + int status = GSL_SUCCESS; + int pindex; + +#ifndef GSL_NO_MMU + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_device_attachcallback(gsl_device_t *device=0x%08x, unsigned int pid=0x%08x)\n", device, pid ); + + if (device->flags & GSL_FLAGS_INITIALIZED) + { + if (kgsl_driver_getcallerprocessindex(pid, &pindex) == GSL_SUCCESS) + { + device->callerprocess[pindex] = pid; + + status = kgsl_mmu_attachcallback(&device->mmu, pid); + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_attachcallback. Return value: %B\n", status ); + +#else + (void)pid; + (void)device; +#endif + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_detachcallback(gsl_device_t *device, unsigned int pid) +{ + int status = GSL_SUCCESS; + int pindex; + +#ifndef GSL_NO_MMU + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_device_detachcallback(gsl_device_t *device=0x%08x, unsigned int pid=0x%08x)\n", device, pid ); + + if (device->flags & GSL_FLAGS_INITIALIZED) + { + if (kgsl_driver_getcallerprocessindex(pid, &pindex) == GSL_SUCCESS) + { + status |= kgsl_mmu_detachcallback(&device->mmu, pid); + + device->callerprocess[pindex] = 0; + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_detachcallback. Return value: %B\n", status ); + +#else + (void)pid; + (void)device; +#endif + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_getproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes) +{ + int status = GSL_SUCCESS; + gsl_device_t *device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_getproperty(gsl_deviceid_t device_id=%D, gsl_property_type_t type=%T, void *value=0x%08x, uint sizebytes=%u)\n", device_id, type, value, sizebytes ); + + DEBUG_ASSERT(value); + +#ifndef _DEBUG + (void) sizebytes; // unreferenced formal parameter +#endif + + switch (type) + { + case GSL_PROP_SHMEM: + { + gsl_shmemprop_t *shem = (gsl_shmemprop_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_shmemprop_t)); + + shem->numapertures = gsl_driver.shmem.numapertures; + shem->aperture_mask = GSL_APERTURE_MASK; + shem->aperture_shift = GSL_APERTURE_SHIFT; + + break; + } + + case GSL_PROP_SHMEM_APERTURES: + { + int i; + gsl_apertureprop_t *aperture = (gsl_apertureprop_t *) value; + + DEBUG_ASSERT(sizebytes == (sizeof(gsl_apertureprop_t) * gsl_driver.shmem.numapertures)); + + for (i = 0; i < gsl_driver.shmem.numapertures; i++) + { + if (gsl_driver.shmem.apertures[i].memarena) + { + aperture->gpuaddr = GSL_APERTURE_GETGPUADDR(gsl_driver.shmem, i); + aperture->hostaddr = GSL_APERTURE_GETHOSTADDR(gsl_driver.shmem, i); + } + else + { + aperture->gpuaddr = 0x0; + aperture->hostaddr = 0x0; + } + aperture++; + } + + break; + } + + case GSL_PROP_DEVICE_SHADOW: + { + gsl_shadowprop_t *shadowprop = (gsl_shadowprop_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_shadowprop_t)); + + memset(shadowprop, 0, sizeof(gsl_shadowprop_t)); + +#ifdef GSL_DEVICE_SHADOW_MEMSTORE_TO_USER + if (device->memstore.hostptr) + { + shadowprop->hostaddr = (unsigned int) device->memstore.hostptr; + shadowprop->size = device->memstore.size; + shadowprop->flags = GSL_FLAGS_INITIALIZED; + } +#endif // GSL_DEVICE_SHADOW_MEMSTORE_TO_USER + + break; + } + + default: + { + if (device->ftbl.device_getproperty) + { + status = device->ftbl.device_getproperty(device, type, value, sizebytes); + } + + break; + } + } + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_getproperty. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_setproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes) +{ + int status = GSL_SUCCESS; + gsl_device_t *device; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_setproperty(gsl_deviceid_t device_id=%D, gsl_property_type_t type=%T, void *value=0x%08x, uint sizebytes=%u)\n", device_id, type, value, sizebytes ); + + DEBUG_ASSERT(value); + + mutex_lock(&gsl_driver.lock); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + if (device->flags & GSL_FLAGS_INITIALIZED) + { + if (device->ftbl.device_setproperty) + { + status = device->ftbl.device_setproperty(device, type, value, sizebytes); + } + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_setproperty. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_start(gsl_deviceid_t device_id, gsl_flags_t flags) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + gsl_device_t *device; + gsl_hal_t *hal = (gsl_hal_t *)gsl_driver.hal; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_start(gsl_deviceid_t device_id=%D, gsl_flags_t flags=%d)\n", device_id, flags ); + + mutex_lock(&gsl_driver.lock); + + if ((GSL_DEVICE_G12 == device_id) && !(hal->has_z160)) { + mutex_unlock(&gsl_driver.lock); + return GSL_FAILURE_NOTSUPPORTED; + } + + if ((GSL_DEVICE_YAMATO == device_id) && !(hal->has_z430)) { + mutex_unlock(&gsl_driver.lock); + return GSL_FAILURE_NOTSUPPORTED; + } + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + kgsl_device_active(device); + + if (!(device->flags & GSL_FLAGS_INITIALIZED)) + { + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_ERROR, "ERROR: Trying to start uninitialized device.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_start. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + device->refcnt++; + + if (device->flags & GSL_FLAGS_STARTED) + { + mutex_unlock(&gsl_driver.lock); + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_start. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); + } + + // start device in safe mode + if (flags & GSL_FLAGS_SAFEMODE) + { + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_INFO, "Running the device in safe mode.\n" ); + device->flags |= GSL_FLAGS_SAFEMODE; + } + + if (device->ftbl.device_start) + { + status = device->ftbl.device_start(device, flags); + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_start. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_stop(gsl_deviceid_t device_id) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + gsl_device_t *device; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_stop(gsl_deviceid_t device_id=%D)\n", device_id ); + + mutex_lock(&gsl_driver.lock); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + if (device->flags & GSL_FLAGS_STARTED) + { + DEBUG_ASSERT(device->refcnt); + + device->refcnt--; + + if (device->refcnt == 0) + { + if (device->ftbl.device_stop) + { + status = device->ftbl.device_stop(device); + } + } + else + { + status = GSL_SUCCESS; + } + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_stop. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_idle(gsl_deviceid_t device_id, unsigned int timeout) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + gsl_device_t *device; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_idle(gsl_deviceid_t device_id=%D, unsigned int timeout=%d)\n", device_id, timeout ); + + mutex_lock(&gsl_driver.lock); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + kgsl_device_active(device); + + if (device->ftbl.device_idle) + { + status = device->ftbl.device_idle(device, timeout); + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_idle. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_isidle(gsl_deviceid_t device_id) +{ + gsl_timestamp_t retired = kgsl_cmdstream_readtimestamp0(device_id, GSL_TIMESTAMP_RETIRED); + gsl_timestamp_t consumed = kgsl_cmdstream_readtimestamp0(device_id, GSL_TIMESTAMP_CONSUMED); + gsl_timestamp_t ts_diff = retired - consumed; + return (ts_diff >= 0) || (ts_diff < -GSL_TIMESTAMP_EPSILON) ? GSL_SUCCESS : GSL_FAILURE; +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_regread(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int *value) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + gsl_device_t *device; + + +#ifdef GSL_LOG + if( offsetwords != mmRBBM_STATUS && offsetwords != mmCP_RB_RPTR ) // Would otherwise flood the log + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_regread(gsl_deviceid_t device_id=%D, unsigned int offsetwords=%R, unsigned int *value=0x%08x)\n", device_id, offsetwords, value ); +#endif + + mutex_lock(&gsl_driver.lock); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + DEBUG_ASSERT(value); + DEBUG_ASSERT(offsetwords < device->regspace.sizebytes); + + if (device->ftbl.device_regread) + { + status = device->ftbl.device_regread(device, offsetwords, value); + } + + mutex_unlock(&gsl_driver.lock); + +#ifdef GSL_LOG + if( offsetwords != mmRBBM_STATUS && offsetwords != mmCP_RB_RPTR ) + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_regread. Return value %B\n", status ); +#endif + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_regwrite(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int value) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + gsl_device_t *device; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_regwrite(gsl_deviceid_t device_id=%D, unsigned int offsetwords=%R, uint value=0x%08x)\n", device_id, offsetwords, value ); + + mutex_lock(&gsl_driver.lock); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + DEBUG_ASSERT(offsetwords < device->regspace.sizebytes); + + if (device->ftbl.device_regwrite) + { + status = device->ftbl.device_regwrite(device, offsetwords, value); + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_regwrite. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_waitirq(gsl_deviceid_t device_id, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + gsl_device_t *device; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_waitirq(gsl_deviceid_t device_id=%D, gsl_intrid_t intr_id=%d, unsigned int *count=0x%08x, unsigned int timout=0x%08x)\n", device_id, intr_id, count, timeout); + + mutex_lock(&gsl_driver.lock); + + device = &gsl_driver.device[device_id-1]; // device_id is 1 based + + if (device->ftbl.device_waitirq) + { + status = device->ftbl.device_waitirq(device, intr_id, count, timeout); + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_waitirq. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_device_runpending(gsl_device_t *device) +{ + int status = GSL_FAILURE_NOTINITIALIZED; + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_device_runpending(gsl_device_t *device=0x%08x )\n", device ); + + if (device->flags & GSL_FLAGS_INITIALIZED) + { + if (device->ftbl.device_runpending) + { + status = device->ftbl.device_runpending(device); + } + } + + // free any pending freeontimestamps + kgsl_cmdstream_memqueue_drain(device); + + kgsl_log_write( KGSL_LOG_GROUP_DEVICE | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_device_runpending. Return value %B\n", status ); + + return (status); +} + diff --git a/drivers/mxc/amd-gpu/gsl_drawctxt.c b/drivers/mxc/amd-gpu/gsl_drawctxt.c new file mode 100644 index 00000000000..3ff861bea9b --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_drawctxt.c @@ -0,0 +1,1796 @@ +/* Copyright (c) 2002,2007-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" +#include "gsl_hal.h" + +#ifdef GSL_BLD_YAMATO + +////////////////////////////////////////////////////////////////////////////// +// +// Memory Map for Register, Constant & Instruction Shadow, and Command Buffers (34.5KB) +// +// +---------------------+------------+-------------+---+---------------------+ +// | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow | +// +---------------------+------------+-------------+---+---------------------+ +// ________________________________' '___________________ +// ' ' +// +--------------+-----------+------+-----------+------------------------+ +// | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused | +// +--------------+-----------+------+-----------+------------------------+ +// +// 8K - ALU Constant Shadow (8K aligned) +// 4K - H/W Register Shadow (8K aligned) +// 9K - Command and Vertex Buffers +// - Indirect command buffer : Const/Reg restore +// - includes Loop & Bool const shadows +// - Indirect command buffer : Const/Reg save +// - Quad vertices & texture coordinates +// - Indirect command buffer : Gmem save +// - Indirect command buffer : Gmem restore +// - Unused (padding to 8KB boundary) +// <1K - Texture Constant Shadow (768 bytes) (8K aligned) +// 18K - Shader Instruction Shadow +// - 6K vertex (32 byte aligned) +// - 6K pixel (32 byte aligned) +// - 6K shared (32 byte aligned) +// +// Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes +// 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of +// 16 bytes per constant. If the texture constants were transfered this way, +// the Command & Vertex Buffers section would extend past the 16K boundary. +// By moving the texture constant shadow area to start at 16KB boundary, we +// only require approximately 40 bytes more memory, but are able to use the +// LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up +// context switching. +// +// [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool +// constants would require an additional 8KB each, for alignment.] +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// Constants +////////////////////////////////////////////////////////////////////////////// + +#define ALU_CONSTANTS 2048 // DWORDS +#define NUM_REGISTERS 1024 // DWORDS +#ifdef DISABLE_SHADOW_WRITES + #define CMD_BUFFER_LEN 9216 // DWORDS +#else + #define CMD_BUFFER_LEN 3072 // DWORDS +#endif +#define TEX_CONSTANTS (32*6) // DWORDS +#define BOOL_CONSTANTS 8 // DWORDS +#define LOOP_CONSTANTS 56 // DWORDS +#define SHADER_INSTRUCT_LOG2 9U // 2^n == SHADER_INSTRUCTIONS + +#if defined(PM4_IM_STORE) +#define SHADER_INSTRUCT (1< exp) + frac = ( uintval & ( ~( 1 << exp ) ) ) << ( 23 - exp ); + + /* Exp is biased by 127 and shifted 23 bits */ + exp = ( exp + 127 ) << 23; + + return exp | frac; +} + +////////////////////////////////////////////////////////////////////////////// +// Helper function to divide two unsigned ints and return the result as a floating point value +////////////////////////////////////////////////////////////////////////////// +unsigned int uintdivide(unsigned int a, unsigned int b) +{ + uint64_t a_fixed = a << 16; + uint64_t b_fixed = b << 16; + + // Assume the result is 0.fraction + unsigned int fraction; + unsigned int exp = 126; + + if( b == 0 ) return 0; + + a_fixed = a_fixed << 32; + do_div(a_fixed, b_fixed); + fraction = (unsigned int)a_fixed; + + if( fraction == 0 ) return 0; + + // Normalize + while( !(fraction & (1<<31)) ) + { + fraction <<= 1; + exp--; + } + // Remove hidden bit + fraction <<= 1; + + // Round + if( ( fraction & 0x1ff ) > 256 ) + { + int rounded = 0; + int i = 9; + + // Do the bit addition + while( !rounded ) + { + if( fraction & (1<>= 9; + + return ( ( exp << 23 ) | fraction ); +} + + + +////////////////////////////////////////////////////////////////////////////// +// context save (gmem -> sys) +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// pre-compiled vertex shader program +// +// attribute vec4 P; +// void main(void) +// { +// gl_Position = P; +// } +// +////////////////////////////////////////////////////////////////////////////// + +#define GMEM2SYS_VTX_PGM_LEN 0x12 + +static const unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = { + 0x00011003, 0x00001000, 0xc2000000, + 0x00001004, 0x00001000, 0xc4000000, + 0x00001005, 0x00002000, 0x00000000, + 0x1cb81000, 0x00398a88, 0x00000003, + 0x140f803e, 0x00000000, 0xe2010100, + 0x14000000, 0x00000000, 0xe2000000 +}; + + +////////////////////////////////////////////////////////////////////////////// +// pre-compiled fragment shader program +// +// precision highp float; +// uniform vec4 clear_color; +// void main(void) +// { +// gl_FragColor = clear_color; +// } +// +////////////////////////////////////////////////////////////////////////////// + +#define GMEM2SYS_FRAG_PGM_LEN 0x0c + +static const unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = { + 0x00000000, 0x1002c400, 0x10000000, + 0x00001003, 0x00002000, 0x00000000, + 0x140f8000, 0x00000000, 0x22000000, + 0x14000000, 0x00000000, 0xe2000000 +}; + + +////////////////////////////////////////////////////////////////////////////// +// context restore (sys -> gmem) +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// pre-compiled vertex shader program +// +// attribute vec4 position; +// attribute vec4 texcoord; +// varying vec4 texcoord0; +// void main() +// { +// gl_Position = position; +// texcoord0 = texcoord; +// } +// +////////////////////////////////////////////////////////////////////////////// + +#define SYS2GMEM_VTX_PGM_LEN 0x18 + +static const unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = { + 0x00052003, 0x00001000, 0xc2000000, 0x00001005, + 0x00001000, 0xc4000000, 0x00001006, 0x10071000, + 0x20000000, 0x18981000, 0x0039ba88, 0x00000003, + 0x12982000, 0x40257b08, 0x00000002, 0x140f803e, + 0x00000000, 0xe2010100, 0x140f8000, 0x00000000, + 0xe2020200, 0x14000000, 0x00000000, 0xe2000000 +}; + + +////////////////////////////////////////////////////////////////////////////// +// pre-compiled fragment shader program +// +// precision mediump float; +// uniform sampler2D tex0; +// varying vec4 texcoord0; +// void main() +// { +// gl_FragColor = texture2D(tex0, texcoord0.xy); +// } +// +////////////////////////////////////////////////////////////////////////////// + +#define SYS2GMEM_FRAG_PGM_LEN 0x0f + +static const unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = { + 0x00011002, 0x00001000, 0xc4000000, 0x00001003, + 0x10041000, 0x20000000, 0x10000001, 0x1ffff688, + 0x00000002, 0x140f8000, 0x00000000, 0xe2000000, + 0x14000000, 0x00000000, 0xe2000000 +}; + + +////////////////////////////////////////////////////////////////////////////// +// shader texture constants (sysmem -> gmem) +////////////////////////////////////////////////////////////////////////////// + +#define SYS2GMEM_TEX_CONST_LEN 6 + +static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = +{ + // Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,RFMode=ZeroClamp-1,Dim=1:2d + 0x00000002, // Pitch = TBD + + // Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0, NearestClamp=1:OGL Mode + 0x00000806, // Address[31:12] = TBD + + // Width, Height, EndianSwap=0:None + 0, // Width & Height = TBD + + // NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point, Mip=2:BaseMap + 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23, + + // VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0, Dim3d=0 + 0, + + // BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0, Dim=1:2d, MipPacking=0 + 1 << 9 // Mip Address[31:12] = TBD +}; + + +////////////////////////////////////////////////////////////////////////////// +// quad for copying GMEM to context shadow +////////////////////////////////////////////////////////////////////////////// + +#define QUAD_LEN 12 + +static unsigned int gmem_copy_quad[QUAD_LEN] = { + 0x00000000, 0x00000000, 0x3f800000, + 0x00000000, 0x00000000, 0x3f800000, + 0x00000000, 0x00000000, 0x3f800000, + 0x00000000, 0x00000000, 0x3f800000 +}; + +#define TEXCOORD_LEN 8 + +static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = { + 0x00000000, 0x3f800000, + 0x3f800000, 0x3f800000, + 0x00000000, 0x00000000, + 0x3f800000, 0x00000000 +}; + +#define NUM_COLOR_FORMATS 13 + +static SurfaceFormat surface_format_table[NUM_COLOR_FORMATS] = +{ + FMT_4_4_4_4, // COLORX_4_4_4_4 + FMT_1_5_5_5, // COLORX_1_5_5_5 + FMT_5_6_5, // COLORX_5_6_5 + FMT_8, // COLORX_8 + FMT_8_8, // COLORX_8_8 + FMT_8_8_8_8, // COLORX_8_8_8_8 + FMT_8_8_8_8, // COLORX_S8_8_8_8 + FMT_16_FLOAT, // COLORX_16_FLOAT + FMT_16_16_FLOAT, // COLORX_16_16_FLOAT + FMT_16_16_16_16_FLOAT, // COLORX_16_16_16_16_FLOAT + FMT_32_FLOAT, // COLORX_32_FLOAT + FMT_32_32_FLOAT, // COLORX_32_32_FLOAT + FMT_32_32_32_32_FLOAT, // COLORX_32_32_32_32_FLOAT +}; + +static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = +{ + 2, // COLORX_4_4_4_4 + 2, // COLORX_1_5_5_5 + 2, // COLORX_5_6_5 + 1, // COLORX_8 + 2, // COLORX_8_8_8 + 4, // COLORX_8_8_8_8 + 4, // COLORX_S8_8_8_8 + 2, // COLORX_16_FLOAT + 4, // COLORX_16_16_FLOAT + 8, // COLORX_16_16_16_16_FLOAT + 4, // COLORX_32_FLOAT + 8, // COLORX_32_32_FLOAT + 16, // COLORX_32_32_32_32_FLOAT +}; + +////////////////////////////////////////////////////////////////////////////// +// shader linkage info +////////////////////////////////////////////////////////////////////////////// + +#define SHADER_CONST_ADDR (11 * 6 + 3) + + +////////////////////////////////////////////////////////////////////////////// +// gmem command buffer length +////////////////////////////////////////////////////////////////////////////// + +#define PM4_REG(reg) ((0x4 << 16) | (GSL_HAL_SUBBLOCK_OFFSET(reg))) + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +static void +config_gmemsize(gmem_shadow_t *shadow, int gmem_size) +{ + int w=64, h=64; // 16KB surface, minimum + + // convert from bytes to 32-bit words + gmem_size = (gmem_size + 3)/4; + + // find the right surface size, close to a square. + while (w * h < gmem_size) + if (w < h) + w *= 2; + else + h *= 2; + + shadow->width = w; + shadow->height = h; + shadow->pitch = w; + shadow->format = COLORX_8_8_8_8; + shadow->size = shadow->pitch * shadow->height * 4; + + shadow->gmem_width = w; + shadow->gmem_height = h; + shadow->gmem_pitch = w; +} + + +////////////////////////////////////////////////////////////////////////////// + +static unsigned int +gpuaddr(unsigned int *cmd, gsl_memdesc_t *memdesc) +{ + return memdesc->gpuaddr + ((char *)cmd - (char *)memdesc->hostptr); +} + + +////////////////////////////////////////////////////////////////////////////// + +static void +create_ib1(gsl_drawctxt_t *drawctxt, unsigned int *cmd, unsigned int *start, unsigned int *end) +{ + cmd[0] = PM4_HDR_INDIRECT_BUFFER_PFD; + cmd[1] = gpuaddr(start, &drawctxt->gpustate); + cmd[2] = end - start; +} + + +////////////////////////////////////////////////////////////////////////////// + +static unsigned int * +program_shader(unsigned int *cmds, int vtxfrag, const unsigned int *shader_pgm, int dwords) +{ + // load the patched vertex shader stream + *cmds++ = pm4_type3_packet(PM4_IM_LOAD_IMMEDIATE, 2 + dwords); + *cmds++ = vtxfrag; // 0=vertex shader, 1=fragment shader + *cmds++ = ( (0 << 16) | dwords ); // instruction start & size (in 32-bit words) + + memcpy(cmds, shader_pgm, dwords<<2); + cmds += dwords; + + return cmds; +} + + +////////////////////////////////////////////////////////////////////////////// + +static unsigned int * +reg_to_mem(unsigned int *cmds, gpuaddr_t dst, gpuaddr_t src, int dwords) +{ + while (dwords-- > 0) + { + *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmds++ = src++; + *cmds++ = dst; + dst += 4; + } + + return cmds; +} + + + +#ifdef DISABLE_SHADOW_WRITES + +static void build_reg_to_mem_range(unsigned int start, unsigned int end, unsigned int** cmd, gsl_drawctxt_t *drawctxt) +{ + unsigned int i = start; + + for(i=start; i<=end; i++) + { + *(*cmd)++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *(*cmd)++ = i | (1<<30); + *(*cmd)++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) + (i-0x2000)*4; + } +} + +#endif + +////////////////////////////////////////////////////////////////////////////// +// chicken restore +////////////////////////////////////////////////////////////////////////////// +static unsigned int* +build_chicken_restore_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) +{ + unsigned int *start = ctx->cmd; + unsigned int *cmds = start; + + *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmds++ = 0; + + *cmds++ = pm4_type0_packet(mmTP0_CHICKEN, 1); + ctx->chicken_restore = gpuaddr(cmds, &drawctxt->gpustate); + *cmds++ = 0x00000000; + + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds); + + return cmds; +} + + + +////////////////////////////////////////////////////////////////////////////// +// context save +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// save h/w regs, alu constants, texture contants, etc. ... +// requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr +////////////////////////////////////////////////////////////////////////////// + +static void +build_regsave_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) +{ + unsigned int *start = ctx->cmd; + unsigned int *cmd = start; + +#ifdef DISABLE_SHADOW_WRITES + // Write HW registers into shadow + build_reg_to_mem_range(mmRB_SURFACE_INFO, mmRB_DEPTH_INFO, &cmd, drawctxt); + build_reg_to_mem_range(mmCOHER_DEST_BASE_0, mmPA_SC_SCREEN_SCISSOR_BR, &cmd, drawctxt); + build_reg_to_mem_range(mmPA_SC_WINDOW_OFFSET, mmPA_SC_WINDOW_SCISSOR_BR, &cmd, drawctxt); + build_reg_to_mem_range(mmVGT_MAX_VTX_INDX, mmRB_FOG_COLOR, &cmd, drawctxt); + build_reg_to_mem_range(mmRB_STENCILREFMASK_BF, mmPA_CL_VPORT_ZOFFSET, &cmd, drawctxt); + build_reg_to_mem_range(mmSQ_PROGRAM_CNTL, mmSQ_WRAPPING_1, &cmd, drawctxt); + build_reg_to_mem_range(mmRB_DEPTHCONTROL, mmRB_MODECONTROL, &cmd, drawctxt); + build_reg_to_mem_range(mmPA_SU_POINT_SIZE, mmPA_SC_LINE_STIPPLE, &cmd, drawctxt); + build_reg_to_mem_range(mmPA_SC_VIZ_QUERY, mmPA_SC_VIZ_QUERY, &cmd, drawctxt); + build_reg_to_mem_range(mmPA_SC_LINE_CNTL, mmSQ_PS_CONST, &cmd, drawctxt); + build_reg_to_mem_range(mmPA_SC_AA_MASK, mmPA_SC_AA_MASK, &cmd, drawctxt); + build_reg_to_mem_range(mmVGT_VERTEX_REUSE_BLOCK_CNTL, mmRB_DEPTH_CLEAR, &cmd, drawctxt); + build_reg_to_mem_range(mmRB_SAMPLE_COUNT_CTL, mmRB_COLOR_DEST_MASK, &cmd, drawctxt); + build_reg_to_mem_range(mmPA_SU_POLY_OFFSET_FRONT_SCALE, mmPA_SU_POLY_OFFSET_BACK_OFFSET, &cmd, drawctxt); + + // Copy ALU constants + cmd = reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000, mmSQ_CONSTANT_0, ALU_CONSTANTS); + + // Copy Tex constants + cmd = reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000, mmSQ_FETCH_0, TEX_CONSTANTS); +#else + // insert a wait for idle (adreno.c:542 from qualcomm kernel) + *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmd++ = 0; + + // H/w registers are already shadowed; just need to disable shadowing to prevent corruption. + *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); + *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000; + *cmd++ = 4 << 16; // regs, start=0 + *cmd++ = 0x0; // count = 0 + + // ALU constants are already shadowed; just need to disable shadowing to prevent corruption. + *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); + *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000; + *cmd++ = 0 << 16; // ALU, start=0 + *cmd++ = 0x0; // count = 0 + + // Tex constants are already shadowed; just need to disable shadowing to prevent corruption. + *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); + *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000; + *cmd++ = 1 << 16; // Tex, start=0 + *cmd++ = 0x0; // count = 0 +#endif + + + + + // Need to handle some of the registers separately + *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmd++ = mmSQ_GPR_MANAGEMENT; + *cmd++ = ctx->reg_values[0]; + *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmd++ = mmTP0_CHICKEN; + *cmd++ = ctx->reg_values[1]; + + // Copy Boolean constants + cmd = reg_to_mem(cmd, ctx->bool_shadow, mmSQ_CF_BOOLEANS, BOOL_CONSTANTS); + + // Copy Loop constants + cmd = reg_to_mem(cmd, ctx->loop_shadow, mmSQ_CF_LOOP, LOOP_CONSTANTS); + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, drawctxt->reg_save, start, cmd); + + ctx->cmd = cmd; +} + + +////////////////////////////////////////////////////////////////////////////// +// copy colour, depth, & stencil buffers from graphics memory to system memory +////////////////////////////////////////////////////////////////////////////// + +static unsigned int* +build_gmem2sys_cmds(gsl_drawctxt_t *drawctxt, ctx_t* ctx, gmem_shadow_t *shadow) +{ + unsigned int *cmds = shadow->gmem_save_commands; + unsigned int *start = cmds; + + // Store TP0_CHICKEN register + *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmds++ = mmTP0_CHICKEN; + if( ctx ) + *cmds++ = ctx->chicken_restore; + else + cmds++; + + *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmds++ = 0; + + // Set TP0_CHICKEN to zero + *cmds++ = pm4_type0_packet(mmTP0_CHICKEN, 1); + *cmds++ = 0x00000000; + + /* Set PA_SC_AA_CONFIG to 0 - from Qualcomm*/ + //*cmds++ = pm4_type0_packet(mmPA_SC_AA_CONFIG, 1); + //*cmds++ = 0x00000000; + + // -------------- + // program shader + // -------------- + + // load shader vtx constants ... 5 dwords + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4); + *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR; + *cmds++ = 0; + *cmds++ = shadow->quad_vertices.gpuaddr | 0x3; // valid(?) vtx constant flag & addr + *cmds++ = 0x00000030; // limit = 12 dwords + + // Invalidate L2 cache to make sure vertices are updated + *cmds++ = pm4_type0_packet(mmTC_CNTL_STATUS, 1); + *cmds++ = 0x1; + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4); + *cmds++ = PM4_REG(mmVGT_MAX_VTX_INDX); + *cmds++ = 0x00ffffff; //mmVGT_MAX_VTX_INDX + *cmds++ = 0x0; //mmVGT_MIN_VTX_INDX + *cmds++ = 0x00000000; //mmVGT_INDX_OFFSET + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_SC_AA_MASK); + *cmds++ = 0x0000ffff; //mmPA_SC_AA_MASK + + + // load the patched vertex shader stream + cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN); + + // Load the patched fragment shader stream + cmds = program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN); + + // SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmSQ_PROGRAM_CNTL); + *cmds++ = 0x10010001; + *cmds++ = 0x00000008; + + + // -------------- + // resolve + // -------------- + + // PA_CL_VTE_CNTL + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_CL_VTE_CNTL); + *cmds++ = 0x00000b00; // disable X/Y/Z transforms, X/Y/Z are premultiplied by W + + // change colour buffer to RGBA8888, MSAA = 1, and matching pitch + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmRB_SURFACE_INFO); + *cmds++ = shadow->gmem_pitch; + + // RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0, Base=gmem_base + if( ctx ) + { + DEBUG_ASSERT((ctx->gmem_base & 0xFFF) == 0); // gmem base assumed 4K aligned. + *cmds++ = (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | ctx->gmem_base; + } + else + { + unsigned int temp = *cmds; + *cmds++ = (temp & ~RB_COLOR_INFO__COLOR_FORMAT_MASK) | (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT); + } + + // disable Z + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_DEPTHCONTROL); + *cmds++ = 0; + + // set mmPA_SU_SC_MODE_CNTL + // Front_ptype = draw triangles + // Back_ptype = draw triangles + // Provoking vertex = last + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_SU_SC_MODE_CNTL); + *cmds++ = 0x00080240; + + // set the scissor to the extents of the draw surface + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmPA_SC_SCREEN_SCISSOR_TL); + *cmds++ = (shadow->gmem_offset_y << 16) | shadow->gmem_offset_x; + *cmds++ = (shadow->gmem_height << 16) | shadow->gmem_width; + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmPA_SC_WINDOW_SCISSOR_TL); + *cmds++ = (1U << 31) | (0 << 16) | 0; + *cmds++ = (shadow->height << 16) | shadow->width; + + // load the viewport so that z scale = clear depth and z offset = 0.0f + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmPA_CL_VPORT_ZSCALE); + *cmds++ = 0xbf800000; // -1.0f + *cmds++ = 0x0; + + // load the COPY state + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 6); + *cmds++ = PM4_REG(mmRB_COPY_CONTROL); + *cmds++ = 0; // RB_COPY_CONTROL + + { + // Calculate the new offset based on the adjusted base + unsigned int bytesperpixel = format2bytesperpixel[shadow->format]; + unsigned int addr = (shadow->gmemshadow.gpuaddr + shadow->offset * bytesperpixel); + unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel; + + *cmds++ = addr & 0xfffff000; // RB_COPY_DEST_BASE + *cmds++ = shadow->pitch >> 5; // RB_COPY_DEST_PITCH + *cmds++ = 0x0003c008 | (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT); // Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,MaskWrite:R=G=B=A=1 + + DEBUG_ASSERT( (offset & 0xfffff000) == 0 ); // Make sure we stay in offsetx field. + *cmds++ = offset; + } + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_MODECONTROL); + *cmds++ = 0x6; // EDRAM copy + + // gleaned from qualcomm source + //*cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + //*cmds++ = PM4_REG(mmPA_CL_CLIP_CNTL); + //*cmds++ = 0x00010000; + + // queue the draw packet + *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2); + *cmds++ = 0; // viz query info. + *cmds++ = 0x00030088; // PrimType=RectList, NumIndices=3, SrcSel=AutoIndex + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, shadow->gmem_save, start, cmds); + + return cmds; +} + + +////////////////////////////////////////////////////////////////////////////// +// context restore +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// copy colour, depth, & stencil buffers from system memory to graphics memory +////////////////////////////////////////////////////////////////////////////// + +static unsigned int* +build_sys2gmem_cmds(gsl_drawctxt_t *drawctxt, ctx_t* ctx, gmem_shadow_t *shadow) +{ + unsigned int *cmds = shadow->gmem_restore_commands; + unsigned int *start = cmds; + + // Store TP0_CHICKEN register + *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmds++ = mmTP0_CHICKEN; + if( ctx ) + *cmds++ = ctx->chicken_restore; + else + cmds++; + + *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmds++ = 0; + + // Set TP0_CHICKEN to zero + *cmds++ = pm4_type0_packet(mmTP0_CHICKEN, 1); + *cmds++ = 0x00000000; + + /* Set PA_SC_AA_CONFIG to 0 */ + //*cmds++ = pm4_type0_packet(mmPA_SC_AA_CONFIG, 1); + //*cmds++ = 0x00000000; + + // ---------------- + // shader constants + // ---------------- + + // vertex buffer constants + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 7); + + *cmds++ = (0x1 << 16) | (9 * 6); + *cmds++ = shadow->quad_vertices.gpuaddr | 0x3; // valid(?) vtx constant flag & addr + *cmds++ = 0x00000030; // limit = 12 dwords + *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3; // valid(?) vtx constant flag & addr + *cmds++ = 0x00000020; // limit = 8 dwords + *cmds++ = 0; + *cmds++ = 0; + + // Invalidate L2 cache to make sure vertices and texture coordinates are updated + *cmds++ = pm4_type0_packet(mmTC_CNTL_STATUS, 1); + *cmds++ = 0x1; + + // load the patched vertex shader stream + cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN); + + // Load the patched fragment shader stream + cmds = program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN); + + // SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmSQ_PROGRAM_CNTL); + *cmds++ = 0x10030002; + *cmds++ = 0x00000008; + + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_SC_AA_MASK); + *cmds++ = 0x0000ffff; //mmPA_SC_AA_MASK + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_SC_VIZ_QUERY); + *cmds++ = 0x0; //mmPA_SC_VIZ_QUERY + + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_COLORCONTROL); + *cmds++ = 0x00000c20; // RB_COLORCONTROL + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4); + *cmds++ = PM4_REG(mmVGT_MAX_VTX_INDX); + *cmds++ = 0x00ffffff; //mmVGT_MAX_VTX_INDX + *cmds++ = 0x0; //mmVGT_MIN_VTX_INDX + *cmds++ = 0x00000000; //mmVGT_INDX_OFFSET + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmVGT_VERTEX_REUSE_BLOCK_CNTL); + *cmds++ = 0x00000002; //mmVGT_VERTEX_REUSE_BLOCK_CNTL + *cmds++ = 0x00000002; //mmVGT_OUT_DEALLOC_CNTL + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmSQ_INTERPOLATOR_CNTL); + *cmds++ = 0xffffffff; //mmSQ_INTERPOLATOR_CNTL + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_SC_AA_CONFIG); + *cmds++ = 0x00000000; //mmPA_SC_AA_CONFIG + + + // set mmPA_SU_SC_MODE_CNTL + // Front_ptype = draw triangles + // Back_ptype = draw triangles + // Provoking vertex = last + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_SU_SC_MODE_CNTL); + *cmds++ = 0x00080240; + + // texture constants + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1)); + *cmds++ = (0x1 << 16) | (0 * 6); + memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN<<2); + cmds[0] |= (shadow->pitch >> 5) << 22; + cmds[1] |= shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format]; + cmds[2] |= (shadow->width+shadow->offset_x-1) | (shadow->height+shadow->offset_y-1) << 13; + cmds += SYS2GMEM_TEX_CONST_LEN; + + // change colour buffer to RGBA8888, MSAA = 1, and matching pitch + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmRB_SURFACE_INFO); + *cmds++ = shadow->gmem_pitch; // GMEM pitch is equal to context GMEM shadow pitch + + // RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0, Base=gmem_base + if( ctx ) + { + *cmds++ = (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | ctx->gmem_base; + } + else + { + unsigned int temp = *cmds; + *cmds++ = (temp & ~RB_COLOR_INFO__COLOR_FORMAT_MASK) | (shadow->format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT); + } + + // RB_DEPTHCONTROL + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_DEPTHCONTROL); + *cmds++ = 0; // disable Z + + // set the scissor to the extents of the draw surface + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmPA_SC_SCREEN_SCISSOR_TL); + *cmds++ = (0 << 16) | 0; + *cmds++ = (shadow->height << 16) | shadow->width; + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmPA_SC_WINDOW_SCISSOR_TL); + *cmds++ = (1U << 31) | (shadow->gmem_offset_y << 16) | shadow->gmem_offset_x; + *cmds++ = (shadow->gmem_height << 16) | shadow->gmem_width; + + // PA_CL_VTE_CNTL + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmPA_CL_VTE_CNTL); + *cmds++ = 0x00000b00; // disable X/Y/Z transforms, X/Y/Z are premultiplied by W + + // load the viewport so that z scale = clear depth and z offset = 0.0f + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmPA_CL_VPORT_ZSCALE); + *cmds++ = 0xbf800000; + *cmds++ = 0x0; + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_COLOR_MASK); + *cmds++ = 0x0000000f; // R = G = B = 1:enabled + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_COLOR_DEST_MASK); + *cmds++ = 0xffffffff; + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3); + *cmds++ = PM4_REG(mmSQ_WRAPPING_0); + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + + *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2); + *cmds++ = PM4_REG(mmRB_MODECONTROL); + *cmds++ = 0x4; // draw pixels with color and depth/stencil component + + // queue the draw packet + *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2); + *cmds++ = 0; // viz query info. + *cmds++ = 0x00030088; // PrimType=RectList, NumIndices=3, SrcSel=AutoIndex + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, shadow->gmem_restore, start, cmds); + + return cmds; +} + + +////////////////////////////////////////////////////////////////////////////// +// restore h/w regs, alu constants, texture constants, etc. ... +////////////////////////////////////////////////////////////////////////////// + +static unsigned * +reg_range(unsigned int *cmd, unsigned int start, unsigned int end) +{ + *cmd++ = PM4_REG(start); // h/w regs, start addr + *cmd++ = end - start + 1; // count + return cmd; +} + + +////////////////////////////////////////////////////////////////////////////// + +static void +build_regrestore_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) +{ + unsigned int *start = ctx->cmd; + unsigned int *cmd = start; + + // H/W Registers + cmd++; // deferred pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, ???); +#ifdef DISABLE_SHADOW_WRITES + *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1; // Force mismatch +#else + *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000; +#endif + + cmd = reg_range(cmd, mmRB_SURFACE_INFO, mmPA_SC_SCREEN_SCISSOR_BR); + cmd = reg_range(cmd, mmPA_SC_WINDOW_OFFSET, mmPA_SC_WINDOW_SCISSOR_BR); + cmd = reg_range(cmd, mmVGT_MAX_VTX_INDX, mmPA_CL_VPORT_ZOFFSET); + cmd = reg_range(cmd, mmSQ_PROGRAM_CNTL, mmSQ_WRAPPING_1); + cmd = reg_range(cmd, mmRB_DEPTHCONTROL, mmRB_MODECONTROL); + cmd = reg_range(cmd, mmPA_SU_POINT_SIZE, mmPA_SC_VIZ_QUERY); + cmd = reg_range(cmd, mmPA_SC_LINE_CNTL, mmRB_COLOR_DEST_MASK); + cmd = reg_range(cmd, mmPA_SU_POLY_OFFSET_FRONT_SCALE, mmPA_SU_POLY_OFFSET_BACK_OFFSET); + + // Now we know how many register blocks we have, we can compute command length + start[0] = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, (cmd-start)-1); +#ifdef DISABLE_SHADOW_WRITES + start[2] |= (0<<24) | (4 << 16); // Disable shadowing. +#else + start[2] |= (1<<24) | (4 << 16); // Enable shadowing for the entire register block. +#endif + + // Need to handle some of the registers separately + *cmd++ = pm4_type0_packet(mmSQ_GPR_MANAGEMENT, 1); + ctx->reg_values[0] = gpuaddr(cmd, &drawctxt->gpustate); + *cmd++ = 0x00040400; + + *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmd++ = 0; + *cmd++ = pm4_type0_packet(mmTP0_CHICKEN, 1); + ctx->reg_values[1] = gpuaddr(cmd, &drawctxt->gpustate); + *cmd++ = 0x00000000; + + // ALU Constants + *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); + *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000; +#ifdef DISABLE_SHADOW_WRITES + *cmd++ = (0<<24) | (0<<16) | 0; // Disable shadowing +#else + *cmd++ = (1<<24) | (0<<16) | 0; +#endif + *cmd++ = ALU_CONSTANTS; + + + // Texture Constants + *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3); + *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000; +#ifdef DISABLE_SHADOW_WRITES + *cmd++ = (0<<24) | (1<<16) | 0; // Disable shadowing +#else + *cmd++ = (1<<24) | (1<<16) | 0; +#endif + *cmd++ = TEX_CONSTANTS; + + + // Boolean Constants + *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + BOOL_CONSTANTS); + *cmd++ = (2<<16) | 0; + + // the next BOOL_CONSTANT dwords is the shadow area for boolean constants. + ctx->bool_shadow = gpuaddr(cmd, &drawctxt->gpustate); + cmd += BOOL_CONSTANTS; + + + // Loop Constants + *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + LOOP_CONSTANTS); + *cmd++ = (3<<16) | 0; + + // the next LOOP_CONSTANTS dwords is the shadow area for loop constants. + ctx->loop_shadow = gpuaddr(cmd, &drawctxt->gpustate); + cmd += LOOP_CONSTANTS; + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, drawctxt->reg_restore, start, cmd); + + ctx->cmd = cmd; +} + + +////////////////////////////////////////////////////////////////////////////// +// quad for saving/restoring gmem +////////////////////////////////////////////////////////////////////////////// + +static void set_gmem_copy_quad( gmem_shadow_t* shadow ) +{ + unsigned int tex_offset[2]; + + // set vertex buffer values + + gmem_copy_quad[1] = uint2float( shadow->gmem_height + shadow->gmem_offset_y ); + gmem_copy_quad[3] = uint2float( shadow->gmem_width + shadow->gmem_offset_x ); + gmem_copy_quad[4] = uint2float( shadow->gmem_height + shadow->gmem_offset_y ); + gmem_copy_quad[9] = uint2float( shadow->gmem_width + shadow->gmem_offset_x ); + + gmem_copy_quad[0] = uint2float( shadow->gmem_offset_x ); + gmem_copy_quad[6] = uint2float( shadow->gmem_offset_x ); + gmem_copy_quad[7] = uint2float( shadow->gmem_offset_y ); + gmem_copy_quad[10] = uint2float( shadow->gmem_offset_y ); + + tex_offset[0] = uintdivide( shadow->offset_x, (shadow->offset_x+shadow->width) ); + tex_offset[1] = uintdivide( shadow->offset_y, (shadow->offset_y+shadow->height) ); + + gmem_copy_texcoord[0] = gmem_copy_texcoord[4] = tex_offset[0]; + gmem_copy_texcoord[5] = gmem_copy_texcoord[7] = tex_offset[1]; + + // copy quad data to vertex buffer + memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2); + + // copy tex coord data to tex coord buffer + memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord, TEXCOORD_LEN << 2); +} + + +static void +build_quad_vtxbuff(gsl_drawctxt_t *drawctxt, ctx_t *ctx, gmem_shadow_t* shadow) +{ + unsigned int *cmd = ctx->cmd; + + // quad vertex buffer location + shadow->quad_vertices.hostptr = cmd; + shadow->quad_vertices.gpuaddr = gpuaddr(cmd, &drawctxt->gpustate); + cmd += QUAD_LEN; + + // tex coord buffer location (in GPU space) + shadow->quad_texcoords.hostptr = cmd; + shadow->quad_texcoords.gpuaddr = gpuaddr(cmd, &drawctxt->gpustate); + + + cmd += TEXCOORD_LEN; + + set_gmem_copy_quad(shadow); + + + ctx->cmd = cmd; +} + + +////////////////////////////////////////////////////////////////////////////// + +static void +build_shader_save_restore_cmds(gsl_drawctxt_t *drawctxt, ctx_t *ctx) +{ + unsigned int *cmd = ctx->cmd; + unsigned int *save, *restore, *fixup; +#if defined(PM4_IM_STORE) + unsigned int *startSizeVtx, *startSizePix, *startSizeShared; +#endif + unsigned int *partition1; + unsigned int *shaderBases, *partition2; + +#if defined(PM4_IM_STORE) + // compute vertex, pixel and shared instruction shadow GPU addresses + ctx->shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET; + ctx->shader_pixel = ctx->shader_vertex + SHADER_SHADOW_SIZE; + ctx->shader_shared = ctx->shader_pixel + SHADER_SHADOW_SIZE; +#endif + + + //------------------------------------------------------------------- + // restore shader partitioning and instructions + //------------------------------------------------------------------- + + restore = cmd; // start address + + // Invalidate Vertex & Pixel instruction code address and sizes + *cmd++ = pm4_type3_packet(PM4_INVALIDATE_STATE, 1); + *cmd++ = 0x00000300; // 0x100 = Vertex, 0x200 = Pixel + + // Restore previous shader vertex & pixel instruction bases. + *cmd++ = pm4_type3_packet(PM4_SET_SHADER_BASES, 1); + shaderBases = cmd++; // TBD #5: shader bases (from fixup) + + // write the shader partition information to a scratch register + *cmd++ = pm4_type0_packet(mmSQ_INST_STORE_MANAGMENT, 1); + partition1 = cmd++; // TBD #4a: partition info (from save) + +#if defined(PM4_IM_STORE) + // load vertex shader instructions from the shadow. + *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2); + *cmd++ = ctx->shader_vertex + 0x0; // 0x0 = Vertex + startSizeVtx = cmd++; // TBD #1: start/size (from save) + + // load pixel shader instructions from the shadow. + *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2); + *cmd++ = ctx->shader_pixel + 0x1; // 0x1 = Pixel + startSizePix = cmd++; // TBD #2: start/size (from save) + + // load shared shader instructions from the shadow. + *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2); + *cmd++ = ctx->shader_shared + 0x2; // 0x2 = Shared + startSizeShared = cmd++; // TBD #3: start/size (from save) +#endif + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd); + + + //------------------------------------------------------------------- + // fixup SET_SHADER_BASES data + // + // since self-modifying PM4 code is being used here, a seperate + // command buffer is used for this fixup operation, to ensure the + // commands are not read by the PM4 engine before the data fields + // have been written. + //------------------------------------------------------------------- + + fixup = cmd; // start address + + // write the shader partition information to a scratch register + *cmd++ = pm4_type0_packet(mmSCRATCH_REG2, 1); + partition2 = cmd++; // TBD #4b: partition info (from save) + + // mask off unused bits, then OR with shader instruction memory size + *cmd++ = pm4_type3_packet(PM4_REG_RMW, 3); + *cmd++ = mmSCRATCH_REG2; + *cmd++ = 0x0FFF0FFF; // AND off invalid bits. + *cmd++ = (unsigned int)((SHADER_INSTRUCT_LOG2-5U) << 29); // OR in instruction memory size + + // write the computed value to the SET_SHADER_BASES data field + *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmd++ = mmSCRATCH_REG2; + *cmd++ = gpuaddr(shaderBases, &drawctxt->gpustate); // TBD #5: shader bases (to restore) + + // create indirect buffer command for above command sequence + create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd); + + + //------------------------------------------------------------------- + // save shader partitioning and instructions + //------------------------------------------------------------------- + + save = cmd; // start address + + *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmd++ = 0; + + // Fetch the SQ_INST_STORE_MANAGMENT register value, + // Store the value in the data fields of the SET_CONSTANT commands above. + *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmd++ = mmSQ_INST_STORE_MANAGMENT; + *cmd++ = gpuaddr(partition1, &drawctxt->gpustate); // TBD #4a: partition info (to restore) + *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2); + *cmd++ = mmSQ_INST_STORE_MANAGMENT; + *cmd++ = gpuaddr(partition2, &drawctxt->gpustate); // TBD #4b: partition info (to fixup) + +#if defined(PM4_IM_STORE) + // Store the vertex shader instructions + *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2); + *cmd++ = ctx->shader_vertex + 0x0; // 0x0 = Vertex + *cmd++ = gpuaddr(startSizeVtx, &drawctxt->gpustate); // TBD #1: start/size (to restore) + + // store the pixel shader instructions + *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2); + *cmd++ = ctx->shader_pixel + 0x1; // 0x1 = Pixel + *cmd++ = gpuaddr(startSizePix, &drawctxt->gpustate); // TBD #2: start/size (to restore) + + // Store the shared shader instructions + *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2); + *cmd++ = ctx->shader_shared + 0x2; // 0x2 = Shared + *cmd++ = gpuaddr(startSizeShared, &drawctxt->gpustate); // TBD #3: start/size (to restore) +#endif + + *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *cmd++ = 0; + + + + // Create indirect buffer command for above command sequence + create_ib1(drawctxt, drawctxt->shader_save, save, cmd); + + + ctx->cmd = cmd; +} + + + +////////////////////////////////////////////////////////////////////////////// +// create buffers for saving/restoring registers and constants +////////////////////////////////////////////////////////////////////////////// + +static int +create_gpustate_shadow(gsl_device_t *device, gsl_drawctxt_t *drawctxt, ctx_t *ctx) +{ + gsl_flags_t flags; + + flags = (GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_ALIGN8K); + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, flags = (GSL_MEMFLAGS_EMEM | GSL_MEMFLAGS_ALIGN8K)); + + // allocate memory to allow HW to save sub-blocks for efficient context save/restore + if (kgsl_sharedmem_alloc0(device->id, flags, CONTEXT_SIZE, &drawctxt->gpustate) != GSL_SUCCESS) + return GSL_FAILURE; + + drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW; + + // Blank out h/w register, constant, and command buffer shadows. + kgsl_sharedmem_set0(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE); + + // set-up command and vertex buffer pointers + ctx->cmd = ctx->start = (unsigned int *) ((char *)drawctxt->gpustate.hostptr + CMD_OFFSET); + + // build indirect command buffers to save & restore regs/constants + build_regrestore_cmds(drawctxt, ctx); + build_regsave_cmds(drawctxt, ctx); + + build_shader_save_restore_cmds(drawctxt, ctx); + + return GSL_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +// Allocate GMEM shadow buffer +////////////////////////////////////////////////////////////////////////////// +static int +allocate_gmem_shadow_buffer(gsl_device_t *device, gsl_drawctxt_t *drawctxt) +{ + // allocate memory for GMEM shadow + if (kgsl_sharedmem_alloc0(device->id, (GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_ALIGN8K), + drawctxt->context_gmem_shadow.size, &drawctxt->context_gmem_shadow.gmemshadow) != GSL_SUCCESS) + return GSL_FAILURE; + + // blank out gmem shadow. + kgsl_sharedmem_set0(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0, drawctxt->context_gmem_shadow.size); + + return GSL_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +// create GMEM save/restore specific stuff +////////////////////////////////////////////////////////////////////////////// + +static int +create_gmem_shadow(gsl_device_t *device, gsl_drawctxt_t *drawctxt, ctx_t *ctx) +{ + unsigned int i; + config_gmemsize(&drawctxt->context_gmem_shadow, device->gmemspace.sizebytes); + ctx->gmem_base = device->gmemspace.gpu_base; + + if( drawctxt->flags & CTXT_FLAGS_GMEM_SHADOW ) + { + if( allocate_gmem_shadow_buffer(device, drawctxt) != GSL_SUCCESS ) + return GSL_FAILURE; + } + else + { + memset( &drawctxt->context_gmem_shadow.gmemshadow, 0, sizeof( gsl_memdesc_t ) ); + } + + // build quad vertex buffer + build_quad_vtxbuff(drawctxt, ctx, &drawctxt->context_gmem_shadow); + + // build TP0_CHICKEN register restore command buffer + ctx->cmd = build_chicken_restore_cmds(drawctxt, ctx); + + // build indirect command buffers to save & restore gmem + drawctxt->context_gmem_shadow.gmem_save_commands = ctx->cmd; + ctx->cmd = build_gmem2sys_cmds(drawctxt, ctx, &drawctxt->context_gmem_shadow); + drawctxt->context_gmem_shadow.gmem_restore_commands = ctx->cmd; + ctx->cmd = build_sys2gmem_cmds(drawctxt, ctx, &drawctxt->context_gmem_shadow); + + for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) + { + // build quad vertex buffer + build_quad_vtxbuff(drawctxt, ctx, &drawctxt->user_gmem_shadow[i]); + + // build indirect command buffers to save & restore gmem + drawctxt->user_gmem_shadow[i].gmem_save_commands = ctx->cmd; + ctx->cmd = build_gmem2sys_cmds(drawctxt, ctx, &drawctxt->user_gmem_shadow[i]); + + drawctxt->user_gmem_shadow[i].gmem_restore_commands = ctx->cmd; + ctx->cmd = build_sys2gmem_cmds(drawctxt, ctx, &drawctxt->user_gmem_shadow[i]); + } + + return GSL_SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////// +// init draw context +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_drawctxt_init(gsl_device_t *device) +{ + return (GSL_SUCCESS); +} + + +////////////////////////////////////////////////////////////////////////////// +// close draw context +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_drawctxt_close(gsl_device_t *device) +{ + return (GSL_SUCCESS); +} + + +////////////////////////////////////////////////////////////////////////////// +// create a new drawing context +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_drawctxt_create(gsl_device_t* device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags) +{ + gsl_drawctxt_t *drawctxt; + int index; + ctx_t ctx; + + kgsl_device_active(device); + + if (device->drawctxt_count >= GSL_CONTEXT_MAX) + { + return (GSL_FAILURE); + } + + // find a free context slot + index = 0; + while (index < GSL_CONTEXT_MAX) + { + if (device->drawctxt[index].flags == CTXT_FLAGS_NOT_IN_USE) + break; + + index++; + } + + if (index >= GSL_CONTEXT_MAX) + { + return (GSL_FAILURE); + } + + drawctxt = &device->drawctxt[index]; + + memset( &drawctxt->context_gmem_shadow, 0, sizeof( gmem_shadow_t ) ); + + drawctxt->pid = current->tgid; + drawctxt->flags = CTXT_FLAGS_IN_USE; + drawctxt->type = type; + + device->drawctxt_count++; + + // create context shadows, when not running in safe mode + if (!(device->flags & GSL_FLAGS_SAFEMODE)) + { + if (create_gpustate_shadow(device, drawctxt, &ctx) != GSL_SUCCESS) + { + kgsl_drawctxt_destroy(device, index); + + return (GSL_FAILURE); + } + + // Save the shader instruction memory & GMEM on context switching + drawctxt->flags |= ( CTXT_FLAGS_SHADER_SAVE | CTXT_FLAGS_GMEM_SHADOW ); + + // Clear out user defined GMEM shadow buffer structs + memset( drawctxt->user_gmem_shadow, 0, sizeof(gmem_shadow_t)*GSL_MAX_GMEM_SHADOW_BUFFERS ); + + // create gmem shadow + if (create_gmem_shadow(device, drawctxt, &ctx) != GSL_SUCCESS) + { + kgsl_drawctxt_destroy(device, index); + + return (GSL_FAILURE); + } + + DEBUG_ASSERT(ctx.cmd - ctx.start <= CMD_BUFFER_LEN); + } + + *drawctxt_id = index; + + return (GSL_SUCCESS); +} + + +////////////////////////////////////////////////////////////////////////////// +// destroy a drawing context +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_drawctxt_destroy(gsl_device_t* device, unsigned int drawctxt_id) +{ + gsl_drawctxt_t *drawctxt; + + drawctxt = &device->drawctxt[drawctxt_id]; + + if (drawctxt->flags != CTXT_FLAGS_NOT_IN_USE) + { + // deactivate context + if (device->drawctxt_active == drawctxt) + { + // no need to save GMEM or shader, the context is being destroyed. + drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE | CTXT_FLAGS_SHADER_SAVE); + + kgsl_drawctxt_switch(device, GSL_CONTEXT_NONE, 0); + } + + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + + // destroy state shadow, if allocated + if (drawctxt->flags & CTXT_FLAGS_STATE_SHADOW) + kgsl_sharedmem_free0(&drawctxt->gpustate, current->tgid); + + + // destroy gmem shadow, if allocated + if (drawctxt->context_gmem_shadow.gmemshadow.size > 0) + { + kgsl_sharedmem_free0(&drawctxt->context_gmem_shadow.gmemshadow, current->tgid); + drawctxt->context_gmem_shadow.gmemshadow.size = 0; + } + + drawctxt->flags = CTXT_FLAGS_NOT_IN_USE; + drawctxt->pid = 0; + + device->drawctxt_count--; + DEBUG_ASSERT(device->drawctxt_count >= 0); + } + + return (GSL_SUCCESS); +} + +////////////////////////////////////////////////////////////////////////////// +// Binds a user specified buffer as GMEM shadow area +// +// gmem_rect: defines the rectangle that is copied from GMEM. X and Y +// coordinates need to be multiples of 8 after conversion to 32bpp. +// X, Y, width, and height need to be at 32-bit boundary to avoid +// rounding. +// +// shadow_x & shadow_y: Position in GMEM shadow buffer where the contents of +// gmem_rect is copied. Both must be multiples of 8 after +// conversion to 32bpp. They also need to be at 32-bit +// boundary to avoid rounding. +// +// shadow_buffer: Description of the GMEM shadow buffer. BPP needs to be +// 8, 16, 32, 64, or 128. Enabled tells if the buffer is +// used or not (values 0 and 1). All the other buffer +// parameters are ignored when enabled=0. +// +// buffer_id: Two different buffers can be defined. Use buffer IDs 0 and 1. +// +// +////////////////////////////////////////////////////////////////////////////// +int kgsl_drawctxt_bind_gmem_shadow(gsl_deviceid_t device_id, unsigned int drawctxt_id, const gsl_rect_t* gmem_rect, unsigned int shadow_x, unsigned int shadow_y, const gsl_buffer_desc_t* shadow_buffer, unsigned int buffer_id) +{ + gsl_device_t *device = &gsl_driver.device[device_id-1]; + gsl_drawctxt_t *drawctxt = &device->drawctxt[drawctxt_id]; + gmem_shadow_t *shadow = &drawctxt->user_gmem_shadow[buffer_id]; + unsigned int i; + + mutex_lock(&gsl_driver.lock); + + if( !shadow_buffer->enabled ) + { + // Disable shadow + shadow->gmemshadow.size = 0; + } + else + { + // Sanity checks + DEBUG_ASSERT((gmem_rect->x % 2) == 0); // Needs to be a multiple of 2 + DEBUG_ASSERT((gmem_rect->y % 2) == 0); // Needs to be a multiple of 2 + DEBUG_ASSERT((gmem_rect->width % 2) == 0); // Needs to be a multiple of 2 + DEBUG_ASSERT((gmem_rect->height % 2) == 0); // Needs to be a multiple of 2 + DEBUG_ASSERT((gmem_rect->pitch % 32) == 0); // Needs to be a multiple of 32 + + DEBUG_ASSERT((shadow_x % 2) == 0); // Needs to be a multiple of 2 + DEBUG_ASSERT((shadow_y % 2) == 0); // Needs to be a multiple of 2 + + DEBUG_ASSERT(shadow_buffer->format >= COLORX_4_4_4_4); + DEBUG_ASSERT(shadow_buffer->format <= COLORX_32_32_32_32_FLOAT); + DEBUG_ASSERT((shadow_buffer->pitch % 32) == 0); // Needs to be a multiple of 32 + DEBUG_ASSERT(buffer_id >= 0); + DEBUG_ASSERT(buffer_id < GSL_MAX_GMEM_SHADOW_BUFFERS); + + // Set up GMEM shadow regions + memcpy( &shadow->gmemshadow, &shadow_buffer->data, sizeof( gsl_memdesc_t ) ); + shadow->size = shadow->gmemshadow.size; + + shadow->width = shadow_buffer->width; + shadow->height = shadow_buffer->height; + shadow->pitch = shadow_buffer->pitch; + shadow->format = shadow_buffer->format; + + shadow->offset = shadow->pitch * (shadow_y - gmem_rect->y) + shadow_x - gmem_rect->x; + + shadow->offset_x = shadow_x; + shadow->offset_y = shadow_y; + + shadow->gmem_width = gmem_rect->width; + shadow->gmem_height = gmem_rect->height; + shadow->gmem_pitch = gmem_rect->pitch; + + shadow->gmem_offset_x = gmem_rect->x; + shadow->gmem_offset_y = gmem_rect->y; + + // Modify quad vertices + set_gmem_copy_quad(shadow); + + // Modify commands + build_gmem2sys_cmds(drawctxt, NULL, shadow); + build_sys2gmem_cmds(drawctxt, NULL, shadow); + + // Release context GMEM shadow if found + if (drawctxt->context_gmem_shadow.gmemshadow.size > 0) + { + kgsl_sharedmem_free0(&drawctxt->context_gmem_shadow.gmemshadow, current->tgid); + drawctxt->context_gmem_shadow.gmemshadow.size = 0; + } + } + + // Enable GMEM shadowing if we have any of the user buffers enabled + drawctxt->flags &= ~CTXT_FLAGS_GMEM_SHADOW; + for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) + { + if( drawctxt->user_gmem_shadow[i].gmemshadow.size > 0 ) + { + drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW; + } + } + + mutex_unlock(&gsl_driver.lock); + + return (GSL_SUCCESS); +} + + + +////////////////////////////////////////////////////////////////////////////// +// switch drawing contexts +////////////////////////////////////////////////////////////////////////////// + +void +kgsl_drawctxt_switch(gsl_device_t *device, gsl_drawctxt_t *drawctxt, gsl_flags_t flags) +{ + gsl_drawctxt_t *active_ctxt = device->drawctxt_active; + + if (drawctxt != GSL_CONTEXT_NONE) + { + if( flags & GSL_CONTEXT_SAVE_GMEM ) + { + // Set the flag in context so that the save is done when this context is switched out. + drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE; + } + else + { + // Remove GMEM saving flag from the context + drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE; + } + } + + // already current? + if (active_ctxt == drawctxt) + { + return; + } + + // save old context, when not running in safe mode + if (active_ctxt != GSL_CONTEXT_NONE && !(device->flags & GSL_FLAGS_SAFEMODE)) + { + // save registers and constants. + kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->reg_save, 3, active_ctxt->pid); + + if (active_ctxt->flags & CTXT_FLAGS_SHADER_SAVE) + { + // save shader partitioning and instructions. + kgsl_ringbuffer_issuecmds(device, 1, active_ctxt->shader_save, 3, active_ctxt->pid); + + // fixup shader partitioning parameter for SET_SHADER_BASES. + kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->shader_fixup, 3, active_ctxt->pid); + + active_ctxt->flags |= CTXT_FLAGS_SHADER_RESTORE; + } + + if (active_ctxt->flags & CTXT_FLAGS_GMEM_SHADOW && active_ctxt->flags & CTXT_FLAGS_GMEM_SAVE ) + { + // save gmem. (note: changes shader. shader must already be saved.) + + unsigned int i, numbuffers = 0; + + for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) + { + if( active_ctxt->user_gmem_shadow[i].gmemshadow.size > 0 ) + { + kgsl_ringbuffer_issuecmds(device, 1, active_ctxt->user_gmem_shadow[i].gmem_save, 3, active_ctxt->pid); + + // Restore TP0_CHICKEN + kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->chicken_restore, 3, active_ctxt->pid); + numbuffers++; + } + } + if( numbuffers == 0 ) + { + // No user defined buffers -> use context default + kgsl_ringbuffer_issuecmds(device, 1, active_ctxt->context_gmem_shadow.gmem_save, 3, active_ctxt->pid); + // Restore TP0_CHICKEN + kgsl_ringbuffer_issuecmds(device, 0, active_ctxt->chicken_restore, 3, active_ctxt->pid); + } + + active_ctxt->flags |= CTXT_FLAGS_GMEM_RESTORE; + } + } + + device->drawctxt_active = drawctxt; + + // restore new context, when not running in safe mode + if (drawctxt != GSL_CONTEXT_NONE && !(device->flags & GSL_FLAGS_SAFEMODE)) + { + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MEMWRITE, drawctxt->gpustate.gpuaddr, (unsigned int)drawctxt->gpustate.hostptr, LCC_SHADOW_SIZE + REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE , "kgsl_drawctxt_switch")); + + // restore gmem. (note: changes shader. shader must not already be restored.) + if (drawctxt->flags & CTXT_FLAGS_GMEM_RESTORE) + { + unsigned int i, numbuffers = 0; + + for( i = 0; i < GSL_MAX_GMEM_SHADOW_BUFFERS; i++ ) + { + if( drawctxt->user_gmem_shadow[i].gmemshadow.size > 0 ) + { + kgsl_ringbuffer_issuecmds(device, 1, drawctxt->user_gmem_shadow[i].gmem_restore, 3, drawctxt->pid); + + // Restore TP0_CHICKEN + kgsl_ringbuffer_issuecmds(device, 0, drawctxt->chicken_restore, 3, drawctxt->pid); + numbuffers++; + } + } + if( numbuffers == 0 ) + { + // No user defined buffers -> use context default + kgsl_ringbuffer_issuecmds(device, 1, drawctxt->context_gmem_shadow.gmem_restore, 3, drawctxt->pid); + // Restore TP0_CHICKEN + kgsl_ringbuffer_issuecmds(device, 0, drawctxt->chicken_restore, 3, drawctxt->pid); + } + + drawctxt->flags &= ~CTXT_FLAGS_GMEM_RESTORE; + } + + // restore registers and constants. + kgsl_ringbuffer_issuecmds(device, 0, drawctxt->reg_restore, 3, drawctxt->pid); + + // restore shader instructions & partitioning. + if (drawctxt->flags & CTXT_FLAGS_SHADER_RESTORE) + { + kgsl_ringbuffer_issuecmds(device, 0, drawctxt->shader_restore, 3, drawctxt->pid); + } + } +} + + +////////////////////////////////////////////////////////////////////////////// +// destroy all drawing contexts +////////////////////////////////////////////////////////////////////////////// +int +kgsl_drawctxt_destroyall(gsl_device_t *device) +{ + int i; + gsl_drawctxt_t *drawctxt; + + for (i = 0; i < GSL_CONTEXT_MAX; i++) + { + drawctxt = &device->drawctxt[i]; + + if (drawctxt->flags != CTXT_FLAGS_NOT_IN_USE) + { + // destroy state shadow, if allocated + if (drawctxt->flags & CTXT_FLAGS_STATE_SHADOW) + kgsl_sharedmem_free0(&drawctxt->gpustate, current->tgid); + + // destroy gmem shadow, if allocated + if (drawctxt->context_gmem_shadow.gmemshadow.size > 0) + { + kgsl_sharedmem_free0(&drawctxt->context_gmem_shadow.gmemshadow, current->tgid); + drawctxt->context_gmem_shadow.gmemshadow.size = 0; + } + + drawctxt->flags = CTXT_FLAGS_NOT_IN_USE; + + device->drawctxt_count--; + DEBUG_ASSERT(device->drawctxt_count >= 0); + } + } + + return (GSL_SUCCESS); +} + +#endif diff --git a/drivers/mxc/amd-gpu/gsl_driver.c b/drivers/mxc/amd-gpu/gsl_driver.c new file mode 100644 index 00000000000..679ba7b97e5 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_driver.c @@ -0,0 +1,322 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include + +#include "gsl.h" +#include "gsl_hal.h" + + +////////////////////////////////////////////////////////////////////////////// +// defines +////////////////////////////////////////////////////////////////////////////// +#define GSL_PROCESSID_NONE 0x00000000 + +#define GSL_DRVFLAGS_EXTERNAL 0x10000000 +#define GSL_DRVFLAGS_INTERNAL 0x20000000 + + +////////////////////////////////////////////////////////////////////////////// +// globals +////////////////////////////////////////////////////////////////////////////// +#ifndef KGSL_USER_MODE +static gsl_flags_t gsl_driver_initialized = 0; +gsl_driver_t gsl_driver; +#else +extern gsl_flags_t gsl_driver_initialized; +extern gsl_driver_t gsl_driver; +#endif + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_driver_init0(gsl_flags_t flags, gsl_flags_t flags_debug) +{ + int status = GSL_SUCCESS; + + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0)) + { +#ifdef GSL_LOG + kgsl_log_start( KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP + | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID ); +#endif + memset(&gsl_driver, 0, sizeof(gsl_driver_t)); + mutex_init(&gsl_driver.lock); + } + +#ifdef _DEBUG + // set debug flags on every entry, and prior to hal initialization + gsl_driver.flags_debug |= flags_debug; +#else + (void) flags_debug; // unref formal parameter +#endif // _DEBUG + + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + KGSL_DEBUG_DUMPX_OPEN("dumpx.tb", 0); + KGSL_DEBUG_DUMPX( BB_DUMP_ENABLE, 0, 0, 0, " "); + }); + + KGSL_DEBUG_TBDUMP_OPEN("tbdump.txt"); + + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0)) + { + mutex_lock(&gsl_driver.lock); + + // init hal + status = kgsl_hal_init(); + + if (status == GSL_SUCCESS) + { + gsl_driver_initialized |= flags; + gsl_driver_initialized |= GSL_FLAGS_INITIALIZED0; + } + + mutex_unlock(&gsl_driver.lock); + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_close0(gsl_flags_t flags) +{ + int status = GSL_SUCCESS; + + if ((gsl_driver_initialized & GSL_FLAGS_INITIALIZED0) && (gsl_driver_initialized & flags)) + { + mutex_lock(&gsl_driver.lock); + // close hal + status = kgsl_hal_close(); + mutex_unlock(&gsl_driver.lock); + +#ifdef GSL_LOG + kgsl_log_finish(); +#endif + + gsl_driver_initialized &= ~flags; + gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED0; + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + KGSL_DEBUG_DUMPX_CLOSE(); + }); + + KGSL_DEBUG_TBDUMP_CLOSE(); + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_init() +{ + // only an external (platform specific device driver) component should call this + + return(kgsl_driver_init0(GSL_DRVFLAGS_EXTERNAL, 0)); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_close() +{ + // only an external (platform specific device driver) component should call this + + return(kgsl_driver_close0(GSL_DRVFLAGS_EXTERNAL)); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_entry(gsl_flags_t flags) +{ + int status = GSL_FAILURE; + int index, i; + unsigned int pid; + + if (kgsl_driver_init0(GSL_DRVFLAGS_INTERNAL, flags) != GSL_SUCCESS) + { + return (GSL_FAILURE); + } + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_entry( gsl_flags_t flags=%x )\n", flags ); + + mutex_lock(&gsl_driver.lock); + + pid = current->tgid; + + // if caller process has not already opened access + status = kgsl_driver_getcallerprocessindex(pid, &index); + if (status != GSL_SUCCESS) + { + // then, add caller pid to process table + status = kgsl_driver_getcallerprocessindex(GSL_PROCESSID_NONE, &index); + if (status == GSL_SUCCESS) + { + gsl_driver.callerprocess[index] = pid; + gsl_driver.refcnt++; + } + } + + if (status == GSL_SUCCESS) + { + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED)) + { + // init memory apertures + status = kgsl_sharedmem_init(&gsl_driver.shmem); + if (status == GSL_SUCCESS) + { + // init devices + status = GSL_FAILURE; + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + if (kgsl_device_init(&gsl_driver.device[i], (gsl_deviceid_t)(i + 1)) == GSL_SUCCESS) { + status = GSL_SUCCESS; + } + } + } + + if (status == GSL_SUCCESS) + { + gsl_driver_initialized |= GSL_FLAGS_INITIALIZED; + } + } + + // walk through process attach callbacks + if (status == GSL_SUCCESS) + { + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + status = kgsl_device_attachcallback(&gsl_driver.device[i], pid); + if (status != GSL_SUCCESS) + { + break; + } + } + } + + // if something went wrong + if (status != GSL_SUCCESS) + { + // then, remove caller pid from process table + if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS) + { + gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE; + gsl_driver.refcnt--; + } + } + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_entry. Return value: %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_exit0(unsigned int pid) +{ + int status = GSL_SUCCESS; + int index, i; + + mutex_lock(&gsl_driver.lock); + + if (gsl_driver_initialized & GSL_FLAGS_INITIALIZED) + { + if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS) + { + // walk through process detach callbacks + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + // Empty the freememqueue of this device + kgsl_cmdstream_memqueue_drain(&gsl_driver.device[i]); + + // Detach callback + status = kgsl_device_detachcallback(&gsl_driver.device[i], pid); + if (status != GSL_SUCCESS) + { + break; + } + } + + // last running caller process + if (gsl_driver.refcnt - 1 == 0) + { + // close devices + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + kgsl_device_close(&gsl_driver.device[i]); + } + + // shutdown memory apertures + kgsl_sharedmem_close(&gsl_driver.shmem); + + gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED; + } + + // remove caller pid from process table + gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE; + gsl_driver.refcnt--; + } + } + + mutex_unlock(&gsl_driver.lock); + + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED)) + { + kgsl_driver_close0(GSL_DRVFLAGS_INTERNAL); + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_exit(void) +{ + int status; + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_exit()\n" ); + + status = kgsl_driver_exit0(current->tgid); + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_exit(). Return value: %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_destroy(unsigned int pid) +{ + return (kgsl_driver_exit0(pid)); +} diff --git a/drivers/mxc/amd-gpu/gsl_g12.c b/drivers/mxc/amd-gpu/gsl_g12.c new file mode 100644 index 00000000000..d979cd54926 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_g12.c @@ -0,0 +1,909 @@ +/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" +#include "gsl_hal.h" +#include "gsl_cmdstream.h" + +#ifdef CONFIG_ARCH_MX35 +#define V3_SYNC +#endif + +#ifdef GSL_BLD_G12 +#define GSL_IRQ_TIMEOUT 200 + + +//---------------------------------------------------------------------------- + +#define GSL_HAL_NUMCMDBUFFERS 5 +#define GSL_HAL_CMDBUFFERSIZE (1024 + 13) * sizeof(unsigned int) + +#define ALIGN_IN_BYTES( dim, alignment ) ( ( (dim) + (alignment-1) ) & ~(alignment-1) ) + + +#ifdef _Z180 +#define NUMTEXUNITS 4 +#define TEXUNITREGCOUNT 25 +#define VG_REGCOUNT 0x39 +#define GSL_HAL_EDGE0BUFSIZE 0x3E8+64 +#define GSL_HAL_EDGE1BUFSIZE 0x8000+64 +#define GSL_HAL_EDGE2BUFSIZE 0x80020+64 +#define GSL_HAL_EDGE0REG ADDR_VGV1_CBUF +#define GSL_HAL_EDGE1REG ADDR_VGV1_BBUF +#define GSL_HAL_EDGE2REG ADDR_VGV1_EBUF +#else +#define NUMTEXUNITS 2 +#define TEXUNITREGCOUNT 24 +#define VG_REGCOUNT 0x3A +#define L1TILESIZE 64 +#define GSL_HAL_EDGE0BUFSIZE L1TILESIZE*L1TILESIZE*4+64 +#define GSL_HAL_EDGE1BUFSIZE L1TILESIZE*L1TILESIZE*16+64 +#define GSL_HAL_EDGE0REG ADDR_VGV1_CBASE1 +#define GSL_HAL_EDGE1REG ADDR_VGV1_UBASE2 +#endif + +#define PACKETSIZE_BEGIN 3 +#define PACKETSIZE_G2DCOLOR 2 +#define PACKETSIZE_TEXUNIT (TEXUNITREGCOUNT*2) +#define PACKETSIZE_REG (VG_REGCOUNT*2) +#define PACKETSIZE_STATE (PACKETSIZE_TEXUNIT*NUMTEXUNITS + PACKETSIZE_REG + PACKETSIZE_BEGIN + PACKETSIZE_G2DCOLOR) +#define PACKETSIZE_STATESTREAM ALIGN_IN_BYTES((PACKETSIZE_STATE*sizeof(unsigned int)), 32) / sizeof(unsigned int) + +//---------------------------------------------------------------------------- + +typedef struct +{ + unsigned int id; + // unsigned int regs[]; +}gsl_hal_z1xxdrawctx_t; + +typedef struct +{ + unsigned int offs; + unsigned int curr; + unsigned int prevctx; + + gsl_memdesc_t e0; + gsl_memdesc_t e1; + gsl_memdesc_t e2; + unsigned int* cmdbuf[GSL_HAL_NUMCMDBUFFERS]; + gsl_memdesc_t cmdbufdesc[GSL_HAL_NUMCMDBUFFERS]; + gsl_timestamp_t timestamp[GSL_HAL_NUMCMDBUFFERS]; + + unsigned int numcontext; + unsigned int nextUniqueContextID; +}gsl_z1xx_t; + +static gsl_z1xx_t g_z1xx = {0}; + +extern int z160_version; + +//---------------------------------------------------------------------------- + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +static int kgsl_g12_addtimestamp(gsl_device_t* device, gsl_timestamp_t *timestamp); +static int kgsl_g12_issueibcmds(gsl_device_t* device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, unsigned int flags); +static int kgsl_g12_context_create(gsl_device_t* device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags); +static int kgsl_g12_context_destroy(gsl_device_t* device, unsigned int drawctxt_id); +static unsigned int drawctx_id = 0; +static int kgsl_g12_idle(gsl_device_t *device, unsigned int timeout); + +//---------------------------------------------------------------------------- + +void +kgsl_g12_intrcallback(gsl_intrid_t id, void *cookie) +{ + gsl_device_t *device = (gsl_device_t *) cookie; + + switch(id) + { + // non-error condition interrupt + case GSL_INTR_G12_G2D: + queue_work(device->irq_workq, &(device->irq_work)); + break; +#ifndef _Z180 + case GSL_INTR_G12_FBC: + // signal intr completion event + complete_all(&device->intr.evnt[id]); + break; +#endif //_Z180 + + // error condition interrupt + case GSL_INTR_G12_FIFO: + printk(KERN_ERR "GPU: Z160 FIFO Error\n"); + schedule_work(&device->irq_err_work); + break; + + case GSL_INTR_G12_MH: + // don't do anything. this is handled by the MMU manager + break; + + default: + break; + } +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_isr(gsl_device_t *device) +{ + unsigned int status; +#ifdef _DEBUG + REG_MH_MMU_PAGE_FAULT page_fault = {0}; + REG_MH_AXI_ERROR axi_error = {0}; +#endif // DEBUG + + // determine if G12 is interrupting + device->ftbl.device_regread(device, (ADDR_VGC_IRQSTATUS >> 2), &status); + + if (status) + { + // if G12 MH is interrupting, clear MH block interrupt first, then master G12 MH interrupt + if (status & (1 << VGC_IRQSTATUS_MH_FSHIFT)) + { +#ifdef _DEBUG + // obtain mh error information + device->ftbl.device_regread(device, ADDR_MH_MMU_PAGE_FAULT, (unsigned int *)&page_fault); + device->ftbl.device_regread(device, ADDR_MH_AXI_ERROR, (unsigned int *)&axi_error); +#endif // DEBUG + + kgsl_intr_decode(device, GSL_INTR_BLOCK_G12_MH); + } + + kgsl_intr_decode(device, GSL_INTR_BLOCK_G12); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_tlbinvalidate(gsl_device_t *device, unsigned int reg_invalidate, unsigned int pid) +{ +#ifndef GSL_NO_MMU + REG_MH_MMU_INVALIDATE mh_mmu_invalidate = {0}; + + // unreferenced formal parameter + (void) pid; + + mh_mmu_invalidate.INVALIDATE_ALL = 1; + mh_mmu_invalidate.INVALIDATE_TC = 1; + + device->ftbl.device_regwrite(device, reg_invalidate, *(unsigned int *) &mh_mmu_invalidate); +#else + (void)device; + (void)reg_invalidate; +#endif + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_setpagetable(gsl_device_t *device, unsigned int reg_ptbase, gpuaddr_t ptbase, unsigned int pid) +{ + // unreferenced formal parameter + (void) pid; +#ifndef GSL_NO_MMU + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + device->ftbl.device_regwrite(device, reg_ptbase, ptbase); +#else + (void)device; + (void)reg_ptbase; + (void)reg_varange; +#endif + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static void kgsl_g12_updatetimestamp(gsl_device_t *device) +{ + unsigned int count = 0; + device->ftbl.device_regread(device, (ADDR_VGC_IRQ_ACTIVE_CNT >> 2), &count); + count >>= 8; + count &= 255; + device->timestamp += count; +#ifdef V3_SYNC + if (device->current_timestamp > device->timestamp) + { + kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 2); + kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); + } +#endif + kgsl_sharedmem_write0(&device->memstore, GSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp), &device->timestamp, 4, 0); +} + +//---------------------------------------------------------------------------- + +static void kgsl_g12_irqtask(struct work_struct *work) +{ + gsl_device_t *device = &gsl_driver.device[GSL_DEVICE_G12-1]; + kgsl_g12_updatetimestamp(device); + wake_up_interruptible_all(&device->timestamp_waitq); +} + +static void kgsl_g12_irqerr(struct work_struct *work) +{ + gsl_device_t *device = &gsl_driver.device[GSL_DEVICE_G12-1]; + device->ftbl.device_destroy(device); +} + + +//---------------------------------------------------------------------------- + +int +kgsl_g12_init(gsl_device_t *device) +{ + int status = GSL_FAILURE; + + device->flags |= GSL_FLAGS_INITIALIZED; + + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_ON, 100); + + // setup MH arbiter - MH offsets are considered to be dword based, therefore no down shift + device->ftbl.device_regwrite(device, ADDR_MH_ARBITER_CONFIG, *(unsigned int *) &gsl_cfg_g12_mharb); + + // init interrupt + status = kgsl_intr_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } + + // enable irq + device->ftbl.device_regwrite(device, (ADDR_VGC_IRQENABLE >> 2), 0x3); + +#ifndef GSL_NO_MMU + // enable master interrupt for G12 MH + kgsl_intr_attach(&device->intr, GSL_INTR_G12_MH, kgsl_g12_intrcallback, (void *) device); + kgsl_intr_enable(&device->intr, GSL_INTR_G12_MH); + + // init mmu + status = kgsl_mmu_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } +#endif + +#ifdef IRQTHREAD_POLL + // Create event to trigger IRQ polling thread + init_completion(&device->irqthread_event); +#endif + + // enable interrupts + kgsl_intr_attach(&device->intr, GSL_INTR_G12_G2D, kgsl_g12_intrcallback, (void *) device); + kgsl_intr_attach(&device->intr, GSL_INTR_G12_FIFO, kgsl_g12_intrcallback, (void *) device); + kgsl_intr_enable(&device->intr, GSL_INTR_G12_G2D); + kgsl_intr_enable(&device->intr, GSL_INTR_G12_FIFO); + +#ifndef _Z180 + kgsl_intr_attach(&device->intr, GSL_INTR_G12_FBC, kgsl_g12_intrcallback, (void *) device); + //kgsl_intr_enable(&device->intr, GSL_INTR_G12_FBC); +#endif //_Z180 + + // create thread for IRQ handling + device->irq_workq = create_singlethread_workqueue("z160_workqueue"); + INIT_WORK(&device->irq_work, kgsl_g12_irqtask); + INIT_WORK(&device->irq_err_work, kgsl_g12_irqerr); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_close(gsl_device_t *device) +{ + int status = GSL_FAILURE; + + if (device->refcnt == 0) + { + // wait pending interrupts before shutting down G12 intr thread to + // empty irq counters. Otherwise there's a possibility to have them in + // registers next time systems starts up and this results in a hang. + status = device->ftbl.device_idle(device, 1000); + DEBUG_ASSERT(status == GSL_SUCCESS); + + destroy_workqueue(device->irq_workq); + + // shutdown command window + kgsl_cmdwindow_close(device); + +#ifndef GSL_NO_MMU + // shutdown mmu + kgsl_mmu_close(device); +#endif + // disable interrupts + kgsl_intr_detach(&device->intr, GSL_INTR_G12_MH); + kgsl_intr_detach(&device->intr, GSL_INTR_G12_G2D); + kgsl_intr_detach(&device->intr, GSL_INTR_G12_FIFO); +#ifndef _Z180 + kgsl_intr_detach(&device->intr, GSL_INTR_G12_FBC); +#endif //_Z180 + + // shutdown interrupt + kgsl_intr_close(device); + + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_OFF, 0); + + device->flags &= ~GSL_FLAGS_INITIALIZED; + + drawctx_id = 0; + + DEBUG_ASSERT(g_z1xx.numcontext == 0); + + memset(&g_z1xx, 0, sizeof(gsl_z1xx_t)); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_destroy(gsl_device_t *device) +{ + int i; + unsigned int pid; + +#ifdef _DEBUG + // for now, signal catastrophic failure in a brute force way + DEBUG_ASSERT(0); +#endif // _DEBUG + + //todo: hard reset core? + + for (i = 0; i < GSL_CALLER_PROCESS_MAX; i++) + { + pid = device->callerprocess[i]; + if (pid) + { + device->ftbl.device_stop(device); + kgsl_driver_destroy(pid); + + // todo: terminate client process? + } + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_start(gsl_device_t *device, gsl_flags_t flags) +{ + int status = GSL_SUCCESS; + + (void) flags; // unreferenced formal parameter + + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_ON, 100); + + // init command window + status = kgsl_cmdwindow_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } + + DEBUG_ASSERT(g_z1xx.numcontext == 0); + + device->flags |= GSL_FLAGS_STARTED; + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_stop(gsl_device_t *device) +{ + int status; + + DEBUG_ASSERT(device->refcnt == 0); + + /* wait for device to idle before setting it's clock off */ + status = device->ftbl.device_idle(device, 1000); + DEBUG_ASSERT(status == GSL_SUCCESS); + + status = kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_OFF, 0); + device->flags &= ~GSL_FLAGS_STARTED; + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_getproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) +{ + int status = GSL_FAILURE; + // unreferenced formal parameter + (void) sizebytes; + + if (type == GSL_PROP_DEVICE_INFO) + { + gsl_devinfo_t *devinfo = (gsl_devinfo_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_devinfo_t)); + + devinfo->device_id = device->id; + devinfo->chip_id = (gsl_chipid_t)device->chip_id; +#ifndef GSL_NO_MMU + devinfo->mmu_enabled = kgsl_mmu_isenabled(&device->mmu); +#endif + if (z160_version == 1) + devinfo->high_precision = 1; + else + devinfo->high_precision = 0; + + status = GSL_SUCCESS; + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_setproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) +{ + int status = GSL_FAILURE; + + // unreferenced formal parameters + (void) device; + + if (type == GSL_PROP_DEVICE_POWER) + { + gsl_powerprop_t *power = (gsl_powerprop_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_powerprop_t)); + + if (!(device->flags & GSL_FLAGS_SAFEMODE)) + { + kgsl_hal_setpowerstate(device->id, power->flags, power->value); + } + + status = GSL_SUCCESS; + } + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_idle(gsl_device_t *device, unsigned int timeout) +{ + if ( device->flags & GSL_FLAGS_STARTED ) + { + for ( ; ; ) + { + gsl_timestamp_t retired = kgsl_cmdstream_readtimestamp0( device->id, GSL_TIMESTAMP_RETIRED ); + gsl_timestamp_t ts_diff = retired - device->current_timestamp; + if ( ts_diff >= 0 || ts_diff < -GSL_TIMESTAMP_EPSILON ) + break; + msleep(10); + } + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_regread(gsl_device_t *device, unsigned int offsetwords, unsigned int *value) +{ + // G12 MH register values can only be retrieved via dedicated read registers + if ((offsetwords >= ADDR_MH_ARBITER_CONFIG && offsetwords <= ADDR_MH_AXI_HALT_CONTROL) || + (offsetwords >= ADDR_MH_MMU_CONFIG && offsetwords <= ADDR_MH_MMU_MPU_END)) + { +#ifdef _Z180 + device->ftbl.device_regwrite(device, (ADDR_VGC_MH_READ_ADDR >> 2), offsetwords); + GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, (ADDR_VGC_MH_READ_ADDR >> 2), value); +#else + device->ftbl.device_regwrite(device, (ADDR_MMU_READ_ADDR >> 2), offsetwords); + GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, (ADDR_MMU_READ_DATA >> 2), value); +#endif + } + else + { + GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_regwrite(gsl_device_t *device, unsigned int offsetwords, unsigned int value) +{ + // G12 MH registers can only be written via the command window + if ((offsetwords >= ADDR_MH_ARBITER_CONFIG && offsetwords <= ADDR_MH_AXI_HALT_CONTROL) || + (offsetwords >= ADDR_MH_MMU_CONFIG && offsetwords <= ADDR_MH_MMU_MPU_END)) + { + kgsl_cmdwindow_write0(device->id, GSL_CMDWINDOW_MMU, offsetwords, value); + } + else + { + GSL_HAL_REG_WRITE(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); + } + + // idle device when running in safe mode + if (device->flags & GSL_FLAGS_SAFEMODE) + { + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_waitirq(gsl_device_t *device, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout) +{ + int status = GSL_FAILURE_NOTSUPPORTED; + int complete = 0; + +#ifndef _Z180 + if (intr_id == GSL_INTR_G12_G2D || intr_id == GSL_INTR_G12_FBC) +#else + if (intr_id == GSL_INTR_G12_G2D) +#endif //_Z180 + { + if (kgsl_intr_isenabled(&device->intr, intr_id) == GSL_SUCCESS) + { + // wait until intr completion event is received and check that + // the interrupt is still enabled. If event is received, but + // interrupt is not enabled any more, the driver is shutting + // down and event structure is not valid anymore. + + if (timeout != OS_INFINITE) + complete = wait_for_completion_timeout(&device->intr.evnt[intr_id], msecs_to_jiffies(timeout)); + else + complete = wait_for_completion_killable(&device->intr.evnt[intr_id]); + + if (complete && kgsl_intr_isenabled(&device->intr, intr_id) == GSL_SUCCESS) + { + unsigned int cntrs; + int i; + struct completion *comp = &device->intr.evnt[intr_id]; + + kgsl_device_active(device); + + INIT_COMPLETION(*comp); + device->ftbl.device_regread(device, (ADDR_VGC_IRQ_ACTIVE_CNT >> 2), &cntrs); + + for (i = 0; i < GSL_G12_INTR_COUNT; i++) + { + int intrcnt = cntrs >> ((8 * i)) & 255; + + // maximum allowed counter value is 254. if set to 255 then something has gone wrong + if (intrcnt && (intrcnt < 0xFF)) + { + device->intrcnt[i] += intrcnt; + } + } + + *count = device->intrcnt[intr_id - GSL_INTR_G12_MH]; + device->intrcnt[intr_id - GSL_INTR_G12_MH] = 0; + status = GSL_SUCCESS; + } + else + { + status = GSL_FAILURE_TIMEOUT; + } + } + } + else if(intr_id == GSL_INTR_FOOBAR) + { + if (kgsl_intr_isenabled(&device->intr, GSL_INTR_G12_G2D) == GSL_SUCCESS) + { + complete_all(&device->intr.evnt[GSL_INTR_G12_G2D]); + } + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_g12_waittimestamp(gsl_device_t *device, gsl_timestamp_t timestamp, unsigned int timeout) +{ + int status = wait_event_interruptible_timeout(device->timestamp_waitq, + kgsl_cmdstream_check_timestamp(device->id, timestamp), + msecs_to_jiffies(timeout)); + if (status > 0) + return GSL_SUCCESS; + else + return GSL_FAILURE; +} + +int +kgsl_g12_getfunctable(gsl_functable_t *ftbl) +{ + ftbl->device_init = kgsl_g12_init; + ftbl->device_close = kgsl_g12_close; + ftbl->device_destroy = kgsl_g12_destroy; + ftbl->device_start = kgsl_g12_start; + ftbl->device_stop = kgsl_g12_stop; + ftbl->device_getproperty = kgsl_g12_getproperty; + ftbl->device_setproperty = kgsl_g12_setproperty; + ftbl->device_idle = kgsl_g12_idle; + ftbl->device_regread = kgsl_g12_regread; + ftbl->device_regwrite = kgsl_g12_regwrite; + ftbl->device_waitirq = kgsl_g12_waitirq; + ftbl->device_waittimestamp = kgsl_g12_waittimestamp; + ftbl->device_runpending = NULL; + ftbl->device_addtimestamp = kgsl_g12_addtimestamp; + ftbl->intr_isr = kgsl_g12_isr; + ftbl->mmu_tlbinvalidate = kgsl_g12_tlbinvalidate; + ftbl->mmu_setpagetable = kgsl_g12_setpagetable; + ftbl->cmdstream_issueibcmds = kgsl_g12_issueibcmds; + ftbl->context_create = kgsl_g12_context_create; + ftbl->context_destroy = kgsl_g12_context_destroy; + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static void addmarker(gsl_z1xx_t* z1xx) +{ + DEBUG_ASSERT(z1xx); + { + unsigned int *p = z1xx->cmdbuf[z1xx->curr]; + /* todo: use symbolic values */ + p[z1xx->offs++] = 0x7C000176; + p[z1xx->offs++] = (0x8000|5); + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = 0x7C000176; + p[z1xx->offs++] = 5; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + } +} + +//---------------------------------------------------------------------------- +static void beginpacket(gsl_z1xx_t* z1xx, gpuaddr_t cmd, unsigned int nextcnt) +{ + unsigned int *p = z1xx->cmdbuf[z1xx->curr]; + + p[z1xx->offs++] = 0x7C000176; + p[z1xx->offs++] = 5; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = 0x7C000275; + p[z1xx->offs++] = cmd; + p[z1xx->offs++] = 0x1000|nextcnt; // nextcount + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; + p[z1xx->offs++] = ADDR_VGV3_LAST<<24; +} + +//---------------------------------------------------------------------------- + +static int +kgsl_g12_issueibcmds(gsl_device_t* device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, unsigned int flags) +{ + unsigned int ofs = PACKETSIZE_STATESTREAM*sizeof(unsigned int); + unsigned int cnt = 5; + unsigned int cmd = ibaddr; + unsigned int nextbuf = (g_z1xx.curr+1)%GSL_HAL_NUMCMDBUFFERS; + unsigned int nextaddr = g_z1xx.cmdbufdesc[nextbuf].gpuaddr; + unsigned int nextcnt = 0x9000|5; + gsl_memdesc_t tmp = {0}; + gsl_timestamp_t processed_timestamp; + + (void) flags; + + // read what is the latest timestamp device have processed + GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (int *)&processed_timestamp); + + /* wait for the next buffer's timestamp to occur */ + while(processed_timestamp < g_z1xx.timestamp[nextbuf]) + { + kgsl_cmdstream_waittimestamp(device->id, g_z1xx.timestamp[nextbuf], 1000); + GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, (int *)&processed_timestamp); + } + + *timestamp = g_z1xx.timestamp[nextbuf] = device->current_timestamp + 1; + + /* context switch */ + if (drawctxt_index != (int)g_z1xx.prevctx) + { + cnt = PACKETSIZE_STATESTREAM; + ofs = 0; + } + g_z1xx.prevctx = drawctxt_index; + + g_z1xx.offs = 10; + beginpacket(&g_z1xx, cmd+ofs, cnt); + + tmp.gpuaddr=ibaddr+(sizedwords*sizeof(unsigned int)); + kgsl_sharedmem_write0(&tmp, 4, &nextaddr, 4, false); + kgsl_sharedmem_write0(&tmp, 8, &nextcnt, 4, false); + + /* sync mem */ + kgsl_sharedmem_write0((const gsl_memdesc_t *)&g_z1xx.cmdbufdesc[g_z1xx.curr], 0, g_z1xx.cmdbuf[g_z1xx.curr], (512 + 13) * sizeof(unsigned int), false); + + g_z1xx.offs = 0; + g_z1xx.curr = nextbuf; + + /* increment mark counter */ +#ifdef V3_SYNC + if (device->timestamp == device->current_timestamp) + { + kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, flags); + kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); + } +#else + kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, flags); + kgsl_cmdwindow_write0(2, GSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); +#endif + + /* increment consumed timestamp */ + device->current_timestamp++; + kgsl_sharedmem_write0(&device->memstore, GSL_DEVICE_MEMSTORE_OFFSET(soptimestamp), &device->current_timestamp, 4, 0); + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static int +kgsl_g12_context_create(gsl_device_t* device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags) +{ + int status = 0; + int i; + int cmd; + gsl_flags_t gslflags = (GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_ALIGNPAGE); + + // unreferenced formal parameters + (void) device; + (void) type; + //(void) drawctxt_id; + (void) flags; + + kgsl_device_active(device); + + if (g_z1xx.numcontext==0) + { + g_z1xx.nextUniqueContextID = 0; + /* todo: move this to device create or start. Error checking!! */ + for (i=0;itgid); + kfree(g_z1xx.cmdbuf[i]); + } + kgsl_sharedmem_free0(&g_z1xx.e0, current->tgid); + kgsl_sharedmem_free0(&g_z1xx.e1, current->tgid); +#ifdef _Z180 + kgsl_sharedmem_free0(&g_z1xx.e2, current->tgid); +#endif + } + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static int +kgsl_g12_addtimestamp(gsl_device_t* device, gsl_timestamp_t *timestamp) +{ + device->current_timestamp++; + *timestamp = device->current_timestamp; + + return (GSL_SUCCESS); +} +#endif diff --git a/drivers/mxc/amd-gpu/gsl_hal.c b/drivers/mxc/amd-gpu/gsl_hal.c new file mode 100644 index 00000000000..69908c4eb78 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_hal.c @@ -0,0 +1,570 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +#include "gsl_hal.h" +#include "gsl_halconfig.h" +#include "gsl_linux_map.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define GSL_HAL_MEM1 0 +#define GSL_HAL_MEM2 1 +//#define GSL_HAL_MEM3 2 + +#define GSL_HAL_DEBUG + +extern phys_addr_t gpu_2d_regbase; +extern int gpu_2d_regsize; +extern phys_addr_t gpu_3d_regbase; +extern int gpu_3d_regsize; +extern int gmem_size; +extern phys_addr_t gpu_reserved_mem; +extern int gpu_reserved_mem_size; +extern int gpu_2d_irq, gpu_3d_irq; +extern int enable_mmu; + + +KGSLHAL_API int +kgsl_hal_allocphysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[]) +{ + /* allocate physically contiguous memory */ + + int i; + void *va; + + va = gsl_linux_map_alloc(virtaddr, numpages*PAGE_SIZE); + + if (!va) + return GSL_FAILURE_OUTOFMEM; + + for (i = 0; i < numpages; i++) { + scattergatterlist[i] = page_to_phys(vmalloc_to_page(va)); + va += PAGE_SIZE; + } + + return GSL_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +KGSLHAL_API int +kgsl_hal_freephysical(unsigned int virtaddr, unsigned int numpages, unsigned int scattergatterlist[]) +{ + /* free physical memory */ + + gsl_linux_map_free(virtaddr); + + return GSL_SUCCESS; +} + +/* ---------------------------------------------------------------------------- */ + +KGSLHAL_API int +kgsl_hal_init(void) +{ + gsl_hal_t *hal; + unsigned long physsize, virtsize; + unsigned int va, pa; + + if (gsl_driver.hal) { + return GSL_FAILURE_ALREADYINITIALIZED; + } + + gsl_driver.hal = (void *)kmalloc(sizeof(gsl_hal_t), GFP_KERNEL); + + if (!gsl_driver.hal) { + return GSL_FAILURE_OUTOFMEM; + } + + memset(gsl_driver.hal, 0, sizeof(gsl_hal_t)); + + + /* overlay structure on hal memory */ + hal = (gsl_hal_t *) gsl_driver.hal; + + if (gpu_3d_regbase && gpu_3d_regsize && gpu_3d_irq) { + hal->has_z430 = 1; + } else { + hal->has_z430 = 0; + } + + if (gpu_2d_regbase && gpu_2d_regsize && gpu_2d_irq) { + hal->has_z160 = 1; + } else { + hal->has_z160 = 0; + } + + gsl_driver.enable_mmu = enable_mmu; + + /* setup register space */ + if (hal->has_z430) { + hal->z430_regspace.mmio_phys_base = gpu_3d_regbase; + hal->z430_regspace.sizebytes = gpu_3d_regsize; + hal->z430_regspace.mmio_virt_base = (unsigned char *)ioremap(hal->z430_regspace.mmio_phys_base, hal->z430_regspace.sizebytes); + + if (hal->z430_regspace.mmio_virt_base == NULL) { + return GSL_FAILURE_SYSTEMERROR; + } + +#ifdef GSL_HAL_DEBUG + printk(KERN_INFO "%s: hal->z430_regspace.mmio_phys_base = 0x%p\n", __func__, (void *)hal->z430_regspace.mmio_phys_base); + printk(KERN_INFO "%s: hal->z430_regspace.mmio_virt_base = 0x%p\n", __func__, (void *)hal->z430_regspace.mmio_virt_base); + printk(KERN_INFO "%s: hal->z430_regspace.sizebytes = 0x%08x\n", __func__, hal->z430_regspace.sizebytes); +#endif + } + + if (hal->has_z160) { + hal->z160_regspace.mmio_phys_base = gpu_2d_regbase; + hal->z160_regspace.sizebytes = gpu_2d_regsize; + hal->z160_regspace.mmio_virt_base = (unsigned char *)ioremap(hal->z160_regspace.mmio_phys_base, hal->z160_regspace.sizebytes); + + if (hal->z160_regspace.mmio_virt_base == NULL) { + return GSL_FAILURE_SYSTEMERROR; + } + +#ifdef GSL_HAL_DEBUG + printk(KERN_INFO "%s: hal->z160_regspace.mmio_phys_base = 0x%p\n", __func__, (void *)hal->z160_regspace.mmio_phys_base); + printk(KERN_INFO "%s: hal->z160_regspace.mmio_virt_base = 0x%p\n", __func__, (void *)hal->z160_regspace.mmio_virt_base); + printk(KERN_INFO "%s: hal->z160_regspace.sizebytes = 0x%08x\n", __func__, hal->z160_regspace.sizebytes); +#endif + } + + physsize = SZ_8M; + + if (gsl_driver.enable_mmu) { + printk(KERN_INFO "GPU MMU enabled\n"); + virtsize = GSL_HAL_SHMEM_SIZE_EMEM_MMU; + if (gpu_reserved_mem && gpu_reserved_mem_size >= physsize) { + pa = gpu_reserved_mem; + va = (unsigned int)ioremap/*_wc*/(gpu_reserved_mem, gpu_reserved_mem_size); + physsize = gpu_reserved_mem_size; + } else { + if (gpu_reserved_mem_size > 0) { + printk(KERN_INFO "Reallocating PHYS aperture: reserved memory going to waste\n"); + } + gpu_reserved_mem = 0; + va = (unsigned int)dma_alloc_coherent(0, physsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL); + } + } else { + printk(KERN_INFO "GPU MMU disabled\n"); + if (gpu_reserved_mem && gpu_reserved_mem_size >= physsize) { + physsize = gpu_reserved_mem_size; + pa = gpu_reserved_mem; + va = (unsigned int)ioremap(gpu_reserved_mem, gpu_reserved_mem_size); + } else { + if (gpu_reserved_mem_size > 0) { + printk(KERN_INFO "Reallocating PHYS aperture: reserved memory going to waste\n"); + } + gpu_reserved_mem = 0; + physsize = GSL_HAL_SHMEM_SIZE_PHYS_NOMMU; + va = (unsigned int)dma_alloc_coherent(0, physsize, (dma_addr_t *)&pa, GFP_DMA | GFP_KERNEL); + } + virtsize = physsize - GSL_HAL_SHMEM_SIZE_PHYS_NOMMU; + } + + if (va) { + memset((void *)va, 0, physsize); + + hal->memchunk.mmio_virt_base = (void *)va; + hal->memchunk.mmio_phys_base = pa; + hal->memchunk.sizebytes = physsize; + +#ifdef GSL_HAL_DEBUG + printk(KERN_INFO "Reserved memory: pa = 0x%p va = 0x%p size = 0x%08x\n", + (void *)hal->memchunk.mmio_phys_base, + (void *)hal->memchunk.mmio_virt_base, + hal->memchunk.sizebytes + ); +#endif + + hal->memspace[GSL_HAL_MEM2].mmio_virt_base = (void *) va; + hal->memspace[GSL_HAL_MEM2].gpu_base = pa; + hal->memspace[GSL_HAL_MEM2].sizebytes = physsize; + va += physsize; + pa += physsize; + +#ifdef GSL_HAL_DEBUG + printk(KERN_INFO "GSL_HAL_MEM2 aperture (PHYS) pa = 0x%p va = 0x%p size = 0x%08x\n", + (void *)hal->memspace[GSL_HAL_MEM2].gpu_base, + (void *)hal->memspace[GSL_HAL_MEM2].mmio_virt_base, + hal->memspace[GSL_HAL_MEM2].sizebytes + ); +#endif + + if (gsl_driver.enable_mmu) { + gsl_linux_map_init(); + hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *)GSL_LINUX_MAP_RANGE_START; + hal->memspace[GSL_HAL_MEM1].gpu_base = GSL_LINUX_MAP_RANGE_START; + } else { + hal->memspace[GSL_HAL_MEM1].mmio_virt_base = (void *) va; + hal->memspace[GSL_HAL_MEM1].gpu_base = pa; + } + hal->memspace[GSL_HAL_MEM1].sizebytes = virtsize; + +#ifdef GSL_HAL_DEBUG + printk(KERN_INFO "GSL_HAL_MEM1 aperture (%s) pa = 0x%p va = 0x%p size = 0x%08x\n", + gsl_driver.enable_mmu ? "MMU" : "EMEM", + (void *)hal->memspace[GSL_HAL_MEM1].gpu_base, + (void *)hal->memspace[GSL_HAL_MEM1].mmio_virt_base, + hal->memspace[GSL_HAL_MEM1].sizebytes + ); +#endif + } else { + kgsl_hal_close(); + return GSL_FAILURE_SYSTEMERROR; + } + + return GSL_SUCCESS; +} + +/* ---------------------------------------------------------------------------- */ + +KGSLHAL_API int +kgsl_hal_close(void) +{ + gsl_hal_t *hal; + + if (gsl_driver.hal) { + /* overlay structure on hal memory */ + hal = (gsl_hal_t *) gsl_driver.hal; + + /* unmap registers */ + if (hal->has_z430 && hal->z430_regspace.mmio_virt_base) { + iounmap(hal->z430_regspace.mmio_virt_base); + } + + if (hal->has_z160 && hal->z160_regspace.mmio_virt_base) { + iounmap(hal->z160_regspace.mmio_virt_base); + } + + /* free physical block */ + if (hal->memchunk.mmio_virt_base && gpu_reserved_mem) { + iounmap(hal->memchunk.mmio_virt_base); + } else { + dma_free_coherent(0, hal->memchunk.sizebytes, hal->memchunk.mmio_virt_base, hal->memchunk.mmio_phys_base); + } + + if (gsl_driver.enable_mmu) { + gsl_linux_map_destroy(); + } + + /* release hal struct */ + memset(hal, 0, sizeof(gsl_hal_t)); + kfree(gsl_driver.hal); + gsl_driver.hal = NULL; + } + + return GSL_SUCCESS; +} + +/* ---------------------------------------------------------------------------- */ + +KGSLHAL_API int +kgsl_hal_getshmemconfig(gsl_shmemconfig_t *config) +{ + int status = GSL_FAILURE_DEVICEERROR; + gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal; + + memset(config, 0, sizeof(gsl_shmemconfig_t)); + + if (hal) { + config->numapertures = GSL_SHMEM_MAX_APERTURES; + + if (gsl_driver.enable_mmu) { + config->apertures[0].id = GSL_APERTURE_MMU; + } else { + config->apertures[0].id = GSL_APERTURE_EMEM; + } + config->apertures[0].channel = GSL_CHANNEL_1; + config->apertures[0].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM1].mmio_virt_base; + config->apertures[0].gpubase = hal->memspace[GSL_HAL_MEM1].gpu_base; + config->apertures[0].sizebytes = hal->memspace[GSL_HAL_MEM1].sizebytes; + + config->apertures[1].id = GSL_APERTURE_PHYS; + config->apertures[1].channel = GSL_CHANNEL_1; + config->apertures[1].hostbase = (unsigned int)hal->memspace[GSL_HAL_MEM2].mmio_virt_base; + config->apertures[1].gpubase = hal->memspace[GSL_HAL_MEM2].gpu_base; + config->apertures[1].sizebytes = hal->memspace[GSL_HAL_MEM2].sizebytes; + + status = GSL_SUCCESS; + } + + return status; +} + +/* ---------------------------------------------------------------------------- */ + +KGSLHAL_API int +kgsl_hal_getdevconfig(gsl_deviceid_t device_id, gsl_devconfig_t *config) +{ + int status = GSL_FAILURE_DEVICEERROR; + gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal; + + memset(config, 0, sizeof(gsl_devconfig_t)); + + if (hal) { + switch (device_id) { + case GSL_DEVICE_YAMATO: + { + if (hal->has_z430) { + mh_mmu_config_u mmu_config = {0}; + + config->gmemspace.gpu_base = 0; + config->gmemspace.mmio_virt_base = 0; + config->gmemspace.mmio_phys_base = 0; + if (gmem_size) { + config->gmemspace.sizebytes = gmem_size; + } else { + config->gmemspace.sizebytes = 0; + } + + config->regspace.gpu_base = 0; + config->regspace.mmio_virt_base = (unsigned char *)hal->z430_regspace.mmio_virt_base; + config->regspace.mmio_phys_base = (unsigned int) hal->z430_regspace.mmio_phys_base; + config->regspace.sizebytes = GSL_HAL_SIZE_REG_YDX; + + mmu_config.f.mmu_enable = 1; + + if (gsl_driver.enable_mmu) { + mmu_config.f.split_mode_enable = 0; + mmu_config.f.rb_w_clnt_behavior = 1; + mmu_config.f.cp_w_clnt_behavior = 1; + mmu_config.f.cp_r0_clnt_behavior = 1; + mmu_config.f.cp_r1_clnt_behavior = 1; + mmu_config.f.cp_r2_clnt_behavior = 1; + mmu_config.f.cp_r3_clnt_behavior = 1; + mmu_config.f.cp_r4_clnt_behavior = 1; + mmu_config.f.vgt_r0_clnt_behavior = 1; + mmu_config.f.vgt_r1_clnt_behavior = 1; + mmu_config.f.tc_r_clnt_behavior = 1; + mmu_config.f.pa_w_clnt_behavior = 1; + } + + config->mmu_config = mmu_config.val; + + if (gsl_driver.enable_mmu) { + config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base; + config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes; + } else { + config->va_base = 0x00000000; + config->va_range = 0x00000000; + } + + /* turn off memory protection unit by setting acceptable physical address range to include all pages */ + config->mpu_base = 0x00000000; /* hal->memchunk.mmio_virt_base; */ + config->mpu_range = 0xFFFFF000; /* hal->memchunk.sizebytes; */ + status = GSL_SUCCESS; + } + break; + } + + case GSL_DEVICE_G12: + { + mh_mmu_config_u mmu_config = {0}; + + config->regspace.gpu_base = 0; + config->regspace.mmio_virt_base = (unsigned char *)hal->z160_regspace.mmio_virt_base; + config->regspace.mmio_phys_base = (unsigned int) hal->z160_regspace.mmio_phys_base; + config->regspace.sizebytes = GSL_HAL_SIZE_REG_G12; + + mmu_config.f.mmu_enable = 1; + + if (gsl_driver.enable_mmu) { + config->mmu_config = 0x00555551; + config->va_base = hal->memspace[GSL_HAL_MEM1].gpu_base; + config->va_range = hal->memspace[GSL_HAL_MEM1].sizebytes; + } else { + config->mmu_config = mmu_config.val; + config->va_base = 0x00000000; + config->va_range = 0x00000000; + } + + config->mpu_base = 0x00000000; /* (unsigned int) hal->memchunk.mmio_virt_base; */ + config->mpu_range = 0xFFFFF000; /* hal->memchunk.sizebytes; */ + + status = GSL_SUCCESS; + break; + } + + default: + break; + } + } + + return status; +} + +/*---------------------------------------------------------------------------- + * kgsl_hal_getchipid + * + * The proper platform method, build from RBBM_PERIPHIDx and RBBM_PATCH_RELEASE + *---------------------------------------------------------------------------- + */ +KGSLHAL_API gsl_chipid_t +kgsl_hal_getchipid(gsl_deviceid_t device_id) +{ + gsl_hal_t *hal = (gsl_hal_t *) gsl_driver.hal; + gsl_device_t *device = &gsl_driver.device[device_id-1]; + gsl_chipid_t chipid = 0; + unsigned int coreid, majorid, minorid, patchid, revid; + + if (hal->has_z430 && (device_id == GSL_DEVICE_YAMATO)) { + device->ftbl.device_regread(device, mmRBBM_PERIPHID1, &coreid); + coreid &= 0xF; + + device->ftbl.device_regread(device, mmRBBM_PERIPHID2, &majorid); + majorid = (majorid >> 4) & 0xF; + + device->ftbl.device_regread(device, mmRBBM_PATCH_RELEASE, &revid); + + minorid = ((revid >> 0) & 0xFF); /* this is a 16bit field, but extremely unlikely it would ever get this high */ + + patchid = ((revid >> 16) & 0xFF); + + chipid = ((coreid << 24) | (majorid << 16) | (minorid << 8) | (patchid << 0)); + +#ifdef GSL_HAL_DEBUG + printk(KERN_INFO "Z430 found: core %u major %u minor %u patch %u (chipid 0x%08x)\n", coreid, majorid, minorid, patchid, chipid); +#endif + } + + return chipid; +} + +/* --------------------------------------------------------------------------- */ + +KGSLHAL_API int +kgsl_hal_setpowerstate(gsl_deviceid_t device_id, int state, unsigned int value) +{ + gsl_device_t *device = &gsl_driver.device[device_id-1]; + struct clk *gpu_clk = NULL; + struct clk *garb_clk = NULL; + struct clk *emi_garb_clk = NULL; + + /* unreferenced formal parameters */ + (void) value; + + switch (device_id) { + case GSL_DEVICE_G12: + gpu_clk = clk_get(0, "gpu2d_clk"); + break; + case GSL_DEVICE_YAMATO: + gpu_clk = clk_get(0, "gpu3d_clk"); + garb_clk = clk_get(0, "garb_clk"); + emi_garb_clk = clk_get(0, "emi_garb_clk"); + break; + default: + return GSL_FAILURE_DEVICEERROR; + } + + if (!gpu_clk) { + return GSL_FAILURE_DEVICEERROR; + } + + switch (state) { + case GSL_PWRFLAGS_CLK_ON: + break; + case GSL_PWRFLAGS_POWER_ON: + clk_enable(gpu_clk); + if (garb_clk) { + clk_enable(garb_clk); + } + if (emi_garb_clk) { + clk_enable(emi_garb_clk); + } + kgsl_device_autogate_init(&gsl_driver.device[device_id-1]); + break; + case GSL_PWRFLAGS_CLK_OFF: + break; + case GSL_PWRFLAGS_POWER_OFF: + if (device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT) != GSL_SUCCESS) { + return GSL_FAILURE_DEVICEERROR; + } + kgsl_device_autogate_exit(&gsl_driver.device[device_id-1]); + clk_disable(gpu_clk); + if (garb_clk) { + clk_disable(garb_clk); + } + if (emi_garb_clk) { + clk_disable(emi_garb_clk); + } + break; + default: + break; + } + + return GSL_SUCCESS; +} + +KGSLHAL_API int kgsl_clock(gsl_deviceid_t dev, int enable) +{ + struct clk *gpu_clk = NULL; + struct clk *garb_clk = NULL; + struct clk *emi_garb_clk = NULL; + + switch (dev) { + case GSL_DEVICE_G12: + gpu_clk = clk_get(0, "gpu2d_clk"); + break; + case GSL_DEVICE_YAMATO: + gpu_clk = clk_get(0, "gpu3d_clk"); + garb_clk = clk_get(0, "garb_clk"); + emi_garb_clk = clk_get(0, "emi_garb_clk"); + break; + default: + printk(KERN_ERR "GPU device %d is invalid!\n", dev); + return GSL_FAILURE_DEVICEERROR; + } + + if (IS_ERR(gpu_clk)) { + printk(KERN_ERR "%s: GPU clock get failed!\n", __func__); + return GSL_FAILURE_DEVICEERROR; + } + + if (enable) { + clk_enable(gpu_clk); + if (garb_clk) { + clk_enable(garb_clk); + } + if (emi_garb_clk) { + clk_enable(emi_garb_clk); + } + } else { + clk_disable(gpu_clk); + if (garb_clk) { + clk_disable(garb_clk); + } + if (emi_garb_clk) { + clk_disable(emi_garb_clk); + } + } + + return GSL_SUCCESS; +} diff --git a/drivers/mxc/amd-gpu/gsl_intrmgr.c b/drivers/mxc/amd-gpu/gsl_intrmgr.c new file mode 100644 index 00000000000..1a81a3c9e99 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_intrmgr.c @@ -0,0 +1,301 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" + +////////////////////////////////////////////////////////////////////////////// +// macros +////////////////////////////////////////////////////////////////////////////// +#define GSL_INTRID_VALIDATE(id) (((id) < 0) || ((id) >= GSL_INTR_COUNT)) + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +static const gsl_intrblock_reg_t * +kgsl_intr_id2block(gsl_intrid_t id) +{ + const gsl_intrblock_reg_t *block; + int i; + + // interrupt id to hw block + for (i = 0; i < GSL_INTR_BLOCK_COUNT; i++) + { + block = &gsl_cfg_intrblock_reg[i]; + + if (block->first_id <= id && id <= block->last_id) + { + return (block); + } + } + + return (NULL); +} + +//---------------------------------------------------------------------------- + +void +kgsl_intr_decode(gsl_device_t *device, gsl_intrblock_t block_id) +{ + const gsl_intrblock_reg_t *block = &gsl_cfg_intrblock_reg[block_id]; + gsl_intrid_t id; + unsigned int status; + + // read the block's interrupt status bits + /* exclude CP block here to avoid hang in heavy loading with VPU+GPU */ + if ((block_id == GSL_INTR_BLOCK_YDX_CP) && (device->flags & GSL_FLAGS_STARTED)) { + status = 0x80000000; + } else { + device->ftbl.device_regread(device, block->status_reg, &status); + } + + // mask off any interrupts which are disabled + status &= device->intr.enabled[block->id]; + + // acknowledge the block's interrupts + device->ftbl.device_regwrite(device, block->clear_reg, status); + + // loop through the block's masks, determine which interrupt bits are active, and call callback (or TODO queue DPC) + for (id = block->first_id; id <= block->last_id; id++) + { + if (status & gsl_cfg_intr_mask[id]) + { + device->intr.handler[id].callback(id, device->intr.handler[id].cookie); + } + } +} + +//---------------------------------------------------------------------------- + +void +kgsl_intr_isr(gsl_device_t *device) +{ + if (device->intr.flags & GSL_FLAGS_INITIALIZED) { + kgsl_device_active(device); + device->ftbl.intr_isr(device); + } +} + +//---------------------------------------------------------------------------- + +int kgsl_intr_init(gsl_device_t *device) +{ + if (device->ftbl.intr_isr == NULL) + { + return (GSL_FAILURE_BADPARAM); + } + + if (device->intr.flags & GSL_FLAGS_INITIALIZED) + { + return (GSL_SUCCESS); + } + + device->intr.device = device; + device->intr.flags |= GSL_FLAGS_INITIALIZED; + + // os_interrupt_setcallback(YAMATO_INTR, kgsl_intr_isr); + // os_interrupt_enable(YAMATO_INTR); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int kgsl_intr_close(gsl_device_t *device) +{ + const gsl_intrblock_reg_t *block; + int i, id; + + if (device->intr.flags & GSL_FLAGS_INITIALIZED) + { + // check if there are any enabled interrupts lingering around + for (i = 0; i < GSL_INTR_BLOCK_COUNT; i++) + { + if (device->intr.enabled[i]) + { + block = &gsl_cfg_intrblock_reg[i]; + + // loop through the block's masks, disable interrupts which active + for (id = block->first_id; id <= block->last_id; id++) + { + if (device->intr.enabled[i] & gsl_cfg_intr_mask[id]) + { + kgsl_intr_disable(&device->intr, (gsl_intrid_t)id); + } + } + } + } + + memset(&device->intr, 0, sizeof(gsl_intr_t)); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int kgsl_intr_enable(gsl_intr_t *intr, gsl_intrid_t id) +{ + const gsl_intrblock_reg_t *block; + unsigned int mask; + unsigned int enabled; + + if (GSL_INTRID_VALIDATE(id)) + { + return (GSL_FAILURE_BADPARAM); + } + + if (intr->handler[id].callback == NULL) + { + return (GSL_FAILURE_NOTINITIALIZED); + } + + block = kgsl_intr_id2block(id); + if (block == NULL) + { + return (GSL_FAILURE_SYSTEMERROR); + } + + mask = gsl_cfg_intr_mask[id]; + enabled = intr->enabled[block->id]; + + if (mask && !(enabled & mask)) + { + init_completion(&intr->evnt[id]); + + enabled |= mask; + intr->enabled[block->id] = enabled; + intr->device->ftbl.device_regwrite(intr->device, block->mask_reg, enabled); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int kgsl_intr_disable(gsl_intr_t *intr, gsl_intrid_t id) +{ + const gsl_intrblock_reg_t *block; + unsigned int mask; + unsigned int enabled; + + if (GSL_INTRID_VALIDATE(id)) + { + return (GSL_FAILURE_BADPARAM); + } + + if (intr->handler[id].callback == NULL) + { + return (GSL_FAILURE_NOTINITIALIZED); + } + + block = kgsl_intr_id2block(id); + if (block == NULL) + { + return (GSL_FAILURE_SYSTEMERROR); + } + + mask = gsl_cfg_intr_mask[id]; + enabled = intr->enabled[block->id]; + + if (enabled & mask) + { + enabled &= ~mask; + intr->enabled[block->id] = enabled; + intr->device->ftbl.device_regwrite(intr->device, block->mask_reg, enabled); + + complete_all(&intr->evnt[id]); // wake up waiting threads before destroying the event + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_intr_attach(gsl_intr_t *intr, gsl_intrid_t id, gsl_intr_callback_t callback, void *cookie) +{ + if (GSL_INTRID_VALIDATE(id) || callback == NULL) + { + return (GSL_FAILURE_BADPARAM); + } + + if (intr->handler[id].callback != NULL) + { + if (intr->handler[id].callback == callback && intr->handler[id].cookie == cookie) + { + return (GSL_FAILURE_ALREADYINITIALIZED); + } + else + { + return (GSL_FAILURE_NOMOREAVAILABLE); + } + } + + intr->handler[id].callback = callback; + intr->handler[id].cookie = cookie; + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_intr_detach(gsl_intr_t *intr, gsl_intrid_t id) +{ + if (GSL_INTRID_VALIDATE(id)) + { + return (GSL_FAILURE_BADPARAM); + } + + if (intr->handler[id].callback == NULL) + { + return (GSL_FAILURE_NOTINITIALIZED); + } + + kgsl_intr_disable(intr, id); + + intr->handler[id].callback = NULL; + intr->handler[id].cookie = NULL; + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_intr_isenabled(gsl_intr_t *intr, gsl_intrid_t id) +{ + int status = GSL_FAILURE; + const gsl_intrblock_reg_t *block = kgsl_intr_id2block(id); + + if (block != NULL) + { + // check if interrupt is enabled + if (intr->enabled[block->id] & gsl_cfg_intr_mask[id]) + { + status = GSL_SUCCESS; + } + } + + return (status); +} diff --git a/drivers/mxc/amd-gpu/gsl_kmod.c b/drivers/mxc/amd-gpu/gsl_kmod.c new file mode 100644 index 00000000000..da39bc3ef12 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_kmod.c @@ -0,0 +1,983 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include "gsl_types.h" +#include "gsl.h" +#include "gsl_buildconfig.h" +#include "gsl_halconfig.h" +#include "gsl_ioctl.h" +#include "gsl_kmod_cleanup.h" +#include "gsl_linux_map.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +int gpu_2d_irq, gpu_3d_irq; + +phys_addr_t gpu_2d_regbase; +int gpu_2d_regsize; +phys_addr_t gpu_3d_regbase; +int gpu_3d_regsize; +int gmem_size; +phys_addr_t gpu_reserved_mem; +int gpu_reserved_mem_size; +int z160_version; +int enable_mmu; + +static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr); +static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr); +static int gsl_kmod_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, unsigned long arg); +static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma); +static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +static int gsl_kmod_open(struct inode *inode, struct file *fd); +static int gsl_kmod_release(struct inode *inode, struct file *fd); +static irqreturn_t z160_irq_handler(int irq, void *dev_id); +static irqreturn_t z430_irq_handler(int irq, void *dev_id); + +static int gsl_kmod_major; +static struct class *gsl_kmod_class; +DEFINE_MUTEX(gsl_mutex); + +static const struct file_operations gsl_kmod_fops = +{ + .owner = THIS_MODULE, + .read = gsl_kmod_read, + .write = gsl_kmod_write, + .ioctl = gsl_kmod_ioctl, + .mmap = gsl_kmod_mmap, + .open = gsl_kmod_open, + .release = gsl_kmod_release +}; + +static struct vm_operations_struct gsl_kmod_vmops = +{ + .fault = gsl_kmod_fault, +}; + +static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) +{ + return 0; +} + +static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) +{ + return 0; +} + +static int gsl_kmod_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, unsigned long arg) +{ + int kgslStatus = GSL_FAILURE; + + switch (cmd) { + case IOCTL_KGSL_DEVICE_START: + { + kgsl_device_start_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_start_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_start(param.device_id, param.flags); + break; + } + case IOCTL_KGSL_DEVICE_STOP: + { + kgsl_device_stop_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_stop_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_stop(param.device_id); + break; + } + case IOCTL_KGSL_DEVICE_IDLE: + { + kgsl_device_idle_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_idle_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_idle(param.device_id, param.timeout); + break; + } + case IOCTL_KGSL_DEVICE_ISIDLE: + { + kgsl_device_isidle_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_isidle_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_isidle(param.device_id); + break; + } + case IOCTL_KGSL_DEVICE_GETPROPERTY: + { + kgsl_device_getproperty_t param; + void *tmp; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_getproperty_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + tmp = kmalloc(param.sizebytes, GFP_KERNEL); + if (!tmp) + { + printk(KERN_ERR "%s:kmalloc error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_getproperty(param.device_id, param.type, tmp, param.sizebytes); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.value, tmp, param.sizebytes)) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + kfree(tmp); + break; + } + } + else + { + printk(KERN_ERR "%s: kgsl_device_getproperty error\n", __func__); + } + kfree(tmp); + break; + } + case IOCTL_KGSL_DEVICE_SETPROPERTY: + { + kgsl_device_setproperty_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_setproperty_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_setproperty(param.device_id, param.type, param.value, param.sizebytes); + if (kgslStatus != GSL_SUCCESS) + { + printk(KERN_ERR "%s: kgsl_device_setproperty error\n", __func__); + } + break; + } + case IOCTL_KGSL_DEVICE_REGREAD: + { + kgsl_device_regread_t param; + unsigned int tmp; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_regread_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_regread(param.device_id, param.offsetwords, &tmp); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.value, &tmp, sizeof(unsigned int))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + } + break; + } + case IOCTL_KGSL_DEVICE_REGWRITE: + { + kgsl_device_regwrite_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_regwrite_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_regwrite(param.device_id, param.offsetwords, param.value); + break; + } + case IOCTL_KGSL_DEVICE_WAITIRQ: + { + kgsl_device_waitirq_t param; + unsigned int count; + + printk(KERN_ERR "IOCTL_KGSL_DEVICE_WAITIRQ obsoleted!\n"); +// kgslStatus = -ENOTTY; break; + + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_waitirq_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_waitirq(param.device_id, param.intr_id, &count, param.timeout); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.count, &count, sizeof(unsigned int))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + } + break; + } + case IOCTL_KGSL_CMDSTREAM_ISSUEIBCMDS: + { + kgsl_cmdstream_issueibcmds_t param; + gsl_timestamp_t tmp; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_issueibcmds_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_cmdstream_issueibcmds(param.device_id, param.drawctxt_index, param.ibaddr, param.sizedwords, &tmp, param.flags); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + } + break; + } + case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP: + { + kgsl_cmdstream_readtimestamp_t param; + gsl_timestamp_t tmp; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_readtimestamp_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + tmp = kgsl_cmdstream_readtimestamp(param.device_id, param.type); + if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = GSL_SUCCESS; + break; + } + case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP: + { + int err; + kgsl_cmdstream_freememontimestamp_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_freememontimestamp_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + err = del_memblock_from_allocated_list(fd, param.memdesc); + if(err) + { + /* tried to remove a block of memory that is not allocated! + * NOTE that -EINVAL is Linux kernel's error codes! + * the drivers error codes COULD mix up with kernel's. */ + kgslStatus = -EINVAL; + } + else + { + kgslStatus = kgsl_cmdstream_freememontimestamp(param.device_id, + param.memdesc, + param.timestamp, + param.type); + } + break; + } + case IOCTL_KGSL_CMDSTREAM_WAITTIMESTAMP: + { + kgsl_cmdstream_waittimestamp_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_waittimestamp_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_cmdstream_waittimestamp(param.device_id, param.timestamp, param.timeout); + break; + } + case IOCTL_KGSL_CMDWINDOW_WRITE: + { + kgsl_cmdwindow_write_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdwindow_write_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_cmdwindow_write(param.device_id, param.target, param.addr, param.data); + break; + } + case IOCTL_KGSL_CONTEXT_CREATE: + { + kgsl_context_create_t param; + unsigned int tmp; + int tmpStatus; + + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_context_create_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_context_create(param.device_id, param.type, &tmp, param.flags); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.drawctxt_id, &tmp, sizeof(unsigned int))) + { + tmpStatus = kgsl_context_destroy(param.device_id, tmp); + /* is asserting ok? Basicly we should return the error from copy_to_user + * but will the user space interpret it correctly? Will the user space + * always check against GSL_SUCCESS or GSL_FAILURE as they are not the only + * return values. + */ + DEBUG_ASSERT(tmpStatus == GSL_SUCCESS); + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + else + { + add_device_context_to_array(fd, param.device_id, tmp); + } + } + break; + } + case IOCTL_KGSL_CONTEXT_DESTROY: + { + kgsl_context_destroy_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_context_destroy_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_context_destroy(param.device_id, param.drawctxt_id); + del_device_context_from_array(fd, param.device_id, param.drawctxt_id); + break; + } + case IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW: + { + kgsl_drawctxt_bind_gmem_shadow_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_drawctxt_bind_gmem_shadow_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_drawctxt_bind_gmem_shadow(param.device_id, param.drawctxt_id, param.gmem_rect, param.shadow_x, param.shadow_y, param.shadow_buffer, param.buffer_id); + break; + } + case IOCTL_KGSL_SHAREDMEM_ALLOC: + { + kgsl_sharedmem_alloc_t param; + gsl_memdesc_t tmp; + int tmpStatus; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_alloc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_sharedmem_alloc(param.device_id, param.flags, param.sizebytes, &tmp); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t))) + { + tmpStatus = kgsl_sharedmem_free(&tmp); + DEBUG_ASSERT(tmpStatus == GSL_SUCCESS); + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + else + { + add_memblock_to_allocated_list(fd, &tmp); + } + } + break; + } + case IOCTL_KGSL_SHAREDMEM_FREE: + { + kgsl_sharedmem_free_t param; + gsl_memdesc_t tmp; + int err; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_free_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + if (copy_from_user(&tmp, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + err = del_memblock_from_allocated_list(fd, &tmp); + if(err) + { + printk(KERN_ERR "%s: tried to free memdesc that was not allocated!\n", __func__); + kgslStatus = err; + break; + } + kgslStatus = kgsl_sharedmem_free(&tmp); + if (kgslStatus == GSL_SUCCESS) + { + if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + } + break; + } + case IOCTL_KGSL_SHAREDMEM_READ: + { + kgsl_sharedmem_read_t param; + gsl_memdesc_t memdesc; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_read_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_sharedmem_read(&memdesc, param.dst, param.offsetbytes, param.sizebytes, true); + if (kgslStatus != GSL_SUCCESS) + { + printk(KERN_ERR "%s: kgsl_sharedmem_read failed\n", __func__); + } + break; + } + case IOCTL_KGSL_SHAREDMEM_WRITE: + { + kgsl_sharedmem_write_t param; + gsl_memdesc_t memdesc; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_write_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_sharedmem_write(&memdesc, param.offsetbytes, param.src, param.sizebytes, true); + if (kgslStatus != GSL_SUCCESS) + { + printk(KERN_ERR "%s: kgsl_sharedmem_write failed\n", __func__); + } + + break; + } + case IOCTL_KGSL_SHAREDMEM_SET: + { + kgsl_sharedmem_set_t param; + gsl_memdesc_t memdesc; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_set_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_sharedmem_set(&memdesc, param.offsetbytes, param.value, param.sizebytes); + break; + } + case IOCTL_KGSL_SHAREDMEM_LARGESTFREEBLOCK: + { + kgsl_sharedmem_largestfreeblock_t param; + unsigned int largestfreeblock; + + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_largestfreeblock_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + largestfreeblock = kgsl_sharedmem_largestfreeblock(param.device_id, param.flags); + if (copy_to_user(param.largestfreeblock, &largestfreeblock, sizeof(unsigned int))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = GSL_SUCCESS; + break; + } + case IOCTL_KGSL_SHAREDMEM_CACHEOPERATION: + { + kgsl_sharedmem_cacheoperation_t param; + gsl_memdesc_t memdesc; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_cacheoperation_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_sharedmem_cacheoperation(&memdesc, param.offsetbytes, param.sizebytes, param.operation); + break; + } + case IOCTL_KGSL_SHAREDMEM_FROMHOSTPOINTER: + { + kgsl_sharedmem_fromhostpointer_t param; + gsl_memdesc_t memdesc; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_fromhostpointer_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_sharedmem_fromhostpointer(param.device_id, &memdesc, param.hostptr); + break; + } + case IOCTL_KGSL_ADD_TIMESTAMP: + { + kgsl_add_timestamp_t param; + gsl_timestamp_t tmp; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_add_timestamp_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + tmp = kgsl_add_timestamp(param.device_id, &tmp); + if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) + { + printk(KERN_ERR "%s: copy_to_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = GSL_SUCCESS; + break; + } + + case IOCTL_KGSL_DEVICE_CLOCK: + { + kgsl_device_clock_t param; + if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_clock_t))) + { + printk(KERN_ERR "%s: copy_from_user error\n", __func__); + kgslStatus = GSL_FAILURE; + break; + } + kgslStatus = kgsl_device_clock(param.device, param.enable); + break; + } + default: + kgslStatus = -ENOTTY; + break; + } + + return kgslStatus; +} + +static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma) +{ + int status = 0; + unsigned long start = vma->vm_start; + unsigned long pfn = vma->vm_pgoff; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long prot = pgprot_writecombine(vma->vm_page_prot); + unsigned long addr = vma->vm_pgoff << PAGE_SHIFT; + void *va = NULL; + + if (gsl_driver.enable_mmu && (addr < GSL_LINUX_MAP_RANGE_END) && (addr >= GSL_LINUX_MAP_RANGE_START)) { + va = gsl_linux_map_find(addr); + while (size > 0) { + if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot)) { + return -EAGAIN; + } + start += PAGE_SIZE; + va += PAGE_SIZE; + size -= PAGE_SIZE; + } + } else { + if (remap_pfn_range(vma, start, pfn, size, prot)) { + status = -EAGAIN; + } + } + + vma->vm_ops = &gsl_kmod_vmops; + + return status; +} + +static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + return VM_FAULT_SIGBUS; +} + +static int gsl_kmod_open(struct inode *inode, struct file *fd) +{ + gsl_flags_t flags = 0; + struct gsl_kmod_per_fd_data *datp; + int err = 0; + + if(mutex_lock_interruptible(&gsl_mutex)) + { + return -EINTR; + } + + if (kgsl_driver_entry(flags) != GSL_SUCCESS) + { + printk(KERN_INFO "%s: kgsl_driver_entry error\n", __func__); + err = -EIO; // TODO: not sure why did it fail? + } + else + { + /* allocate per file descriptor data structure */ + datp = (struct gsl_kmod_per_fd_data *)kzalloc( + sizeof(struct gsl_kmod_per_fd_data), + GFP_KERNEL); + if(datp) + { + init_created_contexts_array(datp->created_contexts_array[0]); + INIT_LIST_HEAD(&datp->allocated_blocks_head); + + fd->private_data = (void *)datp; + } + else + { + err = -ENOMEM; + } + } + + mutex_unlock(&gsl_mutex); + + return err; +} + +static int gsl_kmod_release(struct inode *inode, struct file *fd) +{ + struct gsl_kmod_per_fd_data *datp; + int err = 0; + + if(mutex_lock_interruptible(&gsl_mutex)) + { + return -EINTR; + } + + /* make sure contexts are destroyed */ + del_all_devices_contexts(fd); + + if (kgsl_driver_exit() != GSL_SUCCESS) + { + printk(KERN_INFO "%s: kgsl_driver_exit error\n", __func__); + err = -EIO; // TODO: find better error code + } + else + { + /* release per file descriptor data structure */ + datp = (struct gsl_kmod_per_fd_data *)fd->private_data; + del_all_memblocks_from_allocated_list(fd); + kfree(datp); + fd->private_data = 0; + } + + mutex_unlock(&gsl_mutex); + + return err; +} + +static struct class *gsl_kmod_class; + +static irqreturn_t z160_irq_handler(int irq, void *dev_id) +{ + kgsl_intr_isr(&gsl_driver.device[GSL_DEVICE_G12-1]); + return IRQ_HANDLED; +} + +static irqreturn_t z430_irq_handler(int irq, void *dev_id) +{ + kgsl_intr_isr(&gsl_driver.device[GSL_DEVICE_YAMATO-1]); + return IRQ_HANDLED; +} + +static int gpu_probe(struct platform_device *pdev) +{ + int i; + struct resource *res; + struct device *dev; + struct mxc_gpu_platform_data *gpu_data = NULL; + + gpu_data = (struct mxc_gpu_platform_data *)pdev->dev.platform_data; + + if (gpu_data == NULL) + return 0; + + z160_version = gpu_data->z160_revision; + enable_mmu = gpu_data->enable_mmu; + + for(i = 0; i < 2; i++){ + res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (!res) { + if (i == 0) { + printk(KERN_ERR "gpu: unable to get gpu irq\n"); + return -ENODEV; + } else { + break; + } + } + if(strcmp(res->name, "gpu_2d_irq") == 0){ + gpu_2d_irq = res->start; + }else if(strcmp(res->name, "gpu_3d_irq") == 0){ + gpu_3d_irq = res->start; + } + } + + for(i = 0; i < 4; i++){ + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) { + gpu_2d_regbase = 0; + gpu_2d_regsize = 0; + gpu_3d_regbase = 0; + gpu_2d_regsize = 0; + gmem_size = 0; + gpu_reserved_mem = 0; + gpu_reserved_mem_size = 0; + break; + }else{ + if(strcmp(res->name, "gpu_2d_registers") == 0){ + gpu_2d_regbase = res->start; + gpu_2d_regsize = res->end - res->start + 1; + }else if(strcmp(res->name, "gpu_3d_registers") == 0){ + gpu_3d_regbase = res->start; + gpu_3d_regsize = res->end - res->start + 1; + }else if(strcmp(res->name, "gpu_graphics_mem") == 0){ + gmem_size = res->end - res->start + 1; + }else if(strcmp(res->name, "gpu_reserved_mem") == 0){ + gpu_reserved_mem = res->start; + gpu_reserved_mem_size = res->end - res->start + 1; + } + } + } + + if (gpu_3d_irq > 0) + { + if (request_irq(gpu_3d_irq, z430_irq_handler, 0, "ydx", NULL) < 0) { + printk(KERN_ERR "%s: request_irq error\n", __func__); + gpu_3d_irq = 0; + goto request_irq_error; + } + } + + if (gpu_2d_irq > 0) + { + if (request_irq(gpu_2d_irq, z160_irq_handler, 0, "g12", NULL) < 0) { + printk(KERN_ERR "Could not allocate IRQ for OpenVG!\n"); + gpu_2d_irq = 0; + } + } + + if (kgsl_driver_init() != GSL_SUCCESS) { + printk(KERN_ERR "%s: kgsl_driver_init error\n", __func__); + goto kgsl_driver_init_error; + } + + gsl_kmod_major = register_chrdev(0, "gsl_kmod", &gsl_kmod_fops); + gsl_kmod_vmops.fault = gsl_kmod_fault; + + if (gsl_kmod_major <= 0) + { + pr_err("%s: register_chrdev error\n", __func__); + goto register_chrdev_error; + } + + gsl_kmod_class = class_create(THIS_MODULE, "gsl_kmod"); + + if (IS_ERR(gsl_kmod_class)) + { + pr_err("%s: class_create error\n", __func__); + goto class_create_error; + } + + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) + dev = device_create(gsl_kmod_class, NULL, MKDEV(gsl_kmod_major, 0), "gsl_kmod"); + #else + dev = device_create(gsl_kmod_class, NULL, MKDEV(gsl_kmod_major, 0), NULL,"gsl_kmod"); + #endif + + if (!IS_ERR(dev)) + { + // gsl_kmod_data.device = dev; + return 0; + } + + pr_err("%s: device_create error\n", __func__); + +class_create_error: + class_destroy(gsl_kmod_class); + +register_chrdev_error: + unregister_chrdev(gsl_kmod_major, "gsl_kmod"); + +kgsl_driver_init_error: + kgsl_driver_close(); + if (gpu_2d_irq > 0) { + free_irq(gpu_2d_irq, NULL); + } + if (gpu_3d_irq > 0) { + free_irq(gpu_3d_irq, NULL); + } +request_irq_error: + return 0; // TODO: return proper error code +} + +static int gpu_remove(struct platform_device *pdev) +{ + device_destroy(gsl_kmod_class, MKDEV(gsl_kmod_major, 0)); + class_destroy(gsl_kmod_class); + unregister_chrdev(gsl_kmod_major, "gsl_kmod"); + + if (gpu_3d_irq) + { + free_irq(gpu_3d_irq, NULL); + } + + if (gpu_2d_irq) + { + free_irq(gpu_2d_irq, NULL); + } + + kgsl_driver_close(); + return 0; +} + +#ifdef CONFIG_PM +static int gpu_suspend(struct platform_device *pdev, pm_message_t state) +{ + int i; + gsl_powerprop_t power; + + power.flags = GSL_PWRFLAGS_POWER_OFF; + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + kgsl_device_setproperty( + (gsl_deviceid_t) (i+1), + GSL_PROP_DEVICE_POWER, + &power, + sizeof(gsl_powerprop_t)); + } + + return 0; +} + +static int gpu_resume(struct platform_device *pdev) +{ + int i; + gsl_powerprop_t power; + + power.flags = GSL_PWRFLAGS_POWER_ON; + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + kgsl_device_setproperty( + (gsl_deviceid_t) (i+1), + GSL_PROP_DEVICE_POWER, + &power, + sizeof(gsl_powerprop_t)); + } + + return 0; +} +#else +#define gpu_suspend NULL +#define gpu_resume NULL +#endif /* !CONFIG_PM */ + +/*! Driver definition + */ +static struct platform_driver gpu_driver = { + .driver = { + .name = "mxc_gpu", + }, + .probe = gpu_probe, + .remove = gpu_remove, + .suspend = gpu_suspend, + .resume = gpu_resume, +}; + +static int __init gsl_kmod_init(void) +{ + return platform_driver_register(&gpu_driver); +} + +static void __exit gsl_kmod_exit(void) +{ + platform_driver_unregister(&gpu_driver); +} + +module_init(gsl_kmod_init); +module_exit(gsl_kmod_exit); +MODULE_AUTHOR("Advanced Micro Devices"); +MODULE_DESCRIPTION("AMD graphics core driver for i.MX"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mxc/amd-gpu/gsl_kmod_cleanup.c b/drivers/mxc/amd-gpu/gsl_kmod_cleanup.c new file mode 100644 index 00000000000..3908bef506e --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_kmod_cleanup.c @@ -0,0 +1,269 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include "gsl.h" +#include "gsl_kmod_cleanup.h" + +#include +#include + +/* + * Local helper functions to check and convert device/context id's (1 based) + * to index (0 based). + */ +static u32 device_id_to_device_index(gsl_deviceid_t device_id) +{ + DEBUG_ASSERT((GSL_DEVICE_ANY < device_id) && + (device_id <= GSL_DEVICE_MAX)); + return (u32)(device_id - 1); +} + +/* + * Local helper function to check and get pointer to per file descriptor data + */ +static struct gsl_kmod_per_fd_data *get_fd_private_data(struct file *fd) +{ + struct gsl_kmod_per_fd_data *datp; + + DEBUG_ASSERT(fd); + datp = (struct gsl_kmod_per_fd_data *)fd->private_data; + DEBUG_ASSERT(datp); + return datp; +} + +static s8 *find_first_entry_with(s8 *subarray, s8 context_id) +{ + s8 *entry = NULL; + int i; + +//printk(KERN_DEBUG "At %s, ctx_id = %d\n", __func__, context_id); + + DEBUG_ASSERT(context_id >= EMPTY_ENTRY); + DEBUG_ASSERT(context_id <= GSL_CONTEXT_MAX); // TODO: check the bound. + + for(i = 0; i < GSL_CONTEXT_MAX; i++) // TODO: check the bound. + { + if(subarray[i] == (s8)context_id) + { + entry = &subarray[i]; + break; + } + } + + return entry; +} + + +/* + * Add a memdesc into a list of allocated memory blocks for this file + * descriptor. The list is build in such a way that it implements FIFO (i.e. + * list). Traces of tiger, tiger_ri and VG11 CTs should be analysed to make + * informed choice. + * + * NOTE! gsl_memdesc_ts are COPIED so user space should NOT change them. + */ +int add_memblock_to_allocated_list(struct file *fd, + gsl_memdesc_t *allocated_block) +{ + int err = 0; + struct gsl_kmod_per_fd_data *datp; + struct gsl_kmod_alloc_list *lisp; + struct list_head *head; + + DEBUG_ASSERT(allocated_block); + + datp = get_fd_private_data(fd); + + head = &datp->allocated_blocks_head; + DEBUG_ASSERT(head); + + /* allocate and put new entry in the list of allocated memory descriptors */ + lisp = (struct gsl_kmod_alloc_list *)kzalloc(sizeof(struct gsl_kmod_alloc_list), GFP_KERNEL); + if(lisp) + { + INIT_LIST_HEAD(&lisp->node); + + /* builds FIFO (list_add() would build LIFO) */ + list_add_tail(&lisp->node, head); + memcpy(&lisp->allocated_block, allocated_block, sizeof(gsl_memdesc_t)); + lisp->allocation_number = datp->maximum_number_of_blocks; +// printk(KERN_DEBUG "List entry #%u allocated\n", lisp->allocation_number); + + datp->maximum_number_of_blocks++; + datp->number_of_allocated_blocks++; + + err = 0; + } + else + { + printk(KERN_ERR "%s: Could not allocate new list element\n", __func__); + err = -ENOMEM; + } + + return err; +} + +/* Delete a previously allocated memdesc from a list of allocated memory blocks */ +int del_memblock_from_allocated_list(struct file *fd, + gsl_memdesc_t *freed_block) +{ + struct gsl_kmod_per_fd_data *datp; + struct gsl_kmod_alloc_list *cursor, *next; + struct list_head *head; +// int is_different; + + DEBUG_ASSERT(freed_block); + + datp = get_fd_private_data(fd); + + head = &datp->allocated_blocks_head; + DEBUG_ASSERT(head); + + DEBUG_ASSERT(datp->number_of_allocated_blocks > 0); + + if(!list_empty(head)) + { + list_for_each_entry_safe(cursor, next, head, node) + { + if(cursor->allocated_block.gpuaddr == freed_block->gpuaddr) + { +// is_different = memcmp(&cursor->allocated_block, freed_block, sizeof(gsl_memdesc_t)); +// DEBUG_ASSERT(!is_different); + + list_del(&cursor->node); +// printk(KERN_DEBUG "List entry #%u freed\n", cursor->allocation_number); + kfree(cursor); + datp->number_of_allocated_blocks--; + return 0; + } + } + } + return -EINVAL; // tried to free entry not existing or from empty list. +} + +/* Delete all previously allocated memdescs from a list */ +int del_all_memblocks_from_allocated_list(struct file *fd) +{ + struct gsl_kmod_per_fd_data *datp; + struct gsl_kmod_alloc_list *cursor, *next; + struct list_head *head; + + datp = get_fd_private_data(fd); + + head = &datp->allocated_blocks_head; + DEBUG_ASSERT(head); + + if(!list_empty(head)) + { + printk(KERN_INFO "Not all allocated memory blocks were freed. Doing it now.\n"); + list_for_each_entry_safe(cursor, next, head, node) + { + printk(KERN_INFO "Freeing list entry #%u, gpuaddr=%x\n", (u32)cursor->allocation_number, cursor->allocated_block.gpuaddr); + kgsl_sharedmem_free(&cursor->allocated_block); + list_del(&cursor->node); + kfree(cursor); + } + } + + DEBUG_ASSERT(list_empty(head)); + datp->number_of_allocated_blocks = 0; + + return 0; +} + +void init_created_contexts_array(s8 *array) +{ + memset((void*)array, EMPTY_ENTRY, GSL_DEVICE_MAX * GSL_CONTEXT_MAX); +} + + +void add_device_context_to_array(struct file *fd, + gsl_deviceid_t device_id, + unsigned int context_id) +{ + struct gsl_kmod_per_fd_data *datp; + s8 *entry; + s8 *subarray; + u32 device_index = device_id_to_device_index(device_id); + + datp = get_fd_private_data(fd); + + subarray = datp->created_contexts_array[device_index]; + entry = find_first_entry_with(subarray, EMPTY_ENTRY); + + DEBUG_ASSERT(entry); + DEBUG_ASSERT((datp->created_contexts_array[device_index] <= entry) && + (entry < datp->created_contexts_array[device_index] + GSL_CONTEXT_MAX)); + DEBUG_ASSERT(context_id < 127); + *entry = (s8)context_id; +} + +void del_device_context_from_array(struct file *fd, + gsl_deviceid_t device_id, + unsigned int context_id) +{ + struct gsl_kmod_per_fd_data *datp; + u32 device_index = device_id_to_device_index(device_id); + s8 *entry; + s8 *subarray; + + datp = get_fd_private_data(fd); + + DEBUG_ASSERT(context_id < 127); + subarray = &(datp->created_contexts_array[device_index][0]); + entry = find_first_entry_with(subarray, context_id); + DEBUG_ASSERT(entry); + DEBUG_ASSERT((datp->created_contexts_array[device_index] <= entry) && + (entry < datp->created_contexts_array[device_index] + GSL_CONTEXT_MAX)); + *entry = EMPTY_ENTRY; +} + +void del_all_devices_contexts(struct file *fd) +{ + struct gsl_kmod_per_fd_data *datp; + gsl_deviceid_t id; + u32 device_index; + u32 ctx_array_index; + s8 ctx; + int err; + + datp = get_fd_private_data(fd); + + /* device_id is 1 based */ + for(id = GSL_DEVICE_ANY + 1; id <= GSL_DEVICE_MAX; id++) + { + device_index = device_id_to_device_index(id); + for(ctx_array_index = 0; ctx_array_index < GSL_CONTEXT_MAX; ctx_array_index++) + { + ctx = datp->created_contexts_array[device_index][ctx_array_index]; + if(ctx != EMPTY_ENTRY) + { + err = kgsl_context_destroy(id, ctx); + if(err != GSL_SUCCESS) + { + printk(KERN_ERR "%s: could not destroy context %d on device id = %u\n", __func__, ctx, id); + } + else + { + printk(KERN_DEBUG "%s: Destroyed context %d on device id = %u\n", __func__, ctx, id); + } + } + } + } +} + diff --git a/drivers/mxc/amd-gpu/gsl_kmod_cleanup.h b/drivers/mxc/amd-gpu/gsl_kmod_cleanup.h new file mode 100644 index 00000000000..475ee3be2e5 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_kmod_cleanup.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GSL_KMOD_CLEANUP_H +#define __GSL_KMOD_CLEANUP_H +#include "gsl_types.h" + +#include +#include +#include +#include + +#if (GSL_CONTEXT_MAX > 127) + #error created_contexts_array supports context numbers only 127 or less. +#endif + +static const s8 EMPTY_ENTRY = -1; + +/* A structure to make list of allocated memory blocks. List per fd. */ +/* should probably be allocated from slab cache to minimise fragmentation */ +struct gsl_kmod_alloc_list +{ + struct list_head node; + gsl_memdesc_t allocated_block; + u32 allocation_number; +}; + +/* A structure to hold abovementioned list of blocks. Contain per fd data. */ +struct gsl_kmod_per_fd_data +{ + struct list_head allocated_blocks_head; // list head + u32 maximum_number_of_blocks; + u32 number_of_allocated_blocks; + s8 created_contexts_array[GSL_DEVICE_MAX][GSL_CONTEXT_MAX]; +}; + + +/* + * prototypes + */ + +/* allocated memory block tracking */ +int add_memblock_to_allocated_list(struct file *fd, + gsl_memdesc_t *allocated_block); + +int del_memblock_from_allocated_list(struct file *fd, + gsl_memdesc_t *freed_block); + +int del_all_memblocks_from_allocated_list(struct file *fd); + +/* created contexts tracking */ +void init_created_contexts_array(s8 *array); + +void add_device_context_to_array(struct file *fd, + gsl_deviceid_t device_id, + unsigned int context_id); + +void del_device_context_from_array(struct file *fd, + gsl_deviceid_t device_id, + unsigned int context_id); + +void del_all_devices_contexts(struct file *fd); + +#endif // __GSL_KMOD_CLEANUP_H + diff --git a/drivers/mxc/amd-gpu/gsl_linux_map.c b/drivers/mxc/amd-gpu/gsl_linux_map.c new file mode 100644 index 00000000000..9a2c4b30ce8 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_linux_map.c @@ -0,0 +1,221 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "gsl_linux_map.h" + +struct gsl_linux_map +{ + struct list_head list; + unsigned int gpu_addr; + void *kernel_virtual_addr; + unsigned int size; +}; + +static LIST_HEAD(gsl_linux_map_list); +static DEFINE_MUTEX(gsl_linux_map_mutex); + +int gsl_linux_map_init() +{ + mutex_lock(&gsl_linux_map_mutex); + INIT_LIST_HEAD(&gsl_linux_map_list); + mutex_unlock(&gsl_linux_map_mutex); + + return 0; +} + +void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size) +{ + struct gsl_linux_map * map; + struct list_head *p; + void *va; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each(p, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + if(map->gpu_addr == gpu_addr){ + mutex_unlock(&gsl_linux_map_mutex); + return map->kernel_virtual_addr; + } + } + + va = __vmalloc(size, GFP_KERNEL, pgprot_writecombine(pgprot_kernel)); + if(va == NULL){ + mutex_unlock(&gsl_linux_map_mutex); + return NULL; + } + + map = (struct gsl_linux_map *)kmalloc(sizeof(*map), GFP_KERNEL); + map->gpu_addr = gpu_addr; + map->kernel_virtual_addr = va; + map->size = size; + + INIT_LIST_HEAD(&map->list); + list_add_tail(&map->list, &gsl_linux_map_list); + + mutex_unlock(&gsl_linux_map_mutex); + return va; +} + +void gsl_linux_map_free(unsigned int gpu_addr) +{ + int found = 0; + struct gsl_linux_map * map; + struct list_head *p; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each(p, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + if(map->gpu_addr == gpu_addr){ + found = 1; + break; + } + } + + if(found){ + vfree(map->kernel_virtual_addr); + list_del(&map->list); + kfree(map); + } + + mutex_unlock(&gsl_linux_map_mutex); +} + +void *gsl_linux_map_find(unsigned int gpu_addr) +{ + struct gsl_linux_map * map; + struct list_head *p; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each(p, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + if(map->gpu_addr == gpu_addr){ + mutex_unlock(&gsl_linux_map_mutex); + return map->kernel_virtual_addr; + } + } + + mutex_unlock(&gsl_linux_map_mutex); + return NULL; +} + +void *gsl_linux_map_read(void *dst, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace) +{ + struct gsl_linux_map * map; + struct list_head *p; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each(p, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + if(map->gpu_addr <= gpuoffset && + (map->gpu_addr + map->size) > gpuoffset){ + void *src = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr); + mutex_unlock(&gsl_linux_map_mutex); + if (touserspace) + { + return (void *)copy_to_user(dst, map->kernel_virtual_addr + gpuoffset - map->gpu_addr, sizebytes); + } + else + { + return memcpy(dst, src, sizebytes); + } + } + } + + mutex_unlock(&gsl_linux_map_mutex); + return NULL; +} + +void *gsl_linux_map_write(void *src, unsigned int gpuoffset, unsigned int sizebytes, unsigned int fromuserspace) +{ + struct gsl_linux_map * map; + struct list_head *p; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each(p, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + if(map->gpu_addr <= gpuoffset && + (map->gpu_addr + map->size) > gpuoffset){ + void *dst = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr); + mutex_unlock(&gsl_linux_map_mutex); + if (fromuserspace) + { + return (void *)copy_from_user(map->kernel_virtual_addr + gpuoffset - map->gpu_addr, src, sizebytes); + } + else + { + return memcpy(dst, src, sizebytes); + } + } + } + + mutex_unlock(&gsl_linux_map_mutex); + return NULL; +} + +void *gsl_linux_map_set(unsigned int gpuoffset, unsigned int value, unsigned int sizebytes) +{ + struct gsl_linux_map * map; + struct list_head *p; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each(p, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + if(map->gpu_addr <= gpuoffset && + (map->gpu_addr + map->size) > gpuoffset){ + void *ptr = map->kernel_virtual_addr + (gpuoffset - map->gpu_addr); + mutex_unlock(&gsl_linux_map_mutex); + return memset(ptr, value, sizebytes); + } + } + + mutex_unlock(&gsl_linux_map_mutex); + return NULL; +} + +int gsl_linux_map_destroy() +{ + struct gsl_linux_map * map; + struct list_head *p, *tmp; + + mutex_lock(&gsl_linux_map_mutex); + + list_for_each_safe(p, tmp, &gsl_linux_map_list){ + map = list_entry(p, struct gsl_linux_map, list); + vfree(map->kernel_virtual_addr); + list_del(&map->list); + kfree(map); + } + + INIT_LIST_HEAD(&gsl_linux_map_list); + + mutex_unlock(&gsl_linux_map_mutex); + return 0; +} diff --git a/drivers/mxc/amd-gpu/gsl_log.c b/drivers/mxc/amd-gpu/gsl_log.c new file mode 100644 index 00000000000..268012a16d4 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_log.c @@ -0,0 +1,557 @@ +/* Copyright (c) 2002,2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#ifdef GSL_LOG + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include + +#include "gsl.h" + +#define REG_OUTPUT( X ) case X: b += sprintf( b, "%s", #X ); break; +#define INTRID_OUTPUT( X ) case X: b += sprintf( b, "%s", #X ); break; + +typedef struct log_output +{ + unsigned int flags; + struct log_output* next; +} log_output_t; + +static log_output_t* outputs = NULL; + +static struct mutex log_mutex; +static char buffer[1024]; +static char buffer2[1024]; +static int log_initialized = 0; + +//---------------------------------------------------------------------------- + +int kgsl_log_start( unsigned int log_flags ) +{ + log_output_t* output; + + if( log_initialized ) return GSL_SUCCESS; + + mutex_init(&log_mutex); + log_initialized = 1; + + output = kmalloc( sizeof( log_output_t ), GFP_KERNEL ); + output->flags = log_flags; + + // Add to the list + if( outputs == NULL ) + { + // First node in the list. + outputs = output; + output->next = NULL; + } + else + { + // Add to the start of the list + output->next = outputs; + outputs = output; + } + + return GSL_SUCCESS; +} + +//---------------------------------------------------------------------------- + +int kgsl_log_finish() +{ + if( !log_initialized ) return GSL_SUCCESS; + + // Go throught output list and free every node + while( outputs != NULL ) + { + log_output_t* temp = outputs->next; + + kfree( outputs ); + outputs = temp; + } + + log_initialized = 0; + + return GSL_SUCCESS; +} + +//---------------------------------------------------------------------------- + +int kgsl_log_write( unsigned int log_flags, char* format, ... ) +{ + char *c = format; + char *b = buffer; + char *p1, *p2; + log_output_t* output; + va_list arguments; + + if( !log_initialized ) return GSL_SUCCESS; + + // Acquire mutex lock as we are using shared buffer for the string parsing + mutex_lock(&log_mutex); + + // Add separator + *(b++) = '|'; *(b++) = ' '; + + va_start( arguments, format ); + + while( 1 ) + { + // Find the first occurence of % + p1 = strchr( c, '%' ); + if( !p1 ) + { + // No more % characters -> copy rest of the string + strcpy( b, c ); + + break; + } + + // Find the second occurence of % and handle the string until that point + p2 = strchr( p1+1, '%' ); + + // If not found, just use the end of the buffer + if( !p2 ) p2 = strchr( p1+1, '\0' ); + + // Break the string to this point + memcpy( buffer2, c, p2-c ); + *(buffer2+(unsigned int)(p2-c)) = '\0'; + + switch( *(p1+1) ) + { + // gsl_memdesc_t + case 'M': + { + gsl_memdesc_t *val = va_arg( arguments, gsl_memdesc_t *); + // Handle string before %M + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %M + b += sprintf( b, "[hostptr=0x%08x,gpuaddr=0x%08x,size=%u,flags=%x]", val->hostptr, val->gpuaddr, val->size, (unsigned int) val->priv ); + // Handle string after %M + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + // GSL_SUCCESS/GSL_FAILURE + case 'B': + { + int val = va_arg( arguments, int ); + char *s; + // Handle string before %B + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %B + switch (val) { + case GSL_SUCCESS: + s = "GSL_SUCCESS"; + break; + case GSL_FAILURE: + default: + s = "GSL_FAILURE"; + break; + } + b += sprintf( b, "%s", s ); + // Handle string after %B + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + // gsl_deviceid_t + case 'D': + { + gsl_deviceid_t val = va_arg( arguments, gsl_deviceid_t ); + // Handle string before %D + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %D + switch( val ) + { + case GSL_DEVICE_ANY: + b += sprintf( b, "%s", "GSL_DEVICE_ANY" ); + break; + case GSL_DEVICE_YAMATO: + b += sprintf( b, "%s", "GSL_DEVICE_YAMATO" ); + break; + case GSL_DEVICE_G12: + b += sprintf( b, "%s", "GSL_DEVICE_G12" ); + break; + default: + b += sprintf( b, "%s", "UNKNOWN DEVICE" ); + break; + } + // Handle string after %D + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + // gsl_intrid_t + case 'I': + { + unsigned int val = va_arg( arguments, unsigned int ); + // Handle string before %I + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %I + switch( val ) + { + INTRID_OUTPUT( GSL_INTR_YDX_MH_AXI_READ_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_MH_AXI_WRITE_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_MH_MMU_PAGE_FAULT ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_SW_INT ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_T0_PACKET_IN_IB ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_OPCODE_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_RESERVED_BIT_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_IB_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_IB2_INT ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_IB1_INT ); + INTRID_OUTPUT( GSL_INTR_YDX_CP_RING_BUFFER ); + INTRID_OUTPUT( GSL_INTR_YDX_RBBM_READ_ERROR ); + INTRID_OUTPUT( GSL_INTR_YDX_RBBM_DISPLAY_UPDATE ); + INTRID_OUTPUT( GSL_INTR_YDX_RBBM_GUI_IDLE ); + INTRID_OUTPUT( GSL_INTR_YDX_SQ_PS_WATCHDOG ); + INTRID_OUTPUT( GSL_INTR_YDX_SQ_VS_WATCHDOG ); + INTRID_OUTPUT( GSL_INTR_G12_MH ); + INTRID_OUTPUT( GSL_INTR_G12_G2D ); + INTRID_OUTPUT( GSL_INTR_G12_FIFO ); +#ifndef _Z180 + INTRID_OUTPUT( GSL_INTR_G12_FBC ); +#endif // _Z180 + INTRID_OUTPUT( GSL_INTR_G12_MH_AXI_READ_ERROR ); + INTRID_OUTPUT( GSL_INTR_G12_MH_AXI_WRITE_ERROR ); + INTRID_OUTPUT( GSL_INTR_G12_MH_MMU_PAGE_FAULT ); + INTRID_OUTPUT( GSL_INTR_COUNT ); + INTRID_OUTPUT( GSL_INTR_FOOBAR ); + + default: + b += sprintf( b, "%s", "UNKNOWN INTERRUPT ID" ); + break; + } + // Handle string after %I + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + // Register offset + case 'R': + { + unsigned int val = va_arg( arguments, unsigned int ); + + // Handle string before %R + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %R + switch( val ) + { + REG_OUTPUT( mmPA_CL_VPORT_XSCALE ); REG_OUTPUT( mmPA_CL_VPORT_XOFFSET ); REG_OUTPUT( mmPA_CL_VPORT_YSCALE ); + REG_OUTPUT( mmPA_CL_VPORT_YOFFSET ); REG_OUTPUT( mmPA_CL_VPORT_ZSCALE ); REG_OUTPUT( mmPA_CL_VPORT_ZOFFSET ); + REG_OUTPUT( mmPA_CL_VTE_CNTL ); REG_OUTPUT( mmPA_CL_CLIP_CNTL ); REG_OUTPUT( mmPA_CL_GB_VERT_CLIP_ADJ ); + REG_OUTPUT( mmPA_CL_GB_VERT_DISC_ADJ ); REG_OUTPUT( mmPA_CL_GB_HORZ_CLIP_ADJ ); REG_OUTPUT( mmPA_CL_GB_HORZ_DISC_ADJ ); + REG_OUTPUT( mmPA_CL_ENHANCE ); REG_OUTPUT( mmPA_SC_ENHANCE ); REG_OUTPUT( mmPA_SU_VTX_CNTL ); + REG_OUTPUT( mmPA_SU_POINT_SIZE ); REG_OUTPUT( mmPA_SU_POINT_MINMAX ); REG_OUTPUT( mmPA_SU_LINE_CNTL ); + REG_OUTPUT( mmPA_SU_FACE_DATA ); REG_OUTPUT( mmPA_SU_SC_MODE_CNTL ); REG_OUTPUT( mmPA_SU_POLY_OFFSET_FRONT_SCALE ); + REG_OUTPUT( mmPA_SU_POLY_OFFSET_FRONT_OFFSET ); REG_OUTPUT( mmPA_SU_POLY_OFFSET_BACK_SCALE ); REG_OUTPUT( mmPA_SU_POLY_OFFSET_BACK_OFFSET ); + REG_OUTPUT( mmPA_SU_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmPA_SU_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmPA_SU_PERFCOUNTER2_SELECT ); + REG_OUTPUT( mmPA_SU_PERFCOUNTER3_SELECT ); REG_OUTPUT( mmPA_SU_PERFCOUNTER0_LOW ); REG_OUTPUT( mmPA_SU_PERFCOUNTER0_HI ); + REG_OUTPUT( mmPA_SU_PERFCOUNTER1_LOW ); REG_OUTPUT( mmPA_SU_PERFCOUNTER1_HI ); REG_OUTPUT( mmPA_SU_PERFCOUNTER2_LOW ); + REG_OUTPUT( mmPA_SU_PERFCOUNTER2_HI ); REG_OUTPUT( mmPA_SU_PERFCOUNTER3_LOW ); REG_OUTPUT( mmPA_SU_PERFCOUNTER3_HI ); + REG_OUTPUT( mmPA_SC_WINDOW_OFFSET ); REG_OUTPUT( mmPA_SC_AA_CONFIG ); REG_OUTPUT( mmPA_SC_AA_MASK ); + REG_OUTPUT( mmPA_SC_LINE_STIPPLE ); REG_OUTPUT( mmPA_SC_LINE_CNTL ); REG_OUTPUT( mmPA_SC_WINDOW_SCISSOR_TL ); + REG_OUTPUT( mmPA_SC_WINDOW_SCISSOR_BR ); REG_OUTPUT( mmPA_SC_SCREEN_SCISSOR_TL ); REG_OUTPUT( mmPA_SC_SCREEN_SCISSOR_BR ); + REG_OUTPUT( mmPA_SC_VIZ_QUERY ); REG_OUTPUT( mmPA_SC_VIZ_QUERY_STATUS ); REG_OUTPUT( mmPA_SC_LINE_STIPPLE_STATE ); + REG_OUTPUT( mmPA_SC_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmPA_SC_PERFCOUNTER0_LOW ); REG_OUTPUT( mmPA_SC_PERFCOUNTER0_HI ); + REG_OUTPUT( mmPA_CL_CNTL_STATUS ); REG_OUTPUT( mmPA_SU_CNTL_STATUS ); REG_OUTPUT( mmPA_SC_CNTL_STATUS ); + REG_OUTPUT( mmPA_SU_DEBUG_CNTL ); REG_OUTPUT( mmPA_SU_DEBUG_DATA ); REG_OUTPUT( mmPA_SC_DEBUG_CNTL ); + REG_OUTPUT( mmPA_SC_DEBUG_DATA ); REG_OUTPUT( mmGFX_COPY_STATE ); REG_OUTPUT( mmVGT_DRAW_INITIATOR ); + REG_OUTPUT( mmVGT_EVENT_INITIATOR ); REG_OUTPUT( mmVGT_DMA_BASE ); REG_OUTPUT( mmVGT_DMA_SIZE ); + REG_OUTPUT( mmVGT_BIN_BASE ); REG_OUTPUT( mmVGT_BIN_SIZE ); REG_OUTPUT( mmVGT_CURRENT_BIN_ID_MIN ); + REG_OUTPUT( mmVGT_CURRENT_BIN_ID_MAX ); REG_OUTPUT( mmVGT_IMMED_DATA ); REG_OUTPUT( mmVGT_MAX_VTX_INDX ); + REG_OUTPUT( mmVGT_MIN_VTX_INDX ); REG_OUTPUT( mmVGT_INDX_OFFSET ); REG_OUTPUT( mmVGT_VERTEX_REUSE_BLOCK_CNTL ); + REG_OUTPUT( mmVGT_OUT_DEALLOC_CNTL ); REG_OUTPUT( mmVGT_MULTI_PRIM_IB_RESET_INDX ); REG_OUTPUT( mmVGT_ENHANCE ); + REG_OUTPUT( mmVGT_VTX_VECT_EJECT_REG ); REG_OUTPUT( mmVGT_LAST_COPY_STATE ); REG_OUTPUT( mmVGT_DEBUG_CNTL ); + REG_OUTPUT( mmVGT_DEBUG_DATA ); REG_OUTPUT( mmVGT_CNTL_STATUS ); REG_OUTPUT( mmVGT_CRC_SQ_DATA ); + REG_OUTPUT( mmVGT_CRC_SQ_CTRL ); REG_OUTPUT( mmVGT_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmVGT_PERFCOUNTER1_SELECT ); + REG_OUTPUT( mmVGT_PERFCOUNTER2_SELECT ); REG_OUTPUT( mmVGT_PERFCOUNTER3_SELECT ); REG_OUTPUT( mmVGT_PERFCOUNTER0_LOW ); + REG_OUTPUT( mmVGT_PERFCOUNTER1_LOW ); REG_OUTPUT( mmVGT_PERFCOUNTER2_LOW ); REG_OUTPUT( mmVGT_PERFCOUNTER3_LOW ); + REG_OUTPUT( mmVGT_PERFCOUNTER0_HI ); REG_OUTPUT( mmVGT_PERFCOUNTER1_HI ); REG_OUTPUT( mmVGT_PERFCOUNTER2_HI ); + REG_OUTPUT( mmVGT_PERFCOUNTER3_HI ); REG_OUTPUT( mmTC_CNTL_STATUS ); REG_OUTPUT( mmTCR_CHICKEN ); + REG_OUTPUT( mmTCF_CHICKEN ); REG_OUTPUT( mmTCM_CHICKEN ); REG_OUTPUT( mmTCR_PERFCOUNTER0_SELECT ); + REG_OUTPUT( mmTCR_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmTCR_PERFCOUNTER0_HI ); REG_OUTPUT( mmTCR_PERFCOUNTER1_HI ); + REG_OUTPUT( mmTCR_PERFCOUNTER0_LOW ); REG_OUTPUT( mmTCR_PERFCOUNTER1_LOW ); REG_OUTPUT( mmTP_TC_CLKGATE_CNTL ); + REG_OUTPUT( mmTPC_CNTL_STATUS ); REG_OUTPUT( mmTPC_DEBUG0 ); REG_OUTPUT( mmTPC_DEBUG1 ); + REG_OUTPUT( mmTPC_CHICKEN ); REG_OUTPUT( mmTP0_CNTL_STATUS ); REG_OUTPUT( mmTP0_DEBUG ); + REG_OUTPUT( mmTP0_CHICKEN ); REG_OUTPUT( mmTP0_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmTP0_PERFCOUNTER0_HI ); + REG_OUTPUT( mmTP0_PERFCOUNTER0_LOW ); REG_OUTPUT( mmTP0_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmTP0_PERFCOUNTER1_HI ); + REG_OUTPUT( mmTP0_PERFCOUNTER1_LOW ); REG_OUTPUT( mmTCM_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmTCM_PERFCOUNTER1_SELECT ); + REG_OUTPUT( mmTCM_PERFCOUNTER0_HI ); REG_OUTPUT( mmTCM_PERFCOUNTER1_HI ); REG_OUTPUT( mmTCM_PERFCOUNTER0_LOW ); + REG_OUTPUT( mmTCM_PERFCOUNTER1_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER1_SELECT ); + REG_OUTPUT( mmTCF_PERFCOUNTER2_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER3_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER4_SELECT ); + REG_OUTPUT( mmTCF_PERFCOUNTER5_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER6_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER7_SELECT ); + REG_OUTPUT( mmTCF_PERFCOUNTER8_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER9_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER10_SELECT ); + REG_OUTPUT( mmTCF_PERFCOUNTER11_SELECT ); REG_OUTPUT( mmTCF_PERFCOUNTER0_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER1_HI ); + REG_OUTPUT( mmTCF_PERFCOUNTER2_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER3_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER4_HI ); + REG_OUTPUT( mmTCF_PERFCOUNTER5_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER6_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER7_HI ); + REG_OUTPUT( mmTCF_PERFCOUNTER8_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER9_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER10_HI ); + REG_OUTPUT( mmTCF_PERFCOUNTER11_HI ); REG_OUTPUT( mmTCF_PERFCOUNTER0_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER1_LOW ); + REG_OUTPUT( mmTCF_PERFCOUNTER2_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER3_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER4_LOW ); + REG_OUTPUT( mmTCF_PERFCOUNTER5_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER6_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER7_LOW ); + REG_OUTPUT( mmTCF_PERFCOUNTER8_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER9_LOW ); REG_OUTPUT( mmTCF_PERFCOUNTER10_LOW ); + REG_OUTPUT( mmTCF_PERFCOUNTER11_LOW ); REG_OUTPUT( mmTCF_DEBUG ); REG_OUTPUT( mmTCA_FIFO_DEBUG ); + REG_OUTPUT( mmTCA_PROBE_DEBUG ); REG_OUTPUT( mmTCA_TPC_DEBUG ); REG_OUTPUT( mmTCB_CORE_DEBUG ); + REG_OUTPUT( mmTCB_TAG0_DEBUG ); REG_OUTPUT( mmTCB_TAG1_DEBUG ); REG_OUTPUT( mmTCB_TAG2_DEBUG ); + REG_OUTPUT( mmTCB_TAG3_DEBUG ); REG_OUTPUT( mmTCB_FETCH_GEN_SECTOR_WALKER0_DEBUG ); REG_OUTPUT( mmTCB_FETCH_GEN_WALKER_DEBUG ); + REG_OUTPUT( mmTCB_FETCH_GEN_PIPE0_DEBUG ); REG_OUTPUT( mmTCD_INPUT0_DEBUG ); REG_OUTPUT( mmTCD_DEGAMMA_DEBUG ); + REG_OUTPUT( mmTCD_DXTMUX_SCTARB_DEBUG ); REG_OUTPUT( mmTCD_DXTC_ARB_DEBUG ); REG_OUTPUT( mmTCD_STALLS_DEBUG ); + REG_OUTPUT( mmTCO_STALLS_DEBUG ); REG_OUTPUT( mmTCO_QUAD0_DEBUG0 ); REG_OUTPUT( mmTCO_QUAD0_DEBUG1 ); + REG_OUTPUT( mmSQ_GPR_MANAGEMENT ); REG_OUTPUT( mmSQ_FLOW_CONTROL ); REG_OUTPUT( mmSQ_INST_STORE_MANAGMENT ); + REG_OUTPUT( mmSQ_RESOURCE_MANAGMENT ); REG_OUTPUT( mmSQ_EO_RT ); REG_OUTPUT( mmSQ_DEBUG_MISC ); + REG_OUTPUT( mmSQ_ACTIVITY_METER_CNTL ); REG_OUTPUT( mmSQ_ACTIVITY_METER_STATUS ); REG_OUTPUT( mmSQ_INPUT_ARB_PRIORITY ); + REG_OUTPUT( mmSQ_THREAD_ARB_PRIORITY ); REG_OUTPUT( mmSQ_VS_WATCHDOG_TIMER ); REG_OUTPUT( mmSQ_PS_WATCHDOG_TIMER ); + REG_OUTPUT( mmSQ_INT_CNTL ); REG_OUTPUT( mmSQ_INT_STATUS ); REG_OUTPUT( mmSQ_INT_ACK ); + REG_OUTPUT( mmSQ_DEBUG_INPUT_FSM ); REG_OUTPUT( mmSQ_DEBUG_CONST_MGR_FSM ); REG_OUTPUT( mmSQ_DEBUG_TP_FSM ); + REG_OUTPUT( mmSQ_DEBUG_FSM_ALU_0 ); REG_OUTPUT( mmSQ_DEBUG_FSM_ALU_1 ); REG_OUTPUT( mmSQ_DEBUG_EXP_ALLOC ); + REG_OUTPUT( mmSQ_DEBUG_PTR_BUFF ); REG_OUTPUT( mmSQ_DEBUG_GPR_VTX ); REG_OUTPUT( mmSQ_DEBUG_GPR_PIX ); + REG_OUTPUT( mmSQ_DEBUG_TB_STATUS_SEL ); REG_OUTPUT( mmSQ_DEBUG_VTX_TB_0 ); REG_OUTPUT( mmSQ_DEBUG_VTX_TB_1 ); + REG_OUTPUT( mmSQ_DEBUG_VTX_TB_STATUS_REG ); REG_OUTPUT( mmSQ_DEBUG_VTX_TB_STATE_MEM ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_0 ); + REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_0 ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_1 ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_2 ); + REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATUS_REG_3 ); REG_OUTPUT( mmSQ_DEBUG_PIX_TB_STATE_MEM ); REG_OUTPUT( mmSQ_PERFCOUNTER0_SELECT ); + REG_OUTPUT( mmSQ_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmSQ_PERFCOUNTER2_SELECT ); REG_OUTPUT( mmSQ_PERFCOUNTER3_SELECT ); + REG_OUTPUT( mmSQ_PERFCOUNTER0_LOW ); REG_OUTPUT( mmSQ_PERFCOUNTER0_HI ); REG_OUTPUT( mmSQ_PERFCOUNTER1_LOW ); + REG_OUTPUT( mmSQ_PERFCOUNTER1_HI ); REG_OUTPUT( mmSQ_PERFCOUNTER2_LOW ); REG_OUTPUT( mmSQ_PERFCOUNTER2_HI ); + REG_OUTPUT( mmSQ_PERFCOUNTER3_LOW ); REG_OUTPUT( mmSQ_PERFCOUNTER3_HI ); REG_OUTPUT( mmSX_PERFCOUNTER0_SELECT ); + REG_OUTPUT( mmSX_PERFCOUNTER0_LOW ); REG_OUTPUT( mmSX_PERFCOUNTER0_HI ); REG_OUTPUT( mmSQ_INSTRUCTION_ALU_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_ALU_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_ALU_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_EXEC_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_CF_EXEC_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_EXEC_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_LOOP_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_CF_LOOP_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_LOOP_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_JMP_CALL_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_CF_JMP_CALL_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_JMP_CALL_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_ALLOC_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_CF_ALLOC_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_CF_ALLOC_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_TFETCH_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_TFETCH_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_TFETCH_2 ); REG_OUTPUT( mmSQ_INSTRUCTION_VFETCH_0 ); + REG_OUTPUT( mmSQ_INSTRUCTION_VFETCH_1 ); REG_OUTPUT( mmSQ_INSTRUCTION_VFETCH_2 ); REG_OUTPUT( mmSQ_CONSTANT_0 ); + REG_OUTPUT( mmSQ_CONSTANT_1 ); REG_OUTPUT( mmSQ_CONSTANT_2 ); REG_OUTPUT( mmSQ_CONSTANT_3 ); + REG_OUTPUT( mmSQ_FETCH_0 ); REG_OUTPUT( mmSQ_FETCH_1 ); REG_OUTPUT( mmSQ_FETCH_2 ); + REG_OUTPUT( mmSQ_FETCH_3 ); REG_OUTPUT( mmSQ_FETCH_4 ); REG_OUTPUT( mmSQ_FETCH_5 ); + REG_OUTPUT( mmSQ_CONSTANT_VFETCH_0 ); REG_OUTPUT( mmSQ_CONSTANT_VFETCH_1 ); REG_OUTPUT( mmSQ_CONSTANT_T2 ); + REG_OUTPUT( mmSQ_CONSTANT_T3 ); REG_OUTPUT( mmSQ_CF_BOOLEANS ); REG_OUTPUT( mmSQ_CF_LOOP ); + REG_OUTPUT( mmSQ_CONSTANT_RT_0 ); REG_OUTPUT( mmSQ_CONSTANT_RT_1 ); REG_OUTPUT( mmSQ_CONSTANT_RT_2 ); + REG_OUTPUT( mmSQ_CONSTANT_RT_3 ); REG_OUTPUT( mmSQ_FETCH_RT_0 ); REG_OUTPUT( mmSQ_FETCH_RT_1 ); + REG_OUTPUT( mmSQ_FETCH_RT_2 ); REG_OUTPUT( mmSQ_FETCH_RT_3 ); REG_OUTPUT( mmSQ_FETCH_RT_4 ); + REG_OUTPUT( mmSQ_FETCH_RT_5 ); REG_OUTPUT( mmSQ_CF_RT_BOOLEANS ); REG_OUTPUT( mmSQ_CF_RT_LOOP ); + REG_OUTPUT( mmSQ_VS_PROGRAM ); REG_OUTPUT( mmSQ_PS_PROGRAM ); REG_OUTPUT( mmSQ_CF_PROGRAM_SIZE ); + REG_OUTPUT( mmSQ_INTERPOLATOR_CNTL ); REG_OUTPUT( mmSQ_PROGRAM_CNTL ); REG_OUTPUT( mmSQ_WRAPPING_0 ); + REG_OUTPUT( mmSQ_WRAPPING_1 ); REG_OUTPUT( mmSQ_VS_CONST ); REG_OUTPUT( mmSQ_PS_CONST ); + REG_OUTPUT( mmSQ_CONTEXT_MISC ); REG_OUTPUT( mmSQ_CF_RD_BASE ); REG_OUTPUT( mmSQ_DEBUG_MISC_0 ); + REG_OUTPUT( mmSQ_DEBUG_MISC_1 ); REG_OUTPUT( mmMH_ARBITER_CONFIG ); REG_OUTPUT( mmMH_CLNT_AXI_ID_REUSE ); + REG_OUTPUT( mmMH_INTERRUPT_MASK ); REG_OUTPUT( mmMH_INTERRUPT_STATUS ); REG_OUTPUT( mmMH_INTERRUPT_CLEAR ); + REG_OUTPUT( mmMH_AXI_ERROR ); REG_OUTPUT( mmMH_PERFCOUNTER0_SELECT ); REG_OUTPUT( mmMH_PERFCOUNTER1_SELECT ); + REG_OUTPUT( mmMH_PERFCOUNTER0_CONFIG ); REG_OUTPUT( mmMH_PERFCOUNTER1_CONFIG ); REG_OUTPUT( mmMH_PERFCOUNTER0_LOW ); + REG_OUTPUT( mmMH_PERFCOUNTER1_LOW ); REG_OUTPUT( mmMH_PERFCOUNTER0_HI ); REG_OUTPUT( mmMH_PERFCOUNTER1_HI ); + REG_OUTPUT( mmMH_DEBUG_CTRL ); REG_OUTPUT( mmMH_DEBUG_DATA ); REG_OUTPUT( mmMH_AXI_HALT_CONTROL ); + REG_OUTPUT( mmMH_MMU_CONFIG ); REG_OUTPUT( mmMH_MMU_VA_RANGE ); REG_OUTPUT( mmMH_MMU_PT_BASE ); + REG_OUTPUT( mmMH_MMU_PAGE_FAULT ); REG_OUTPUT( mmMH_MMU_TRAN_ERROR ); REG_OUTPUT( mmMH_MMU_INVALIDATE ); + REG_OUTPUT( mmMH_MMU_MPU_BASE ); REG_OUTPUT( mmMH_MMU_MPU_END ); REG_OUTPUT( mmWAIT_UNTIL ); + REG_OUTPUT( mmRBBM_ISYNC_CNTL ); REG_OUTPUT( mmRBBM_STATUS ); REG_OUTPUT( mmRBBM_DSPLY ); + REG_OUTPUT( mmRBBM_RENDER_LATEST ); REG_OUTPUT( mmRBBM_RTL_RELEASE ); REG_OUTPUT( mmRBBM_PATCH_RELEASE ); + REG_OUTPUT( mmRBBM_AUXILIARY_CONFIG ); REG_OUTPUT( mmRBBM_PERIPHID0 ); REG_OUTPUT( mmRBBM_PERIPHID1 ); + REG_OUTPUT( mmRBBM_PERIPHID2 ); REG_OUTPUT( mmRBBM_PERIPHID3 ); REG_OUTPUT( mmRBBM_CNTL ); + REG_OUTPUT( mmRBBM_SKEW_CNTL ); REG_OUTPUT( mmRBBM_SOFT_RESET ); REG_OUTPUT( mmRBBM_PM_OVERRIDE1 ); + REG_OUTPUT( mmRBBM_PM_OVERRIDE2 ); REG_OUTPUT( mmGC_SYS_IDLE ); REG_OUTPUT( mmNQWAIT_UNTIL ); + REG_OUTPUT( mmRBBM_DEBUG_OUT ); REG_OUTPUT( mmRBBM_DEBUG_CNTL ); REG_OUTPUT( mmRBBM_DEBUG ); + REG_OUTPUT( mmRBBM_READ_ERROR ); REG_OUTPUT( mmRBBM_WAIT_IDLE_CLOCKS ); REG_OUTPUT( mmRBBM_INT_CNTL ); + REG_OUTPUT( mmRBBM_INT_STATUS ); REG_OUTPUT( mmRBBM_INT_ACK ); REG_OUTPUT( mmMASTER_INT_SIGNAL ); + REG_OUTPUT( mmRBBM_PERFCOUNTER1_SELECT ); REG_OUTPUT( mmRBBM_PERFCOUNTER1_LO ); REG_OUTPUT( mmRBBM_PERFCOUNTER1_HI ); + REG_OUTPUT( mmCP_RB_BASE ); REG_OUTPUT( mmCP_RB_CNTL ); REG_OUTPUT( mmCP_RB_RPTR_ADDR ); + REG_OUTPUT( mmCP_RB_RPTR ); REG_OUTPUT( mmCP_RB_RPTR_WR ); REG_OUTPUT( mmCP_RB_WPTR ); + REG_OUTPUT( mmCP_RB_WPTR_DELAY ); REG_OUTPUT( mmCP_RB_WPTR_BASE ); REG_OUTPUT( mmCP_IB1_BASE ); + REG_OUTPUT( mmCP_IB1_BUFSZ ); REG_OUTPUT( mmCP_IB2_BASE ); REG_OUTPUT( mmCP_IB2_BUFSZ ); + REG_OUTPUT( mmCP_ST_BASE ); REG_OUTPUT( mmCP_ST_BUFSZ ); REG_OUTPUT( mmCP_QUEUE_THRESHOLDS ); + REG_OUTPUT( mmCP_MEQ_THRESHOLDS ); REG_OUTPUT( mmCP_CSQ_AVAIL ); REG_OUTPUT( mmCP_STQ_AVAIL ); + REG_OUTPUT( mmCP_MEQ_AVAIL ); REG_OUTPUT( mmCP_CSQ_RB_STAT ); REG_OUTPUT( mmCP_CSQ_IB1_STAT ); + REG_OUTPUT( mmCP_CSQ_IB2_STAT ); REG_OUTPUT( mmCP_NON_PREFETCH_CNTRS ); REG_OUTPUT( mmCP_STQ_ST_STAT ); + REG_OUTPUT( mmCP_MEQ_STAT ); REG_OUTPUT( mmCP_MIU_TAG_STAT ); REG_OUTPUT( mmCP_CMD_INDEX ); + REG_OUTPUT( mmCP_CMD_DATA ); REG_OUTPUT( mmCP_ME_CNTL ); REG_OUTPUT( mmCP_ME_STATUS ); + REG_OUTPUT( mmCP_ME_RAM_WADDR ); REG_OUTPUT( mmCP_ME_RAM_RADDR ); REG_OUTPUT( mmCP_ME_RAM_DATA ); + REG_OUTPUT( mmCP_ME_RDADDR ); REG_OUTPUT( mmCP_DEBUG ); REG_OUTPUT( mmSCRATCH_REG0 ); + REG_OUTPUT( mmSCRATCH_REG1 ); REG_OUTPUT( mmSCRATCH_REG2 ); REG_OUTPUT( mmSCRATCH_REG3 ); + REG_OUTPUT( mmSCRATCH_REG4 ); REG_OUTPUT( mmSCRATCH_REG5 ); REG_OUTPUT( mmSCRATCH_REG6 ); + REG_OUTPUT( mmSCRATCH_REG7 ); + REG_OUTPUT( mmSCRATCH_UMSK ); REG_OUTPUT( mmSCRATCH_ADDR ); REG_OUTPUT( mmCP_ME_VS_EVENT_SRC ); + REG_OUTPUT( mmCP_ME_VS_EVENT_ADDR ); REG_OUTPUT( mmCP_ME_VS_EVENT_DATA ); REG_OUTPUT( mmCP_ME_VS_EVENT_ADDR_SWM ); + REG_OUTPUT( mmCP_ME_VS_EVENT_DATA_SWM ); REG_OUTPUT( mmCP_ME_PS_EVENT_SRC ); REG_OUTPUT( mmCP_ME_PS_EVENT_ADDR ); + REG_OUTPUT( mmCP_ME_PS_EVENT_DATA ); REG_OUTPUT( mmCP_ME_PS_EVENT_ADDR_SWM ); REG_OUTPUT( mmCP_ME_PS_EVENT_DATA_SWM ); + REG_OUTPUT( mmCP_ME_CF_EVENT_SRC ); REG_OUTPUT( mmCP_ME_CF_EVENT_ADDR ); REG_OUTPUT( mmCP_ME_CF_EVENT_DATA ); + REG_OUTPUT( mmCP_ME_NRT_ADDR ); REG_OUTPUT( mmCP_ME_NRT_DATA ); REG_OUTPUT( mmCP_ME_VS_FETCH_DONE_SRC ); + REG_OUTPUT( mmCP_ME_VS_FETCH_DONE_ADDR ); REG_OUTPUT( mmCP_ME_VS_FETCH_DONE_DATA ); REG_OUTPUT( mmCP_INT_CNTL ); + REG_OUTPUT( mmCP_INT_STATUS ); REG_OUTPUT( mmCP_INT_ACK ); REG_OUTPUT( mmCP_PFP_UCODE_ADDR ); + REG_OUTPUT( mmCP_PFP_UCODE_DATA ); REG_OUTPUT( mmCP_PERFMON_CNTL ); REG_OUTPUT( mmCP_PERFCOUNTER_SELECT ); + REG_OUTPUT( mmCP_PERFCOUNTER_LO ); REG_OUTPUT( mmCP_PERFCOUNTER_HI ); REG_OUTPUT( mmCP_BIN_MASK_LO ); + REG_OUTPUT( mmCP_BIN_MASK_HI ); REG_OUTPUT( mmCP_BIN_SELECT_LO ); REG_OUTPUT( mmCP_BIN_SELECT_HI ); + REG_OUTPUT( mmCP_NV_FLAGS_0 ); REG_OUTPUT( mmCP_NV_FLAGS_1 ); REG_OUTPUT( mmCP_NV_FLAGS_2 ); + REG_OUTPUT( mmCP_NV_FLAGS_3 ); REG_OUTPUT( mmCP_STATE_DEBUG_INDEX ); REG_OUTPUT( mmCP_STATE_DEBUG_DATA ); + REG_OUTPUT( mmCP_PROG_COUNTER ); REG_OUTPUT( mmCP_STAT ); REG_OUTPUT( mmBIOS_0_SCRATCH ); + REG_OUTPUT( mmBIOS_1_SCRATCH ); REG_OUTPUT( mmBIOS_2_SCRATCH ); REG_OUTPUT( mmBIOS_3_SCRATCH ); + REG_OUTPUT( mmBIOS_4_SCRATCH ); REG_OUTPUT( mmBIOS_5_SCRATCH ); REG_OUTPUT( mmBIOS_6_SCRATCH ); + REG_OUTPUT( mmBIOS_7_SCRATCH ); REG_OUTPUT( mmBIOS_8_SCRATCH ); REG_OUTPUT( mmBIOS_9_SCRATCH ); + REG_OUTPUT( mmBIOS_10_SCRATCH ); REG_OUTPUT( mmBIOS_11_SCRATCH ); REG_OUTPUT( mmBIOS_12_SCRATCH ); + REG_OUTPUT( mmBIOS_13_SCRATCH ); REG_OUTPUT( mmBIOS_14_SCRATCH ); REG_OUTPUT( mmBIOS_15_SCRATCH ); + REG_OUTPUT( mmCOHER_SIZE_PM4 ); REG_OUTPUT( mmCOHER_BASE_PM4 ); REG_OUTPUT( mmCOHER_STATUS_PM4 ); + REG_OUTPUT( mmCOHER_SIZE_HOST ); REG_OUTPUT( mmCOHER_BASE_HOST ); REG_OUTPUT( mmCOHER_STATUS_HOST ); + REG_OUTPUT( mmCOHER_DEST_BASE_0 ); REG_OUTPUT( mmCOHER_DEST_BASE_1 ); REG_OUTPUT( mmCOHER_DEST_BASE_2 ); + REG_OUTPUT( mmCOHER_DEST_BASE_3 ); REG_OUTPUT( mmCOHER_DEST_BASE_4 ); REG_OUTPUT( mmCOHER_DEST_BASE_5 ); + REG_OUTPUT( mmCOHER_DEST_BASE_6 ); REG_OUTPUT( mmCOHER_DEST_BASE_7 ); REG_OUTPUT( mmRB_SURFACE_INFO ); + REG_OUTPUT( mmRB_COLOR_INFO ); REG_OUTPUT( mmRB_DEPTH_INFO ); REG_OUTPUT( mmRB_STENCILREFMASK ); + REG_OUTPUT( mmRB_ALPHA_REF ); REG_OUTPUT( mmRB_COLOR_MASK ); REG_OUTPUT( mmRB_BLEND_RED ); + REG_OUTPUT( mmRB_BLEND_GREEN ); REG_OUTPUT( mmRB_BLEND_BLUE ); REG_OUTPUT( mmRB_BLEND_ALPHA ); + REG_OUTPUT( mmRB_FOG_COLOR ); REG_OUTPUT( mmRB_STENCILREFMASK_BF ); REG_OUTPUT( mmRB_DEPTHCONTROL ); + REG_OUTPUT( mmRB_BLENDCONTROL ); REG_OUTPUT( mmRB_COLORCONTROL ); REG_OUTPUT( mmRB_MODECONTROL ); + REG_OUTPUT( mmRB_COLOR_DEST_MASK ); REG_OUTPUT( mmRB_COPY_CONTROL ); REG_OUTPUT( mmRB_COPY_DEST_BASE ); + REG_OUTPUT( mmRB_COPY_DEST_PITCH ); REG_OUTPUT( mmRB_COPY_DEST_INFO ); REG_OUTPUT( mmRB_COPY_DEST_PIXEL_OFFSET ); + REG_OUTPUT( mmRB_DEPTH_CLEAR ); REG_OUTPUT( mmRB_SAMPLE_COUNT_CTL ); REG_OUTPUT( mmRB_SAMPLE_COUNT_ADDR ); + REG_OUTPUT( mmRB_BC_CONTROL ); REG_OUTPUT( mmRB_EDRAM_INFO ); REG_OUTPUT( mmRB_CRC_RD_PORT ); + REG_OUTPUT( mmRB_CRC_CONTROL ); REG_OUTPUT( mmRB_CRC_MASK ); REG_OUTPUT( mmRB_PERFCOUNTER0_SELECT ); + REG_OUTPUT( mmRB_PERFCOUNTER0_LOW ); REG_OUTPUT( mmRB_PERFCOUNTER0_HI ); REG_OUTPUT( mmRB_TOTAL_SAMPLES ); + REG_OUTPUT( mmRB_ZPASS_SAMPLES ); REG_OUTPUT( mmRB_ZFAIL_SAMPLES ); REG_OUTPUT( mmRB_SFAIL_SAMPLES ); + REG_OUTPUT( mmRB_DEBUG_0 ); REG_OUTPUT( mmRB_DEBUG_1 ); REG_OUTPUT( mmRB_DEBUG_2 ); + REG_OUTPUT( mmRB_DEBUG_3 ); REG_OUTPUT( mmRB_DEBUG_4 ); REG_OUTPUT( mmRB_FLAG_CONTROL ); + REG_OUTPUT( mmRB_BC_SPARES ); REG_OUTPUT( mmBC_DUMMY_CRAYRB_ENUMS ); REG_OUTPUT( mmBC_DUMMY_CRAYRB_MOREENUMS ); + + default: + b += sprintf( b, "%s", "UNKNOWN REGISTER OFFSET" ); + break; + } + // Handle string after %R + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + // gsl_scatterlist_t + case 'S': + { + gsl_scatterlist_t *val = va_arg(arguments, gsl_scatterlist_t *); + // handle string before %S + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %S + b += sprintf( b, "[contiguous=%d,num=%u]",val->contiguous,val->num); + // Handle string after %S + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + // gsl_property_type_t + case 'T': + { + char *prop; + gsl_property_type_t val = va_arg(arguments, gsl_property_type_t); + // handle string before %T + memcpy( b, c, p1-c ); + b += (unsigned int)p1-(unsigned int)c; + // Replace %T + switch (val) { + case GSL_PROP_DEVICE_INFO: + prop = "GSL_PROP_DEVICE_INFO"; + break; + case GSL_PROP_DEVICE_SHADOW: + prop = "GSL_PROP_DEVICE_SHADOW"; + break; + case GSL_PROP_DEVICE_POWER: + prop = "GSL_PROP_DEVICE_POWER"; + break; + case GSL_PROP_SHMEM: + prop = "GSL_PROP_SHMEM"; + break; + case GSL_PROP_SHMEM_APERTURES: + prop = "GSL_PROP_SHMEM_APERTURES"; + break; + case GSL_PROP_DEVICE_DMI: + prop = "GSL_PROP_DEVICE_DMI"; + break; + default: + prop = "????????"; + break; + } + b += sprintf( b, "%s",prop); + // Handle string after %T + memcpy( b, p1+2, p2-(p1+2) ); + b += (unsigned int)p2-(unsigned int)(p1+2); + *b = '\0'; + } + break; + + default: + { + int val = va_arg( arguments, int ); + // Standard format. Use vsprintf. + b += sprintf( b, buffer2, val ); + } + break; + } + + c = p2; + } + + // Add this string to all outputs + output = outputs; + + while( output != NULL ) + { + // Filter according to the flags + if( ( output->flags & log_flags ) == log_flags ) + { + /* + // Write timestamp if enabled + if( output->flags & KGSL_LOG_TIMESTAMP ) + printf( "[Timestamp: %d] ", kos_timestamp() ); + // Write process id if enabled + if( output->flags & KGSL_LOG_PROCESS_ID ) + printf( "[Process ID: %d] ", kos_process_getid() ); + // Write thread id if enabled + if( output->flags & KGSL_LOG_THREAD_ID ) + printf( "[Thread ID: %d] ", kos_thread_getid() ); + */ + // Write the message + printk( buffer ); + } + + output = output->next; + } + + va_end( arguments ); + + mutex_unlock(&log_mutex ); + + return GSL_SUCCESS; +} + +//---------------------------------------------------------------------------- +#endif diff --git a/drivers/mxc/amd-gpu/gsl_memmgr.c b/drivers/mxc/amd-gpu/gsl_memmgr.c new file mode 100644 index 00000000000..ba1e3361c02 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_memmgr.c @@ -0,0 +1,970 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include + +#include "gsl.h" +#include "gsl_hal.h" + +/* + * defines + * + * these are a bit overzealous: a whole byte for a bit flag? + */ +#define GSL_MEMARENAPRIV_SIGNATURE_MASK 0x0000FFFF +#define GSL_MEMARENAPRIV_APERTUREID_MASK 0xF0000000 +#define GSL_MEMARENAPRIV_MMUVIRTUALIZED_MASK 0x0F000000 +#define GSL_MEMARENAPRIV_CONPHYS_MASK 0x00F00000 //neko + +#define GSL_MEMARENAPRIV_SIGNATURE_SHIFT 0 +#define GSL_MEMARENAPRIV_MMUVIRTUALIZED_SHIFT 24 +#define GSL_MEMARENAPRIV_APERTUREID_SHIFT 28 +#define GSL_MEMARENAPRIV_CONPHYS_SHIFT 20 //neko + +#define GSL_MEMARENA_INSTANCE_SIGNATURE 0x0000CAFE + +#ifdef GSL_STATS_MEM +#define GSL_MEMARENA_STATS(x) x +#else +#define GSL_MEMARENA_STATS(x) +#endif // GSL_STATS_MEM + + +// macros +#define GSL_MEMARENA_SET_SIGNATURE (memarena->priv |= ((GSL_MEMARENA_INSTANCE_SIGNATURE << GSL_MEMARENAPRIV_SIGNATURE_SHIFT) & GSL_MEMARENAPRIV_SIGNATURE_MASK)) +#define GSL_MEMARENA_SET_MMU_VIRTUALIZED (memarena->priv |= ((mmu_virtualized << GSL_MEMARENAPRIV_MMUVIRTUALIZED_SHIFT) & GSL_MEMARENAPRIV_MMUVIRTUALIZED_MASK)) +#define GSL_MEMARENA_SET_ID (memarena->priv |= ((aperture_id << GSL_MEMARENAPRIV_APERTUREID_SHIFT) & GSL_MEMARENAPRIV_APERTUREID_MASK)) +#define GSL_MEMARENA_SET_CONPHYS (memarena->priv |= ((conphys << GSL_MEMARENAPRIV_CONPHYS_SHIFT) & GSL_MEMARENAPRIV_CONPHYS_MASK))//neko + +#define GSL_MEMARENA_GET_SIGNATURE ((memarena->priv & GSL_MEMARENAPRIV_SIGNATURE_MASK) >> GSL_MEMARENAPRIV_SIGNATURE_SHIFT) +#define GSL_MEMARENA_IS_MMU_VIRTUALIZED ((memarena->priv & GSL_MEMARENAPRIV_MMUVIRTUALIZED_MASK) >> GSL_MEMARENAPRIV_MMUVIRTUALIZED_SHIFT) +#define GSL_MEMARENA_GET_ID ((memarena->priv & GSL_MEMARENAPRIV_APERTUREID_MASK) >> GSL_MEMARENAPRIV_APERTUREID_SHIFT) +#define GSL_MEMARENA_IS_CONPHYS ((memarena->priv & GSL_MEMARENAPRIV_CONPHYS_MASK) >> GSL_MEMARENAPRIV_CONPHYS_SHIFT)//neko + +// validate +#define GSL_MEMARENA_VALIDATE(memarena) \ + DEBUG_ASSERT(memarena); \ + if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) \ + { \ + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, \ + "ERROR: Memarena validation failed.\n" ); \ + return (GSL_FAILURE); \ + } + +// " neko + +// block alignment shift count +static __inline unsigned int +gsl_memarena_alignmentshift(gsl_flags_t flags) +{ + int alignshift = ((flags & GSL_MEMFLAGS_ALIGN_MASK) >> GSL_MEMFLAGS_ALIGN_SHIFT); + if (alignshift == 0) + alignshift = 5; // 32 bytes is the minimum alignment boundary + return (alignshift); +} + +// address alignment +static __inline unsigned int +gsl_memarena_alignaddr(unsigned int address, int shift) +{ + // + // the value of the returned address is guaranteed to be an even multiple + // of the block alignment shift specified. + // + unsigned int alignedbaseaddr = ((address) >> shift) << shift; + if (alignedbaseaddr < address) + { + alignedbaseaddr += (1 << shift); + } + return (alignedbaseaddr); +} + + +// memory management API +#ifdef GSL_MEMARENA_NODE_POOL_ENABLED +static __inline memblk_t* +kgsl_memarena_getmemblknode_pool(gsl_memarena_t *memarena) +{ + gsl_nodepool_t *nodepool = memarena->nodepool; + memblk_t *memblk = NULL; + int allocnewpool = 1; + int i; + + if (nodepool) + { + // walk through list of existing pools + for ( ; ; ) + { + // if there is a pool with a free memblk node + if (nodepool->priv != (1 << GSL_MEMARENA_NODE_POOL_MAX)-1) + { + // get index of the first free memblk node + for (i = 0; i < GSL_MEMARENA_NODE_POOL_MAX; i++) + { + if (((nodepool->priv >> i) & 0x1) == 0) + { + break; + } + } + + // mark memblk node as used + nodepool->priv |= 1 << i; + + memblk = &nodepool->memblk[i]; + memblk->nodepoolindex = i; + memblk->blkaddr = 0; + memblk->blksize = 0; + + allocnewpool = 0; + + break; + } + else + { + nodepool = nodepool->next; + + if (nodepool == memarena->nodepool) + { + // no free memblk node found + break; + } + } + } + } + + // if no existing pool has a free memblk node + if (allocnewpool) + { + // alloc new pool of memblk nodes + nodepool = ((gsl_nodepool_t *)kmalloc(sizeof(gsl_nodepool_t), GFP_KERNEL)); + if (nodepool) + { + memset(nodepool, 0, sizeof(gsl_nodepool_t)); + + if (memarena->nodepool) + { + nodepool->next = memarena->nodepool->next; + nodepool->prev = memarena->nodepool; + memarena->nodepool->next->prev = nodepool; + memarena->nodepool->next = nodepool; + } + else + { + nodepool->next = nodepool; + nodepool->prev = nodepool; + } + + // reposition pool head + memarena->nodepool = nodepool; + + // mark memblk node as used + nodepool->priv |= 0x1; + + memblk = &nodepool->memblk[0]; + memblk->nodepoolindex = 0; + } + } + + DEBUG_ASSERT(memblk); + + return (memblk); +} +#endif + +static __inline memblk_t* +kgsl_memarena_getmemblknode(gsl_memarena_t *memarena) +{ +#ifdef GSL_MEMARENA_NODE_POOL_ENABLED + return( kgsl_memarena_getmemblknode_pool(gsl_memarena_t *memarena) ); +#else + // unreferenced formal parameter + (void) memarena; + + return ((memblk_t *)kmalloc(sizeof(memblk_t), GFP_KERNEL)); +#endif // GSL_MEMARENA_NODE_POOL_ENABLED +} + +//---------------------------------------------------------------------------- + +#ifdef GSL_MEMARENA_NODE_POOL_ENABLED +static __inline void +kgsl_memarena_releasememblknode_pool(gsl_memarena_t *memarena, memblk_t *memblk) +{ + gsl_nodepool_t *nodepool = memarena->nodepool; + + DEBUG_ASSERT(memblk); + DEBUG_ASSERT(nodepool); + + // locate pool to which this memblk node belongs + while (((unsigned int) memblk) < ((unsigned int) nodepool) || + ((unsigned int) memblk) > ((unsigned int) nodepool) + sizeof(gsl_nodepool_t)) + { + nodepool = nodepool->prev; + + DEBUG_ASSERT(nodepool != memarena->nodepool); + } + + // mark memblk node as unused + nodepool->priv &= ~(1 << memblk->nodepoolindex); + + // free pool when all its memblk nodes are unused + if (nodepool->priv == 0) + { + if (nodepool != nodepool->prev) + { + // reposition pool head + if (nodepool == memarena->nodepool) + { + memarena->nodepool = nodepool->prev; + } + + nodepool->prev->next = nodepool->next; + nodepool->next->prev = nodepool->prev; + } + else + { + memarena->nodepool = NULL; + } + + kfree((void *)nodepool); + } + else + { + // leave pool head in last pool a memblk node was released + memarena->nodepool = nodepool; + } +} +#endif + +static __inline void +kgsl_memarena_releasememblknode(gsl_memarena_t *memarena, memblk_t *memblk) +{ +#ifdef GSL_MEMARENA_NODE_POOL_ENABLED + kgsl_memarena_releasememblknode(memarena, memblk) +#else + // unreferenced formal parameter + (void) memarena; + + kfree((void *)memblk); +#endif // GSL_MEMARENA_NODE_POOL_ENABLED +} + +//---------------------------------------------------------------------------- + +gsl_memarena_t* +kgsl_memarena_create(int aperture_id, int mmu_virtualized, unsigned int hostbaseaddr, gpuaddr_t gpubaseaddr, int sizebytes) +{ + static int count = 0; + gsl_memarena_t *memarena; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> gsl_memarena_t* kgsl_memarena_create(int aperture_id=%d, gpuaddr_t gpubaseaddr=0x%08x, int sizebytes=%d)\n", aperture_id, gpubaseaddr, sizebytes ); + + memarena = (gsl_memarena_t *)kmalloc(sizeof(gsl_memarena_t), GFP_KERNEL); + + if (!memarena) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, + "ERROR: Memarena allocation failed.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "<-- kgsl_memarena_create. Return value: 0x%08x\n", NULL ); + return (NULL); + } + + memset(memarena, 0, sizeof(gsl_memarena_t)); + + GSL_MEMARENA_SET_SIGNATURE; + GSL_MEMARENA_SET_MMU_VIRTUALIZED; + GSL_MEMARENA_SET_ID; + + mutex_init(&memarena->lock); + + // set up the memory arena + memarena->hostbaseaddr = hostbaseaddr; + memarena->gpubaseaddr = gpubaseaddr; + memarena->sizebytes = sizebytes; + + // allocate a memory block in free list which represents all memory in arena + memarena->freelist.head = kgsl_memarena_getmemblknode(memarena); + memarena->freelist.head->blkaddr = 0; + memarena->freelist.head->blksize = memarena->sizebytes; + memarena->freelist.head->next = memarena->freelist.head; + memarena->freelist.head->prev = memarena->freelist.head; + memarena->freelist.allocrover = memarena->freelist.head; + memarena->freelist.freerover = memarena->freelist.head; + + count++; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_create. Return value: 0x%08x\n", memarena ); + + return (memarena); +} + +//---------------------------------------------------------------------------- + +int +kgsl_memarena_destroy(gsl_memarena_t *memarena) +{ + int status = GSL_SUCCESS; + int err; + memblk_t *p, *next; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_memarena_destroy(gsl_memarena_t *memarena=0x%08x)\n", memarena ); + + GSL_MEMARENA_VALIDATE(memarena); + + err = mutex_lock_interruptible(&memarena->lock); + if (err == -EINTR) { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, + "WARNING: memarena mutex lock was interrupted\n"); + } + +#ifdef _DEBUG + // memory leak check + if (memarena->freelist.head->blksize != memarena->sizebytes) + { + if (GSL_MEMARENA_GET_ID == GSL_APERTURE_EMEM) + { + // external memory leak detected + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, + "ERROR: External memory leak detected.\n" ); + return (GSL_FAILURE); + } + } +#endif // _DEBUG + + p = memarena->freelist.head; + do + { + next = p->next; + kgsl_memarena_releasememblknode(memarena, p); + p = next; + } while (p != memarena->freelist.head); + + mutex_unlock(&memarena->lock); + + kfree((void *)memarena); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_destroy. Return value: %B\n", GSL_SUCCESS ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_memarena_isvirtualized(gsl_memarena_t *memarena) +{ + // mmu virtualization enabled + return (GSL_MEMARENA_IS_MMU_VIRTUALIZED); +} + +//---------------------------------------------------------------------------- + +int +kgsl_memarena_checkconsistency(gsl_memarena_t *memarena) +{ + memblk_t *p; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_memarena_checkconsistency(gsl_memarena_t *memarena=0x%08x)\n", memarena ); + + // go through list of free blocks and make sure there are no detectable errors + + p = memarena->freelist.head; + do + { + if (p->next->blkaddr != memarena->freelist.head->blkaddr) + { + if (p->prev->next->blkaddr != p->blkaddr || + p->next->prev->blkaddr != p->blkaddr || + p->blkaddr + p->blksize >= p->next->blkaddr) + { + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkconsistency. Return value: %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + } + p = p->next; + + } while (p != memarena->freelist.head); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkconsistency. Return value: %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_memarena_querystats(gsl_memarena_t *memarena, gsl_memarena_stats_t *stats) +{ +#ifdef GSL_STATS_MEM + DEBUG_ASSERT(stats); + GSL_MEMARENA_VALIDATE(memarena); + + memcpy(stats, &memarena->stats, sizeof(gsl_memarena_stats_t)); + + return (GSL_SUCCESS); +#else + // unreferenced formal parameters + (void) memarena; + (void) stats; + + return (GSL_FAILURE_NOTSUPPORTED); +#endif // GSL_STATS_MEM +} + +//---------------------------------------------------------------------------- + +int +kgsl_memarena_checkfreeblock(gsl_memarena_t *memarena, int bytesneeded) +{ + memblk_t *p; + int err; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_memarena_checkfreeblock(gsl_memarena_t *memarena=0x%08x, int bytesneeded=%d)\n", memarena, bytesneeded ); + + GSL_MEMARENA_VALIDATE(memarena); + + if (bytesneeded < 1) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Illegal number of bytes needed.\n" ); + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkfreeblock. Return value: %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + err = mutex_lock_interruptible(&memarena->lock); + if (err == -EINTR) { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, + "WARNING: memarena mutex lock was interrupted\n"); + } + + p = memarena->freelist.head; + do + { + if (p->blksize >= (unsigned int)bytesneeded) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkfreeblock. Return value: %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); + } + + p = p->next; + } while (p != memarena->freelist.head); + + mutex_unlock(&memarena->lock); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_checkfreeblock. Return value: %B\n", GSL_FAILURE ); + + return (GSL_FAILURE); +} + +//---------------------------------------------------------------------------- + +int +kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_memdesc_t *memdesc) +{ + int result = GSL_FAILURE_OUTOFMEM; + memblk_t *ptrfree, *ptrlast, *p; + unsigned int blksize; + unsigned int baseaddr, alignedbaseaddr, alignfragment; + int freeblk, alignmentshift; + int err; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_memarena_alloc(gsl_memarena_t *memarena=0x%08x, gsl_flags_t flags=%x, int size=%d, gsl_memdesc_t *memdesc=%M)\n", memarena, flags, size, memdesc ); + + GSL_MEMARENA_VALIDATE(memarena); + + if (size <= 0) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid size for memory allocation.\n" ); + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_alloc. Return value: %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // + // go through the list of free blocks. check to find block which can satisfy the alloc request + // + // if no block can satisfy the alloc request this implies that the memory is too fragmented + // and the requestor needs to free up other memory blocks and re-request the allocation + // + // if we do find a block that can satisfy the alloc request then reduce the size of free block + // by blksize and return the address after allocating the memory. if the free block size becomes + // 0 then remove this node from the free list + // + // there would be no node on the free list if all available memory were to be allocated. + // handling an empty list would require executing error checking code in the main branch which + // is not desired. instead, the free list will have at least one node at all times. This node + // could have a block size of zero + // + // we use a next fit allocation mechanism that uses a roving pointer on a circular free block list. + // the pointer is advanced along the chain when searching for a fit. Thus each allocation begins + // looking where the previous one finished. + // + + // when allocating from external memory aperture, round up size of requested block to multiple of page size if needed + if (GSL_MEMARENA_GET_ID == GSL_APERTURE_EMEM) + { + if ((flags & GSL_MEMFLAGS_FORCEPAGESIZE) || GSL_MEMARENA_IS_MMU_VIRTUALIZED) + { + if (size & (GSL_PAGESIZE-1)) + { + size = ((size >> GSL_PAGESIZE_SHIFT) + 1) << GSL_PAGESIZE_SHIFT; + } + } + } + + // determine shift count for alignment requested + alignmentshift = gsl_memarena_alignmentshift(flags); + + // adjust size of requested block to include alignment + blksize = (unsigned int)((size + ((1 << alignmentshift) - 1)) >> alignmentshift) << alignmentshift; + + err = mutex_lock_interruptible(&memarena->lock); + if (err == -EINTR) { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, + "WARNING: memarena mutex lock was interrupted\n"); + } + + // check consistency, debug only + KGSL_DEBUG(GSL_DBGFLAGS_MEMMGR, kgsl_memarena_checkconsistency(memarena)); + + ptrfree = memarena->freelist.allocrover; + ptrlast = memarena->freelist.head->prev; + freeblk = 0; + + do + { + // align base address + baseaddr = ptrfree->blkaddr + memarena->gpubaseaddr; + alignedbaseaddr = gsl_memarena_alignaddr(baseaddr, alignmentshift); + + alignfragment = alignedbaseaddr - baseaddr; + + if (ptrfree->blksize >= blksize + alignfragment) + { + result = GSL_SUCCESS; + freeblk = 1; + + memdesc->gpuaddr = alignedbaseaddr; + memdesc->hostptr = kgsl_memarena_gethostptr(memarena, memdesc->gpuaddr); + memdesc->size = blksize; + + if (alignfragment > 0) + { + // insert new node to handle newly created (small) fragment + p = kgsl_memarena_getmemblknode(memarena); + p->blkaddr = ptrfree->blkaddr; + p->blksize = alignfragment; + + p->next = ptrfree; + p->prev = ptrfree->prev; + ptrfree->prev->next = p; + ptrfree->prev = p; + + if (ptrfree == memarena->freelist.head) + { + memarena->freelist.head = p; + } + } + + ptrfree->blkaddr += alignfragment + blksize; + ptrfree->blksize -= alignfragment + blksize; + + memarena->freelist.allocrover = ptrfree; + + if (ptrfree->blksize == 0 && ptrfree != ptrlast) + { + ptrfree->prev->next = ptrfree->next; + ptrfree->next->prev = ptrfree->prev; + if (ptrfree == memarena->freelist.head) + { + memarena->freelist.head = ptrfree->next; + } + if (ptrfree == memarena->freelist.allocrover) + { + memarena->freelist.allocrover = ptrfree->next; + } + if (ptrfree == memarena->freelist.freerover) + { + memarena->freelist.freerover = ptrfree->prev; + } + p = ptrfree; + ptrfree = ptrfree->prev; + kgsl_memarena_releasememblknode(memarena, p); + } + } + + ptrfree = ptrfree->next; + + } while (!freeblk && ptrfree != memarena->freelist.allocrover); + + + mutex_unlock(&memarena->lock); + + if (result == GSL_SUCCESS) + { + GSL_MEMARENA_STATS( + { + int i = 0; + while (memdesc->size >> (GSL_PAGESIZE_SHIFT + i)) + { + i++; + } + i = i > (GSL_MEMARENA_PAGE_DIST_MAX-1) ? (GSL_MEMARENA_PAGE_DIST_MAX-1) : i; + memarena->stats.allocs_pagedistribution[i]++; + }); + + GSL_MEMARENA_STATS(memarena->stats.allocs_success++); + } + else + { + GSL_MEMARENA_STATS(memarena->stats.allocs_fail++); + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_alloc. Return value: %B\n", result ); + + return (result); +} + +//---------------------------------------------------------------------------- + +void +kgsl_memarena_free(gsl_memarena_t *memarena, gsl_memdesc_t *memdesc) +{ + // + // request to free a malloc'ed block from the memory arena + // add this block to the free list + // adding a block to the free list requires the following: + // going through the list of free blocks to decide where to add this free block (based on address) + // coalesce free blocks + // + memblk_t *ptrfree, *ptrend, *p; + int mallocfreeblk, clockwise; + unsigned int addrtofree; + int err; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> void kgsl_memarena_free(gsl_memarena_t *memarena=0x%08x, gsl_memdesc_t *memdesc=%M)\n", memarena, memdesc ); + + DEBUG_ASSERT(memarena); + if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_free.\n" ); + return; + } + + // check size of malloc'ed block + if (memdesc->size <= 0) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Illegal size for the memdesc.\n" ); + DEBUG_ASSERT(0); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_free.\n" ); + return; + } + + // check address range + DEBUG_ASSERT( memarena->gpubaseaddr <= memdesc->gpuaddr); + DEBUG_ASSERT((memarena->gpubaseaddr + memarena->sizebytes) >= memdesc->gpuaddr + memdesc->size); + + err = mutex_lock_interruptible(&memarena->lock); + if (err == -EINTR) { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, + "WARNING: memarena mutex lock was interrupted\n"); + } + + // check consistency of memory map, debug only + KGSL_DEBUG(GSL_DBGFLAGS_MEMMGR, kgsl_memarena_checkconsistency(memarena)); + + addrtofree = memdesc->gpuaddr - memarena->gpubaseaddr; + mallocfreeblk = 1; + + if (addrtofree < memarena->freelist.head->blkaddr) + { + // add node to head of free list + + if (addrtofree + memdesc->size == memarena->freelist.head->blkaddr) + { + memarena->freelist.head->blkaddr = addrtofree; + memarena->freelist.head->blksize += memdesc->size; + + mallocfreeblk = 0; + } + + ptrfree = memarena->freelist.head->prev; + } + else if (addrtofree >= memarena->freelist.head->prev->blkaddr) + { + // add node to tail of free list + + ptrfree = memarena->freelist.head->prev; + + if (ptrfree->blkaddr + ptrfree->blksize == addrtofree) + { + ptrfree->blksize += memdesc->size; + + mallocfreeblk = 0; + } + } + else + { + // determine range of free list nodes to traverse and orientation in which to traverse them + // keep this code segment unrolled for performance reasons! + if (addrtofree > memarena->freelist.freerover->blkaddr) + { + if (addrtofree - memarena->freelist.freerover->blkaddr < memarena->freelist.head->prev->blkaddr - addrtofree) + { + ptrfree = memarena->freelist.freerover; // rover + ptrend = memarena->freelist.head->prev; // tail + clockwise = 1; + } + else + { + ptrfree = memarena->freelist.head->prev->prev; // tail + ptrend = memarena->freelist.freerover->prev; // rover + clockwise = 0; + } + } + else + { + if (addrtofree - memarena->freelist.head->blkaddr < memarena->freelist.freerover->blkaddr - addrtofree) + { + ptrfree = memarena->freelist.head; // head + ptrend = memarena->freelist.freerover; // rover + clockwise = 1; + } + else + { + ptrfree = memarena->freelist.freerover->prev; // rover + ptrend = memarena->freelist.head->prev; // head + clockwise = 0; + } + } + + // traverse the nodes + do + { + if ((addrtofree >= ptrfree->blkaddr + ptrfree->blksize) && + (addrtofree + memdesc->size <= ptrfree->next->blkaddr)) + { + if (addrtofree == ptrfree->blkaddr + ptrfree->blksize) + { + memblk_t *next; + + ptrfree->blksize += memdesc->size; + next = ptrfree->next; + + if (ptrfree->blkaddr + ptrfree->blksize == next->blkaddr) + { + ptrfree->blksize += next->blksize; + ptrfree->next = next->next; + next->next->prev = ptrfree; + + if (next == memarena->freelist.allocrover) + { + memarena->freelist.allocrover = ptrfree; + } + + kgsl_memarena_releasememblknode(memarena, next); + } + + mallocfreeblk = 0; + } + else if (addrtofree + memdesc->size == ptrfree->next->blkaddr) + { + ptrfree->next->blkaddr = addrtofree; + ptrfree->next->blksize += memdesc->size; + + mallocfreeblk = 0; + } + + break; + } + + if (clockwise) + { + ptrfree = ptrfree->next; + } + else + { + ptrfree = ptrfree->prev; + } + + } while (ptrfree != ptrend); + } + + // this free block could not be coalesced, so create a new free block + // and add it to the free list in the memory arena + if (mallocfreeblk) + { + p = kgsl_memarena_getmemblknode(memarena); + p->blkaddr = addrtofree; + p->blksize = memdesc->size; + + p->next = ptrfree->next; + p->prev = ptrfree; + ptrfree->next->prev = p; + ptrfree->next = p; + + if (p->blkaddr < memarena->freelist.head->blkaddr) + { + memarena->freelist.head = p; + } + + memarena->freelist.freerover = p; + } + else + { + memarena->freelist.freerover = ptrfree; + } + + mutex_unlock(&memarena->lock); + + GSL_MEMARENA_STATS( + { + int i = 0; + while (memdesc->size >> (GSL_PAGESIZE_SHIFT + i)) + { + i++; + } + i = i > (GSL_MEMARENA_PAGE_DIST_MAX-1) ? (GSL_MEMARENA_PAGE_DIST_MAX-1) : i; + memarena->stats.frees_pagedistribution[i]++; + }); + + GSL_MEMARENA_STATS(memarena->stats.frees++); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_free.\n" ); +} + +//---------------------------------------------------------------------------- + +void *kgsl_memarena_gethostptr(gsl_memarena_t *memarena, gpuaddr_t gpuaddr) +{ + // + // get the host mapped address for a hardware device address + // + + void *hostptr = NULL; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> void* kgsl_memarena_gethostptr(gsl_memarena_t *memarena=0x%08x, gpuaddr_t gpuaddr=0x%08x)\n", memarena, gpuaddr ); + + DEBUG_ASSERT(memarena); + if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_gethostptr. Return value: 0x%08x\n", NULL ); + return (NULL); + } + + // check address range + DEBUG_ASSERT(gpuaddr >= memarena->gpubaseaddr); + DEBUG_ASSERT(gpuaddr < memarena->gpubaseaddr + memarena->sizebytes); + + hostptr = (void *)((gpuaddr - memarena->gpubaseaddr) + memarena->hostbaseaddr); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_gethostptr. Return value: 0x%08x\n", hostptr ); + + return (hostptr); +} + +//---------------------------------------------------------------------------- + +gpuaddr_t kgsl_memarena_getgpuaddr(gsl_memarena_t *memarena, void *hostptr) +{ + // + // get the hardware device address for a host mapped address + // + + gpuaddr_t gpuaddr = 0; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_memarena_getgpuaddr(gsl_memarena_t *memarena=0x%08x, void *hostptr=0x%08x)\n", memarena, hostptr ); + + DEBUG_ASSERT(memarena); + if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getgpuaddr. Return value: 0x%08x\n", 0 ); + return (0); + } + + // check address range + DEBUG_ASSERT(hostptr >= (void *)memarena->hostbaseaddr); + DEBUG_ASSERT(hostptr < (void *)(memarena->hostbaseaddr + memarena->sizebytes)); + + gpuaddr = ((unsigned int)hostptr - memarena->hostbaseaddr) + memarena->gpubaseaddr; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getgpuaddr. Return value: 0x%08x\n", gpuaddr ); + + return (gpuaddr); +} + +//---------------------------------------------------------------------------- + +unsigned int +kgsl_memarena_getlargestfreeblock(gsl_memarena_t *memarena, gsl_flags_t flags) +{ + memblk_t *ptrfree; + unsigned int blocksize, largestblocksize = 0; + int alignmentshift; + int err; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> unsigned int kgsl_memarena_getlargestfreeblock(gsl_memarena_t *memarena=0x%08x, gsl_flags_t flags=%x)\n", memarena, flags ); + + DEBUG_ASSERT(memarena); + if (GSL_MEMARENA_GET_SIGNATURE != GSL_MEMARENA_INSTANCE_SIGNATURE) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getlargestfreeblock. Return value: %d\n", 0 ); + return (0); + } + + // determine shift count for alignment requested + alignmentshift = gsl_memarena_alignmentshift(flags); + + err = mutex_lock_interruptible(&memarena->lock); + if (err == -EINTR) { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, + "WARNING: memarena mutex lock was interrupted\n"); + } + + ptrfree = memarena->freelist.head; + + do + { + blocksize = ptrfree->blksize - (ptrfree->blkaddr - ((ptrfree->blkaddr >> alignmentshift) << alignmentshift)); + + if (blocksize > largestblocksize) + { + largestblocksize = blocksize; + } + + ptrfree = ptrfree->next; + + } while (ptrfree != memarena->freelist.head); + + mutex_unlock(&memarena->lock); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_memarena_getlargestfreeblock. Return value: %d\n", largestblocksize ); + + return (largestblocksize); +} diff --git a/drivers/mxc/amd-gpu/gsl_mmu.c b/drivers/mxc/amd-gpu/gsl_mmu.c new file mode 100644 index 00000000000..c5f9c7cc384 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_mmu.c @@ -0,0 +1,1054 @@ +/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" +#include "gsl_hal.h" + + +////////////////////////////////////////////////////////////////////////////// +// types +////////////////////////////////////////////////////////////////////////////// + +// --------- +// pte debug +// --------- + +typedef struct _gsl_pte_debug_t +{ + unsigned int write :1; + unsigned int read :1; + unsigned int reserved :10; + unsigned int phyaddr :20; +} gsl_pte_debug_t; + + +////////////////////////////////////////////////////////////////////////////// +// defines +////////////////////////////////////////////////////////////////////////////// +#define GSL_PT_ENTRY_SIZEBYTES 4 +#define GSL_PT_EXTRA_ENTRIES 16 + +#define GSL_PT_PAGE_WRITE 0x00000001 +#define GSL_PT_PAGE_READ 0x00000002 + +#define GSL_PT_PAGE_AP_MASK 0x00000003 +#define GSL_PT_PAGE_ADDR_MASK ~(GSL_PAGESIZE-1) + +#define GSL_MMUFLAGS_TLBFLUSH 0x80000000 + +#define GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS (sizeof(unsigned char) * 8) + + +////////////////////////////////////////////////////////////////////////////// +// constants +////////////////////////////////////////////////////////////////////////////// +const unsigned int GSL_PT_PAGE_AP[4] = {(GSL_PT_PAGE_READ | GSL_PT_PAGE_WRITE), GSL_PT_PAGE_READ, GSL_PT_PAGE_WRITE, 0}; + + +///////////////////////////////////////////////////////////////////////////// +// macros +////////////////////////////////////////////////////////////////////////////// + +#define GSL_PT_ENTRY_GET(va) ((va - pagetable->va_base) >> GSL_PAGESIZE_SHIFT) +#define GSL_PT_VIRT_GET(pte) (pagetable->va_base + (pte * GSL_PAGESIZE)) + +#define GSL_PT_MAP_APDEFAULT GSL_PT_PAGE_AP[0] + +#define GSL_PT_MAP_GET(pte) *((unsigned int *)(((unsigned int)pagetable->base.hostptr) + ((pte) * GSL_PT_ENTRY_SIZEBYTES))) +#define GSL_PT_MAP_GETADDR(pte) (GSL_PT_MAP_GET(pte) & GSL_PT_PAGE_ADDR_MASK) + +#define GSL_PT_MAP_DEBUG(pte) ((gsl_pte_debug_t*) &GSL_PT_MAP_GET(pte)) + +#define GSL_PT_MAP_SETBITS(pte, bits) (GSL_PT_MAP_GET(pte) |= (((unsigned int) bits) & GSL_PT_PAGE_AP_MASK)) +#define GSL_PT_MAP_SETADDR(pte, pageaddr) (GSL_PT_MAP_GET(pte) = (GSL_PT_MAP_GET(pte) & ~GSL_PT_PAGE_ADDR_MASK) | (((unsigned int) pageaddr) & GSL_PT_PAGE_ADDR_MASK)) + +/* reserve RV and WV bits to work around READ_PROTECTION_ERROR in some cases */ +#define GSL_PT_MAP_RESET(pte) (GSL_PT_MAP_GET(pte) &= ~GSL_PT_PAGE_ADDR_MASK) +#define GSL_PT_MAP_RESETBITS(pte, bits) (GSL_PT_MAP_GET(pte) &= ~(((unsigned int) bits) & GSL_PT_PAGE_AP_MASK)) + +#define GSL_MMU_VIRT_TO_PAGE(va) *((unsigned int *)(pagetable->base.gpuaddr + (GSL_PT_ENTRY_GET(va) * GSL_PT_ENTRY_SIZEBYTES))) +#define GSL_MMU_VIRT_TO_PHYS(va) ((GSL_MMU_VIRT_TO_PAGE(va) & GSL_PT_PAGE_ADDR_MASK) + (va & (GSL_PAGESIZE-1))) + +#define GSL_TLBFLUSH_FILTER_GET(superpte) *((unsigned char *)(((unsigned int)mmu->tlbflushfilter.base) + (superpte / GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS))) +#define GSL_TLBFLUSH_FILTER_SETDIRTY(superpte) (GSL_TLBFLUSH_FILTER_GET((superpte)) |= 1 << (superpte % GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS)) +#define GSL_TLBFLUSH_FILTER_ISDIRTY(superpte) (GSL_TLBFLUSH_FILTER_GET((superpte)) & (1 << (superpte % GSL_TLBFLUSH_FILTER_ENTRY_NUMBITS))) +#define GSL_TLBFLUSH_FILTER_RESET() memset(mmu->tlbflushfilter.base, 0, mmu->tlbflushfilter.size) + + +////////////////////////////////////////////////////////////////////////////// +// process index in pagetable object table +////////////////////////////////////////////////////////////////////////////// +static __inline int +kgsl_mmu_getprocessindex(unsigned int pid, int *pindex) +{ + int status = GSL_SUCCESS; +#ifdef GSL_MMU_PAGETABLE_PERPROCESS + if (kgsl_driver_getcallerprocessindex(pid, pindex) != GSL_SUCCESS) + { + status = GSL_FAILURE; + } +#else + (void) pid; // unreferenced formal parameter + *pindex = 0; +#endif // GSL_MMU_PAGETABLE_PERPROCESS + return (status); +} + +////////////////////////////////////////////////////////////////////////////// +// pagetable object for current caller process +////////////////////////////////////////////////////////////////////////////// +static __inline gsl_pagetable_t* +kgsl_mmu_getpagetableobject(gsl_mmu_t *mmu, unsigned int pid) +{ + int pindex = 0; + if (kgsl_mmu_getprocessindex(pid, &pindex) == GSL_SUCCESS) + { + return (mmu->pagetable[pindex]); + } + else + { + return (NULL); + } +} + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +void +kgsl_mh_intrcallback(gsl_intrid_t id, void *cookie) +{ + gsl_mmu_t *mmu = (gsl_mmu_t *) cookie; + unsigned int devindex = mmu->device->id-1; // device_id is 1 based + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> void kgsl_mh_ntrcallback(gsl_intrid_t id=%I, void *cookie=0x%08x)\n", id, cookie ); + + // error condition interrupt + if (id == gsl_cfg_mh_intr[devindex].AXI_READ_ERROR || + id == gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR || + id == gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT) + { + printk(KERN_ERR "GPU: AXI Read/Write Error or MMU page fault\n"); + schedule_work(&mmu->device->irq_err_work); + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mh_intrcallback.\n" ); +} + +//---------------------------------------------------------------------------- + +#ifdef _DEBUG +static void +kgsl_mmu_debug(gsl_mmu_t *mmu, gsl_mmu_debug_t *regs) +{ + unsigned int devindex = mmu->device->id-1; // device_id is 1 based + + memset(regs, 0, sizeof(gsl_mmu_debug_t)); + + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].CONFIG, ®s->config); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].MPU_BASE, ®s->mpu_base); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].MPU_END, ®s->mpu_end); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].VA_RANGE, ®s->va_range); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].PT_BASE, ®s->pt_base); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].PAGE_FAULT, ®s->page_fault); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].TRAN_ERROR, ®s->trans_error); + mmu->device->ftbl.device_regread(mmu->device, gsl_cfg_mmu_reg[devindex].INVALIDATE, ®s->invalidate); +} +#endif + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_checkconsistency(gsl_pagetable_t *pagetable) +{ + unsigned int pte; + unsigned int data; + gsl_pte_debug_t *pte_debug; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_mmu_checkconsistency(gsl_pagetable_t *pagetable=0x%08x)\n", pagetable ); + + if (pagetable->last_superpte % GSL_PT_SUPER_PTE != 0) + { + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_checkconsistency. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // go through page table and make sure there are no detectable errors + pte = 0; + while (pte < pagetable->max_entries) + { + pte_debug = GSL_PT_MAP_DEBUG(pte); + + if (GSL_PT_MAP_GETADDR(pte) != 0) + { + // pte is in use + + // access first couple bytes of a page + data = *((unsigned int *)GSL_PT_VIRT_GET(pte)); + } + + pte++; + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_checkconsistency. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_destroypagetableobject(gsl_mmu_t *mmu, unsigned int pid) +{ + gsl_deviceid_t tmp_id; + gsl_device_t *tmp_device; + int pindex; + gsl_pagetable_t *pagetable; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> gsl_pagetable_t* kgsl_mmu_destroypagetableobject(gsl_mmu_t *mmu=0x%08x, uint pid=0x%08x)\n", mmu, pid ); + + if (kgsl_mmu_getprocessindex(pid, &pindex) != GSL_SUCCESS) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_destroypagetableobject. Return value 0x%08x\n", GSL_SUCCESS ); + return (GSL_FAILURE); + } + + pagetable = mmu->pagetable[pindex]; + + // if pagetable object exists for current "current device mmu"/"current caller process" combination + if (pagetable) + { + // no more "device mmu"/"caller process" combinations attached to current pagetable object + if (pagetable->refcnt == 0) + { +#ifdef _DEBUG + // memory leak check + if (pagetable->last_superpte != 0 || GSL_PT_MAP_GETADDR(pagetable->last_superpte)) + { + /* many dumpx test cases forcefully exit, and thus trigger this assert. */ + /* Because it is an annoyance for HW guys, it is disabled for dumpx */ + if(!(gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX)) + { + DEBUG_ASSERT(0); + return (GSL_FAILURE); + } + } +#endif // _DEBUG + + if (pagetable->base.gpuaddr) + { + kgsl_sharedmem_free0(&pagetable->base, current->tgid); + } + + kfree(pagetable); + + // clear pagetable object reference for all "device mmu"/"current caller process" combinations + for (tmp_id = GSL_DEVICE_ANY + 1; tmp_id <= GSL_DEVICE_MAX; tmp_id++) + { + tmp_device = &gsl_driver.device[tmp_id-1]; + + if (tmp_device->mmu.flags & GSL_FLAGS_STARTED) + { + tmp_device->mmu.pagetable[pindex] = NULL; + } + } + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_destroypagetableobject. Return value 0x%08x\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +gsl_pagetable_t* +kgsl_mmu_createpagetableobject(gsl_mmu_t *mmu, unsigned int pid) +{ + // + // create pagetable object for "current device mmu"/"current caller + // process" combination. If none exists, setup a new pagetable object. + // + int status = GSL_SUCCESS; + gsl_pagetable_t *tmp_pagetable = NULL; + gsl_deviceid_t tmp_id; + gsl_device_t *tmp_device; + int pindex; + gsl_flags_t flags; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> gsl_pagetable_t* kgsl_mmu_createpagetableobject(gsl_mmu_t *mmu=0x%08x, uint pid=0x%08x)\n", mmu, pid ); + + status = kgsl_mmu_getprocessindex(pid, &pindex); + if (status != GSL_SUCCESS) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_createpagetableobject. Return value 0x%08x\n", NULL ); + return (NULL); + } + // if pagetable object does not already exists for "current device mmu"/"current caller process" combination + if (!mmu->pagetable[pindex]) + { + // then, check if pagetable object already exists for any "other device mmu"/"current caller process" combination + for (tmp_id = GSL_DEVICE_ANY + 1; tmp_id <= GSL_DEVICE_MAX; tmp_id++) + { + tmp_device = &gsl_driver.device[tmp_id-1]; + + if (tmp_device->mmu.flags & GSL_FLAGS_STARTED) + { + if (tmp_device->mmu.pagetable[pindex]) + { + tmp_pagetable = tmp_device->mmu.pagetable[pindex]; + break; + } + } + } + + // pagetable object exists + if (tmp_pagetable) + { + DEBUG_ASSERT(tmp_pagetable->va_base == mmu->va_base); + DEBUG_ASSERT(tmp_pagetable->va_range == mmu->va_range); + + // set pagetable object reference + mmu->pagetable[pindex] = tmp_pagetable; + } + // create new pagetable object + else + { + mmu->pagetable[pindex] = (void *)kmalloc(sizeof(gsl_pagetable_t), GFP_KERNEL); + if (!mmu->pagetable[pindex]) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to allocate pagetable object.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_createpagetableobject. Return value 0x%08x\n", NULL ); + return (NULL); + } + + memset(mmu->pagetable[pindex], 0, sizeof(gsl_pagetable_t)); + + mmu->pagetable[pindex]->pid = pid; + mmu->pagetable[pindex]->refcnt = 0; + mmu->pagetable[pindex]->va_base = mmu->va_base; + mmu->pagetable[pindex]->va_range = mmu->va_range; + mmu->pagetable[pindex]->last_superpte = 0; + mmu->pagetable[pindex]->max_entries = (mmu->va_range >> GSL_PAGESIZE_SHIFT) + GSL_PT_EXTRA_ENTRIES; + + // allocate page table memory + flags = (GSL_MEMFLAGS_ALIGN4K | GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_STRICTREQUEST); + status = kgsl_sharedmem_alloc0(mmu->device->id, flags, mmu->pagetable[pindex]->max_entries * GSL_PT_ENTRY_SIZEBYTES, &mmu->pagetable[pindex]->base); + + if (status == GSL_SUCCESS) + { + // reset page table entries + kgsl_sharedmem_set0(&mmu->pagetable[pindex]->base, 0, 0, mmu->pagetable[pindex]->base.size); + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MMU_TBLADDR, mmu->pagetable[pindex]->base.gpuaddr, 0, mmu->pagetable[pindex]->base.size, "kgsl_mmu_init")); + } + else + { + kgsl_mmu_destroypagetableobject(mmu, pid); + } + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_createpagetableobject. Return value 0x%08x\n", mmu->pagetable[pindex] ); + + return (mmu->pagetable[pindex]); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_setpagetable(gsl_device_t *device, unsigned int pid) +{ + // + // set device mmu to use current caller process's page table + // + int status = GSL_SUCCESS; + unsigned int devindex = device->id-1; // device_id is 1 based + gsl_mmu_t *mmu = &device->mmu; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> gsl_pagetable_t* kgsl_mmu_setpagetable(gsl_device_t *device=0x%08x)\n", device ); + + if (mmu->flags & GSL_FLAGS_STARTED) + { +#ifdef GSL_MMU_PAGETABLE_PERPROCESS + // page table not current, then setup mmu to use new specified page table + if (mmu->hwpagetable->pid != pid) + { + gsl_pagetable_t *pagetable = kgsl_mmu_getpagetableobject(mmu, pid); + if (pagetable) + { + mmu->hwpagetable = pagetable; + + // flag tlb flush + mmu->flags |= GSL_MMUFLAGS_TLBFLUSH; + + status = mmu->device->ftbl.mmu_setpagetable(mmu->device, gsl_cfg_mmu_reg[devindex].PT_BASE, pagetable->base.gpuaddr, pid); + + GSL_MMU_STATS(mmu->stats.pt.switches++); + } + else + { + status = GSL_FAILURE; + } + } +#endif // GSL_MMU_PAGETABLE_PERPROCESS + + // if needed, invalidate device specific tlb + if ((mmu->flags & GSL_MMUFLAGS_TLBFLUSH) && status == GSL_SUCCESS) + { + mmu->flags &= ~GSL_MMUFLAGS_TLBFLUSH; + + GSL_TLBFLUSH_FILTER_RESET(); + + status = mmu->device->ftbl.mmu_tlbinvalidate(mmu->device, gsl_cfg_mmu_reg[devindex].INVALIDATE, pid); + + GSL_MMU_STATS(mmu->stats.tlbflushes++); + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_setpagetable. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_init(gsl_device_t *device) +{ + // + // intialize device mmu + // + // call this with the global lock held + // + int status; + gsl_flags_t flags; + gsl_pagetable_t *pagetable; + unsigned int devindex = device->id-1; // device_id is 1 based + gsl_mmu_t *mmu = &device->mmu; +#ifdef _DEBUG + gsl_mmu_debug_t regs; +#endif // _DEBUG + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_mmu_init(gsl_device_t *device=0x%08x)\n", device ); + + if (device->ftbl.mmu_tlbinvalidate == NULL || device->ftbl.mmu_setpagetable == NULL || + !(device->flags & GSL_FLAGS_INITIALIZED)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + if (mmu->flags & GSL_FLAGS_INITIALIZED0) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_INFO, "MMU already initialized.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); + } + + // setup backward reference + mmu->device = device; + + // disable MMU when running in safe mode + if (device->flags & GSL_FLAGS_SAFEMODE) + { + mmu->config = 0x00000000; + } + + // setup MMU and sub-client behavior + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].CONFIG, mmu->config); + + // enable axi interrupts + kgsl_intr_attach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_READ_ERROR, kgsl_mh_intrcallback, (void *) mmu); + kgsl_intr_attach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR, kgsl_mh_intrcallback, (void *) mmu); + kgsl_intr_enable(&device->intr, gsl_cfg_mh_intr[devindex].AXI_READ_ERROR); + kgsl_intr_enable(&device->intr, gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR); + + mmu->refcnt = 0; + mmu->flags |= GSL_FLAGS_INITIALIZED0; + + // MMU enabled + if (mmu->config & 0x1) + { + // idle device + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + + // make sure aligned to pagesize + DEBUG_ASSERT((mmu->mpu_base & ((1 << GSL_PAGESIZE_SHIFT)-1)) == 0); + DEBUG_ASSERT(((mmu->mpu_base + mmu->mpu_range) & ((1 << GSL_PAGESIZE_SHIFT)-1)) == 0); + + // define physical memory range accessible by the core + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].MPU_BASE, mmu->mpu_base); + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].MPU_END, mmu->mpu_base + mmu->mpu_range); + + // enable page fault interrupt + kgsl_intr_attach(&device->intr, gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT, kgsl_mh_intrcallback, (void *) mmu); + kgsl_intr_enable(&device->intr, gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT); + + mmu->flags |= GSL_FLAGS_INITIALIZED; + + // sub-client MMU lookups require address translation + if ((mmu->config & ~0x1) > 0) + { + // make sure virtual address range is a multiple of 64Kb + DEBUG_ASSERT((mmu->va_range & ((1 << 16)-1)) == 0); + + // setup pagetable object + pagetable = kgsl_mmu_createpagetableobject(mmu, current->tgid); + if (!pagetable) + { + kgsl_mmu_close(device); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + mmu->hwpagetable = pagetable; + + // create tlb flush filter to track dirty superPTE's -- one bit per superPTE + mmu->tlbflushfilter.size = (mmu->va_range / (GSL_PAGESIZE * GSL_PT_SUPER_PTE * 8)) + 1; + mmu->tlbflushfilter.base = (unsigned int *)kmalloc(mmu->tlbflushfilter.size, GFP_KERNEL); + if (!mmu->tlbflushfilter.base) + { + kgsl_mmu_close(device); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + GSL_TLBFLUSH_FILTER_RESET(); + + // set page table base + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].PT_BASE, mmu->hwpagetable->base.gpuaddr); + + // define virtual address range + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].VA_RANGE, (mmu->hwpagetable->va_base | (mmu->hwpagetable->va_range >> 16))); + + // allocate memory used for completing r/w operations that cannot be mapped by the MMU + flags = (GSL_MEMFLAGS_ALIGN32 | GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_STRICTREQUEST); + status = kgsl_sharedmem_alloc0(device->id, flags, 32, &mmu->dummyspace); + if (status != GSL_SUCCESS) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to allocate dummy space memory.\n" ); + kgsl_mmu_close(device); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", status ); + return (status); + } + + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].TRAN_ERROR, mmu->dummyspace.gpuaddr); + + // call device specific tlb invalidate + device->ftbl.mmu_tlbinvalidate(device, gsl_cfg_mmu_reg[devindex].INVALIDATE, mmu->hwpagetable->pid); + + GSL_MMU_STATS(mmu->stats.tlbflushes++); + + mmu->flags |= GSL_FLAGS_STARTED; + } + } + + KGSL_DEBUG(GSL_DBGFLAGS_MMU, kgsl_mmu_debug(&device->mmu, ®s)); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_init. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_map(gsl_mmu_t *mmu, gpuaddr_t gpubaseaddr, const gsl_scatterlist_t *scatterlist, gsl_flags_t flags, unsigned int pid) +{ + // + // map physical pages into the gpu page table + // + int status = GSL_SUCCESS; + unsigned int i, phyaddr, ap; + unsigned int pte, ptefirst, ptelast, superpte; + int flushtlb; + gsl_pagetable_t *pagetable; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_mmu_map(gsl_mmu_t *mmu=0x%08x, gpuaddr_t gpubaseaddr=0x%08x, gsl_scatterlist_t *scatterlist=%S, gsl_flags_t flags=%x, uint pid=0x%08x)\n", + mmu, gpubaseaddr, scatterlist, flags, pid ); + + DEBUG_ASSERT(scatterlist); + + if (scatterlist->num <= 0) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: num pages is too small.\n" ); + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_map. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // get gpu access permissions + ap = GSL_PT_PAGE_AP[((flags & GSL_MEMFLAGS_GPUAP_MASK) >> GSL_MEMFLAGS_GPUAP_SHIFT)]; + + pagetable = kgsl_mmu_getpagetableobject(mmu, pid); + if (!pagetable) + { + return (GSL_FAILURE); + } + + // check consistency, debug only + KGSL_DEBUG(GSL_DBGFLAGS_MMU, kgsl_mmu_checkconsistency(pagetable)); + + ptefirst = GSL_PT_ENTRY_GET(gpubaseaddr); + ptelast = GSL_PT_ENTRY_GET(gpubaseaddr + (GSL_PAGESIZE * (scatterlist->num-1))); + flushtlb = 0; + + if (!GSL_PT_MAP_GETADDR(ptefirst)) + { + // tlb needs to be flushed when the first and last pte are not at superpte boundaries + if ((ptefirst & (GSL_PT_SUPER_PTE-1)) != 0 || ((ptelast+1) & (GSL_PT_SUPER_PTE-1)) != 0) + { + flushtlb = 1; + } + + // create page table entries + for (pte = ptefirst; pte <= ptelast; pte++) + { + if (scatterlist->contiguous) + { + phyaddr = scatterlist->pages[0] + ((pte-ptefirst) * GSL_PAGESIZE); + } + else + { + phyaddr = scatterlist->pages[pte-ptefirst]; + } + + GSL_PT_MAP_SETADDR(pte, phyaddr); + GSL_PT_MAP_SETBITS(pte, ap); + + // tlb needs to be flushed when a dirty superPTE gets backed + if ((pte & (GSL_PT_SUPER_PTE-1)) == 0) + { + if (GSL_TLBFLUSH_FILTER_ISDIRTY(pte / GSL_PT_SUPER_PTE)) + { + flushtlb = 1; + } + } + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_SET_MMUTBL, pte , *(unsigned int*)(((char*)pagetable->base.hostptr) + (pte * GSL_PT_ENTRY_SIZEBYTES)), 0, "kgsl_mmu_map")); + } + + if (flushtlb) + { + // every device's tlb needs to be flushed because the current page table is shared among all devices + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + if (gsl_driver.device[i].flags & GSL_FLAGS_INITIALIZED) + { + gsl_driver.device[i].mmu.flags |= GSL_MMUFLAGS_TLBFLUSH; + } + } + } + + // determine new last mapped superPTE + superpte = ptelast - (ptelast & (GSL_PT_SUPER_PTE-1)); + if (superpte > pagetable->last_superpte) + { + pagetable->last_superpte = superpte; + } + + GSL_MMU_STATS(mmu->stats.pt.maps++); + } + else + { + // this should never happen + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, "FATAL: This should never happen.\n" ); + DEBUG_ASSERT(0); + status = GSL_FAILURE; + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_map. Return value %B\n", GSL_SUCCESS ); + + return (status); +} + +//---------------------------------------------------------------------------- + +static bool is_superpte_empty(gsl_pagetable_t *pagetable, unsigned int superpte) +{ + int i; + for (i = 0; i < GSL_PT_SUPER_PTE; i++) { + if (GSL_PT_MAP_GET(superpte+i)) + return false; + } + return true; +} + +int +kgsl_mmu_unmap(gsl_mmu_t *mmu, gpuaddr_t gpubaseaddr, int range, unsigned int pid) +{ + // + // remove mappings in the specified address range from the gpu page table + // + int status = GSL_SUCCESS; + gsl_pagetable_t *pagetable; + unsigned int numpages; + unsigned int pte, ptefirst, ptelast, superpte; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_mmu_unmap(gsl_mmu_t *mmu=0x%08x, gpuaddr_t gpubaseaddr=0x%08x, int range=%d, uint pid=0x%08x)\n", + mmu, gpubaseaddr, range, pid ); + + if (range <= 0) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Range is too small.\n" ); + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_unmap. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + numpages = (range >> GSL_PAGESIZE_SHIFT); + if (range & (GSL_PAGESIZE-1)) + { + numpages++; + } + + pagetable = kgsl_mmu_getpagetableobject(mmu, pid); + if (!pagetable) + { + return (GSL_FAILURE); + } + + // check consistency, debug only + KGSL_DEBUG(GSL_DBGFLAGS_MMU, kgsl_mmu_checkconsistency(pagetable)); + + ptefirst = GSL_PT_ENTRY_GET(gpubaseaddr); + ptelast = GSL_PT_ENTRY_GET(gpubaseaddr + (GSL_PAGESIZE * (numpages-1))); + + if (GSL_PT_MAP_GETADDR(ptefirst)) + { + superpte = ptefirst - (ptefirst & (GSL_PT_SUPER_PTE-1)); + GSL_TLBFLUSH_FILTER_SETDIRTY(superpte / GSL_PT_SUPER_PTE); + + // remove page table entries + for (pte = ptefirst; pte <= ptelast; pte++) + { + GSL_PT_MAP_RESET(pte); + + superpte = pte - (pte & (GSL_PT_SUPER_PTE-1)); + if (pte == superpte) + { + GSL_TLBFLUSH_FILTER_SETDIRTY(superpte / GSL_PT_SUPER_PTE); + } + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_SET_MMUTBL, pte, *(unsigned int*)(((char*)pagetable->base.hostptr) + (pte * GSL_PT_ENTRY_SIZEBYTES)), 0, "kgsl_mmu_unmap, reset superPTE")); + } + + // determine new last mapped superPTE + superpte = ptelast - (ptelast & (GSL_PT_SUPER_PTE-1)); + if (superpte == pagetable->last_superpte && pagetable->last_superpte >= GSL_PT_SUPER_PTE) + { + do + { + if (is_superpte_empty(pagetable, superpte)) + pagetable->last_superpte -= GSL_PT_SUPER_PTE; + else + break; + } while (!GSL_PT_MAP_GETADDR(pagetable->last_superpte) && pagetable->last_superpte >= GSL_PT_SUPER_PTE); + } + + GSL_MMU_STATS(mmu->stats.pt.unmaps++); + } + else + { + // this should never happen + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_FATAL, "FATAL: This should never happen.\n" ); + DEBUG_ASSERT(0); + status = GSL_FAILURE; + } + + // invalidate tlb, debug only + KGSL_DEBUG(GSL_DBGFLAGS_MMU, mmu->device->ftbl.mmu_tlbinvalidate(mmu->device, gsl_cfg_mmu_reg[mmu->device->id-1].INVALIDATE, pagetable->pid)); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_unmap. Return value %B\n", GSL_SUCCESS ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_getmap(gsl_mmu_t *mmu, gpuaddr_t gpubaseaddr, int range, gsl_scatterlist_t *scatterlist, unsigned int pid) +{ + // + // obtain scatter list of physical pages for the given gpu address range. + // if all pages are physically contiguous they are coalesced into a single + // scatterlist entry. + // + gsl_pagetable_t *pagetable; + unsigned int numpages; + unsigned int pte, ptefirst, ptelast; + unsigned int contiguous = 1; + + numpages = (range >> GSL_PAGESIZE_SHIFT); + if (range & (GSL_PAGESIZE-1)) + { + numpages++; + } + + if (range <= 0 || scatterlist->num != numpages) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Range is too small.\n" ); + DEBUG_ASSERT(0); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_getmap. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + pagetable = kgsl_mmu_getpagetableobject(mmu, pid); + if (!pagetable) + { + return (GSL_FAILURE); + } + + ptefirst = GSL_PT_ENTRY_GET(gpubaseaddr); + ptelast = GSL_PT_ENTRY_GET(gpubaseaddr + (GSL_PAGESIZE * (numpages-1))); + + // determine whether pages are physically contiguous + if (numpages > 1) + { + for (pte = ptefirst; pte <= ptelast-1; pte++) + { + if (GSL_PT_MAP_GETADDR(pte) + GSL_PAGESIZE != GSL_PT_MAP_GETADDR(pte+1)) + { + contiguous = 0; + break; + } + } + } + + if (!contiguous) + { + // populate scatter list + for (pte = ptefirst; pte <= ptelast; pte++) + { + scatterlist->pages[pte-ptefirst] = GSL_PT_MAP_GETADDR(pte); + } + } + else + { + // coalesce physically contiguous pages into a single scatter list entry + scatterlist->pages[0] = GSL_PT_MAP_GETADDR(ptefirst); + } + + scatterlist->contiguous = contiguous; + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_close(gsl_device_t *device) +{ + // + // close device mmu + // + // call this with the global lock held + // + gsl_mmu_t *mmu = &device->mmu; + unsigned int devindex = mmu->device->id-1; // device_id is 1 based +#ifdef _DEBUG + int i; +#endif // _DEBUG + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_close(gsl_device_t *device=0x%08x)\n", device ); + + if (mmu->flags & GSL_FLAGS_INITIALIZED0) + { + if (mmu->flags & GSL_FLAGS_STARTED) + { + // terminate pagetable object + kgsl_mmu_destroypagetableobject(mmu, current->tgid); + } + + // no more processes attached to current device mmu + if (mmu->refcnt == 0) + { +#ifdef _DEBUG + // check if there are any orphaned pagetable objects lingering around + for (i = 0; i < GSL_MMU_PAGETABLE_MAX; i++) + { + if (mmu->pagetable[i]) + { + /* many dumpx test cases forcefully exit, and thus trigger this assert. */ + /* Because it is an annoyance for HW guys, it is disabled for dumpx */ + if(!(gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX)) + { + DEBUG_ASSERT(0); + return (GSL_FAILURE); + } + } + } +#endif // _DEBUG + + // disable mh interrupts + kgsl_intr_detach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_READ_ERROR); + kgsl_intr_detach(&device->intr, gsl_cfg_mh_intr[devindex].AXI_WRITE_ERROR); + kgsl_intr_detach(&device->intr, gsl_cfg_mh_intr[devindex].MMU_PAGE_FAULT); + + // disable MMU + device->ftbl.device_regwrite(device, gsl_cfg_mmu_reg[devindex].CONFIG, 0x00000000); + + if (mmu->tlbflushfilter.base) + { + kfree(mmu->tlbflushfilter.base); + } + + if (mmu->dummyspace.gpuaddr) + { + kgsl_sharedmem_free0(&mmu->dummyspace, current->tgid); + } + + mmu->flags &= ~GSL_FLAGS_STARTED; + mmu->flags &= ~GSL_FLAGS_INITIALIZED; + mmu->flags &= ~GSL_FLAGS_INITIALIZED0; + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_close. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_attachcallback(gsl_mmu_t *mmu, unsigned int pid) +{ + // + // attach process + // + // call this with the global lock held + // + int status = GSL_SUCCESS; + gsl_pagetable_t *pagetable; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_attachcallback(gsl_mmu_t *mmu=0x%08x, uint pid=0x%08x)\n", mmu, pid ); + + if (mmu->flags & GSL_FLAGS_INITIALIZED0) + { + // attach to current device mmu + mmu->refcnt++; + + if (mmu->flags & GSL_FLAGS_STARTED) + { + // attach to pagetable object + pagetable = kgsl_mmu_createpagetableobject(mmu, pid); + if(pagetable) + { + pagetable->refcnt++; + } + else + { + status = GSL_FAILURE; + } + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_attachcallback. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_detachcallback(gsl_mmu_t *mmu, unsigned int pid) +{ + // + // detach process + // + int status = GSL_SUCCESS; + gsl_pagetable_t *pagetable; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_detachcallback(gsl_mmu_t *mmu=0x%08x, uint pid=0x%08x)\n", mmu, pid ); + + if (mmu->flags & GSL_FLAGS_INITIALIZED0) + { + // detach from current device mmu + mmu->refcnt--; + + if (mmu->flags & GSL_FLAGS_STARTED) + { + // detach from pagetable object + pagetable = kgsl_mmu_getpagetableobject(mmu, pid); + if(pagetable) + { + pagetable->refcnt--; + } + else + { + status = GSL_FAILURE; + } + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_detachcallback. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_querystats(gsl_mmu_t *mmu, gsl_mmustats_t *stats) +{ +#ifdef GSL_STATS_MMU + int status = GSL_SUCCESS; + + DEBUG_ASSERT(stats); + + if (mmu->flags & GSL_FLAGS_STARTED) + { + memcpy(stats, &mmu->stats, sizeof(gsl_mmustats_t)); + } + else + { + memset(stats, 0, sizeof(gsl_mmustats_t)); + } + + return (status); +#else + // unreferenced formal parameters + (void) mmu; + (void) stats; + + return (GSL_FAILURE_NOTSUPPORTED); +#endif // GSL_STATS_MMU +} + +//---------------------------------------------------------------------------- + +int +kgsl_mmu_bist(gsl_mmu_t *mmu) +{ + // unreferenced formal parameter + (void) mmu; + + return (GSL_SUCCESS); +} diff --git a/drivers/mxc/amd-gpu/gsl_ringbuffer.c b/drivers/mxc/amd-gpu/gsl_ringbuffer.c new file mode 100644 index 00000000000..d957928e56b --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_ringbuffer.c @@ -0,0 +1,1148 @@ +/* Copyright (c) 2002,2007-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include + +#include "gsl.h" +#include "gsl_hal.h" +#include "gsl_cmdstream.h" +#include "gsl_ringbuffer.h" + +#ifdef GSL_BLD_YAMATO + +////////////////////////////////////////////////////////////////////////////// +// ucode +////////////////////////////////////////////////////////////////////////////// +#define uint32 unsigned int + +#include "pm4_microcode.inl" +#include "pfp_microcode_nrt.inl" + +#undef uint32 + + +////////////////////////////////////////////////////////////////////////////// +// defines +////////////////////////////////////////////////////////////////////////////// +#define GSL_RB_NOP_SIZEDWORDS 2 // default is 2 +#define GSL_RB_PROTECTED_MODE_CONTROL 0x00000000 // protected mode error checking below register address 0x800 + // note: if CP_INTERRUPT packet is used then checking needs + // to change to below register address 0x7C8 + + +////////////////////////////////////////////////////////////////////////////// +// ringbuffer size log2 quadwords equivalent +////////////////////////////////////////////////////////////////////////////// +static __inline unsigned int +gsl_ringbuffer_sizelog2quadwords(unsigned int sizedwords) +{ + unsigned int sizelog2quadwords = 0; + int i = sizedwords >> 1; + while (i >>= 1) + { + sizelog2quadwords++; + } + return (sizelog2quadwords); +} + + +////////////////////////////////////////////////////////////////////////////// +// private prototypes +////////////////////////////////////////////////////////////////////////////// +#ifdef _DEBUG +static void kgsl_ringbuffer_debug(gsl_ringbuffer_t *rb, gsl_rb_debug_t *rb_debug); +#endif + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +void +kgsl_cp_intrcallback(gsl_intrid_t id, void *cookie) +{ + gsl_ringbuffer_t *rb = (gsl_ringbuffer_t *) cookie; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> void kgsl_cp_intrcallback(gsl_intrid_t id=%I, void *cookie=0x%08x)\n", id, cookie ); + + switch(id) + { + // error condition interrupt + case GSL_INTR_YDX_CP_T0_PACKET_IN_IB: + case GSL_INTR_YDX_CP_OPCODE_ERROR: + case GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR: + case GSL_INTR_YDX_CP_RESERVED_BIT_ERROR: + case GSL_INTR_YDX_CP_IB_ERROR: + printk(KERN_ERR "GPU: CP Error\n"); + schedule_work(&rb->device->irq_err_work); + break; + + // non-error condition interrupt + case GSL_INTR_YDX_CP_SW_INT: + case GSL_INTR_YDX_CP_IB2_INT: + case GSL_INTR_YDX_CP_IB1_INT: + case GSL_INTR_YDX_CP_RING_BUFFER: + + // signal intr completion event + complete_all(&rb->device->intr.evnt[id]); + break; + + default: + + break; + } + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cp_intrcallback.\n" ); +} + +//---------------------------------------------------------------------------- + +void +kgsl_ringbuffer_watchdog() +{ + gsl_ringbuffer_t *rb = &(gsl_driver.device[GSL_DEVICE_YAMATO-1]).ringbuffer; // device_id is 1 based + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> void kgsl_ringbuffer_watchdog()\n" ); + + if (rb->flags & GSL_FLAGS_STARTED) + { + GSL_RB_GET_READPTR(rb, &rb->rptr); + + // ringbuffer is currently not empty + if (rb->rptr != rb->wptr) + { + // and a rptr sample was taken during interval n-1 + if (rb->watchdog.flags & GSL_FLAGS_ACTIVE) + { + // and the rptr did not advance between interval n-1 and n + if (rb->rptr == rb->watchdog.rptr_sample) + { + // then the core has hung + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_FATAL, + "ERROR: Watchdog detected core hung.\n" ); + + rb->device->ftbl.device_destroy(rb->device); + return; + } + } + + // save rptr sample for interval n + rb->watchdog.flags |= GSL_FLAGS_ACTIVE; + rb->watchdog.rptr_sample = rb->rptr; + } + else + { + // clear rptr sample for interval n + rb->watchdog.flags &= ~GSL_FLAGS_ACTIVE; + } + + } + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_watchdog.\n" ); +} + +//---------------------------------------------------------------------------- + +#ifdef _DEBUG + +static __inline void +kgsl_ringbuffer_checkregister(unsigned int reg, int pmodecheck) +{ + if (pmodecheck) + { + // check for register protection mode violation + if (reg <= (GSL_RB_PROTECTED_MODE_CONTROL & 0x3FFF)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Register protection mode violation.\n" ); + DEBUG_ASSERT(0); + } + } + + // range check register offset + if (reg > (gsl_driver.device[GSL_DEVICE_YAMATO-1].regspace.sizebytes >> 2)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Register out of range.\n" ); + DEBUG_ASSERT(0); + } +} + +//---------------------------------------------------------------------------- + +void +kgsl_ringbuffer_checkpm4type0(unsigned int header, unsigned int** cmds, int pmodeoff) +{ + pm4_type0 pm4header = *((pm4_type0*) &header); + unsigned int reg; + + if (pm4header.one_reg_wr) + { + reg = pm4header.base_index; + } + else + { + reg = pm4header.base_index + pm4header.count; + } + + kgsl_ringbuffer_checkregister(reg, !pmodeoff); + + *cmds += pm4header.count + 1; +} + +//---------------------------------------------------------------------------- + +void +kgsl_ringbuffer_checkpm4type3(unsigned int header, unsigned int** cmds, int indirection, int pmodeoff) +{ + pm4_type3 pm4header = *((pm4_type3*) &header); + unsigned int *ordinal2 = *cmds; + unsigned int *ibcmds, *end; + unsigned int reg, length; + + // check indirect buffer level + if (indirection > 2) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Only two levels of indirection supported.\n" ); + DEBUG_ASSERT(0); + } + + switch(pm4header.it_opcode) + { + case PM4_INDIRECT_BUFFER: + case PM4_INDIRECT_BUFFER_PFD: + + // determine ib host base and end address + ibcmds = (unsigned int*) kgsl_sharedmem_convertaddr(*ordinal2, 0); + end = ibcmds + *(ordinal2 + 1); + + // walk through the ib + while(ibcmds < end) + { + unsigned int tmpheader = *(ibcmds++); + + switch(tmpheader & PM4_PKT_MASK) + { + case PM4_TYPE0_PKT: + kgsl_ringbuffer_checkpm4type0(tmpheader, &ibcmds, pmodeoff); + break; + + case PM4_TYPE1_PKT: + case PM4_TYPE2_PKT: + break; + + case PM4_TYPE3_PKT: + kgsl_ringbuffer_checkpm4type3(tmpheader, &ibcmds, (indirection + 1), pmodeoff); + break; + } + } + break; + + case PM4_ME_INIT: + + if(indirection != 0) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: ME INIT packet cannot reside in an ib.\n" ); + DEBUG_ASSERT(0); + } + break; + + case PM4_REG_RMW: + + reg = (*ordinal2) & 0x1FFF; + + kgsl_ringbuffer_checkregister(reg, !pmodeoff); + + break; + + case PM4_SET_CONSTANT: + + if((((*ordinal2) >> 16) & 0xFF) == 0x4) // incremental register update + { + reg = 0x2000 + ((*ordinal2) & 0x3FF); // gfx decode space address starts at 0x2000 + length = pm4header.count - 1; + + kgsl_ringbuffer_checkregister(reg + length, 0); + } + break; + + case PM4_LOAD_CONSTANT_CONTEXT: + + if(((*(ordinal2 + 1) >> 16) & 0xFF) == 0x4) // incremental register update + { + reg = 0x2000 + (*(ordinal2 + 1) & 0x3FF); // gfx decode space address starts at 0x2000 + length = *(ordinal2 + 2); + + kgsl_ringbuffer_checkregister(reg + length, 0); + } + break; + + case PM4_COND_WRITE: + + if(((*ordinal2) & 0x00000100) == 0x0) // write to register + { + reg = *(ordinal2 + 4) & 0x3FFF; + + kgsl_ringbuffer_checkregister(reg, !pmodeoff); + } + break; + } + + *cmds += pm4header.count + 1; +} + +//---------------------------------------------------------------------------- + +void +kgsl_ringbuffer_checkpm4(unsigned int* cmds, unsigned int sizedwords, int pmodeoff) +{ + unsigned int *ringcmds = cmds; + unsigned int *end = cmds + sizedwords; + + while(ringcmds < end) + { + unsigned int header = *(ringcmds++); + + switch(header & PM4_PKT_MASK) + { + case PM4_TYPE0_PKT: + kgsl_ringbuffer_checkpm4type0(header, &ringcmds, pmodeoff); + break; + + case PM4_TYPE1_PKT: + case PM4_TYPE2_PKT: + break; + + case PM4_TYPE3_PKT: + kgsl_ringbuffer_checkpm4type3(header, &ringcmds, 0, pmodeoff); + break; + } + } +} + +#endif // _DEBUG + +//---------------------------------------------------------------------------- + +static void +kgsl_ringbuffer_submit(gsl_ringbuffer_t *rb) +{ + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> static void kgsl_ringbuffer_submit(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); + + DEBUG_ASSERT(rb->wptr != 0); + + kgsl_device_active(rb->device); + + GSL_RB_UPDATE_WPTR_POLLING(rb); + + // send the wptr to the hw + rb->device->ftbl.device_regwrite(rb->device, mmCP_RB_WPTR, rb->wptr); + + rb->flags |= GSL_FLAGS_ACTIVE; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_submit.\n" ); +} + +//---------------------------------------------------------------------------- + +static int +kgsl_ringbuffer_waitspace(gsl_ringbuffer_t *rb, unsigned int numcmds, int wptr_ahead) +{ + int nopcount; + unsigned int freecmds; + unsigned int *cmds; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> static int kgsl_ringbuffer_waitspace(gsl_ringbuffer_t *rb=0x%08x, unsigned int numcmds=%d, int wptr_ahead=%d)\n", + rb, numcmds, wptr_ahead ); + + + // if wptr ahead, fill the remaining with NOPs + if (wptr_ahead) + { + nopcount = rb->sizedwords - rb->wptr - 1; // -1 for header + + cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; + GSL_RB_WRITE(cmds, pm4_nop_packet(nopcount)); + rb->wptr++; + + kgsl_ringbuffer_submit(rb); + + rb->wptr = 0; + + GSL_RB_STATS(rb->stats.wraps++); + } + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_RBWAIT, GSL_DEVICE_YAMATO, rb->wptr, numcmds, "kgsl_ringbuffer_waitspace")); + + // wait for space in ringbuffer + for( ; ; ) + { + GSL_RB_GET_READPTR(rb, &rb->rptr); + + freecmds = rb->rptr - rb->wptr; + + if ((freecmds == 0) || (freecmds > numcmds)) + { + break; + } + + } + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_waitspace. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static unsigned int * +kgsl_ringbuffer_addcmds(gsl_ringbuffer_t *rb, unsigned int numcmds) +{ + unsigned int *ptr; + int status = GSL_SUCCESS; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> static unsigned int* kgsl_ringbuffer_addcmds(gsl_ringbuffer_t *rb=0x%08x, unsigned int numcmds=%d)\n", + rb, numcmds ); + + DEBUG_ASSERT(numcmds < rb->sizedwords); + + // update host copy of read pointer when running in safe mode + if (rb->device->flags & GSL_FLAGS_SAFEMODE) + { + GSL_RB_GET_READPTR(rb, &rb->rptr); + } + + // check for available space + if (rb->wptr >= rb->rptr) + { + // wptr ahead or equal to rptr + if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) // reserve dwords for nop packet + { + status = kgsl_ringbuffer_waitspace(rb, numcmds, 1); + } + } + else + { + // wptr behind rptr + if ((rb->wptr + numcmds) >= rb->rptr) + { + status = kgsl_ringbuffer_waitspace(rb, numcmds, 0); + } + + // check for remaining space + if ((rb->wptr + numcmds) > (rb->sizedwords - GSL_RB_NOP_SIZEDWORDS)) // reserve dwords for nop packet + { + status = kgsl_ringbuffer_waitspace(rb, numcmds, 1); + } + } + + ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; + rb->wptr += numcmds; + + if (status == GSL_SUCCESS) + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_waitspace. Return value 0x%08x\n", ptr ); + return (ptr); + } + else + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_waitspace. Return value 0x%08x\n", NULL ); + return (NULL); + } +} + +//---------------------------------------------------------------------------- +int +kgsl_ringbuffer_start(gsl_ringbuffer_t *rb) +{ + int status; + cp_rb_cntl_u cp_rb_cntl; + int i; + unsigned int *cmds; + gsl_device_t *device = rb->device; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> static int kgsl_ringbuffer_start(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); + + if (rb->flags & GSL_FLAGS_STARTED) + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_start. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); + } + + // clear memptrs values + kgsl_sharedmem_set0(&rb->memptrs_desc, 0, 0, sizeof(gsl_rbmemptrs_t)); + + // clear ringbuffer + kgsl_sharedmem_set0(&rb->buffer_desc, 0, 0x12341234, (rb->sizedwords << 2)); + + // setup WPTR polling address + device->ftbl.device_regwrite(device, mmCP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); + + // setup WPTR delay + device->ftbl.device_regwrite(device, mmCP_RB_WPTR_DELAY, 0/*0x70000010*/); + + // setup RB_CNTL + device->ftbl.device_regread(device, mmCP_RB_CNTL, (unsigned int *)&cp_rb_cntl); + + cp_rb_cntl.f.rb_bufsz = gsl_ringbuffer_sizelog2quadwords(rb->sizedwords); // size of ringbuffer + cp_rb_cntl.f.rb_blksz = rb->blksizequadwords; // quadwords to read before updating mem RPTR + cp_rb_cntl.f.rb_poll_en = GSL_RB_CNTL_POLL_EN; // WPTR polling + cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; // mem RPTR writebacks + + device->ftbl.device_regwrite(device, mmCP_RB_CNTL, cp_rb_cntl.val); + + // setup RB_BASE + device->ftbl.device_regwrite(device, mmCP_RB_BASE, rb->buffer_desc.gpuaddr); + + // setup RPTR_ADDR + device->ftbl.device_regwrite(device, mmCP_RB_RPTR_ADDR, rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_RPTR_OFFSET); + + // explicitly clear all cp interrupts when running in safe mode + if (rb->device->flags & GSL_FLAGS_SAFEMODE) + { + device->ftbl.device_regwrite(device, mmCP_INT_ACK, 0xFFFFFFFF); + } + + // setup scratch/timestamp addr + device->ftbl.device_regwrite(device, mmSCRATCH_ADDR, device->memstore.gpuaddr + GSL_DEVICE_MEMSTORE_OFFSET(soptimestamp)); + + // setup scratch/timestamp mask + device->ftbl.device_regwrite(device, mmSCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); + + // load the CP ucode + device->ftbl.device_regwrite(device, mmCP_DEBUG, 0x02000000); + device->ftbl.device_regwrite(device, mmCP_ME_RAM_WADDR, 0); + + for (i = 0; i < PM4_MICROCODE_SIZE; i++ ) + { + device->ftbl.device_regwrite(device, mmCP_ME_RAM_DATA, aPM4_Microcode[i][0]); + device->ftbl.device_regwrite(device, mmCP_ME_RAM_DATA, aPM4_Microcode[i][1]); + device->ftbl.device_regwrite(device, mmCP_ME_RAM_DATA, aPM4_Microcode[i][2]); + } + + // load the prefetch parser ucode + device->ftbl.device_regwrite(device, mmCP_PFP_UCODE_ADDR, 0); + + for ( i = 0; i < PFP_MICROCODE_SIZE_NRT; i++ ) + { + device->ftbl.device_regwrite(device, mmCP_PFP_UCODE_DATA, aPFP_Microcode_nrt[i]); + } + + // queue thresholds ??? + device->ftbl.device_regwrite(device, mmCP_QUEUE_THRESHOLDS, 0x000C0804); + + // reset pointers + rb->rptr = 0; + rb->wptr = 0; + + // init timestamp + rb->timestamp = 0; + GSL_RB_INIT_TIMESTAMP(rb); + + // clear ME_HALT to start micro engine + device->ftbl.device_regwrite(device, mmCP_ME_CNTL, 0); + + // ME_INIT + cmds = kgsl_ringbuffer_addcmds(rb, 19); + + GSL_RB_WRITE(cmds, PM4_HDR_ME_INIT); + GSL_RB_WRITE(cmds, 0x000003ff); // All fields present (bits 9:0) + GSL_RB_WRITE(cmds, 0x00000000); // Disable/Enable Real-Time Stream processing (present but ignored) + GSL_RB_WRITE(cmds, 0x00000000); // Enable (2D to 3D) and (3D to 2D) implicit synchronization (present but ignored) + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmRB_SURFACE_INFO)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SC_WINDOW_OFFSET)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmVGT_MAX_VTX_INDX)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmSQ_PROGRAM_CNTL)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmRB_DEPTHCONTROL)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SU_POINT_SIZE)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SC_LINE_CNTL)); + GSL_RB_WRITE(cmds, GSL_HAL_SUBBLOCK_OFFSET(mmPA_SU_POLY_OFFSET_FRONT_SCALE)); + GSL_RB_WRITE(cmds, 0x80000180); // Vertex and Pixel Shader Start Addresses in instructions (3 DWORDS per instruction) + GSL_RB_WRITE(cmds, 0x00000001); // Maximum Contexts + GSL_RB_WRITE(cmds, 0x00000000); // Write Confirm Interval and The CP will wait the wait_interval * 16 clocks between polling + GSL_RB_WRITE(cmds, 0x00000000); // NQ and External Memory Swap + GSL_RB_WRITE(cmds, GSL_RB_PROTECTED_MODE_CONTROL); // Protected mode error checking + GSL_RB_WRITE(cmds, 0x00000000); // Disable header dumping and Header dump address + GSL_RB_WRITE(cmds, 0x00000000); // Header dump size + + KGSL_DEBUG(GSL_DBGFLAGS_PM4CHECK, kgsl_ringbuffer_checkpm4((unsigned int *)rb->buffer_desc.hostptr, 19, 1)); + KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPPM4((unsigned int *)rb->buffer_desc.hostptr, 19)); + + kgsl_ringbuffer_submit(rb); + + // idle device to validate ME INIT + status = device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + + if (status == GSL_SUCCESS) + { + rb->flags |= GSL_FLAGS_STARTED; + } + + // enable cp interrupts + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_SW_INT, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_T0_PACKET_IN_IB, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_OPCODE_ERROR, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_RESERVED_BIT_ERROR, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_IB_ERROR, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_IB2_INT, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_IB1_INT, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER, kgsl_cp_intrcallback, (void *) rb); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_SW_INT); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_T0_PACKET_IN_IB); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_OPCODE_ERROR); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_RESERVED_BIT_ERROR); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_IB_ERROR); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_IB2_INT); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_IB1_INT); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER); + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_start. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_ringbuffer_stop(gsl_ringbuffer_t *rb) +{ + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> static int kgsl_ringbuffer_stop(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); + + if (rb->flags & GSL_FLAGS_STARTED) + { + // disable cp interrupts + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_SW_INT); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_T0_PACKET_IN_IB); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_OPCODE_ERROR); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_PROTECTED_MODE_ERROR); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_RESERVED_BIT_ERROR); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_IB_ERROR); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_IB2_INT); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_IB1_INT); + kgsl_intr_detach(&rb->device->intr, GSL_INTR_YDX_CP_RING_BUFFER); + + // ME_HALT + rb->device->ftbl.device_regwrite(rb->device, mmCP_ME_CNTL, 0x10000000); + + rb->flags &= ~GSL_FLAGS_STARTED; + } + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_stop. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_ringbuffer_init(gsl_device_t *device) +{ + int status; + gsl_flags_t flags; + gsl_ringbuffer_t *rb = &device->ringbuffer; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_ringbuffer_init(gsl_device_t *device=0x%08x)\n", device ); + + rb->device = device; + rb->sizedwords = (2 << gsl_cfg_rb_sizelog2quadwords); + rb->blksizequadwords = gsl_cfg_rb_blksizequadwords; + + // allocate memory for ringbuffer, needs to be double octword aligned + // align on page from contiguous physical memory + flags = (GSL_MEMFLAGS_ALIGNPAGE | GSL_MEMFLAGS_CONPHYS | GSL_MEMFLAGS_STRICTREQUEST); + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, flags = (GSL_MEMFLAGS_ALIGNPAGE | GSL_MEMFLAGS_STRICTREQUEST)); /* set MMU table for ringbuffer */ + + status = kgsl_sharedmem_alloc0(device->id, flags, (rb->sizedwords << 2), &rb->buffer_desc); + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_RINGBUF_SET, (unsigned int)rb->buffer_desc.gpuaddr, (unsigned int)rb->buffer_desc.hostptr, 0, "kgsl_ringbuffer_init")); + + if (status != GSL_SUCCESS) + { + kgsl_ringbuffer_close(rb); + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", status ); + return (status); + } + + // allocate memory for polling and timestamps + flags = (GSL_MEMFLAGS_ALIGN32 | GSL_MEMFLAGS_CONPHYS); + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, flags = GSL_MEMFLAGS_ALIGN32); + + status = kgsl_sharedmem_alloc0(device->id, flags, sizeof(gsl_rbmemptrs_t), &rb->memptrs_desc); + + if (status != GSL_SUCCESS) + { + kgsl_ringbuffer_close(rb); + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", status ); + return (status); + } + + // overlay structure on memptrs memory + rb->memptrs = (gsl_rbmemptrs_t *)rb->memptrs_desc.hostptr; + + rb->flags |= GSL_FLAGS_INITIALIZED; + + // validate command stream data when running in safe mode + if (device->flags & GSL_FLAGS_SAFEMODE) + { + gsl_driver.flags_debug |= GSL_DBGFLAGS_PM4CHECK; + } + + // start ringbuffer + status = kgsl_ringbuffer_start(rb); + + if (status != GSL_SUCCESS) + { + kgsl_ringbuffer_close(rb); + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", status ); + return (status); + } + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_init. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_ringbuffer_close(gsl_ringbuffer_t *rb) +{ + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_ringbuffer_close(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); + + // stop ringbuffer + kgsl_ringbuffer_stop(rb); + + // free buffer + if (rb->buffer_desc.hostptr) + { + kgsl_sharedmem_free0(&rb->buffer_desc, current->tgid); + } + + // free memory pointers + if (rb->memptrs_desc.hostptr) + { + kgsl_sharedmem_free0(&rb->memptrs_desc, current->tgid); + } + + rb->flags &= ~GSL_FLAGS_INITIALIZED; + + memset(rb, 0, sizeof(gsl_ringbuffer_t)); + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_close. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +gsl_timestamp_t +kgsl_ringbuffer_issuecmds(gsl_device_t *device, int pmodeoff, unsigned int *cmds, int sizedwords, unsigned int pid) +{ + gsl_ringbuffer_t *rb = &device->ringbuffer; + unsigned int pmodesizedwords; + unsigned int *ringcmds; + unsigned int timestamp; + + pmodeoff = 0; + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> gsl_timestamp_t kgsl_ringbuffer_issuecmds(gsl_device_t *device=0x%08x, int pmodeoff=%d, unsigned int *cmds=0x%08x, int sizedwords=%d, unsigned int pid=0x%08x)\n", + device, pmodeoff, cmds, sizedwords, pid ); + + if (!(device->ringbuffer.flags & GSL_FLAGS_STARTED)) + { + return (0); + } + + // set mmu pagetable + kgsl_mmu_setpagetable(device, pid); + + KGSL_DEBUG(GSL_DBGFLAGS_PM4CHECK, kgsl_ringbuffer_checkpm4(cmds, sizedwords, pmodeoff)); + KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPPM4(cmds, sizedwords)); + + // reserve space to temporarily turn off protected mode error checking if needed + pmodesizedwords = pmodeoff ? 8 : 0; + +#if defined GSL_RB_TIMESTAMP_INTERUPT + pmodesizedwords += 2; +#endif + // allocate space in ringbuffer + ringcmds = kgsl_ringbuffer_addcmds(rb, pmodesizedwords + sizedwords + 6); + + if (pmodeoff) + { + // disable protected mode error checking + *ringcmds++ = pm4_type3_packet(PM4_ME_INIT, 2); + *ringcmds++ = 0x00000080; + *ringcmds++ = 0x00000000; + } + + // copy the cmds to the ringbuffer + memcpy(ringcmds, cmds, (sizedwords << 2)); + + ringcmds += sizedwords; + + if (pmodeoff) + { + *ringcmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + *ringcmds++ = 0; + + // re-enable protected mode error checking + *ringcmds++ = pm4_type3_packet(PM4_ME_INIT, 2); + *ringcmds++ = 0x00000080; + *ringcmds++ = GSL_RB_PROTECTED_MODE_CONTROL; + } + + // increment timestamp + rb->timestamp++; + timestamp = rb->timestamp; + + // start-of-pipeline and end-of-pipeline timestamps + *ringcmds++ = pm4_type0_packet(mmCP_TIMESTAMP, 1); + *ringcmds++ = rb->timestamp; + *ringcmds++ = pm4_type3_packet(PM4_EVENT_WRITE, 3); + *ringcmds++ = CACHE_FLUSH_TS; + *ringcmds++ = device->memstore.gpuaddr + GSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp); + *ringcmds++ = rb->timestamp; + +#if defined GSL_RB_TIMESTAMP_INTERUPT + *ringcmds++ = pm4_type3_packet(PM4_INTERRUPT, 1); + *ringcmds++ = 0x80000000; +#endif + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_MEMWRITE, (unsigned int)((char*)ringcmds - ((pmodesizedwords + sizedwords + 6) << 2)), (unsigned int)((char*)ringcmds - ((pmodesizedwords + sizedwords + 6) << 2)), (pmodesizedwords + sizedwords + 6) << 2, "kgsl_ringbuffer_issuecmds")); + + // issue the commands + kgsl_ringbuffer_submit(rb); + + // stats + GSL_RB_STATS(rb->stats.wordstotal += sizedwords); + GSL_RB_STATS(rb->stats.issues++); + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_issuecmds. Return value %d\n", timestamp ); + + // return timestamp of issued commands + return (timestamp); +} + +//---------------------------------------------------------------------------- +int +kgsl_ringbuffer_issueibcmds(gsl_device_t *device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, gsl_flags_t flags) +{ + unsigned int link[3]; + int dumpx_swap; + (void)dumpx_swap; // used only when BB_DUMPX is defined + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> gsl_timestamp_t kgsl_ringbuffer_issueibcmds(gsl_device_t device=%0x%08x, int drawctxt_index=%d, gpuaddr_t ibaddr=0x%08x, int sizedwords=%d, gsl_timestamp_t *timestamp=0x%08x)\n", + device, drawctxt_index, ibaddr, sizedwords, timestamp ); + + if (!(device->ringbuffer.flags & GSL_FLAGS_STARTED)) + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_issueibcmds. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + DEBUG_ASSERT(ibaddr); + DEBUG_ASSERT(sizedwords); + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, dumpx_swap = kgsl_dumpx_parse_ibs(ibaddr, sizedwords)); + + // context switch if needed + kgsl_drawctxt_switch(device, &device->drawctxt[drawctxt_index], flags); + + link[0] = PM4_HDR_INDIRECT_BUFFER_PFD; + link[1] = ibaddr; + link[2] = sizedwords; + + *timestamp = kgsl_ringbuffer_issuecmds(device, 0, &link[0], 3, current->tgid); + + // idle device when running in safe mode + if (device->flags & GSL_FLAGS_SAFEMODE) + { + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + } + else + { + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + // insert wait for idle after every IB1 + // this is conservative but works reliably and is ok even for performance simulations + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + }); + } + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + if(dumpx_swap) + { + KGSL_DEBUG_DUMPX( BB_DUMP_EXPORT_CBUF, 0, 0, 0, "resolve"); + KGSL_DEBUG_DUMPX( BB_DUMP_FLUSH,0,0,0," "); + } + }); + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_issueibcmds. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +#ifdef _DEBUG +static void +kgsl_ringbuffer_debug(gsl_ringbuffer_t *rb, gsl_rb_debug_t *rb_debug) +{ + memset(rb_debug, 0, sizeof(gsl_rb_debug_t)); + + rb_debug->pm4_ucode_rel = PM4_MICROCODE_VERSION; + rb_debug->pfp_ucode_rel = PFP_MICROCODE_VERSION; + + rb->device->ftbl.device_regread(rb->device, mmCP_RB_BASE, (unsigned int *)&rb_debug->cp_rb_base); + rb->device->ftbl.device_regread(rb->device, mmCP_RB_CNTL, (unsigned int *)&rb_debug->cp_rb_cntl); + rb->device->ftbl.device_regread(rb->device, mmCP_RB_RPTR_ADDR, (unsigned int *)&rb_debug->cp_rb_rptr_addr); + rb->device->ftbl.device_regread(rb->device, mmCP_RB_RPTR, (unsigned int *)&rb_debug->cp_rb_rptr); + rb->device->ftbl.device_regread(rb->device, mmCP_RB_WPTR, (unsigned int *)&rb_debug->cp_rb_wptr); + rb->device->ftbl.device_regread(rb->device, mmCP_RB_WPTR_BASE, (unsigned int *)&rb_debug->cp_rb_wptr_base); + rb->device->ftbl.device_regread(rb->device, mmSCRATCH_UMSK, (unsigned int *)&rb_debug->scratch_umsk); + rb->device->ftbl.device_regread(rb->device, mmSCRATCH_ADDR, (unsigned int *)&rb_debug->scratch_addr); + rb->device->ftbl.device_regread(rb->device, mmCP_ME_CNTL, (unsigned int *)&rb_debug->cp_me_cntl); + rb->device->ftbl.device_regread(rb->device, mmCP_ME_STATUS, (unsigned int *)&rb_debug->cp_me_status); + rb->device->ftbl.device_regread(rb->device, mmCP_DEBUG, (unsigned int *)&rb_debug->cp_debug); + rb->device->ftbl.device_regread(rb->device, mmCP_STAT, (unsigned int *)&rb_debug->cp_stat); + rb->device->ftbl.device_regread(rb->device, mmRBBM_STATUS, (unsigned int *)&rb_debug->rbbm_status); + rb_debug->sop_timestamp = kgsl_cmdstream_readtimestamp(rb->device->id, GSL_TIMESTAMP_CONSUMED); + rb_debug->eop_timestamp = kgsl_cmdstream_readtimestamp(rb->device->id, GSL_TIMESTAMP_RETIRED); +} +#endif + + +//---------------------------------------------------------------------------- + +int +kgsl_ringbuffer_querystats(gsl_ringbuffer_t *rb, gsl_rbstats_t *stats) +{ +#ifdef GSL_STATS_RINGBUFFER + DEBUG_ASSERT(stats); + + if (!(rb->flags & GSL_FLAGS_STARTED)) + { + return (GSL_FAILURE); + } + + memcpy(stats, &rb->stats, sizeof(gsl_rbstats_t)); + + return (GSL_SUCCESS); +#else + // unreferenced formal parameters + (void) rb; + (void) stats; + + return (GSL_FAILURE_NOTSUPPORTED); +#endif // GSL_STATS_RINGBUFFER +} + +//---------------------------------------------------------------------------- + +int +kgsl_ringbuffer_bist(gsl_ringbuffer_t *rb) +{ + unsigned int *cmds; + unsigned int temp, k, j; + int status; + int i; +#ifdef _DEBUG + gsl_rb_debug_t rb_debug; +#endif + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_ringbuffer_bist(gsl_ringbuffer_t *rb=0x%08x)\n", rb ); + + if (!(rb->flags & GSL_FLAGS_STARTED)) + { + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // simple nop submit + cmds = kgsl_ringbuffer_addcmds(rb, 2); + if (!cmds) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + GSL_RB_WRITE(cmds, pm4_nop_packet(1)); + GSL_RB_WRITE(cmds, 0xDEADBEEF); + + kgsl_ringbuffer_submit(rb); + + status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); + + if (status != GSL_SUCCESS) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); + return (status); + } + + // simple scratch submit + cmds = kgsl_ringbuffer_addcmds(rb, 2); + if (!cmds) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + GSL_RB_WRITE(cmds, pm4_type0_packet(mmSCRATCH_REG7, 1)); + GSL_RB_WRITE(cmds, 0xFEEDF00D); + + kgsl_ringbuffer_submit(rb); + + status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); + + if (status != GSL_SUCCESS) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); + return (status); + } + + rb->device->ftbl.device_regread(rb->device, mmSCRATCH_REG7, &temp); + + if (temp != 0xFEEDF00D) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // simple wraps + for (i = 0; i < 256; i+=2) + { + j = ((rb->sizedwords >> 2) - 256) + i; + + cmds = kgsl_ringbuffer_addcmds(rb, j); + if (!cmds) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + k = 0; + + while (k < j) + { + k+=2; + GSL_RB_WRITE(cmds, pm4_type0_packet(mmSCRATCH_REG7, 1)); + GSL_RB_WRITE(cmds, k); + } + + kgsl_ringbuffer_submit(rb); + + status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); + + if (status != GSL_SUCCESS) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); + return (status); + } + + rb->device->ftbl.device_regread(rb->device, mmSCRATCH_REG7, &temp); + + if (temp != k) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + } + + // max size submits, TODO do this at least with regreads + for (i = 0; i < 256; i++) + { + cmds = kgsl_ringbuffer_addcmds(rb, (rb->sizedwords >> 2)); + if (!cmds) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + GSL_RB_WRITE(cmds, pm4_nop_packet((rb->sizedwords >> 2) - 1)); + + kgsl_ringbuffer_submit(rb); + + status = rb->device->ftbl.device_idle(rb->device, GSL_TIMEOUT_DEFAULT); + + if (status != GSL_SUCCESS) + { +#ifdef _DEBUG + kgsl_ringbuffer_debug(rb, &rb_debug); +#endif + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", status ); + return (status); + } + } + + // submit load with randomness + +#ifdef GSL_RB_USE_MEM_TIMESTAMP + // scratch memptr validate +#endif // GSL_RB_USE_MEM_TIMESTAMP + +#ifdef GSL_RB_USE_MEM_RPTR + // rptr memptr validate +#endif // GSL_RB_USE_MEM_RPTR + +#ifdef GSL_RB_USE_WPTR_POLLING + // wptr memptr validate +#endif // GSL_RB_USE_WPTR_POLLING + + kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_bist. Return value %d\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +#endif + diff --git a/drivers/mxc/amd-gpu/gsl_sharedmem.c b/drivers/mxc/amd-gpu/gsl_sharedmem.c new file mode 100644 index 00000000000..434f076705b --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_sharedmem.c @@ -0,0 +1,940 @@ +/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" +#include "gsl_hal.h" + +///////////////////////////////////////////////////////////////////////////// +// macros +////////////////////////////////////////////////////////////////////////////// +#define GSL_SHMEM_APERTURE_MARK(aperture_id) \ + (shmem->priv |= (((aperture_id + 1) << GSL_APERTURE_SHIFT) & GSL_APERTURE_MASK)) + +#define GSL_SHMEM_APERTURE_ISMARKED(aperture_id) \ + (((shmem->priv & GSL_APERTURE_MASK) >> GSL_APERTURE_SHIFT) & (aperture_id + 1)) + +#define GSL_MEMFLAGS_APERTURE_GET(flags, aperture_id) \ + aperture_id = (gsl_apertureid_t)((flags & GSL_MEMFLAGS_APERTURE_MASK) >> GSL_MEMFLAGS_APERTURE_SHIFT); \ + DEBUG_ASSERT(aperture_id < GSL_APERTURE_MAX); + +#define GSL_MEMFLAGS_CHANNEL_GET(flags, channel_id) \ + channel_id = (gsl_channelid_t)((flags & GSL_MEMFLAGS_CHANNEL_MASK) >> GSL_MEMFLAGS_CHANNEL_SHIFT); \ + DEBUG_ASSERT(channel_id < GSL_CHANNEL_MAX); + +#define GSL_MEMDESC_APERTURE_SET(memdesc, aperture_index) \ + memdesc->priv = (memdesc->priv & ~GSL_APERTURE_MASK) | ((aperture_index << GSL_APERTURE_SHIFT) & GSL_APERTURE_MASK); + +#define GSL_MEMDESC_DEVICE_SET(memdesc, device_id) \ + memdesc->priv = (memdesc->priv & ~GSL_DEVICEID_MASK) | ((device_id << GSL_DEVICEID_SHIFT) & GSL_DEVICEID_MASK); + +#define GSL_MEMDESC_EXTALLOC_SET(memdesc, flag) \ + memdesc->priv = (memdesc->priv & ~GSL_EXTALLOC_MASK) | ((flag << GSL_EXTALLOC_SHIFT) & GSL_EXTALLOC_MASK); + +#define GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index) \ + DEBUG_ASSERT(memdesc); \ + aperture_index = ((memdesc->priv & GSL_APERTURE_MASK) >> GSL_APERTURE_SHIFT); \ + DEBUG_ASSERT(aperture_index < GSL_SHMEM_MAX_APERTURES); + +#define GSL_MEMDESC_DEVICE_GET(memdesc, device_id) \ + DEBUG_ASSERT(memdesc); \ + device_id = (gsl_deviceid_t)((memdesc->priv & GSL_DEVICEID_MASK) >> GSL_DEVICEID_SHIFT); \ + DEBUG_ASSERT(device_id <= GSL_DEVICE_MAX); + +#define GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc) \ + ((memdesc->priv & GSL_EXTALLOC_MASK) >> GSL_EXTALLOC_SHIFT) + + +////////////////////////////////////////////////////////////////////////////// +// aperture index in shared memory object +////////////////////////////////////////////////////////////////////////////// +static __inline int +kgsl_sharedmem_getapertureindex(gsl_sharedmem_t *shmem, gsl_apertureid_t aperture_id, gsl_channelid_t channel_id) +{ + DEBUG_ASSERT(shmem->aperturelookup[aperture_id][channel_id] < shmem->numapertures); + + return (shmem->aperturelookup[aperture_id][channel_id]); +} + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_sharedmem_init(gsl_sharedmem_t *shmem) +{ + int i; + int status; + gsl_shmemconfig_t config; + int mmu_virtualized; + gsl_apertureid_t aperture_id; + gsl_channelid_t channel_id; + unsigned int hostbaseaddr; + gpuaddr_t gpubaseaddr; + int sizebytes; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_sharedmem_init(gsl_sharedmem_t *shmem=0x%08x)\n", shmem ); + + if (shmem->flags & GSL_FLAGS_INITIALIZED) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", GSL_SUCCESS ); + return (GSL_SUCCESS); + } + + status = kgsl_hal_getshmemconfig(&config); + if (status != GSL_SUCCESS) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to get sharedmem config.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", status ); + return (status); + } + + shmem->numapertures = config.numapertures; + + for (i = 0; i < shmem->numapertures; i++) + { + aperture_id = config.apertures[i].id; + channel_id = config.apertures[i].channel; + hostbaseaddr = config.apertures[i].hostbase; + gpubaseaddr = config.apertures[i].gpubase; + sizebytes = config.apertures[i].sizebytes; + mmu_virtualized = 0; + + // handle mmu virtualized aperture + if (aperture_id == GSL_APERTURE_MMU) + { + mmu_virtualized = 1; + aperture_id = GSL_APERTURE_EMEM; + } + + // make sure aligned to page size + DEBUG_ASSERT((gpubaseaddr & ((1 << GSL_PAGESIZE_SHIFT) - 1)) == 0); + + // make a multiple of page size + sizebytes = (sizebytes & ~((1 << GSL_PAGESIZE_SHIFT) - 1)); + + if (sizebytes > 0) + { + shmem->apertures[i].memarena = kgsl_memarena_create(aperture_id, mmu_virtualized, hostbaseaddr, gpubaseaddr, sizebytes); + + if (!shmem->apertures[i].memarena) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Unable to allocate memarena.\n" ); + kgsl_sharedmem_close(shmem); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + shmem->apertures[i].id = aperture_id; + shmem->apertures[i].channel = channel_id; + shmem->apertures[i].numbanks = 1; + + // create aperture lookup table + if (GSL_SHMEM_APERTURE_ISMARKED(aperture_id)) + { + // update "current aperture_id"/"current channel_id" index + shmem->aperturelookup[aperture_id][channel_id] = i; + } + else + { + // initialize "current aperture_id"/"channel_id" indexes + for (channel_id = GSL_CHANNEL_1; channel_id < GSL_CHANNEL_MAX; channel_id++) + { + shmem->aperturelookup[aperture_id][channel_id] = i; + } + + GSL_SHMEM_APERTURE_MARK(aperture_id); + } + } + } + + shmem->flags |= GSL_FLAGS_INITIALIZED; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_init. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_close(gsl_sharedmem_t *shmem) +{ + int i; + int result = GSL_SUCCESS; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_sharedmem_close(gsl_sharedmem_t *shmem=0x%08x)\n", shmem ); + + if (shmem->flags & GSL_FLAGS_INITIALIZED) + { + for (i = 0; i < shmem->numapertures; i++) + { + if (shmem->apertures[i].memarena) + { + result = kgsl_memarena_destroy(shmem->apertures[i].memarena); + } + } + + memset(shmem, 0, sizeof(gsl_sharedmem_t)); + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_close. Return value %B\n", result ); + + return (result); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_alloc0(gsl_deviceid_t device_id, gsl_flags_t flags, int sizebytes, gsl_memdesc_t *memdesc) +{ + gsl_apertureid_t aperture_id; + gsl_channelid_t channel_id; + gsl_deviceid_t tmp_id; + int aperture_index, org_index; + int result = GSL_FAILURE; + gsl_mmu_t *mmu = NULL; + gsl_sharedmem_t *shmem = &gsl_driver.shmem; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_alloc(gsl_deviceid_t device_id=%D, gsl_flags_t flags=%x, int sizebytes=%d, gsl_memdesc_t *memdesc=%M)\n", + device_id, flags, sizebytes, memdesc ); + + DEBUG_ASSERT(sizebytes); + DEBUG_ASSERT(memdesc); + + GSL_MEMFLAGS_APERTURE_GET(flags, aperture_id); + GSL_MEMFLAGS_CHANNEL_GET(flags, channel_id); + + memset(memdesc, 0, sizeof(gsl_memdesc_t)); + + if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_alloc. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + // execute pending device action + tmp_id = (device_id != GSL_DEVICE_ANY) ? device_id : device_id+1; + for ( ; tmp_id <= GSL_DEVICE_MAX; tmp_id++) + { + if (gsl_driver.device[tmp_id-1].flags & GSL_FLAGS_INITIALIZED) + { + kgsl_device_runpending(&gsl_driver.device[tmp_id-1]); + + if (tmp_id == device_id) + { + break; + } + } + } + + // convert any device to an actual existing device + if (device_id == GSL_DEVICE_ANY) + { + for ( ; ; ) + { + device_id++; + + if (device_id <= GSL_DEVICE_MAX) + { + if (gsl_driver.device[device_id-1].flags & GSL_FLAGS_INITIALIZED) + { + break; + } + } + else + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid device.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_alloc. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + } + } + + DEBUG_ASSERT(device_id > GSL_DEVICE_ANY && device_id <= GSL_DEVICE_MAX); + + // get mmu reference + mmu = &gsl_driver.device[device_id-1].mmu; + + aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); + + //do not proceed if it is a strict request, the aperture requested is not present, and the MMU is enabled + if (!((flags & GSL_MEMFLAGS_STRICTREQUEST) && aperture_id != shmem->apertures[aperture_index].id && kgsl_mmu_isenabled(mmu))) + { + // do allocation + result = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, sizebytes, memdesc); + + // if allocation failed + if (result != GSL_SUCCESS) + { + org_index = aperture_index; + + // then failover to other channels within the current aperture + for (channel_id = GSL_CHANNEL_1; channel_id < GSL_CHANNEL_MAX; channel_id++) + { + aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); + + if (aperture_index != org_index) + { + // do allocation + result = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, sizebytes, memdesc); + + if (result == GSL_SUCCESS) + { + break; + } + } + } + + // if allocation still has not succeeded, then failover to EMEM/MMU aperture, but + // not if it's a strict request and the MMU is enabled + if (result != GSL_SUCCESS && aperture_id != GSL_APERTURE_EMEM + && !((flags & GSL_MEMFLAGS_STRICTREQUEST) && kgsl_mmu_isenabled(mmu))) + { + aperture_id = GSL_APERTURE_EMEM; + + // try every channel + for (channel_id = GSL_CHANNEL_1; channel_id < GSL_CHANNEL_MAX; channel_id++) + { + aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); + + if (aperture_index != org_index) + { + // do allocation + result = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, sizebytes, memdesc); + + if (result == GSL_SUCCESS) + { + break; + } + } + } + } + } + } + + if (result == GSL_SUCCESS) + { + GSL_MEMDESC_APERTURE_SET(memdesc, aperture_index); + GSL_MEMDESC_DEVICE_SET(memdesc, device_id); + + if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) + { + gsl_scatterlist_t scatterlist; + + scatterlist.contiguous = 0; + scatterlist.num = memdesc->size / GSL_PAGESIZE; + + if (memdesc->size & (GSL_PAGESIZE-1)) + { + scatterlist.num++; + } + + scatterlist.pages = kmalloc(sizeof(unsigned int) * scatterlist.num, GFP_KERNEL); + if (scatterlist.pages) + { + // allocate physical pages + result = kgsl_hal_allocphysical(memdesc->gpuaddr, scatterlist.num, scatterlist.pages); + if (result == GSL_SUCCESS) + { + result = kgsl_mmu_map(mmu, memdesc->gpuaddr, &scatterlist, flags, current->tgid); + if (result != GSL_SUCCESS) + { + kgsl_hal_freephysical(memdesc->gpuaddr, scatterlist.num, scatterlist.pages); + } + } + + kfree(scatterlist.pages); + } + else + { + result = GSL_FAILURE; + } + + if (result != GSL_SUCCESS) + { + kgsl_memarena_free(shmem->apertures[aperture_index].memarena, memdesc); + } + } + } + + KGSL_DEBUG_TBDUMP_SETMEM( memdesc->gpuaddr, 0, memdesc->size ); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_alloc. Return value %B\n", result ); + + return (result); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_alloc(gsl_deviceid_t device_id, gsl_flags_t flags, int sizebytes, gsl_memdesc_t *memdesc) +{ + int status = GSL_SUCCESS; + mutex_lock(&gsl_driver.lock); + status = kgsl_sharedmem_alloc0(device_id, flags, sizebytes, memdesc); + mutex_unlock(&gsl_driver.lock); + return status; +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_free0(gsl_memdesc_t *memdesc, unsigned int pid) +{ + int status = GSL_SUCCESS; + int aperture_index; + gsl_deviceid_t device_id; + gsl_sharedmem_t *shmem; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_sharedmem_free(gsl_memdesc_t *memdesc=%M)\n", memdesc ); + + GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); + GSL_MEMDESC_DEVICE_GET(memdesc, device_id); + + shmem = &gsl_driver.shmem; + + if (shmem->flags & GSL_FLAGS_INITIALIZED) + { + if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) + { + status |= kgsl_mmu_unmap(&gsl_driver.device[device_id-1].mmu, memdesc->gpuaddr, memdesc->size, pid); + + if (!GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) + { + status |= kgsl_hal_freephysical(memdesc->gpuaddr, memdesc->size / GSL_PAGESIZE, NULL); + } + } + + kgsl_memarena_free(shmem->apertures[aperture_index].memarena, memdesc); + + // clear descriptor + memset(memdesc, 0, sizeof(gsl_memdesc_t)); + } + else + { + status = GSL_FAILURE; + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_free. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_free(gsl_memdesc_t *memdesc) +{ + int status = GSL_SUCCESS; + mutex_lock(&gsl_driver.lock); + status = kgsl_sharedmem_free0(memdesc, current->tgid); + mutex_unlock(&gsl_driver.lock); + return status; +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_read0(const gsl_memdesc_t *memdesc, void *dst, unsigned int offsetbytes, unsigned int sizebytes, unsigned int touserspace) +{ + int aperture_index; + gsl_sharedmem_t *shmem; + unsigned int gpuoffsetbytes; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_read(gsl_memdesc_t *memdesc=%M, void *dst=0x%08x, uint offsetbytes=%u, uint sizebytes=%u)\n", + memdesc, dst, offsetbytes, sizebytes ); + + GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); + + if (GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_read. Return value %B\n", GSL_FAILURE_BADPARAM ); + return (GSL_FAILURE_BADPARAM); + } + + shmem = &gsl_driver.shmem; + + if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_read. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + DEBUG_ASSERT(dst); + DEBUG_ASSERT(sizebytes); + + if (memdesc->gpuaddr < shmem->apertures[aperture_index].memarena->gpubaseaddr) + { + return (GSL_FAILURE_BADPARAM); + } + + if (memdesc->gpuaddr + sizebytes > shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes) + { + return (GSL_FAILURE_BADPARAM); + } + + gpuoffsetbytes = (memdesc->gpuaddr - shmem->apertures[aperture_index].memarena->gpubaseaddr) + offsetbytes; + + GSL_HAL_MEM_READ(dst, shmem->apertures[aperture_index].memarena->hostbaseaddr, gpuoffsetbytes, sizebytes, touserspace); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_read. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_read(const gsl_memdesc_t *memdesc, void *dst, unsigned int offsetbytes, unsigned int sizebytes, unsigned int touserspace) +{ + int status = GSL_SUCCESS; + mutex_lock(&gsl_driver.lock); + status = kgsl_sharedmem_read0(memdesc, dst, offsetbytes, sizebytes, touserspace); + mutex_unlock(&gsl_driver.lock); + return status; +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_write0(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, void *src, unsigned int sizebytes, unsigned int fromuserspace) +{ + int aperture_index; + gsl_sharedmem_t *shmem; + unsigned int gpuoffsetbytes; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_write(gsl_memdesc_t *memdesc=%M, uint offsetbytes=%u, void *src=0x%08x, uint sizebytes=%u)\n", + memdesc, offsetbytes, src, sizebytes ); + + GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); + + if (GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_write. Return value %B\n", GSL_FAILURE_BADPARAM ); + return (GSL_FAILURE_BADPARAM); + } + + shmem = &gsl_driver.shmem; + + if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_write. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + DEBUG_ASSERT(src); + DEBUG_ASSERT(sizebytes); + DEBUG_ASSERT(memdesc->gpuaddr >= shmem->apertures[aperture_index].memarena->gpubaseaddr); + DEBUG_ASSERT((memdesc->gpuaddr + sizebytes) <= (shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes)); + + gpuoffsetbytes = (memdesc->gpuaddr - shmem->apertures[aperture_index].memarena->gpubaseaddr) + offsetbytes; + + GSL_HAL_MEM_WRITE(shmem->apertures[aperture_index].memarena->hostbaseaddr, gpuoffsetbytes, src, sizebytes, fromuserspace); + + KGSL_DEBUG(GSL_DBGFLAGS_PM4MEM, KGSL_DEBUG_DUMPMEMWRITE((memdesc->gpuaddr + offsetbytes), sizebytes, src)); + + KGSL_DEBUG_TBDUMP_SYNCMEM( (memdesc->gpuaddr + offsetbytes), src, sizebytes ); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_write. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_write(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, void *src, unsigned int sizebytes, unsigned int fromuserspace) +{ + int status = GSL_SUCCESS; + mutex_lock(&gsl_driver.lock); + status = kgsl_sharedmem_write0(memdesc, offsetbytes, src, sizebytes, fromuserspace); + mutex_unlock(&gsl_driver.lock); + return status; +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_set0(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes) +{ + int aperture_index; + gsl_sharedmem_t *shmem; + unsigned int gpuoffsetbytes; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_set(gsl_memdesc_t *memdesc=%M, unsigned int offsetbytes=%d, unsigned int value=0x%08x, unsigned int sizebytes=%d)\n", + memdesc, offsetbytes, value, sizebytes ); + + GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); + + if (GSL_MEMDESC_EXTALLOC_ISMARKED(memdesc)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_set. Return value %B\n", GSL_FAILURE_BADPARAM ); + return (GSL_FAILURE_BADPARAM); + } + + shmem = &gsl_driver.shmem; + + if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_set. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + + DEBUG_ASSERT(sizebytes); + DEBUG_ASSERT(memdesc->gpuaddr >= shmem->apertures[aperture_index].memarena->gpubaseaddr); + DEBUG_ASSERT((memdesc->gpuaddr + sizebytes) <= (shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes)); + + gpuoffsetbytes = (memdesc->gpuaddr - shmem->apertures[aperture_index].memarena->gpubaseaddr) + offsetbytes; + + GSL_HAL_MEM_SET(shmem->apertures[aperture_index].memarena->hostbaseaddr, gpuoffsetbytes, value, sizebytes); + + KGSL_DEBUG(GSL_DBGFLAGS_PM4MEM, KGSL_DEBUG_DUMPMEMSET((memdesc->gpuaddr + offsetbytes), sizebytes, value)); + + KGSL_DEBUG_TBDUMP_SETMEM( (memdesc->gpuaddr + offsetbytes), value, sizebytes ); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_set. Return value %B\n", GSL_SUCCESS ); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_set(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes) +{ + int status = GSL_SUCCESS; + mutex_lock(&gsl_driver.lock); + status = kgsl_sharedmem_set0(memdesc, offsetbytes, value, sizebytes); + mutex_unlock(&gsl_driver.lock); + return status; +} + +//---------------------------------------------------------------------------- + +unsigned int +kgsl_sharedmem_largestfreeblock(gsl_deviceid_t device_id, gsl_flags_t flags) +{ + gsl_apertureid_t aperture_id; + gsl_channelid_t channel_id; + int aperture_index; + unsigned int result = 0; + gsl_sharedmem_t *shmem; + + // device_id is ignored at this level, it would be used with per-device memarena's + + // unreferenced formal parameter + (void) device_id; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_largestfreeblock(gsl_deviceid_t device_id=%D, gsl_flags_t flags=%x)\n", + device_id, flags ); + + GSL_MEMFLAGS_APERTURE_GET(flags, aperture_id); + GSL_MEMFLAGS_CHANNEL_GET(flags, channel_id); + + mutex_lock(&gsl_driver.lock); + + shmem = &gsl_driver.shmem; + + if (!(shmem->flags & GSL_FLAGS_INITIALIZED)) + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Shared memory not initialized.\n" ); + mutex_unlock(&gsl_driver.lock); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_largestfreeblock. Return value %d\n", 0 ); + return (0); + } + + aperture_index = kgsl_sharedmem_getapertureindex(shmem, aperture_id, channel_id); + + if (aperture_id == shmem->apertures[aperture_index].id) + { + result = kgsl_memarena_getlargestfreeblock(shmem->apertures[aperture_index].memarena, flags); + } + + mutex_unlock(&gsl_driver.lock); + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_largestfreeblock. Return value %d\n", result ); + + return (result); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_map(gsl_deviceid_t device_id, gsl_flags_t flags, const gsl_scatterlist_t *scatterlist, gsl_memdesc_t *memdesc) +{ + int status = GSL_FAILURE; + gsl_sharedmem_t *shmem = &gsl_driver.shmem; + int aperture_index; + gsl_deviceid_t tmp_id; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_map(gsl_deviceid_t device_id=%D, gsl_flags_t flags=%x, gsl_scatterlist_t scatterlist=%S, gsl_memdesc_t *memdesc=%M)\n", + device_id, flags, memdesc, scatterlist ); + + // execute pending device action + tmp_id = (device_id != GSL_DEVICE_ANY) ? device_id : device_id+1; + for ( ; tmp_id <= GSL_DEVICE_MAX; tmp_id++) + { + if (gsl_driver.device[tmp_id-1].flags & GSL_FLAGS_INITIALIZED) + { + kgsl_device_runpending(&gsl_driver.device[tmp_id-1]); + + if (tmp_id == device_id) + { + break; + } + } + } + + // convert any device to an actual existing device + if (device_id == GSL_DEVICE_ANY) + { + for ( ; ; ) + { + device_id++; + + if (device_id <= GSL_DEVICE_MAX) + { + if (gsl_driver.device[device_id-1].flags & GSL_FLAGS_INITIALIZED) + { + break; + } + } + else + { + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_ERROR, "ERROR: Invalid device.\n" ); + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_map. Return value %B\n", GSL_FAILURE ); + return (GSL_FAILURE); + } + } + } + + DEBUG_ASSERT(device_id > GSL_DEVICE_ANY && device_id <= GSL_DEVICE_MAX); + + if (shmem->flags & GSL_FLAGS_INITIALIZED) + { + aperture_index = kgsl_sharedmem_getapertureindex(shmem, GSL_APERTURE_EMEM, GSL_CHANNEL_1); + + if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) + { + DEBUG_ASSERT(scatterlist->num); + DEBUG_ASSERT(scatterlist->pages); + + status = kgsl_memarena_alloc(shmem->apertures[aperture_index].memarena, flags, scatterlist->num *GSL_PAGESIZE, memdesc); + if (status == GSL_SUCCESS) + { + GSL_MEMDESC_APERTURE_SET(memdesc, aperture_index); + GSL_MEMDESC_DEVICE_SET(memdesc, device_id); + + // mark descriptor's memory as externally allocated -- i.e. outside GSL + GSL_MEMDESC_EXTALLOC_SET(memdesc, 1); + + status = kgsl_mmu_map(&gsl_driver.device[device_id-1].mmu, memdesc->gpuaddr, scatterlist, flags, current->tgid); + if (status != GSL_SUCCESS) + { + kgsl_memarena_free(shmem->apertures[aperture_index].memarena, memdesc); + } + } + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_map. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_unmap(gsl_memdesc_t *memdesc) +{ + return (kgsl_sharedmem_free0(memdesc, current->tgid)); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_getmap(const gsl_memdesc_t *memdesc, gsl_scatterlist_t *scatterlist) +{ + int status = GSL_SUCCESS; + int aperture_index; + gsl_deviceid_t device_id; + gsl_sharedmem_t *shmem; + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, + "--> int kgsl_sharedmem_getmap(gsl_memdesc_t *memdesc=%M, gsl_scatterlist_t scatterlist=%S)\n", + memdesc, scatterlist ); + + GSL_MEMDESC_APERTURE_GET(memdesc, aperture_index); + GSL_MEMDESC_DEVICE_GET(memdesc, device_id); + + shmem = &gsl_driver.shmem; + + if (shmem->flags & GSL_FLAGS_INITIALIZED) + { + DEBUG_ASSERT(scatterlist->num); + DEBUG_ASSERT(scatterlist->pages); + DEBUG_ASSERT(memdesc->gpuaddr >= shmem->apertures[aperture_index].memarena->gpubaseaddr); + DEBUG_ASSERT((memdesc->gpuaddr + memdesc->size) <= (shmem->apertures[aperture_index].memarena->gpubaseaddr + shmem->apertures[aperture_index].memarena->sizebytes)); + + memset(scatterlist->pages, 0, sizeof(unsigned int) * scatterlist->num); + + if (kgsl_memarena_isvirtualized(shmem->apertures[aperture_index].memarena)) + { + status = kgsl_mmu_getmap(&gsl_driver.device[device_id-1].mmu, memdesc->gpuaddr, memdesc->size, scatterlist, current->tgid); + } + else + { + // coalesce physically contiguous pages into a single scatter list entry + scatterlist->pages[0] = memdesc->gpuaddr; + scatterlist->contiguous = 1; + } + } + + kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_sharedmem_getmap. Return value %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_querystats(gsl_sharedmem_t *shmem, gsl_sharedmem_stats_t *stats) +{ +#ifdef GSL_STATS_MEM + int status = GSL_SUCCESS; + int i; + + DEBUG_ASSERT(stats); + + if (shmem->flags & GSL_FLAGS_INITIALIZED) + { + for (i = 0; i < shmem->numapertures; i++) + { + if (shmem->apertures[i].memarena) + { + stats->apertures[i].id = shmem->apertures[i].id; + stats->apertures[i].channel = shmem->apertures[i].channel; + + status |= kgsl_memarena_querystats(shmem->apertures[i].memarena, &stats->apertures[i].memarena); + } + } + } + else + { + memset(stats, 0, sizeof(gsl_sharedmem_stats_t)); + } + + return (status); +#else + // unreferenced formal parameters + (void) shmem; + (void) stats; + + return (GSL_FAILURE_NOTSUPPORTED); +#endif // GSL_STATS_MEM +} + +//---------------------------------------------------------------------------- + +unsigned int +kgsl_sharedmem_convertaddr(unsigned int addr, int type) +{ + gsl_sharedmem_t *shmem = &gsl_driver.shmem; + unsigned int cvtaddr = 0; + unsigned int gpubaseaddr, hostbaseaddr, sizebytes; + int i; + + if ((shmem->flags & GSL_FLAGS_INITIALIZED)) + { + for (i = 0; i < shmem->numapertures; i++) + { + hostbaseaddr = shmem->apertures[i].memarena->hostbaseaddr; + gpubaseaddr = shmem->apertures[i].memarena->gpubaseaddr; + sizebytes = shmem->apertures[i].memarena->sizebytes; + + // convert from gpu to host + if (type == 0) + { + if (addr >= gpubaseaddr && addr < (gpubaseaddr + sizebytes)) + { + cvtaddr = hostbaseaddr + (addr - gpubaseaddr); + break; + } + } + // convert from host to gpu + else if (type == 1) + { + if (addr >= hostbaseaddr && addr < (hostbaseaddr + sizebytes)) + { + cvtaddr = gpubaseaddr + (addr - hostbaseaddr); + break; + } + } + } + } + + return (cvtaddr); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_cacheoperation(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int sizebytes, unsigned int operation) +{ + int status = GSL_FAILURE; + + /* unreferenced formal parameter */ + (void)memdesc; + (void)offsetbytes; + (void)sizebytes; + (void)operation; + + /* do cache operation */ + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_sharedmem_fromhostpointer(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, void* hostptr) +{ + int status = GSL_FAILURE; + + memdesc->gpuaddr = (gpuaddr_t)hostptr; /* map physical address with hostptr */ + memdesc->hostptr = hostptr; /* set virtual address also in memdesc */ + + /* unreferenced formal parameter */ + (void)device_id; + + return (status); +} diff --git a/drivers/mxc/amd-gpu/gsl_tbdump.c b/drivers/mxc/amd-gpu/gsl_tbdump.c new file mode 100644 index 00000000000..0279f313a4a --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_tbdump.c @@ -0,0 +1,241 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include + +#include "gsl.h" +#include "gsl_tbdump.h" + +#ifdef TBDUMP + +typedef struct TBDump_ +{ + void* file; +} TBDump; + + +static TBDump g_tb; +static struct mutex *tbdump_mutex = NULL; + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +static void tbdump_printline(const char* format, ...) +{ + if(g_tb.file) + { + va_list va; + va_start(va, format); + vfprintf((FILE*)g_tb.file, format, va); + va_end(va); + fprintf((FILE*)g_tb.file, "\n"); + } +} + +static void tbdump_printinfo(const char* message ) +{ + tbdump_printline("15 %s", message); +} + +static void tbdump_getmemhex(char* buffer, unsigned int addr, unsigned int sizewords) +{ + unsigned int i = 0; + static const char* hexChars = "0123456789abcdef"; + unsigned char* ptr = (unsigned char*)addr; + + for (i = 0; i < sizewords; i++) + { + buffer[(sizewords - i) * 2 - 1] = hexChars[ptr[i] & 0x0f]; + buffer[(sizewords - i) * 2 - 2] = hexChars[ptr[i] >> 4]; + } + buffer[sizewords * 2] = '\0'; +} + +/* ------------------------------------------------------------------------ */ + +void tbdump_open(char* filename) +{ + if( !tbdump_mutex ) { + tbdump_mutex = (struct mutex *) kmalloc(sizeof(struct mutex), GFP_KERNEL); + if (tbdump_mutex) + mutex_init(tbdump_mutex); + } + + memset( &g_tb, 0, sizeof( g_tb ) ); + + g_tb.file = kos_fopen( filename, "wt" ); + + tbdump_printinfo("reset"); + tbdump_printline("0"); + tbdump_printline("1 00000000 00000eff"); + + /* Enable interrupts */ + tbdump_printline("1 00000000 00000003"); +} + +void tbdump_close() +{ + if (tbdump_mutex) + mutex_lock(tbdump_mutex); + + kos_fclose( g_tb.file ); + g_tb.file = 0; + + if( tbdump_mutex ) { + mutex_unlock(tbdump_mutex); + kfree( tbdump_mutex ); + } +} + +/* ------------------------------------------------------------------------ */ + +void tbdump_syncmem(unsigned int addr, unsigned int src, unsigned int sizebytes) +{ + /* Align starting address and size */ + unsigned int beg = addr; + unsigned int end = addr+sizebytes; + char buffer[65]; + + if (tbdump_mutex) + mutex_lock(tbdump_mutex); + + beg = (beg+15) & ~15; + end &= ~15; + + if( sizebytes <= 16 ) + { + tbdump_getmemhex(buffer, src, 16); + + tbdump_printline("19 %08x %i 1 %s", addr, sizebytes, buffer); + + if (tbdump_mutex) + mutex_unlock(tbdump_mutex); + return; + } + + /* Handle unaligned start */ + if( beg != addr ) + { + tbdump_getmemhex(buffer, src, 16); + + tbdump_printline("19 %08x %i 1 %s", addr, beg-addr, buffer); + + src += beg-addr; + } + + /* Dump the memory writes */ + while( beg < end ) + { + tbdump_getmemhex(buffer, src, 16); + + tbdump_printline("2 %08x %s", beg, buffer); + + beg += 16; + src += 16; + } + + /* Handle unaligned end */ + if( end != addr+sizebytes ) + { + tbdump_getmemhex(buffer, src, 16); + + tbdump_printline("19 %08x %i 1 %s", end, (addr+sizebytes)-end, buffer); + } + + if (tbdump_mutex) + mutex_unlock(tbdump_mutex); +} + +/* ------------------------------------------------------------------------ */ + +void tbdump_setmem(unsigned int addr, unsigned int value, unsigned int sizebytes) +{ + if (tbdump_mutex) + mutex_lock(tbdump_mutex); + + tbdump_printline("19 %08x 4 %i %032x", addr, (sizebytes+3)/4, value ); + + if (tbdump_mutex) + mutex_unlock(tbdump_mutex); +} + +/* ------------------------------------------------------------------------ */ + +void tbdump_slavewrite(unsigned int addr, unsigned int value) +{ + if (tbdump_mutex) + mutex_lock(tbdump_mutex); + + tbdump_printline("1 %08x %08x", addr, value); + + if (tbdump_mutex) + mutex_unlock(tbdump_mutex); +} + +/* ------------------------------------------------------------------------ */ + + +int +kgsl_tbdump_waitirq() +{ + if(!g_tb.file) return GSL_FAILURE; + + if (tbdump_mutex) + mutex_lock(tbdump_mutex); + + tbdump_printinfo("wait irq"); + tbdump_printline("10"); + + /* ACK IRQ */ + tbdump_printline("1 00000418 00000003"); + tbdump_printline("18 00000018 00000000 # slave read & assert"); + + if (tbdump_mutex) + mutex_unlock(tbdump_mutex); + + return GSL_SUCCESS; +} + +/* ------------------------------------------------------------------------ */ + +int +kgsl_tbdump_exportbmp(const void* addr, unsigned int format, unsigned int stride, unsigned int width, unsigned int height) +{ + static char filename[20]; + static int numframe = 0; + + if(!g_tb.file) return GSL_FAILURE; + + if (tbdump_mutex) + mutex_lock(tbdump_mutex); + + #pragma warning(disable:4996) + sprintf( filename, "tbdump_%08d.bmp", numframe++ ); + + tbdump_printline("13 %s %d %08x %d %d %d 0", filename, format, (unsigned int)addr, stride, width, height); + + if (tbdump_mutex) + mutex_unlock(tbdump_mutex); + + return GSL_SUCCESS; +} + +/* ------------------------------------------------------------------------ */ + +#endif /* TBDUMP */ diff --git a/drivers/mxc/amd-gpu/gsl_yamato.c b/drivers/mxc/amd-gpu/gsl_yamato.c new file mode 100644 index 00000000000..9b36ea96d46 --- /dev/null +++ b/drivers/mxc/amd-gpu/gsl_yamato.c @@ -0,0 +1,918 @@ +/* Copyright (c) 2002,2007-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include + +#include "gsl.h" +#include "gsl_hal.h" + +#ifdef GSL_BLD_YAMATO + +#include "gsl_ringbuffer.h" +#include "gsl_drawctxt.h" + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +static int +kgsl_yamato_gmeminit(gsl_device_t *device) +{ + rb_edram_info_u rb_edram_info = {0}; + unsigned int gmem_size; + unsigned int edram_value = 0; + + // make sure edram range is aligned to size + DEBUG_ASSERT((device->gmemspace.gpu_base & (device->gmemspace.sizebytes - 1)) == 0); + + // get edram_size value equivalent + gmem_size = (device->gmemspace.sizebytes >> 14); + while (gmem_size >>= 1) + { + edram_value++; + } + + rb_edram_info.f.edram_size = edram_value; + rb_edram_info.f.edram_mapping_mode = 0; // EDRAM_MAP_UPPER + rb_edram_info.f.edram_range = (device->gmemspace.gpu_base >> 14); // must be aligned to size + + device->ftbl.device_regwrite(device, mmRB_EDRAM_INFO, (unsigned int)rb_edram_info.val); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static int +kgsl_yamato_gmemclose(gsl_device_t *device) +{ + device->ftbl.device_regwrite(device, mmRB_EDRAM_INFO, 0x00000000); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +void +kgsl_yamato_rbbmintrcallback(gsl_intrid_t id, void *cookie) +{ + gsl_device_t *device = (gsl_device_t *) cookie; + + switch(id) + { + // error condition interrupt + case GSL_INTR_YDX_RBBM_READ_ERROR: + printk(KERN_ERR "GPU: Z430 RBBM Read Error\n"); + schedule_work(&device->irq_err_work); + break; + + // non-error condition interrupt + case GSL_INTR_YDX_RBBM_DISPLAY_UPDATE: + case GSL_INTR_YDX_RBBM_GUI_IDLE: + + complete_all(&device->intr.evnt[id]); + break; + + default: + + break; + } +} + +//---------------------------------------------------------------------------- + +void +kgsl_yamato_cpintrcallback(gsl_intrid_t id, void *cookie) +{ + gsl_device_t *device = (gsl_device_t *) cookie; + + switch(id) + { + case GSL_INTR_YDX_CP_RING_BUFFER: + wake_up_interruptible_all(&(device->timestamp_waitq)); + break; + default: + break; + } +} +//---------------------------------------------------------------------------- + +void +kgsl_yamato_sqintrcallback(gsl_intrid_t id, void *cookie) +{ + (void) cookie; // unreferenced formal parameter + /*gsl_device_t *device = (gsl_device_t *) cookie;*/ + + switch(id) + { + // error condition interrupt + case GSL_INTR_YDX_SQ_PS_WATCHDOG: + case GSL_INTR_YDX_SQ_VS_WATCHDOG: + + // todo: take appropriate action + + break; + + default: + + break; + } +} + +//---------------------------------------------------------------------------- + +#ifdef _DEBUG + +static int +kgsl_yamato_bist(gsl_device_t *device) +{ + int status = GSL_FAILURE; + unsigned int link[2]; + + if (!(device->flags & GSL_FLAGS_STARTED)) + { + return (GSL_FAILURE); + } + + status = kgsl_ringbuffer_bist(&device->ringbuffer); + if (status != GSL_SUCCESS) + { + return (status); + } + + // interrupt bist + link[0] = pm4_type3_packet(PM4_INTERRUPT, 1); + link[1] = CP_INT_CNTL__RB_INT_MASK; + kgsl_ringbuffer_issuecmds(device, 1, &link[0], 2, current->tgid); + + status = kgsl_mmu_bist(&device->mmu); + if (status != GSL_SUCCESS) + { + return (status); + } + + return (status); +} +#endif + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_isr(gsl_device_t *device) +{ + unsigned int status; +#ifdef _DEBUG + mh_mmu_page_fault_u page_fault = {0}; + mh_axi_error_u axi_error = {0}; + mh_clnt_axi_id_reuse_u clnt_axi_id_reuse = {0}; + rbbm_read_error_u read_error = {0}; +#endif // DEBUG + + // determine if yamato is interrupting, and if so, which block + device->ftbl.device_regread(device, mmMASTER_INT_SIGNAL, &status); + + if (status & MASTER_INT_SIGNAL__MH_INT_STAT) + { +#ifdef _DEBUG + // obtain mh error information + device->ftbl.device_regread(device, mmMH_MMU_PAGE_FAULT, (unsigned int *)&page_fault); + device->ftbl.device_regread(device, mmMH_AXI_ERROR, (unsigned int *)&axi_error); + device->ftbl.device_regread(device, mmMH_CLNT_AXI_ID_REUSE, (unsigned int *)&clnt_axi_id_reuse); +#endif // DEBUG + + kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_MH); + } + + if (status & MASTER_INT_SIGNAL__CP_INT_STAT) + { + kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_CP); + } + + if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) + { +#ifdef _DEBUG + // obtain rbbm error information + device->ftbl.device_regread(device, mmRBBM_READ_ERROR, (unsigned int *)&read_error); +#endif // DEBUG + + kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_RBBM); + } + + if (status & MASTER_INT_SIGNAL__SQ_INT_STAT) + { + kgsl_intr_decode(device, GSL_INTR_BLOCK_YDX_SQ); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_tlbinvalidate(gsl_device_t *device, unsigned int reg_invalidate, unsigned int pid) +{ + unsigned int link[2]; + mh_mmu_invalidate_u mh_mmu_invalidate = {0}; + + mh_mmu_invalidate.f.invalidate_all = 1; + mh_mmu_invalidate.f.invalidate_tc = 1; + + // if possible, invalidate via command stream, otherwise via direct register writes + if (device->flags & GSL_FLAGS_STARTED) + { + link[0] = pm4_type0_packet(reg_invalidate, 1); + link[1] = mh_mmu_invalidate.val; + + kgsl_ringbuffer_issuecmds(device, 1, &link[0], 2, pid); + } + else + { + + device->ftbl.device_regwrite(device, reg_invalidate, mh_mmu_invalidate.val); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_setpagetable(gsl_device_t *device, unsigned int reg_ptbase, gpuaddr_t ptbase, unsigned int pid) +{ + unsigned int link[25]; + + // if there is an active draw context, set via command stream, + if (device->flags & GSL_FLAGS_STARTED) + { + // wait for graphics pipe to be idle + link[0] = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + link[1] = 0x00000000; + + // set page table base + link[2] = pm4_type0_packet(reg_ptbase, 1); + link[3] = ptbase; + + // HW workaround: to resolve MMU page fault interrupts caused by the VGT. It prevents + // the CP PFP from filling the VGT DMA request fifo too early, thereby ensuring that + // the VGT will not fetch vertex/bin data until after the page table base register + // has been updated. + // + // Two null DRAW_INDX_BIN packets are inserted right after the page table base update, + // followed by a wait for idle. The null packets will fill up the VGT DMA request + // fifo and prevent any further vertex/bin updates from occurring until the wait + // has finished. + link[4] = pm4_type3_packet(PM4_SET_CONSTANT, 2); + link[5] = (0x4 << 16) | (mmPA_SU_SC_MODE_CNTL - 0x2000); + link[6] = 0; // disable faceness generation + link[7] = pm4_type3_packet(PM4_SET_BIN_BASE_OFFSET, 1); + link[8] = device->mmu.dummyspace.gpuaddr; + link[9] = pm4_type3_packet(PM4_DRAW_INDX_BIN, 6); + link[10] = 0; // viz query info + link[11] = 0x0003C004; // draw indicator + link[12] = 0; // bin base + link[13] = 3; // bin size + link[14] = device->mmu.dummyspace.gpuaddr; // dma base + link[15] = 6; // dma size + link[16] = pm4_type3_packet(PM4_DRAW_INDX_BIN, 6); + link[17] = 0; // viz query info + link[18] = 0x0003C004; // draw indicator + link[19] = 0; // bin base + link[20] = 3; // bin size + link[21] = device->mmu.dummyspace.gpuaddr; // dma base + link[22] = 6; // dma size + link[23] = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + link[24] = 0x00000000; + + kgsl_ringbuffer_issuecmds(device, 1, &link[0], 25, pid); + } + else + { + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + device->ftbl.device_regwrite(device, reg_ptbase, ptbase); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +static void kgsl_yamato_irqerr(struct work_struct *work) +{ + gsl_device_t *device = &gsl_driver.device[GSL_DEVICE_YAMATO-1]; + device->ftbl.device_destroy(device); +} + +int +kgsl_yamato_init(gsl_device_t *device) +{ + int status = GSL_FAILURE; + + device->flags |= GSL_FLAGS_INITIALIZED; + + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_ON, 100); + + //We need to make sure all blocks are powered up and clocked before + //issuing a soft reset. The overrides will be turned off (set to 0) + //later in kgsl_yamato_start. + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, 0xfffffffe); + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, 0xffffffff); + + // soft reset + device->ftbl.device_regwrite(device, mmRBBM_SOFT_RESET, 0xFFFFFFFF); + msleep(50); + device->ftbl.device_regwrite(device, mmRBBM_SOFT_RESET, 0x00000000); + + // RBBM control + device->ftbl.device_regwrite(device, mmRBBM_CNTL, 0x00004442); + + // setup MH arbiter + device->ftbl.device_regwrite(device, mmMH_ARBITER_CONFIG, *(unsigned int *) &gsl_cfg_yamato_mharb); + + // SQ_*_PROGRAM + device->ftbl.device_regwrite(device, mmSQ_VS_PROGRAM, 0x00000000); + device->ftbl.device_regwrite(device, mmSQ_PS_PROGRAM, 0x00000000); + + // init interrupt + status = kgsl_intr_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } + + // init mmu + status = kgsl_mmu_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } + + /* handle error condition */ + INIT_WORK(&device->irq_err_work, kgsl_yamato_irqerr); + + return(status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_close(gsl_device_t *device) +{ + if (device->refcnt == 0) + { + // shutdown mmu + kgsl_mmu_close(device); + + // shutdown interrupt + kgsl_intr_close(device); + + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_POWER_OFF, 0); + + device->flags &= ~GSL_FLAGS_INITIALIZED; + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_destroy(gsl_device_t *device) +{ + int i; + unsigned int pid; + +#ifdef _DEBUG + // for now, signal catastrophic failure in a brute force way + DEBUG_ASSERT(0); +#endif // _DEBUG + + // todo: - hard reset core? + + kgsl_drawctxt_destroyall(device); + + for (i = 0; i < GSL_CALLER_PROCESS_MAX; i++) + { + pid = device->callerprocess[i]; + if (pid) + { + device->ftbl.device_stop(device); + kgsl_driver_destroy(pid); + + // todo: terminate client process? + } + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_start(gsl_device_t *device, gsl_flags_t flags) +{ + int status = GSL_FAILURE; + unsigned int pm1, pm2; + + KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPFBSTART(device)); + + (void) flags; // unreferenced formal parameter + + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_ON, 100); + + // default power management override when running in safe mode + pm1 = (device->flags & GSL_FLAGS_SAFEMODE) ? 0xFFFFFFFE : 0x00000000; + pm2 = (device->flags & GSL_FLAGS_SAFEMODE) ? 0x000000FF : 0x00000000; + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, pm1); + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, pm2); + + // enable rbbm interrupts + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_RBBM_READ_ERROR, kgsl_yamato_rbbmintrcallback, (void *) device); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_RBBM_DISPLAY_UPDATE, kgsl_yamato_rbbmintrcallback, (void *) device); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_RBBM_GUI_IDLE, kgsl_yamato_rbbmintrcallback, (void *) device); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_RBBM_READ_ERROR); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_RBBM_DISPLAY_UPDATE); +#if defined GSL_RB_TIMESTAMP_INTERUPT + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER, kgsl_yamato_cpintrcallback, (void *) device); + kgsl_intr_enable(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER); +#endif + + //kgsl_intr_enable(&device->intr, GSL_INTR_YDX_RBBM_GUI_IDLE); + + // enable sq interrupts + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_SQ_PS_WATCHDOG, kgsl_yamato_sqintrcallback, (void *) device); + kgsl_intr_attach(&device->intr, GSL_INTR_YDX_SQ_VS_WATCHDOG, kgsl_yamato_sqintrcallback, (void *) device); + //kgsl_intr_enable(&device->intr, GSL_INTR_YDX_SQ_PS_WATCHDOG); + //kgsl_intr_enable(&device->intr, GSL_INTR_YDX_SQ_VS_WATCHDOG); + + // init gmem + kgsl_yamato_gmeminit(device); + + // init ring buffer + status = kgsl_ringbuffer_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } + + // init draw context + status = kgsl_drawctxt_init(device); + if (status != GSL_SUCCESS) + { + device->ftbl.device_stop(device); + return (status); + } + + device->flags |= GSL_FLAGS_STARTED; + + KGSL_DEBUG(GSL_DBGFLAGS_BIST, kgsl_yamato_bist(device)); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_stop(gsl_device_t *device) +{ + // HW WORKAROUND: Ringbuffer hangs during next start if it is stopped without any + // commands ever being submitted. To avoid this, submit a dummy wait packet. + unsigned int cmds[2]; + cmds[0] = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1); + cmds[0] = 0; + kgsl_ringbuffer_issuecmds(device, 0, cmds, 2, current->tgid); + + // disable rbbm interrupts + kgsl_intr_detach(&device->intr, GSL_INTR_YDX_RBBM_READ_ERROR); + kgsl_intr_detach(&device->intr, GSL_INTR_YDX_RBBM_DISPLAY_UPDATE); + kgsl_intr_detach(&device->intr, GSL_INTR_YDX_RBBM_GUI_IDLE); +#if defined GSL_RB_TIMESTAMP_INTERUPT + kgsl_intr_detach(&device->intr, GSL_INTR_YDX_CP_RING_BUFFER); +#endif + + // disable sq interrupts + kgsl_intr_detach(&device->intr, GSL_INTR_YDX_SQ_PS_WATCHDOG); + kgsl_intr_detach(&device->intr, GSL_INTR_YDX_SQ_VS_WATCHDOG); + + kgsl_drawctxt_close(device); + + // shutdown ringbuffer + kgsl_ringbuffer_close(&device->ringbuffer); + + // shutdown gmem + kgsl_yamato_gmemclose(device); + + if(device->refcnt == 0) + { + kgsl_hal_setpowerstate(device->id, GSL_PWRFLAGS_CLK_OFF, 0); + } + + device->flags &= ~GSL_FLAGS_STARTED; + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_getproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) +{ + int status = GSL_FAILURE; + +#ifndef _DEBUG + (void) sizebytes; // unreferenced formal parameter +#endif + + if (type == GSL_PROP_DEVICE_INFO) + { + gsl_devinfo_t *devinfo = (gsl_devinfo_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_devinfo_t)); + + devinfo->device_id = device->id; + devinfo->chip_id = (gsl_chipid_t)device->chip_id; + devinfo->mmu_enabled = kgsl_mmu_isenabled(&device->mmu); + devinfo->gmem_hostbaseaddr = device->gmemspace.mmio_virt_base; + devinfo->gmem_gpubaseaddr = device->gmemspace.gpu_base; + devinfo->gmem_sizebytes = device->gmemspace.sizebytes; + devinfo->high_precision = 0; + + status = GSL_SUCCESS; + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_setproperty(gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes) +{ + int status = GSL_FAILURE; + +#ifndef _DEBUG + (void) sizebytes; // unreferenced formal parameter +#endif + + if (type == GSL_PROP_DEVICE_POWER) + { + gsl_powerprop_t *power = (gsl_powerprop_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_powerprop_t)); + + if (!(device->flags & GSL_FLAGS_SAFEMODE)) + { + if (power->flags & GSL_PWRFLAGS_OVERRIDE_ON) + { + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, 0xfffffffe); + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, 0xffffffff); + } + else if (power->flags & GSL_PWRFLAGS_OVERRIDE_OFF) + { + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE1, 0x00000000); + device->ftbl.device_regwrite(device, mmRBBM_PM_OVERRIDE2, 0x00000000); + } + else + { + kgsl_hal_setpowerstate(device->id, power->flags, power->value); + } + } + + status = GSL_SUCCESS; + } + else if (type == GSL_PROP_DEVICE_DMI) + { + gsl_dmiprop_t *dmi = (gsl_dmiprop_t *) value; + + DEBUG_ASSERT(sizebytes == sizeof(gsl_dmiprop_t)); + + // + // In order to enable DMI, it must not already be enabled. + // + switch (dmi->flags) + { + case GSL_DMIFLAGS_ENABLE_SINGLE: + case GSL_DMIFLAGS_ENABLE_DOUBLE: + if (!gsl_driver.dmi_state) + { + gsl_driver.dmi_state = OS_TRUE; + gsl_driver.dmi_mode = dmi->flags; + gsl_driver.dmi_frame = -1; + status = GSL_SUCCESS; + } + break; + case GSL_DMIFLAGS_DISABLE: + // + // To disable, we must be enabled. + // + if (gsl_driver.dmi_state) + { + gsl_driver.dmi_state = OS_FALSE; + gsl_driver.dmi_mode = -1; + gsl_driver.dmi_frame = -2; + status = GSL_SUCCESS; + } + break; + case GSL_DMIFLAGS_NEXT_BUFFER: + // + // Going to the next buffer is dependent upon what mod we are in with respect to single, double, or triple buffering. + // DMI must also be enabled. + // + if (gsl_driver.dmi_state) + { + unsigned int cmdbuf[10]; + unsigned int *cmds = &cmdbuf[0]; + int size; + + if (gsl_driver.dmi_frame == -1) + { + size = 8; + + *cmds++ = pm4_type0_packet(mmRBBM_DSPLY, 1); + switch (gsl_driver.dmi_mode) + { + case GSL_DMIFLAGS_ENABLE_SINGLE: + gsl_driver.dmi_max_frame = 1; + *cmds++ = 0x041000410; + break; + case GSL_DMIFLAGS_ENABLE_DOUBLE: + gsl_driver.dmi_max_frame = 2; + *cmds++ = 0x041000510; + break; + case GSL_DMIFLAGS_ENABLE_TRIPLE: + gsl_driver.dmi_max_frame = 3; + *cmds++ = 0x041000610; + break; + } + } + else + { + size = 6; + } + + + // + // Wait for 3D core to be idle and wait for vsync + // + *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); + *cmds++ = 0x00008000; // 3d idle + // *cmds++ = 0x00008008; // 3d idle & vsync + + // + // Update the render latest register. + // + *cmds++ = pm4_type0_packet(mmRBBM_RENDER_LATEST, 1); + switch (gsl_driver.dmi_frame) + { + case 0: + // + // Render frame 0 + // + *cmds++ = 0; + // + // Wait for our max frame # indicator to be de-asserted + // + *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); + *cmds++ = 0x00000008 << gsl_driver.dmi_max_frame; + gsl_driver.dmi_frame = 1; + break; + case -1: + case 1: + // + // Render frame 1 + // + *cmds++ = 1; + *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); + *cmds++ = 0x00000010; // Wait for frame 0 to be deasserted + gsl_driver.dmi_frame = 2; + break; + case 2: + // + // Render frame 2 + // + *cmds++ = 2; + *cmds++ = pm4_type0_packet(mmWAIT_UNTIL, 1); + *cmds++ = 0x00000020; // Wait for frame 1 to be deasserted + gsl_driver.dmi_frame = 0; + break; + } + + // issue the commands + kgsl_ringbuffer_issuecmds(device, 1, &cmdbuf[0], size, current->tgid); + + gsl_driver.dmi_frame %= gsl_driver.dmi_max_frame; + status = GSL_SUCCESS; + } + break; + default: + status = GSL_FAILURE; + break; + } + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_idle(gsl_device_t *device, unsigned int timeout) +{ + int status = GSL_FAILURE; + gsl_ringbuffer_t *rb = &device->ringbuffer; + rbbm_status_u rbbm_status; + + (void) timeout; // unreferenced formal parameter + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, KGSL_DEBUG_DUMPX(BB_DUMP_REGPOLL, device->id, mmRBBM_STATUS, 0x80000000, "kgsl_yamato_idle")); + + // first, wait until the CP has consumed all the commands in the ring buffer + if (rb->flags & GSL_FLAGS_STARTED) + { + do + { + GSL_RB_GET_READPTR(rb, &rb->rptr); + + } while (rb->rptr != rb->wptr); + } + + // now, wait for the GPU to finish its operations + for ( ; ; ) + { + device->ftbl.device_regread(device, mmRBBM_STATUS, (unsigned int *)&rbbm_status); + + if (!(rbbm_status.val & 0x80000000)) + { + status = GSL_SUCCESS; + break; + } + + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_regread(gsl_device_t *device, unsigned int offsetwords, unsigned int *value) +{ + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + if (!(gsl_driver.flags_debug & GSL_DBGFLAGS_DUMPX_WITHOUT_IFH)) + { + if(offsetwords == mmCP_RB_RPTR || offsetwords == mmCP_RB_WPTR) + { + *value = device->ringbuffer.wptr; + return (GSL_SUCCESS); + } + } + }); + + GSL_HAL_REG_READ(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_regwrite(gsl_device_t *device, unsigned int offsetwords, unsigned int value) +{ + KGSL_DEBUG(GSL_DBGFLAGS_PM4, KGSL_DEBUG_DUMPREGWRITE(offsetwords, value)); + + GSL_HAL_REG_WRITE(device->id, (unsigned int) device->regspace.mmio_virt_base, offsetwords, value); + + // idle device when running in safe mode + if (device->flags & GSL_FLAGS_SAFEMODE) + { + device->ftbl.device_idle(device, GSL_TIMEOUT_DEFAULT); + } + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_waitirq(gsl_device_t *device, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout) +{ + int status = GSL_FAILURE_NOTSUPPORTED; + + if (intr_id == GSL_INTR_YDX_CP_IB1_INT || intr_id == GSL_INTR_YDX_CP_IB2_INT || + intr_id == GSL_INTR_YDX_CP_SW_INT || intr_id == GSL_INTR_YDX_RBBM_DISPLAY_UPDATE) + { + if (kgsl_intr_isenabled(&device->intr, intr_id) == GSL_SUCCESS) + { + // wait until intr completion event is received + int complete = OS_SUCCESS; + + if (timeout != OS_INFINITE) + complete = wait_for_completion_timeout(&device->intr.evnt[intr_id], msecs_to_jiffies(timeout)); + else + wait_for_completion_killable(&device->intr.evnt[intr_id]); + + if (complete == OS_SUCCESS) + { + *count = 1; + status = GSL_SUCCESS; + } + else + { + status = GSL_FAILURE_TIMEOUT; + } + } + } + + return (status); +} + +int kgsl_yamato_check_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp) +{ + int i; + /* Reason to use a wait loop: + * When bus is busy, for example vpu is working too, the timestamp is + * possiblly not yet refreshed to memory by yamato. For most cases, it + * will hit on first loop cycle. So it don't effect performance. + */ + for (i = 0; i < 10; i++) { + if (kgsl_cmdstream_check_timestamp(device_id, timestamp)) + return 1; + udelay(10); + } + return 0; +} + +int +kgsl_yamato_waittimestamp(gsl_device_t *device, gsl_timestamp_t timestamp, unsigned int timeout) +{ +#if defined GSL_RB_TIMESTAMP_INTERUPT + int status = wait_event_interruptible_timeout(device->timestamp_waitq, + kgsl_yamato_check_timestamp(device->id, timestamp), + msecs_to_jiffies(timeout)); + if (status > 0) + return GSL_SUCCESS; + else + return GSL_FAILURE; +#else + return (GSL_SUCCESS); +#endif +} +//---------------------------------------------------------------------------- + +int +kgsl_yamato_runpending(gsl_device_t *device) +{ + (void) device; + + return (GSL_SUCCESS); +} + +//---------------------------------------------------------------------------- + +int +kgsl_yamato_getfunctable(gsl_functable_t *ftbl) +{ + ftbl->device_init = kgsl_yamato_init; + ftbl->device_close = kgsl_yamato_close; + ftbl->device_destroy = kgsl_yamato_destroy; + ftbl->device_start = kgsl_yamato_start; + ftbl->device_stop = kgsl_yamato_stop; + ftbl->device_getproperty = kgsl_yamato_getproperty; + ftbl->device_setproperty = kgsl_yamato_setproperty; + ftbl->device_idle = kgsl_yamato_idle; + ftbl->device_waittimestamp = kgsl_yamato_waittimestamp; + ftbl->device_regread = kgsl_yamato_regread; + ftbl->device_regwrite = kgsl_yamato_regwrite; + ftbl->device_waitirq = kgsl_yamato_waitirq; + ftbl->device_runpending = kgsl_yamato_runpending; + ftbl->intr_isr = kgsl_yamato_isr; + ftbl->mmu_tlbinvalidate = kgsl_yamato_tlbinvalidate; + ftbl->mmu_setpagetable = kgsl_yamato_setpagetable; + ftbl->cmdstream_issueibcmds = kgsl_ringbuffer_issueibcmds; + ftbl->context_create = kgsl_drawctxt_create; + ftbl->context_destroy = kgsl_drawctxt_destroy; + + return (GSL_SUCCESS); +} + +#endif + diff --git a/drivers/mxc/amd-gpu/include/api/gsl_displayapi.h b/drivers/mxc/amd-gpu/include/api/gsl_displayapi.h index 7ec10b0c255..aa770b3e143 100644 --- a/drivers/mxc/amd-gpu/include/api/gsl_displayapi.h +++ b/drivers/mxc/amd-gpu/include/api/gsl_displayapi.h @@ -25,7 +25,7 @@ * POSSIBILITY OF SUCH DAMAGE. * */ - + #ifndef __GSL_DISPLAYAPI_H #define __GSL_DISPLAYAPI_H @@ -33,19 +33,7 @@ extern "C" { #endif // __cplusplus -////////////////////////////////////////////////////////////////////////////// -// entrypoints -////////////////////////////////////////////////////////////////////////////// -#ifdef __GSLDISPLAY_EXPORTS -#define DISP_API OS_DLLEXPORT -#else -#define DISP_API OS_DLLIMPORT -#endif // __GSLDISPLAY_EXPORTS - - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// +// defines #define GSL_DISPLAY_PANEL_TOSHIBA_640x480 0 #define GSL_DISPLAY_PANEL_HITACHI_240x320 1 #define GSL_DISPLAY_PANEL_DEFAULT GSL_DISPLAY_PANEL_TOSHIBA_640x480 @@ -70,14 +58,14 @@ typedef struct _gsl_displaymode_t { ////////////////////////////////////////////////////////////////////////////// // prototypes ////////////////////////////////////////////////////////////////////////////// -DISP_API gsl_display_id_t gsl_display_open(gsl_devhandle_t devhandle, int panel_id); -DISP_API int gsl_display_close(gsl_display_id_t display_id); -DISP_API int gsl_display_getcount(void); -DISP_API int gsl_display_setmode(gsl_display_id_t display_id, gsl_displaymode_t displaymode); -DISP_API int gsl_display_getmode(gsl_display_id_t display_id, gsl_displaymode_t *displaymode); -DISP_API gsl_surface_id_t gsl_display_setsurface(gsl_display_id_t display_id, void *buffer); -DISP_API int gsl_display_getactivesurface(gsl_display_id_t display_id, void **buffer); -DISP_API int gsl_display_flipsurface(gsl_display_id_t display_id, gsl_surface_id_t surface_id); +extern gsl_display_id_t gsl_display_open(gsl_devhandle_t devhandle, int panel_id); +extern int gsl_display_close(gsl_display_id_t display_id); +extern int gsl_display_getcount(void); +extern int gsl_display_setmode(gsl_display_id_t display_id, gsl_displaymode_t displaymode); +extern int gsl_display_getmode(gsl_display_id_t display_id, gsl_displaymode_t *displaymode); +extern gsl_surface_id_t gsl_display_setsurface(gsl_display_id_t display_id, void *buffer); +extern int gsl_display_getactivesurface(gsl_display_id_t display_id, void **buffer); +extern int gsl_display_flipsurface(gsl_display_id_t display_id, gsl_surface_id_t surface_id); #ifdef __cplusplus } diff --git a/drivers/mxc/amd-gpu/include/api/gsl_klibapi.h b/drivers/mxc/amd-gpu/include/api/gsl_klibapi.h index c8831840ad1..82ddbaaf91a 100644 --- a/drivers/mxc/amd-gpu/include/api/gsl_klibapi.h +++ b/drivers/mxc/amd-gpu/include/api/gsl_klibapi.h @@ -36,23 +36,8 @@ extern "C" { #include "gsl_types.h" #include "gsl_properties.h" - -////////////////////////////////////////////////////////////////////////////// -// entrypoints -////////////////////////////////////////////////////////////////////////////// -#ifdef __KGSLLIB_EXPORTS -#define KGSL_API OS_DLLEXPORT -#else -#ifdef __KERNEL_MODE__ -#define KGSL_API extern -#else -#define KGSL_API OS_DLLIMPORT -#endif -#endif // __KGSLLIB_EXPORTS - - ////////////////////////////////////////////////////////////////////////////// -// version control +// version control ////////////////////////////////////////////////////////////////////////////// #define KGSLLIB_NAME "AMD GSL Kernel Library" #define KGSLLIB_VERSION "0.1" @@ -61,73 +46,73 @@ extern "C" { ////////////////////////////////////////////////////////////////////////////// // library API ////////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_driver_init(void); -KGSL_API int kgsl_driver_close(void); -KGSL_API int kgsl_driver_entry(gsl_flags_t flags); -KGSL_API int kgsl_driver_exit(void); -KGSL_API int kgsl_driver_destroy(unsigned int pid); +int kgsl_driver_init(void); +int kgsl_driver_close(void); +int kgsl_driver_entry(gsl_flags_t flags); +int kgsl_driver_exit(void); +int kgsl_driver_destroy(unsigned int pid); //////////////////////////////////////////////////////////////////////////// // device API //////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_device_start(gsl_deviceid_t device_id, gsl_flags_t flags); -KGSL_API int kgsl_device_stop(gsl_deviceid_t device_id); -KGSL_API int kgsl_device_idle(gsl_deviceid_t device_id, unsigned int timeout); -KGSL_API int kgsl_device_isidle(gsl_deviceid_t device_id); -KGSL_API int kgsl_device_getproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes); -KGSL_API int kgsl_device_setproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes); -KGSL_API int kgsl_device_regread(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int *value); -KGSL_API int kgsl_device_regwrite(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int value); -KGSL_API int kgsl_device_waitirq(gsl_deviceid_t device_id, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout); +int kgsl_device_start(gsl_deviceid_t device_id, gsl_flags_t flags); +int kgsl_device_stop(gsl_deviceid_t device_id); +int kgsl_device_idle(gsl_deviceid_t device_id, unsigned int timeout); +int kgsl_device_isidle(gsl_deviceid_t device_id); +int kgsl_device_getproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes); +int kgsl_device_setproperty(gsl_deviceid_t device_id, gsl_property_type_t type, void *value, unsigned int sizebytes); +int kgsl_device_regread(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int *value); +int kgsl_device_regwrite(gsl_deviceid_t device_id, unsigned int offsetwords, unsigned int value); +int kgsl_device_waitirq(gsl_deviceid_t device_id, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout); //////////////////////////////////////////////////////////////////////////// // command API //////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_cmdstream_issueibcmds(gsl_deviceid_t device_id, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, gsl_flags_t flags); -KGSL_API gsl_timestamp_t kgsl_cmdstream_readtimestamp(gsl_deviceid_t device_id, gsl_timestamp_type_t type); -KGSL_API int kgsl_cmdstream_freememontimestamp(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, gsl_timestamp_t timestamp, gsl_timestamp_type_t type); -KGSL_API int kgsl_cmdstream_waittimestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp, unsigned int timeout); -KGSL_API int kgsl_cmdwindow_write(gsl_deviceid_t device_id, gsl_cmdwindow_t target, unsigned int addr, unsigned int data); -KGSL_API int kgsl_add_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t *timestamp); -KGSL_API int kgsl_cmdstream_check_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp); +int kgsl_cmdstream_issueibcmds(gsl_deviceid_t device_id, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, gsl_flags_t flags); +gsl_timestamp_t kgsl_cmdstream_readtimestamp(gsl_deviceid_t device_id, gsl_timestamp_type_t type); +int kgsl_cmdstream_freememontimestamp(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, gsl_timestamp_t timestamp, gsl_timestamp_type_t type); +int kgsl_cmdstream_waittimestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp, unsigned int timeout); +int kgsl_cmdwindow_write(gsl_deviceid_t device_id, gsl_cmdwindow_t target, unsigned int addr, unsigned int data); +int kgsl_add_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t *timestamp); +int kgsl_cmdstream_check_timestamp(gsl_deviceid_t device_id, gsl_timestamp_t timestamp); //////////////////////////////////////////////////////////////////////////// // context API //////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_context_create(gsl_deviceid_t device_id, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags); -KGSL_API int kgsl_context_destroy(gsl_deviceid_t device_id, unsigned int drawctxt_id); -KGSL_API int kgsl_drawctxt_bind_gmem_shadow(gsl_deviceid_t device_id, unsigned int drawctxt_id, const gsl_rect_t* gmem_rect, unsigned int shadow_x, unsigned int shadow_y, const gsl_buffer_desc_t* shadow_buffer, unsigned int buffer_id); +int kgsl_context_create(gsl_deviceid_t device_id, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags); +int kgsl_context_destroy(gsl_deviceid_t device_id, unsigned int drawctxt_id); +int kgsl_drawctxt_bind_gmem_shadow(gsl_deviceid_t device_id, unsigned int drawctxt_id, const gsl_rect_t* gmem_rect, unsigned int shadow_x, unsigned int shadow_y, const gsl_buffer_desc_t* shadow_buffer, unsigned int buffer_id); //////////////////////////////////////////////////////////////////////////// // sharedmem API //////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_sharedmem_alloc(gsl_deviceid_t device_id, gsl_flags_t flags, int sizebytes, gsl_memdesc_t *memdesc); -KGSL_API int kgsl_sharedmem_free(gsl_memdesc_t *memdesc); -KGSL_API int kgsl_sharedmem_read(const gsl_memdesc_t *memdesc, void *dst, unsigned int offsetbytes, unsigned int sizebytes, unsigned int touserspace); -KGSL_API int kgsl_sharedmem_write(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, void *src, unsigned int sizebytes, unsigned int fromuserspace); -KGSL_API int kgsl_sharedmem_set(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes); -KGSL_API unsigned int kgsl_sharedmem_largestfreeblock(gsl_deviceid_t device_id, gsl_flags_t flags); -KGSL_API int kgsl_sharedmem_map(gsl_deviceid_t device_id, gsl_flags_t flags, const gsl_scatterlist_t *scatterlist, gsl_memdesc_t *memdesc); -KGSL_API int kgsl_sharedmem_unmap(gsl_memdesc_t *memdesc); -KGSL_API int kgsl_sharedmem_getmap(const gsl_memdesc_t *memdesc, gsl_scatterlist_t *scatterlist); -KGSL_API int kgsl_sharedmem_cacheoperation(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int sizebytes, unsigned int operation); -KGSL_API int kgsl_sharedmem_fromhostpointer(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, void* hostptr); +int kgsl_sharedmem_alloc(gsl_deviceid_t device_id, gsl_flags_t flags, int sizebytes, gsl_memdesc_t *memdesc); +int kgsl_sharedmem_free(gsl_memdesc_t *memdesc); +int kgsl_sharedmem_read(const gsl_memdesc_t *memdesc, void *dst, unsigned int offsetbytes, unsigned int sizebytes, unsigned int touserspace); +int kgsl_sharedmem_write(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, void *src, unsigned int sizebytes, unsigned int fromuserspace); +int kgsl_sharedmem_set(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes); +unsigned int kgsl_sharedmem_largestfreeblock(gsl_deviceid_t device_id, gsl_flags_t flags); +int kgsl_sharedmem_map(gsl_deviceid_t device_id, gsl_flags_t flags, const gsl_scatterlist_t *scatterlist, gsl_memdesc_t *memdesc); +int kgsl_sharedmem_unmap(gsl_memdesc_t *memdesc); +int kgsl_sharedmem_getmap(const gsl_memdesc_t *memdesc, gsl_scatterlist_t *scatterlist); +int kgsl_sharedmem_cacheoperation(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int sizebytes, unsigned int operation); +int kgsl_sharedmem_fromhostpointer(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, void* hostptr); //////////////////////////////////////////////////////////////////////////// // interrupt API //////////////////////////////////////////////////////////////////////////// -KGSL_API void kgsl_intr_isr(gsl_device_t *device); +void kgsl_intr_isr(gsl_device_t *device); //////////////////////////////////////////////////////////////////////////// // TB dump API //////////////////////////////////////////////////////////////////////////// -KGSL_API int kgsl_tbdump_waitirq(void); -KGSL_API int kgsl_tbdump_exportbmp(const void* addr, unsigned int format, unsigned int stride, unsigned int width, unsigned int height); +int kgsl_tbdump_waitirq(void); +int kgsl_tbdump_exportbmp(const void* addr, unsigned int format, unsigned int stride, unsigned int width, unsigned int height); #ifdef __cplusplus } diff --git a/drivers/mxc/amd-gpu/include/api/gsl_libapi.h b/drivers/mxc/amd-gpu/include/api/gsl_libapi.h index 3d359e24f57..973d9fbbd81 100644 --- a/drivers/mxc/amd-gpu/include/api/gsl_libapi.h +++ b/drivers/mxc/amd-gpu/include/api/gsl_libapi.h @@ -35,106 +35,67 @@ extern "C" { #include "gsl_types.h" -////////////////////////////////////////////////////////////////////////////// -// entrypoints -////////////////////////////////////////////////////////////////////////////// -#ifdef __GSLLIB_EXPORTS -#define GSL_API OS_DLLEXPORT -#else -#define GSL_API OS_DLLIMPORT -#endif // __GSLLIB_EXPORTS - - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// +// defines #define GSLLIB_NAME "AMD GSL User Library" #define GSLLIB_VERSION "0.1" -////////////////////////////////////////////////////////////////////////////// // libary API -////////////////////////////////////////////////////////////////////////////// -GSL_API int gsl_library_open(gsl_flags_t flags); -GSL_API int gsl_library_close(void); +int gsl_library_open(gsl_flags_t flags); +int gsl_library_close(void); -//////////////////////////////////////////////////////////////////////////// // device API -//////////////////////////////////////////////////////////////////////////// -GSL_API gsl_devhandle_t gsl_device_open(gsl_deviceid_t device_id, gsl_flags_t flags); -GSL_API int gsl_device_close(gsl_devhandle_t devhandle); -GSL_API int gsl_device_idle(gsl_devhandle_t devhandle, unsigned int timeout); -GSL_API int gsl_device_isidle(gsl_devhandle_t devhandle); -GSL_API int gsl_device_getcount(void); -GSL_API int gsl_device_getinfo(gsl_devhandle_t devhandle, gsl_devinfo_t *devinfo); -GSL_API int gsl_device_setpowerstate(gsl_devhandle_t devhandle, gsl_flags_t flags); -GSL_API int gsl_device_setdmistate(gsl_devhandle_t devhandle, gsl_flags_t flags); -GSL_API int gsl_device_waitirq(gsl_devhandle_t devhandle, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout); -GSL_API int gsl_device_waittimestamp(gsl_devhandle_t devhandle, gsl_timestamp_t timestamp, unsigned int timeout); -GSL_API int gsl_device_addtimestamp(gsl_devhandle_t devhandle, gsl_timestamp_t *timestamp); - -////////////////////////////////////////////////////////////////////////////// +gsl_devhandle_t gsl_device_open(gsl_deviceid_t device_id, gsl_flags_t flags); +int gsl_device_close(gsl_devhandle_t devhandle); +int gsl_device_idle(gsl_devhandle_t devhandle, unsigned int timeout); +int gsl_device_isidle(gsl_devhandle_t devhandle); +int gsl_device_getcount(void); +int gsl_device_getinfo(gsl_devhandle_t devhandle, gsl_devinfo_t *devinfo); +int gsl_device_setpowerstate(gsl_devhandle_t devhandle, gsl_flags_t flags); +int gsl_device_setdmistate(gsl_devhandle_t devhandle, gsl_flags_t flags); +int gsl_device_waitirq(gsl_devhandle_t devhandle, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout); +int gsl_device_waittimestamp(gsl_devhandle_t devhandle, gsl_timestamp_t timestamp, unsigned int timeout); +int gsl_device_addtimestamp(gsl_devhandle_t devhandle, gsl_timestamp_t *timestamp); + // direct register API -////////////////////////////////////////////////////////////////////////////// -GSL_API int gsl_register_read(gsl_devhandle_t devhandle, unsigned int offsetwords, unsigned int *data); +int gsl_register_read(gsl_devhandle_t devhandle, unsigned int offsetwords, unsigned int *data); -////////////////////////////////////////////////////////////////////////////// // command API -////////////////////////////////////////////////////////////////////////////// -GSL_API int gsl_cp_issueibcommands(gsl_devhandle_t devhandle, gsl_ctxthandle_t ctxthandle, gpuaddr_t ibaddr, unsigned int sizewords, gsl_timestamp_t *timestamp, gsl_flags_t flags); -GSL_API gsl_timestamp_t gsl_cp_readtimestamp(gsl_devhandle_t devhandle, gsl_timestamp_type_t type); -GSL_API int gsl_cp_checktimestamp(gsl_devhandle_t devhandle, gsl_timestamp_t timestamp, gsl_timestamp_type_t type); -GSL_API int gsl_cp_freememontimestamp(gsl_devhandle_t devhandle, gsl_memdesc_t *memdesc, gsl_timestamp_t timestamp, gsl_timestamp_type_t type); -GSL_API int gsl_v3_issuecommand(gsl_devhandle_t devhandle, gsl_cmdwindow_t target, unsigned int addr, unsigned int data); - +int gsl_cp_issueibcommands(gsl_devhandle_t devhandle, gsl_ctxthandle_t ctxthandle, gpuaddr_t ibaddr, unsigned int sizewords, gsl_timestamp_t *timestamp, gsl_flags_t flags); +gsl_timestamp_t gsl_cp_readtimestamp(gsl_devhandle_t devhandle, gsl_timestamp_type_t type); +int gsl_cp_checktimestamp(gsl_devhandle_t devhandle, gsl_timestamp_t timestamp, gsl_timestamp_type_t type); +int gsl_cp_freememontimestamp(gsl_devhandle_t devhandle, gsl_memdesc_t *memdesc, gsl_timestamp_t timestamp, gsl_timestamp_type_t type); +int gsl_v3_issuecommand(gsl_devhandle_t devhandle, gsl_cmdwindow_t target, unsigned int addr, unsigned int data); -////////////////////////////////////////////////////////////////////////////// // context API -////////////////////////////////////////////////////////////////////////////// -GSL_API gsl_ctxthandle_t gsl_context_create(gsl_devhandle_t devhandle, gsl_context_type_t type, gsl_flags_t flags); -GSL_API int gsl_context_destroy(gsl_devhandle_t devhandle, gsl_ctxthandle_t ctxthandle); -GSL_API int gsl_context_bind_gmem_shadow(gsl_devhandle_t devhandle, gsl_ctxthandle_t ctxthandle, const gsl_rect_t* gmem_rect, unsigned int shadow_x, unsigned int shadow_y, const gsl_buffer_desc_t* shadow_buffer, unsigned int buffer_id); - +gsl_ctxthandle_t gsl_context_create(gsl_devhandle_t devhandle, gsl_context_type_t type, gsl_flags_t flags); +int gsl_context_destroy(gsl_devhandle_t devhandle, gsl_ctxthandle_t ctxthandle); +int gsl_context_bind_gmem_shadow(gsl_devhandle_t devhandle, gsl_ctxthandle_t ctxthandle, const gsl_rect_t* gmem_rect, unsigned int shadow_x, unsigned int shadow_y, const gsl_buffer_desc_t* shadow_buffer, unsigned int buffer_id); -////////////////////////////////////////////////////////////////////////////// // sharedmem API -////////////////////////////////////////////////////////////////////////////// -GSL_API int gsl_memory_alloc(gsl_deviceid_t device_id, unsigned int sizebytes, gsl_flags_t flags, gsl_memdesc_t *memdesc); -GSL_API int gsl_memory_free(gsl_memdesc_t *memdesc); -GSL_API int gsl_memory_read(const gsl_memdesc_t *memdesc, void *dst, unsigned int sizebytes, unsigned int offsetbytes); -GSL_API int gsl_memory_write(const gsl_memdesc_t *memdesc, void *src, unsigned int sizebytes, unsigned int offsetbytes); -GSL_API int gsl_memory_write_multiple(const gsl_memdesc_t *memdesc, void *src, unsigned int srcstridebytes, unsigned int dststridebytes, unsigned int blocksizebytes, unsigned int numblocks, unsigned int offsetbytes); -GSL_API unsigned int gsl_memory_getlargestfreeblock(gsl_deviceid_t device_id, gsl_flags_t flags); -GSL_API int gsl_memory_set(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes); -GSL_API int gsl_memory_cacheoperation(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int sizebytes, unsigned int operation); -GSL_API int gsl_memory_fromhostpointer(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, void* hostptr); +int gsl_memory_alloc(gsl_deviceid_t device_id, unsigned int sizebytes, gsl_flags_t flags, gsl_memdesc_t *memdesc); +int gsl_memory_free(gsl_memdesc_t *memdesc); +int gsl_memory_read(const gsl_memdesc_t *memdesc, void *dst, unsigned int sizebytes, unsigned int offsetbytes); +int gsl_memory_write(const gsl_memdesc_t *memdesc, void *src, unsigned int sizebytes, unsigned int offsetbytes); +int gsl_memory_write_multiple(const gsl_memdesc_t *memdesc, void *src, unsigned int srcstridebytes, unsigned int dststridebytes, unsigned int blocksizebytes, unsigned int numblocks, unsigned int offsetbytes); +unsigned int gsl_memory_getlargestfreeblock(gsl_deviceid_t device_id, gsl_flags_t flags); +int gsl_memory_set(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes); +int gsl_memory_cacheoperation(const gsl_memdesc_t *memdesc, unsigned int offsetbytes, unsigned int sizebytes, unsigned int operation); +int gsl_memory_fromhostpointer(gsl_deviceid_t device_id, gsl_memdesc_t *memdesc, void* hostptr); #ifdef _DIRECT_MAPPED -GSL_API unsigned int gsl_sharedmem_gethostaddr(const gsl_memdesc_t *memdesc); +unsigned int gsl_sharedmem_gethostaddr(const gsl_memdesc_t *memdesc); #endif // _DIRECT_MAPPED -////////////////////////////////////////////////////////////////////////////// // address translation API -////////////////////////////////////////////////////////////////////////////// -GSL_API int gsl_translate_physaddr(void* virtAddr, unsigned int* physAddr); +int gsl_translate_physaddr(void* virtAddr, unsigned int* physAddr); - -////////////////////////////////////////////////////////////////////////////// // TB dump API -////////////////////////////////////////////////////////////////////////////// -GSL_API int gsl_tbdump_waitirq(); -GSL_API int gsl_tbdump_exportbmp(const void* addr, unsigned int format, unsigned int stride, unsigned int width, unsigned int height); - -////////////////////////////////////////////////////////////////////////////// -// OS specific APIs - need to go into their own gsl_libapi_platform.h file -////////////////////////////////////////////////////////////////////////////// -#ifdef WM7 -GSL_API int gsl_kos_wm7_surfobjfromhbitmap(HBITMAP hbitmap, SURFOBJ *surfobj); -#endif // WM7 - +int gsl_tbdump_waitirq(); +int gsl_tbdump_exportbmp(const void* addr, unsigned int format, unsigned int stride, unsigned int width, unsigned int height); #ifdef __cplusplus } diff --git a/drivers/mxc/amd-gpu/include/api/gsl_types.h b/drivers/mxc/amd-gpu/include/api/gsl_types.h index 99d98496611..5121945e5af 100644 --- a/drivers/mxc/amd-gpu/include/api/gsl_types.h +++ b/drivers/mxc/amd-gpu/include/api/gsl_types.h @@ -29,9 +29,51 @@ #ifndef __GSL_TYPES_H #define __GSL_TYPES_H +#include #include "stddef.h" +////////////////////////////////////////////////////////////////////////////// +// Operating System values +////////////////////////////////////////////////////////////////////////////// +#define OS_SUCCESS 0 +#define OS_FAILURE -1 +#define OS_FAILURE_SYSTEMERROR -2 +#define OS_FAILURE_DEVICEERROR -3 +#define OS_FAILURE_OUTOFMEM -4 +#define OS_FAILURE_BADPARAM -5 +#define OS_FAILURE_NOTSUPPORTED -6 +#define OS_FAILURE_NOMOREAVAILABLE -7 +#define OS_FAILURE_NOTINITIALIZED -8 +#define OS_FAILURE_ALREADYINITIALIZED -9 +#define OS_FAILURE_TIMEOUT -10 + + +#define OS_INFINITE 0xFFFFFFFF +#define OS_TLS_OUTOFINDEXES 0xFFFFFFFF +#define OS_TRUE 1 +#define OS_FALSE 0 + + + +typedef enum { + OS_PROTECTION_GLOBAL, // inter process + OS_PROTECTION_LOCAL, // process local + OS_PROTECTION_NONE, // none +} os_protection_t; + +typedef struct _os_cputimer_t { + int refcount; // Reference count + int enabled; // Counter is enabled + int size; // Number of counters + __s64 start_time; // start time in cpu ticks + __s64 end_time; // end time in cpu ticks + __s64 timer_frequency; // cpu ticks per second + __s64 *counter_array; // number of ticks for each counter +} os_cputimer_t; + + + ////////////////////////////////////////////////////////////////////////////// // status ////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/mxc/amd-gpu/include/gsl.h b/drivers/mxc/amd-gpu/include/gsl.h index 07d8e97dcee..efb2f7afdff 100644 --- a/drivers/mxc/amd-gpu/include/gsl.h +++ b/drivers/mxc/amd-gpu/include/gsl.h @@ -29,7 +29,6 @@ #ifndef __GSL_H #define __GSL_H -//#define __KGSLLIB_EXPORTS #define __KERNEL_MODE__ @@ -45,8 +44,6 @@ typedef struct _gsl_device_t gsl_device_t; ////////////////////////////////////////////////////////////////////////////// #include "gsl_buildconfig.h" -#include "kos_libapi.h" - #include "gsl_klibapi.h" #ifdef GSL_BLD_YAMATO @@ -76,4 +73,7 @@ typedef struct _gsl_device_t gsl_device_t; #include "gsl_config.h" + +#define DEBUG_ASSERT(x) + #endif // __GSL_H diff --git a/drivers/mxc/amd-gpu/include/gsl_buildconfig.h b/drivers/mxc/amd-gpu/include/gsl_buildconfig.h index 4e6be4da7dc..87a56624b74 100644 --- a/drivers/mxc/amd-gpu/include/gsl_buildconfig.h +++ b/drivers/mxc/amd-gpu/include/gsl_buildconfig.h @@ -50,6 +50,6 @@ /* #define GSL_MMU_PAGETABLE_PERPROCESS */ #define GSL_CALLER_PROCESS_MAX 10 -#define GSL_SHMEM_MAX_APERTURES 3 +#define GSL_SHMEM_MAX_APERTURES 2 #endif /* __GSL__BUILDCONFIG_H */ diff --git a/drivers/mxc/amd-gpu/include/gsl_cmdstream.h b/drivers/mxc/amd-gpu/include/gsl_cmdstream.h index 550d5d0005a..a757b286613 100644 --- a/drivers/mxc/amd-gpu/include/gsl_cmdstream.h +++ b/drivers/mxc/amd-gpu/include/gsl_cmdstream.h @@ -29,31 +29,9 @@ #ifndef __GSL_CMDSTREAM_H #define __GSL_CMDSTREAM_H - -////////////////////////////////////////////////////////////////////////////// -// defines -////////////////////////////////////////////////////////////////////////////// - -#ifdef VG_HDK -#define GSL_CMDSTREAM_GET_SOP_TIMESTAMP(device, data) -#else #define GSL_CMDSTREAM_GET_SOP_TIMESTAMP(device, data) kgsl_sharedmem_read0(&device->memstore, (data), GSL_DEVICE_MEMSTORE_OFFSET(soptimestamp), 4, false) -#endif - -#ifdef VG_HDK -#define GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, data) (*((int*)data) = (gsl_driver.device[GSL_DEVICE_G12-1]).timestamp) -#else #define GSL_CMDSTREAM_GET_EOP_TIMESTAMP(device, data) kgsl_sharedmem_read0(&device->memstore, (data), GSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp), 4, false) -#endif - - -////////////////////////////////////////////////////////////////////////////// -// types -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// -// functions -////////////////////////////////////////////////////////////////////////////// gsl_timestamp_t kgsl_cmdstream_readtimestamp0(gsl_deviceid_t device_id, gsl_timestamp_type_t type); void kgsl_cmdstream_memqueue_drain(gsl_device_t *device); int kgsl_cmdstream_init(gsl_device_t *device); diff --git a/drivers/mxc/amd-gpu/include/gsl_config.h b/drivers/mxc/amd-gpu/include/gsl_config.h index aa911b4096a..f921ef7eeeb 100644 --- a/drivers/mxc/amd-gpu/include/gsl_config.h +++ b/drivers/mxc/amd-gpu/include/gsl_config.h @@ -72,7 +72,7 @@ static const REG_MH_ARBITER_CONFIG gsl_cfg_g12_mharb = { 1, /* PAGE_SIZE */ 1, /* TC_REORDER_ENABLE */ 1, /* TC_ARB_HOLD_ENABLE */ - 0, /* IN_FLIGHT_LIMIT_ENABLE */ + 1, /* IN_FLIGHT_LIMIT_ENABLE */ 0x8, /* IN_FLIGHT_LIMIT */ 1, /* CP_CLNT_ENABLE */ 1, /* VGT_CLNT_ENABLE */ diff --git a/drivers/mxc/amd-gpu/include/gsl_debug.h b/drivers/mxc/amd-gpu/include/gsl_debug.h index 1275278f9ea..5c550c428d5 100644 --- a/drivers/mxc/amd-gpu/include/gsl_debug.h +++ b/drivers/mxc/amd-gpu/include/gsl_debug.h @@ -116,9 +116,6 @@ void Yamato_DumpWriteMemory(unsigned int dwAddress, unsigned int dwSi void Yamato_DumpSetMemory(unsigned int dwAddress, unsigned int dwSize, unsigned int pData); void Yamato_DumpFbStart(gsl_device_t *device); void Yamato_DumpRegSpace(gsl_device_t *device); -#ifdef _WIN32 -void Yamato_DumpWindow(unsigned int addr, unsigned int width, unsigned int height); -#endif #endif #ifdef _DEBUG int kgsl_dumpx_parse_ibs(gpuaddr_t gpuaddr, int sizedwords); diff --git a/drivers/mxc/amd-gpu/include/gsl_device.h b/drivers/mxc/amd-gpu/include/gsl_device.h index 07c1438994f..6f27d71ddee 100644 --- a/drivers/mxc/amd-gpu/include/gsl_device.h +++ b/drivers/mxc/amd-gpu/include/gsl_device.h @@ -29,10 +29,8 @@ #ifndef __GSL_DEVICE_H #define __GSL_DEVICE_H -#ifdef _LINUX #include #include -#endif ////////////////////////////////////////////////////////////////////////////// // types @@ -42,96 +40,76 @@ // function table // -------------- typedef struct _gsl_functable_t { - int (*device_init) (gsl_device_t *device); - int (*device_close) (gsl_device_t *device); - int (*device_destroy) (gsl_device_t *device); - int (*device_start) (gsl_device_t *device, gsl_flags_t flags); - int (*device_stop) (gsl_device_t *device); - int (*device_getproperty) (gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes); - int (*device_setproperty) (gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes); - int (*device_idle) (gsl_device_t *device, unsigned int timeout); - int (*device_regread) (gsl_device_t *device, unsigned int offsetwords, unsigned int *value); - int (*device_regwrite) (gsl_device_t *device, unsigned int offsetwords, unsigned int value); - int (*device_waitirq) (gsl_device_t *device, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout); + int (*device_init) (gsl_device_t *device); + int (*device_close) (gsl_device_t *device); + int (*device_destroy) (gsl_device_t *device); + int (*device_start) (gsl_device_t *device, gsl_flags_t flags); + int (*device_stop) (gsl_device_t *device); + int (*device_getproperty) (gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes); + int (*device_setproperty) (gsl_device_t *device, gsl_property_type_t type, void *value, unsigned int sizebytes); + int (*device_idle) (gsl_device_t *device, unsigned int timeout); + int (*device_regread) (gsl_device_t *device, unsigned int offsetwords, unsigned int *value); + int (*device_regwrite) (gsl_device_t *device, unsigned int offsetwords, unsigned int value); + int (*device_waitirq) (gsl_device_t *device, gsl_intrid_t intr_id, unsigned int *count, unsigned int timeout); int (*device_waittimestamp) (gsl_device_t *device, gsl_timestamp_t timestamp, unsigned int timeout); - int (*device_runpending) (gsl_device_t *device); - int (*device_addtimestamp) (gsl_device_t *device_id, gsl_timestamp_t *timestamp); - int (*intr_isr) (gsl_device_t *device); + int (*device_runpending) (gsl_device_t *device); + int (*device_addtimestamp) (gsl_device_t *device_id, gsl_timestamp_t *timestamp); + int (*intr_isr) (gsl_device_t *device); int (*mmu_tlbinvalidate) (gsl_device_t *device, unsigned int reg_invalidate, unsigned int pid); int (*mmu_setpagetable) (gsl_device_t *device, unsigned int reg_ptbase, gpuaddr_t ptbase, unsigned int pid); - int (*cmdstream_issueibcmds) (gsl_device_t *device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, gsl_flags_t flags); - int (*context_create) (gsl_device_t *device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags); - int (*context_destroy) (gsl_device_t *device_id, unsigned int drawctxt_id); + int (*cmdstream_issueibcmds) (gsl_device_t *device, int drawctxt_index, gpuaddr_t ibaddr, int sizedwords, gsl_timestamp_t *timestamp, gsl_flags_t flags); + int (*context_create) (gsl_device_t *device, gsl_context_type_t type, unsigned int *drawctxt_id, gsl_flags_t flags); + int (*context_destroy) (gsl_device_t *device_id, unsigned int drawctxt_id); } gsl_functable_t; -// ------------- -// device object -// ------------- +// device object struct _gsl_device_t { - - unsigned int refcnt; - unsigned int callerprocess[GSL_CALLER_PROCESS_MAX]; // caller process table - gsl_functable_t ftbl; - gsl_flags_t flags; - gsl_deviceid_t id; - unsigned int chip_id; - gsl_memregion_t regspace; - gsl_intr_t intr; - gsl_memdesc_t memstore; - gsl_memqueue_t memqueue; // queue of memfrees pending timestamp elapse + unsigned int refcnt; + unsigned int callerprocess[GSL_CALLER_PROCESS_MAX]; // caller process table + gsl_functable_t ftbl; + gsl_flags_t flags; + gsl_deviceid_t id; + unsigned int chip_id; + gsl_memregion_t regspace; + gsl_intr_t intr; + gsl_memdesc_t memstore; + gsl_memqueue_t memqueue; // queue of memfrees pending timestamp elapse #ifdef GSL_DEVICE_SHADOW_MEMSTORE_TO_USER - unsigned int memstoreshadow[GSL_CALLER_PROCESS_MAX]; + unsigned int memstoreshadow[GSL_CALLER_PROCESS_MAX]; #endif // GSL_DEVICE_SHADOW_MEMSTORE_TO_USER #ifndef GSL_NO_MMU - gsl_mmu_t mmu; + gsl_mmu_t mmu; #endif // GSL_NO_MMU #ifdef GSL_BLD_YAMATO - gsl_memregion_t gmemspace; - gsl_ringbuffer_t ringbuffer; -#ifdef GSL_LOCKING_FINEGRAIN - oshandle_t drawctxt_mutex; -#endif - unsigned int drawctxt_count; - gsl_drawctxt_t *drawctxt_active; - gsl_drawctxt_t drawctxt[GSL_CONTEXT_MAX]; + gsl_memregion_t gmemspace; + gsl_ringbuffer_t ringbuffer; + unsigned int drawctxt_count; + gsl_drawctxt_t *drawctxt_active; + gsl_drawctxt_t drawctxt[GSL_CONTEXT_MAX]; #endif // GSL_BLD_YAMATO #ifdef GSL_BLD_G12 -#ifdef GSL_LOCKING_FINEGRAIN - oshandle_t cmdwindow_mutex; -#endif - unsigned int intrcnt[GSL_G12_INTR_COUNT]; - gsl_timestamp_t current_timestamp; - gsl_timestamp_t timestamp; -#ifndef _LINUX - unsigned int irq_thread; - oshandle_t irq_thread_handle; -#endif + unsigned int intrcnt[GSL_G12_INTR_COUNT]; + gsl_timestamp_t current_timestamp; + gsl_timestamp_t timestamp; #ifdef IRQTHREAD_POLL - oshandle_t irqthread_event; + struct completion irqthread_event; #endif #endif // GSL_BLD_G12 -#ifdef GSL_LOCKING_FINEGRAIN - oshandle_t cmdstream_mutex; -#endif -#ifndef _LINUX - oshandle_t timestamp_event; -#else + wait_queue_head_t timestamp_waitq; struct workqueue_struct *irq_workq; - struct work_struct irq_work; + struct work_struct irq_work; struct work_struct irq_err_work; -#endif - void *autogate; + + void *autogate; }; -////////////////////////////////////////////////////////////////////////////// // prototypes -////////////////////////////////////////////////////////////////////////////// int kgsl_device_init(gsl_device_t *device, gsl_deviceid_t device_id); int kgsl_device_close(gsl_device_t *device); int kgsl_device_destroy(gsl_device_t *device); diff --git a/drivers/mxc/amd-gpu/include/gsl_driver.h b/drivers/mxc/amd-gpu/include/gsl_driver.h index 9c908ce4696..9fbd0106b1b 100644 --- a/drivers/mxc/amd-gpu/include/gsl_driver.h +++ b/drivers/mxc/amd-gpu/include/gsl_driver.h @@ -29,42 +29,20 @@ #ifndef __GSL_DRIVER_H #define __GSL_DRIVER_H - -///////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// -#ifdef GSL_DEDICATED_PROCESS -#define GSL_CALLER_PROCESSID_GET() kos_callerprocess_getid() -#else -#define GSL_CALLER_PROCESSID_GET() kos_process_getid() -#endif // GSL_DEDICATED_PROCESS - -#ifdef GSL_LOCKING_COARSEGRAIN -#define GSL_API_MUTEX_CREATE() gsl_driver.mutex = kos_mutex_create("gsl_global"); \ - if (!gsl_driver.mutex) {return (GSL_FAILURE);} -#define GSL_API_MUTEX_LOCK() kos_mutex_lock(gsl_driver.mutex) -#define GSL_API_MUTEX_UNLOCK() kos_mutex_unlock(gsl_driver.mutex) -#define GSL_API_MUTEX_FREE() kos_mutex_free(gsl_driver.mutex); gsl_driver.mutex = 0; -#else -#define GSL_API_MUTEX_CREATE() -#define GSL_API_MUTEX_LOCK() -#define GSL_API_MUTEX_UNLOCK() -#define GSL_API_MUTEX_FREE() -#endif - +#include ////////////////////////////////////////////////////////////////////////////// // types ////////////////////////////////////////////////////////////////////////////// // ------------- -// driver object +// driver object // ------------- typedef struct _gsl_driver_t { gsl_flags_t flags_debug; int refcnt; unsigned int callerprocess[GSL_CALLER_PROCESS_MAX]; // caller process table - oshandle_t mutex; // global API mutex + struct mutex lock; // global API mutex void *hal; gsl_sharedmem_t shmem; gsl_device_t device[GSL_DEVICE_MAX]; @@ -85,7 +63,7 @@ extern gsl_driver_t gsl_driver; ////////////////////////////////////////////////////////////////////////////// // inline functions ////////////////////////////////////////////////////////////////////////////// -OSINLINE int +static __inline int kgsl_driver_getcallerprocessindex(unsigned int pid, int *index) { int i; @@ -95,7 +73,7 @@ kgsl_driver_getcallerprocessindex(unsigned int pid, int *index) { if (gsl_driver.callerprocess[i] == pid) { - *index = i; + *index = i; return (GSL_SUCCESS); } } diff --git a/drivers/mxc/amd-gpu/include/gsl_hal.h b/drivers/mxc/amd-gpu/include/gsl_hal.h index fcf9f0891f1..b378d40569a 100644 --- a/drivers/mxc/amd-gpu/include/gsl_hal.h +++ b/drivers/mxc/amd-gpu/include/gsl_hal.h @@ -33,19 +33,6 @@ extern "C" { #endif // __cplusplus -/* -#include "gsl_buildconfig.h" -#include "kos_libapi.h" -#include "gsl_klibapi.h" -#ifdef GSL_BLD_YAMATO -#include -#endif -#ifdef GSL_BLD_G12 -#include -#endif -#include "gsl_hwaccess.h" -*/ - #include "gsl.h" #include "gsl_hwaccess.h" @@ -61,7 +48,7 @@ extern "C" { ////////////////////////////////////////////////////////////////////////////// -// version control +// version control ////////////////////////////////////////////////////////////////////////////// #define KGSLHAL_NAME "AMD GSL Kernel HAL" #define KGSLHAL_VERSION "0.1" diff --git a/drivers/mxc/amd-gpu/include/gsl_halconfig.h b/drivers/mxc/amd-gpu/include/gsl_halconfig.h old mode 100644 new mode 100755 index 363474b7a6b..658c4219807 --- a/drivers/mxc/amd-gpu/include/gsl_halconfig.h +++ b/drivers/mxc/amd-gpu/include/gsl_halconfig.h @@ -27,23 +27,20 @@ */ /* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. */ #ifndef __GSL_HALCONFIG_H #define __GSL_HALCONFIG_H #define GSL_HAL_GPUBASE_REG_YDX 0x30000000 -#define GSL_HAL_SIZE_REG_YDX 0x00020000 /* 128KB */ +#define GSL_HAL_SIZE_REG_YDX SZ_128K /* 128KB */ -#define GSL_HAL_SIZE_REG_G12 0x00001000 /* 4KB */ +#define GSL_HAL_SIZE_REG_G12 SZ_4K /* 4KB */ -#define GSL_HAL_SHMEM_SIZE_EMEM1_MMU 0x01800000 /* 24MB */ -#define GSL_HAL_SHMEM_SIZE_EMEM2_MMU 0x00400000 /* 4MB */ -#define GSL_HAL_SHMEM_SIZE_PHYS_MMU 0x00400000 /* 4MB */ +#define GSL_HAL_SHMEM_SIZE_EMEM_MMU SZ_128M -#define GSL_HAL_SHMEM_SIZE_EMEM1_NOMMU 0x00A00000 /* 10MB */ -#define GSL_HAL_SHMEM_SIZE_EMEM2_NOMMU 0x00200000 /* 2MB */ -#define GSL_HAL_SHMEM_SIZE_PHYS_NOMMU 0x00100000 /* 1MB */ +#define GSL_HAL_SHMEM_SIZE_EMEM_NOMMU (10*SZ_1M) +#define GSL_HAL_SHMEM_SIZE_PHYS_NOMMU SZ_1M #endif /* __GSL_HALCONFIG_H */ diff --git a/drivers/mxc/amd-gpu/include/gsl_hwaccess.h b/drivers/mxc/amd-gpu/include/gsl_hwaccess.h new file mode 100644 index 00000000000..88e8a39a2e0 --- /dev/null +++ b/drivers/mxc/amd-gpu/include/gsl_hwaccess.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GSL_HWACCESS_LINUX_H +#define __GSL_HWACCESS_LINUX_H + +#include +#include +#include + +#include "gsl_linux_map.h" + +static __inline void +kgsl_hwaccess_memread(void *dst, unsigned int gpubase, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace) +{ + if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) { + gsl_linux_map_read(dst, gpubase+gpuoffset, sizebytes, touserspace); + } else { + mb(); + dsb(); + if (touserspace) + { + if (copy_to_user(dst, (void *)(gpubase + gpuoffset), sizebytes)) + { + return; + } + } + else + { + memcpy(dst, (void *) (gpubase + gpuoffset), sizebytes); + } + mb(); + dsb(); + } +} + +//---------------------------------------------------------------------------- + +static __inline void +kgsl_hwaccess_memwrite(unsigned int gpubase, unsigned int gpuoffset, void *src, unsigned int sizebytes, unsigned int fromuserspace) +{ + if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) { + gsl_linux_map_write(src, gpubase+gpuoffset, sizebytes, fromuserspace); + } else { + mb(); + dsb(); + if (fromuserspace) + { + if (copy_from_user((void *)(gpubase + gpuoffset), src, sizebytes)) + { + return; + } + } + else + { + memcpy((void *)(gpubase + gpuoffset), src, sizebytes); + } + mb(); + dsb(); + } +} + +//---------------------------------------------------------------------------- + +static __inline void +kgsl_hwaccess_memset(unsigned int gpubase, unsigned int gpuoffset, unsigned int value, unsigned int sizebytes) +{ + if (gsl_driver.enable_mmu && (gpubase >= GSL_LINUX_MAP_RANGE_START) && (gpubase < GSL_LINUX_MAP_RANGE_END)) { + gsl_linux_map_set(gpuoffset+gpubase, value, sizebytes); + } else { + mb(); + dsb(); + memset((void *)(gpubase + gpuoffset), value, sizebytes); + mb(); + dsb(); + } +} + +//---------------------------------------------------------------------------- + +static __inline void +kgsl_hwaccess_regread(gsl_deviceid_t device_id, unsigned int gpubase, unsigned int offsetwords, unsigned int *data) +{ + unsigned int *reg; + + // unreferenced formal parameter + (void) device_id; + + reg = (unsigned int *)(gpubase + (offsetwords << 2)); + + mb(); + dsb(); + *data = __raw_readl(reg); + mb(); + dsb(); +} + +//---------------------------------------------------------------------------- + +static __inline void +kgsl_hwaccess_regwrite(gsl_deviceid_t device_id, unsigned int gpubase, unsigned int offsetwords, unsigned int data) +{ + unsigned int *reg; + + // unreferenced formal parameter + (void) device_id; + + reg = (unsigned int *)(gpubase + (offsetwords << 2)); + mb(); + dsb(); + __raw_writel(data, reg); + mb(); + dsb(); +} +#endif // __GSL_HWACCESS_WINCE_MX51_H diff --git a/drivers/mxc/amd-gpu/include/gsl_intrmgr.h b/drivers/mxc/amd-gpu/include/gsl_intrmgr.h index f46f6d8e6a8..6ced6b1af96 100644 --- a/drivers/mxc/amd-gpu/include/gsl_intrmgr.h +++ b/drivers/mxc/amd-gpu/include/gsl_intrmgr.h @@ -29,6 +29,7 @@ #ifndef __GSL_INTRMGR_H #define __GSL_INTRMGR_H +#include ////////////////////////////////////////////////////////////////////////////// // types @@ -85,7 +86,7 @@ typedef struct _gsl_intr_t gsl_device_t *device; unsigned int enabled[GSL_INTR_BLOCK_COUNT]; gsl_intr_handler_t handler[GSL_INTR_COUNT]; - oshandle_t evnt[GSL_INTR_COUNT]; + struct completion evnt[GSL_INTR_COUNT]; } gsl_intr_t; diff --git a/drivers/mxc/amd-gpu/include/gsl_linux_map.h b/drivers/mxc/amd-gpu/include/gsl_linux_map.h new file mode 100644 index 00000000000..bdab64e9737 --- /dev/null +++ b/drivers/mxc/amd-gpu/include/gsl_linux_map.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GSL_LINUX_MAP_H__ +#define __GSL_LINUX_MAP_H__ + +#include "gsl_halconfig.h" + +#define GSL_LINUX_MAP_RANGE_START (1024*1024) +#define GSL_LINUX_MAP_RANGE_END (GSL_LINUX_MAP_RANGE_START+GSL_HAL_SHMEM_SIZE_EMEM_MMU) + +int gsl_linux_map_init(void); +void *gsl_linux_map_alloc(unsigned int gpu_addr, unsigned int size); +void gsl_linux_map_free(unsigned int gpu_addr); +void *gsl_linux_map_find(unsigned int gpu_addr); +void *gsl_linux_map_read(void *dst, unsigned int gpuoffset, unsigned int sizebytes, unsigned int touserspace); +void *gsl_linux_map_write(void *src, unsigned int gpuoffset, unsigned int sizebytes, unsigned int fromuserspace); +void *gsl_linux_map_set(unsigned int gpuoffset, unsigned int value, unsigned int sizebytes); +int gsl_linux_map_destroy(void); + +#endif diff --git a/drivers/mxc/amd-gpu/include/gsl_log.h b/drivers/mxc/amd-gpu/include/gsl_log.h index dbb7e4c6ef9..6b47dafd803 100644 --- a/drivers/mxc/amd-gpu/include/gsl_log.h +++ b/drivers/mxc/amd-gpu/include/gsl_log.h @@ -50,24 +50,16 @@ #ifdef GSL_LOG -int kgsl_log_init(void); -int kgsl_log_close(void); -int kgsl_log_open_stdout( unsigned int log_flags ); +int kgsl_log_finish(void); +int kgsl_log_start( unsigned int log_flags ); int kgsl_log_write( unsigned int log_flags, char* format, ... ); -int kgsl_log_open_membuf( int* memBufId, unsigned int log_flags ); -int kgsl_log_open_file( char* filename, unsigned int log_flags ); -int kgsl_log_flush_membuf( char* filename, int memBufId ); #else // Empty function definitions -OSINLINE int kgsl_log_init(void) { return GSL_SUCCESS; } -OSINLINE int kgsl_log_close(void) { return GSL_SUCCESS; } -OSINLINE int kgsl_log_open_stdout( unsigned int log_flags ) { (void)log_flags; return GSL_SUCCESS; } -OSINLINE int kgsl_log_write( unsigned int log_flags, char* format, ... ) { (void)log_flags; (void)format; return GSL_SUCCESS; } -OSINLINE int kgsl_log_open_membuf( int* memBufId, unsigned int log_flags ) { (void)memBufId; (void)log_flags; return GSL_SUCCESS; } -OSINLINE int kgsl_log_open_file( char* filename, unsigned int log_flags ) { (void)filename; (void)log_flags; return GSL_SUCCESS; } -OSINLINE int kgsl_log_flush_membuf( char* filename, int memBufId ) { (void) filename; (void) memBufId; return GSL_SUCCESS; } +static __inline int kgsl_log_finish(void) { return GSL_SUCCESS; } +static __inline int kgsl_log_start( unsigned int log_flags ) { (void)log_flags; return GSL_SUCCESS; } +static __inline int kgsl_log_write( unsigned int log_flags, char* format, ... ) { (void)log_flags; (void)format; return GSL_SUCCESS; } #endif diff --git a/drivers/mxc/amd-gpu/include/gsl_memmgr.h b/drivers/mxc/amd-gpu/include/gsl_memmgr.h index ef9ad93ea96..f0739fc2d27 100644 --- a/drivers/mxc/amd-gpu/include/gsl_memmgr.h +++ b/drivers/mxc/amd-gpu/include/gsl_memmgr.h @@ -30,6 +30,8 @@ #define __GSL_MEMMGR_H +#include + ////////////////////////////////////////////////////////////////////////////// // defines ////////////////////////////////////////////////////////////////////////////// @@ -48,13 +50,13 @@ // memory arena stats // ------------------ typedef struct _gsl_memarena_stats_t { - __int64 bytes_read; - __int64 bytes_written; - __int64 allocs_success; - __int64 allocs_fail; - __int64 frees; - __int64 allocs_pagedistribution[GSL_MEMARENA_PAGE_DIST_MAX]; // 0=0--(4K-1), 1=4--(8K-1), 2=8--(16K-1),... max-1=(GSL_PAGESIZE<<(max-1))--infinity - __int64 frees_pagedistribution[GSL_MEMARENA_PAGE_DIST_MAX]; + __s64 bytes_read; + __s64 bytes_written; + __s64 allocs_success; + __s64 allocs_fail; + __s64 frees; + __s64 allocs_pagedistribution[GSL_MEMARENA_PAGE_DIST_MAX]; // 0=0--(4K-1), 1=4--(8K-1), 2=8--(16K-1),... max-1=(GSL_PAGESIZE<<(max-1))--infinity + __s64 frees_pagedistribution[GSL_MEMARENA_PAGE_DIST_MAX]; } gsl_memarena_stats_t; // ------------ @@ -91,7 +93,7 @@ typedef struct _gsl_nodepool_t { // memory arena object // ------------------- typedef struct _gsl_memarena_t { - oshandle_t mutex; + struct mutex lock; unsigned int gpubaseaddr; unsigned int hostbaseaddr; unsigned int sizebytes; diff --git a/drivers/mxc/amd-gpu/include/gsl_mmu.h b/drivers/mxc/amd-gpu/include/gsl_mmu.h index ddb2243b58d..1171ee33d1b 100644 --- a/drivers/mxc/amd-gpu/include/gsl_mmu.h +++ b/drivers/mxc/amd-gpu/include/gsl_mmu.h @@ -97,9 +97,9 @@ typedef struct _gsl_mh_intr_t // page table stats // ---------------- typedef struct _gsl_ptstats_t { - __int64 maps; - __int64 unmaps; - __int64 switches; + __s64 maps; + __s64 unmaps; + __s64 switches; } gsl_ptstats_t; // --------- @@ -107,7 +107,7 @@ typedef struct _gsl_ptstats_t { // --------- typedef struct _gsl_mmustats_t { gsl_ptstats_t pt; - __int64 tlbflushes; + __s64 tlbflushes; } gsl_mmustats_t; // ----------------- @@ -135,9 +135,6 @@ typedef struct _gsl_tlbflushfilter_t { // mmu object // ---------- typedef struct _gsl_mmu_t { -#ifdef GSL_LOCKING_FINEGRAIN - oshandle_t mutex; -#endif unsigned int refcnt; gsl_flags_t flags; gsl_device_t *device; @@ -159,7 +156,7 @@ typedef struct _gsl_mmu_t { ////////////////////////////////////////////////////////////////////////////// // inline functions ////////////////////////////////////////////////////////////////////////////// -OSINLINE int +static __inline int kgsl_mmu_isenabled(gsl_mmu_t *mmu) { // address translation enabled diff --git a/drivers/mxc/amd-gpu/include/gsl_ringbuffer.h b/drivers/mxc/amd-gpu/include/gsl_ringbuffer.h index 57f6297735e..c463fca2730 100644 --- a/drivers/mxc/amd-gpu/include/gsl_ringbuffer.h +++ b/drivers/mxc/amd-gpu/include/gsl_ringbuffer.h @@ -123,9 +123,9 @@ typedef struct _gsl_rbmemptrs_t { // stats // ----- typedef struct _gsl_rbstats_t { - __int64 wraps; - __int64 issues; - __int64 wordstotal; + __s64 wraps; + __s64 issues; + __s64 wordstotal; } gsl_rbstats_t; @@ -136,9 +136,6 @@ typedef struct _gsl_ringbuffer_t { gsl_device_t *device; gsl_flags_t flags; -#ifdef GSL_LOCKING_FINEGRAIN - oshandle_t mutex; -#endif gsl_memdesc_t buffer_desc; // allocated memory descriptor gsl_memdesc_t memptrs_desc; @@ -161,23 +158,6 @@ typedef struct _gsl_ringbuffer_t { } gsl_ringbuffer_t; -////////////////////////////////////////////////////////////////////////////// -// macros -////////////////////////////////////////////////////////////////////////////// - -#ifdef GSL_LOCKING_FINEGRAIN -#define GSL_RB_MUTEX_CREATE() rb->mutex = kos_mutex_create("gsl_ringbuffer"); \ - if (!rb->mutex) {return (GSL_FAILURE);} -#define GSL_RB_MUTEX_LOCK() kos_mutex_lock(rb->mutex) -#define GSL_RB_MUTEX_UNLOCK() kos_mutex_unlock(rb->mutex) -#define GSL_RB_MUTEX_FREE() kos_mutex_free(rb->mutex); rb->mutex = 0; -#else -#define GSL_RB_MUTEX_CREATE() -#define GSL_RB_MUTEX_LOCK() -#define GSL_RB_MUTEX_UNLOCK() -#define GSL_RB_MUTEX_FREE() -#endif - // ---------- // ring write // ---------- diff --git a/drivers/mxc/amd-gpu/include/reg/vgc/vgregs_z160.h b/drivers/mxc/amd-gpu/include/reg/vgc/vgregs_z160.h index 1660bc1c12a..1dd73e8e391 100644 --- a/drivers/mxc/amd-gpu/include/reg/vgc/vgregs_z160.h +++ b/drivers/mxc/amd-gpu/include/reg/vgc/vgregs_z160.h @@ -30,13 +30,9 @@ #ifndef __REGS_G4X_DRIVER_H #define __REGS_G4X_DRIVER_H -#ifndef _LINUX -#include -#else #ifndef assert #define assert(expr) #endif -#endif //----------------------------------------------------- // REGISTER ADDRESSES @@ -1049,7 +1045,7 @@ typedef struct _REG_MH_ARBITER_CONFIG { unsigned L1_ARB_ENABLE : 1; unsigned L1_ARB_HOLD_ENABLE : 1; unsigned L2_ARB_CONTROL : 1; - unsigned PAGE_SIZE : 3; + unsigned MH_PAGE_SIZE : 3; unsigned TC_REORDER_ENABLE : 1; unsigned TC_ARB_HOLD_ENABLE : 1; unsigned IN_FLIGHT_LIMIT_ENABLE : 1; diff --git a/drivers/mxc/amd-gpu/include/reg/yamato.h b/drivers/mxc/amd-gpu/include/reg/yamato.h index 05cae6c4640..af23c0517e9 100644 --- a/drivers/mxc/amd-gpu/include/reg/yamato.h +++ b/drivers/mxc/amd-gpu/include/reg/yamato.h @@ -34,9 +34,6 @@ #endif #if defined(_YDX14) -#if defined(_WIN32) && !defined(__SYMBIAN32__) -#pragma message("YDX 14 header files\r\n") -#endif #include "yamato/14/yamato_enum.h" #include "yamato/14/yamato_ipt.h" #include "yamato/14/yamato_mask.h" @@ -48,9 +45,6 @@ #define _YAMATO_GENENUM_H "reg/yamato/14/yamato_genenum.h" #define _YAMATO_GENREG_H "reg/yamato/14/yamato_genreg.h" #else -#if defined(_WIN32) && !defined(__SYMBIAN32__) -#pragma message("YDX 22 header files\r\n") -#endif #include "yamato/22/yamato_enum.h" #include "yamato/22/yamato_ipt.h" #include "yamato/22/yamato_mask.h" diff --git a/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_genreg.h b/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_genreg.h index d04379887b7..727fc35955a 100644 --- a/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_genreg.h +++ b/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_genreg.h @@ -1877,7 +1877,7 @@ START_REGISTER(MH_ARBITER_CONFIG) GENERATE_FIELD(L1_ARB_ENABLE, bool) GENERATE_FIELD(L1_ARB_HOLD_ENABLE, int) GENERATE_FIELD(L2_ARB_CONTROL, int) - GENERATE_FIELD(PAGE_SIZE, int) + GENERATE_FIELD(MH_PAGE_SIZE, int) GENERATE_FIELD(TC_REORDER_ENABLE, bool) GENERATE_FIELD(TC_ARB_HOLD_ENABLE, bool) GENERATE_FIELD(IN_FLIGHT_LIMIT_ENABLE, bool) diff --git a/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_registers.h b/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_registers.h index bcc28f133b0..f3a435f3854 100644 --- a/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_registers.h +++ b/drivers/mxc/amd-gpu/include/reg/yamato/22/yamato_registers.h @@ -7787,7 +7787,7 @@ unsigned int L1_ARB_ENABLE : 1; unsigned int L1_ARB_HOLD_ENABLE : 1; unsigned int L2_ARB_CONTROL : 1; - unsigned int PAGE_SIZE : 3; + unsigned int MH_PAGE_SIZE : 3; unsigned int TC_REORDER_ENABLE : 1; unsigned int TC_ARB_HOLD_ENABLE : 1; unsigned int IN_FLIGHT_LIMIT_ENABLE : 1; @@ -7809,7 +7809,7 @@ unsigned int IN_FLIGHT_LIMIT_ENABLE : 1; unsigned int TC_ARB_HOLD_ENABLE : 1; unsigned int TC_REORDER_ENABLE : 1; - unsigned int PAGE_SIZE : 3; + unsigned int MH_PAGE_SIZE : 3; unsigned int L2_ARB_CONTROL : 1; unsigned int L1_ARB_HOLD_ENABLE : 1; unsigned int L1_ARB_ENABLE : 1; diff --git a/drivers/mxc/amd-gpu/misc.c b/drivers/mxc/amd-gpu/misc.c new file mode 100644 index 00000000000..210ce79eda7 --- /dev/null +++ b/drivers/mxc/amd-gpu/misc.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include +#include +#include +#include +#include + +typedef struct _gsl_autogate_t { + struct timer_list timer; + spinlock_t lock; + int active; + /* pending indicate the timer has been fired but clock not yet disabled. */ + int pending; + int timeout; + gsl_device_t *dev; + struct work_struct dis_task; +} gsl_autogate_t; + +static gsl_autogate_t *g_autogate[2]; +static DECLARE_MUTEX(sem_dev); + +#define KGSL_DEVICE_IDLE_TIMEOUT 5000 /* unit ms */ + +static void clk_disable_task(struct work_struct *work) +{ + gsl_autogate_t *autogate; + autogate = container_of(work, gsl_autogate_t, dis_task); + if (autogate->dev->ftbl.device_idle) + autogate->dev->ftbl.device_idle(autogate->dev, GSL_TIMEOUT_DEFAULT); + kgsl_clock(autogate->dev->id, 0); + autogate->pending = 0; +} + +static int _kgsl_device_active(gsl_device_t *dev, int all) +{ + unsigned long flags; + int to_active = 0; + gsl_autogate_t *autogate = dev->autogate; + if (!autogate) { + printk(KERN_ERR "%s: autogate has exited!\n", __func__); + return 0; + } +// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, dev->id, autogate->active); + + spin_lock_irqsave(&autogate->lock, flags); + if (in_interrupt()) { + if (!autogate->active && !autogate->pending) + BUG(); + } else { + to_active = !autogate->active; + autogate->active = 1; + } + mod_timer(&autogate->timer, jiffies + msecs_to_jiffies(autogate->timeout)); + spin_unlock_irqrestore(&autogate->lock, flags); + if (to_active) + kgsl_clock(autogate->dev->id, 1); + if (to_active && all) { + int index; + index = autogate->dev->id == GSL_DEVICE_G12 ? GSL_DEVICE_YAMATO - 1 : + GSL_DEVICE_G12 - 1; + down(&sem_dev); + if (g_autogate[index]) + _kgsl_device_active(g_autogate[index]->dev, 0); + up(&sem_dev); + } + return 0; +} +int kgsl_device_active(gsl_device_t *dev) +{ + return _kgsl_device_active(dev, 0); +} + +static void kgsl_device_inactive(unsigned long data) +{ + gsl_autogate_t *autogate = (gsl_autogate_t *)data; + unsigned long flags; + +// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, autogate->dev->id, autogate->active); + del_timer(&autogate->timer); + spin_lock_irqsave(&autogate->lock, flags); + WARN(!autogate->active, "GPU Device %d is already inactive\n", autogate->dev->id); + if (autogate->active) { + autogate->active = 0; + autogate->pending = 1; + schedule_work(&autogate->dis_task); + } + spin_unlock_irqrestore(&autogate->lock, flags); +} + +int kgsl_device_clock(gsl_deviceid_t id, int enable) +{ + int ret = GSL_SUCCESS; + gsl_device_t *device; + + device = &gsl_driver.device[id-1]; // device_id is 1 based + if (device->flags & GSL_FLAGS_INITIALIZED) { + if (enable) + kgsl_device_active(device); + else + kgsl_device_inactive((unsigned long)device); + } else { + printk(KERN_ERR "%s: Dev %d clock is already off!\n", __func__, id); + ret = GSL_FAILURE; + } + + return ret; +} + +int kgsl_device_autogate_init(gsl_device_t *dev) +{ + gsl_autogate_t *autogate; + +// printk(KERN_ERR "%s:%d id %d\n", __func__, __LINE__, dev->id); + autogate = kzalloc(sizeof(gsl_autogate_t), GFP_KERNEL); + if (!autogate) { + printk(KERN_ERR "%s: out of memory!\n", __func__); + return -ENOMEM; + } + down(&sem_dev); + autogate->dev = dev; + autogate->active = 1; + spin_lock_init(&autogate->lock); + autogate->timeout = KGSL_DEVICE_IDLE_TIMEOUT; + init_timer(&autogate->timer); + autogate->timer.expires = jiffies + msecs_to_jiffies(autogate->timeout); + autogate->timer.function = kgsl_device_inactive; + autogate->timer.data = (unsigned long)autogate; + add_timer(&autogate->timer); + INIT_WORK(&autogate->dis_task, clk_disable_task); + dev->autogate = autogate; + g_autogate[dev->id - 1] = autogate; + up(&sem_dev); + return 0; +} + +void kgsl_device_autogate_exit(gsl_device_t *dev) +{ + gsl_autogate_t *autogate = dev->autogate; + +// printk(KERN_ERR "%s:%d id %d active %d\n", __func__, __LINE__, dev->id, autogate->active); + down(&sem_dev); + del_timer_sync(&autogate->timer); + if (!autogate->active) + kgsl_clock(autogate->dev->id, 1); + flush_work(&autogate->dis_task); + g_autogate[dev->id - 1] = NULL; + up(&sem_dev); + kfree(autogate); + dev->autogate = NULL; +} diff --git a/drivers/mxc/amd-gpu/pfp_microcode_nrt.inl b/drivers/mxc/amd-gpu/pfp_microcode_nrt.inl new file mode 100644 index 00000000000..dfe61295e9e --- /dev/null +++ b/drivers/mxc/amd-gpu/pfp_microcode_nrt.inl @@ -0,0 +1,327 @@ +/* Copyright (c) 2008-2010, QUALCOMM Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of QUALCOMM Incorporated nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PFP_MICROCODE_NRT_H +#define PFP_MICROCODE_NRT_H + +#define PFP_MICROCODE_VERSION 308308 + +#define PFP_MICROCODE_SIZE_NRT 288 + +uint32 aPFP_Microcode_nrt[PFP_MICROCODE_SIZE_NRT]={ +0xc60400, +0x7e424b, +0xa00000, +0x7e828b, +0x800001, +0xc60400, +0xcc4003, +0x800000, +0xd60003, +0x800000, +0xc62c00, +0xc80c35, +0x98c000, +0xc80c35, +0x880000, +0xc80c1d, +0x84000b, +0xc60800, +0x98c007, +0xc61000, +0x978003, +0xcc4003, +0xd60004, +0x800000, +0xcd0003, +0x9783e8, +0xc60400, +0x800000, +0xc60400, +0x84000b, +0xc60800, +0x98c00c, +0xc61000, +0xcc4003, +0xc61400, +0xc61800, +0x7d6d40, +0xcd401e, +0x978003, +0xcd801e, +0xd60004, +0x800000, +0xcd0003, +0x800000, +0xd6001f, +0x84000b, +0xc60800, +0x98c007, +0xc60c00, +0xcc4003, +0xcc8003, +0xccc003, +0x800000, +0xd60003, +0x800000, +0xd6001f, +0xc60800, +0x348c08, +0x98c006, +0xc80c1e, +0x98c000, +0xc80c1e, +0x800041, +0xcc8007, +0xcc8008, +0xcc4003, +0x800000, +0xcc8003, +0xc60400, +0x1a9c07, +0xca8821, +0x95c3b9, +0xc8102c, +0x98800a, +0x329418, +0x9a4004, +0xcc6810, +0x042401, +0xd00143, +0xd00162, +0xcd0002, +0x7d514c, +0xcd4003, +0x9b8007, +0x06a801, +0x964003, +0xc28000, +0xcf4003, +0x800001, +0xc60400, +0x800045, +0xc60400, +0x800001, +0xc60400, +0xc60800, +0xc60c00, +0xc8102d, +0x349402, +0x99000b, +0xc8182e, +0xcd4002, +0xcd8002, +0xd001e3, +0xd001c3, +0xccc003, +0xcc801c, +0xcd801d, +0x800001, +0xc60400, +0xd00203, +0x800000, +0xd001c3, +0xc8081f, +0xc60c00, +0xc80c20, +0x988000, +0xc8081f, +0xcc4003, +0xccc003, +0xd60003, +0xccc022, +0xcc001f, +0x800000, +0xcc001f, +0xc81c2f, +0xc60400, +0xc60800, +0xc60c00, +0xc81030, +0x99c000, +0xc81c2f, +0xcc8021, +0xcc4020, +0x990011, +0xc107ff, +0xd00223, +0xd00243, +0x345402, +0x7cb18b, +0x7d95cc, +0xcdc002, +0xccc002, +0xd00263, +0x978005, +0xccc003, +0xc60800, +0x80008a, +0xc60c00, +0x800000, +0xd00283, +0x97836b, +0xc60400, +0xd6001f, +0x800001, +0xc60400, +0xd2000d, +0xcc000d, +0x800000, +0xcc000d, +0xc60800, +0xc60c00, +0xca1433, +0xd022a0, +0xcce000, +0x99435c, +0xcce005, +0x800000, +0x062001, +0xc60800, +0xc60c00, +0xd202c3, +0xcc8003, +0xccc003, +0xcce027, +0x800000, +0x062001, +0xca0831, +0x9883ff, +0xca0831, +0xd6001f, +0x800001, +0xc60400, +0x0a2001, +0x800001, +0xc60400, +0xd20009, +0xd2000a, +0xcc001f, +0x800000, +0xcc001f, +0xd2000b, +0xd2000c, +0xcc001f, +0x800000, +0xcc001f, +0xcc0023, +0xcc4003, +0xce0003, +0x800000, +0xd60003, +0xd00303, +0xcc0024, +0xcc4003, +0x800000, +0xd60003, +0xd00323, +0xcc0025, +0xcc4003, +0x800000, +0xd60003, +0xd00343, +0xcc0026, +0xcc4003, +0x800000, +0xd60003, +0x800000, +0xd6001f, +0x280401, +0xd20001, +0xcc4001, +0xcc4006, +0x8400e7, +0xc40802, +0xc40c02, +0xcc402b, +0x98831f, +0xc63800, +0x8400e7, +0xcf802b, +0x800000, +0xd6001f, +0xcc001f, +0x880000, +0xcc001f, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x000000, +0x0100c8, +0x0200cd, +0x0300d2, +0x050004, +0x1000d7, +0x1700b6, +0x220010, +0x230038, +0x250044, +0x27005e, +0x2d0070, +0x2e007c, +0x4b0009, +0x34001d, +0x36002d, +0x3700a8, +0x3b009b, +0x3f009f, +0x4400d9, +0x4800c3, +0x5000b9, +0x5100be, +0x5500c9, +0x5600ce, +0x5700d3, +0x5d00b0, +0x000006, +0x000006, +0x000006, +0x000006, +0x000006, +0x000006, +}; + +#endif diff --git a/drivers/mxc/amd-gpu/pm4_microcode.inl b/drivers/mxc/amd-gpu/pm4_microcode.inl new file mode 100644 index 00000000000..aa7c9fc9d00 --- /dev/null +++ b/drivers/mxc/amd-gpu/pm4_microcode.inl @@ -0,0 +1,816 @@ +/* Copyright (c) 2008-2010, QUALCOMM Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of QUALCOMM Incorporated nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PM4_MICROCODE_H +#define PM4_MICROCODE_H + +#define PM4_MICROCODE_VERSION 322696 + +#define PM4_MICROCODE_SIZE 768 + + +#ifdef _PRIMLIB_INCLUDE +extern uint32 aPM4_Microcode[PM4_MICROCODE_SIZE][3]; +#else +uint32 aPM4_Microcode[PM4_MICROCODE_SIZE][3]={ + { 0x00000000, 0xc0200400, 0x000 }, + { 0x00000000, 0x00a0000a, 0x000 }, + { 0x000001f3, 0x00204411, 0x000 }, + { 0x01000000, 0x00204811, 0x000 }, + { 0x00000000, 0x00400000, 0x004 }, + { 0x0000ffff, 0x00284621, 0x000 }, + { 0x00000000, 0xd9004800, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0x34e00000, 0x000 }, + { 0x00000000, 0x00600000, 0x28c }, + { 0x0000ffff, 0xc0280a20, 0x000 }, + { 0x00000000, 0x00294582, 0x000 }, + { 0x00000000, 0xd9004800, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0x00600000, 0x28c }, + { 0x0000ffff, 0xc0284620, 0x000 }, + { 0x00000000, 0xd9004800, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0x00600000, 0x2b0 }, + { 0x00000000, 0xc0200c00, 0x000 }, + { 0x000021fc, 0x0029462c, 0x000 }, + { 0x00000000, 0x00404803, 0x021 }, + { 0x00000000, 0x00600000, 0x2b0 }, + { 0x00000000, 0xc0200000, 0x000 }, + { 0x00000000, 0xc0200c00, 0x000 }, + { 0x000021fc, 0x0029462c, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00003fff, 0x002f022f, 0x000 }, + { 0x00000000, 0x0ce00000, 0x000 }, + { 0x0000a1fd, 0x0029462c, 0x000 }, + { 0x00000000, 0xd9004800, 0x000 }, + { 0x00000000, 0x00400000, 0x021 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00001000, 0x00281223, 0x000 }, + { 0x00001000, 0x002f0224, 0x000 }, + { 0x00000000, 0x0ce00000, 0x000 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x0000000e, 0x00404811, 0x000 }, + { 0x00000394, 0x00204411, 0x000 }, + { 0x00000001, 0xc0404811, 0x000 }, + { 0x00000000, 0x00600000, 0x2b0 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000008, 0xc0210a20, 0x000 }, + { 0x00000000, 0x14e00000, 0x02d }, + { 0x00000007, 0x00404811, 0x000 }, + { 0x00000008, 0x00404811, 0x000 }, + { 0x0000001f, 0x40280a20, 0x000 }, + { 0x0000001b, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x043 }, + { 0x00000002, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x04a }, + { 0x00000003, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x051 }, + { 0x00000004, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x058 }, + { 0x00000014, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x058 }, + { 0x00000015, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x060 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000000, 0xc0404802, 0x000 }, + { 0x0000001f, 0x40280a20, 0x000 }, + { 0x0000001b, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x043 }, + { 0x00000002, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x04a }, + { 0x00000000, 0x00400000, 0x051 }, + { 0x0000001f, 0xc0210e20, 0x000 }, + { 0x00000612, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000000, 0x00404802, 0x000 }, + { 0x0000001e, 0xc0210e20, 0x000 }, + { 0x00000600, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000000, 0x00404802, 0x000 }, + { 0x0000001e, 0xc0210e20, 0x000 }, + { 0x00000605, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000000, 0x00404802, 0x000 }, + { 0x0000001f, 0x40280a20, 0x000 }, + { 0x0000001f, 0xc0210e20, 0x000 }, + { 0x0000060a, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000000, 0x00404802, 0x000 }, + { 0x0000001f, 0xc0680a20, 0x2b0 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000000, 0x00404802, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00001fff, 0x40280a20, 0x000 }, + { 0x80000000, 0x40280e20, 0x000 }, + { 0x40000000, 0xc0281220, 0x000 }, + { 0x00040000, 0x00694622, 0x2ba }, + { 0x00000000, 0x00201410, 0x000 }, + { 0x00000000, 0x002f0223, 0x000 }, + { 0x00000000, 0x0ae00000, 0x06d }, + { 0x00000000, 0xc0401800, 0x070 }, + { 0x00001fff, 0xc0281a20, 0x000 }, + { 0x00040000, 0x00694626, 0x2ba }, + { 0x00000000, 0x00201810, 0x000 }, + { 0x00000000, 0x002f0224, 0x000 }, + { 0x00000000, 0x0ae00000, 0x073 }, + { 0x00000000, 0xc0401c00, 0x076 }, + { 0x00001fff, 0xc0281e20, 0x000 }, + { 0x00040000, 0x00694627, 0x2ba }, + { 0x00000000, 0x00201c10, 0x000 }, + { 0x00000000, 0x00204402, 0x000 }, + { 0x00000000, 0x002820c5, 0x000 }, + { 0x00000000, 0x004948e8, 0x000 }, + { 0x00000000, 0x00600000, 0x28c }, + { 0x00000010, 0x40210a20, 0x000 }, + { 0x000000ff, 0x00280a22, 0x000 }, + { 0x000007ff, 0x40280e20, 0x000 }, + { 0x00000002, 0x00221e23, 0x000 }, + { 0x00000005, 0xc0211220, 0x000 }, + { 0x00080000, 0x00281224, 0x000 }, + { 0x00000013, 0x00210224, 0x000 }, + { 0x00000000, 0x14c00000, 0x084 }, + { 0xa100ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204811, 0x000 }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x088 }, + { 0x00000000, 0x0020162d, 0x000 }, + { 0x00004000, 0x00500e23, 0x097 }, + { 0x00000001, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x08c }, + { 0x00000001, 0x0020162d, 0x000 }, + { 0x00004800, 0x00500e23, 0x097 }, + { 0x00000002, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x090 }, + { 0x00000003, 0x0020162d, 0x000 }, + { 0x00004900, 0x00500e23, 0x097 }, + { 0x00000003, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x094 }, + { 0x00000002, 0x0020162d, 0x000 }, + { 0x00004908, 0x00500e23, 0x097 }, + { 0x00000012, 0x0020162d, 0x000 }, + { 0x00002000, 0x00300e23, 0x000 }, + { 0x00000000, 0x00290d83, 0x000 }, + { 0x9400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x002948e5, 0x000 }, + { 0x00000000, 0x00294483, 0x000 }, + { 0x00000000, 0x40201800, 0x000 }, + { 0x00000000, 0xd9004800, 0x000 }, + { 0x00000013, 0x00210224, 0x000 }, + { 0x00000000, 0x14c00000, 0x000 }, + { 0x9400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x002948e5, 0x000 }, + { 0x9300ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00404806, 0x000 }, + { 0x00000000, 0x00600000, 0x28c }, + { 0x00000000, 0xc0200800, 0x000 }, + { 0x00000000, 0xc0201400, 0x000 }, + { 0x0000001f, 0x00211a25, 0x000 }, + { 0x00000000, 0x14e00000, 0x000 }, + { 0x000007ff, 0x00280e25, 0x000 }, + { 0x00000010, 0x00211225, 0x000 }, + { 0x8300ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x002f0224, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0ae }, + { 0x00000000, 0x00203622, 0x000 }, + { 0x00004000, 0x00504a23, 0x0bd }, + { 0x00000001, 0x002f0224, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0b2 }, + { 0x00000001, 0x00203622, 0x000 }, + { 0x00004800, 0x00504a23, 0x0bd }, + { 0x00000002, 0x002f0224, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0b6 }, + { 0x00000003, 0x00203622, 0x000 }, + { 0x00004900, 0x00504a23, 0x0bd }, + { 0x00000003, 0x002f0224, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0ba }, + { 0x00000002, 0x00203622, 0x000 }, + { 0x00004908, 0x00504a23, 0x0bd }, + { 0x00000012, 0x00203622, 0x000 }, + { 0x00000000, 0x00290d83, 0x000 }, + { 0x00002000, 0x00304a23, 0x000 }, + { 0x8400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0x21000000, 0x000 }, + { 0x00000000, 0x00400000, 0x0a4 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00040578, 0x00604411, 0x2ba }, + { 0x00000000, 0xc0400000, 0x000 }, + { 0x00000000, 0xc0200c00, 0x000 }, + { 0x00000000, 0xc0201000, 0x000 }, + { 0x00000000, 0xc0201400, 0x000 }, + { 0x00000000, 0xc0201800, 0x000 }, + { 0x00007f00, 0x00280a21, 0x000 }, + { 0x00004500, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x0cd }, + { 0x00000000, 0xc0201c00, 0x000 }, + { 0x00000000, 0x17000000, 0x000 }, + { 0x00000010, 0x00280a23, 0x000 }, + { 0x00000010, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x0d5 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00040000, 0x00694624, 0x2ba }, + { 0x00000000, 0x00400000, 0x0d6 }, + { 0x00000000, 0x00600000, 0x135 }, + { 0x00000000, 0x002820d0, 0x000 }, + { 0x00000007, 0x00280a23, 0x000 }, + { 0x00000001, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0dd }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x04e00000, 0x0f6 }, + { 0x00000000, 0x00400000, 0x0fd }, + { 0x00000002, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0e2 }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x02e00000, 0x0f6 }, + { 0x00000000, 0x00400000, 0x0fd }, + { 0x00000003, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0e7 }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x0ce00000, 0x0f6 }, + { 0x00000000, 0x00400000, 0x0fd }, + { 0x00000004, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0ec }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0f6 }, + { 0x00000000, 0x00400000, 0x0fd }, + { 0x00000005, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0f1 }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x06e00000, 0x0f6 }, + { 0x00000000, 0x00400000, 0x0fd }, + { 0x00000006, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x0f6 }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x08e00000, 0x0f6 }, + { 0x00000000, 0x00400000, 0x0fd }, + { 0x00007f00, 0x00280a21, 0x000 }, + { 0x00004500, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x000 }, + { 0x00000008, 0x00210a23, 0x000 }, + { 0x00000000, 0x14e00000, 0x11b }, + { 0x00000000, 0xc0204400, 0x000 }, + { 0x00000000, 0xc0404800, 0x000 }, + { 0x00007f00, 0x00280a21, 0x000 }, + { 0x00004500, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x102 }, + { 0x00000000, 0xc0200000, 0x000 }, + { 0x00000000, 0xc0400000, 0x000 }, + { 0x00000000, 0x00404c07, 0x0cd }, + { 0x00000000, 0xc0201000, 0x000 }, + { 0x00000000, 0xc0201400, 0x000 }, + { 0x00000000, 0xc0201800, 0x000 }, + { 0x00000000, 0xc0201c00, 0x000 }, + { 0x00000000, 0x17000000, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00040000, 0x00694624, 0x2ba }, + { 0x00000000, 0x002820d0, 0x000 }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x0ce00000, 0x000 }, + { 0x00000000, 0x00404c07, 0x107 }, + { 0x00000000, 0xc0201000, 0x000 }, + { 0x00000000, 0xc0201400, 0x000 }, + { 0x00000000, 0xc0201800, 0x000 }, + { 0x00000000, 0xc0201c00, 0x000 }, + { 0x00000000, 0x17000000, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00040000, 0x00694624, 0x2ba }, + { 0x00000000, 0x002820d0, 0x000 }, + { 0x00000000, 0x002f00a8, 0x000 }, + { 0x00000000, 0x06e00000, 0x000 }, + { 0x00000000, 0x00404c07, 0x113 }, + { 0x0000060d, 0x00204411, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x0000860e, 0x00204411, 0x000 }, + { 0x00000000, 0xd9004800, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000009, 0x00204811, 0x000 }, + { 0x0000060d, 0x00204411, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0x00404810, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00000000, 0xc0200800, 0x000 }, + { 0x00007fff, 0x00281a22, 0x000 }, + { 0x00040000, 0x00694626, 0x2ba }, + { 0x00000000, 0x00200c10, 0x000 }, + { 0x00000000, 0xc0201000, 0x000 }, + { 0x80000000, 0x00281a22, 0x000 }, + { 0x00000000, 0x002f0226, 0x000 }, + { 0x00000000, 0x0ce00000, 0x132 }, + { 0x00000000, 0x00600000, 0x135 }, + { 0x00000000, 0x00201c10, 0x000 }, + { 0x00000000, 0x00300c67, 0x000 }, + { 0x0000060d, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000000, 0x00404803, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204811, 0x000 }, + { 0xa400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204811, 0x000 }, + { 0x000001ea, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000000, 0x1ac00000, 0x13b }, + { 0x9e00ffff, 0x00204411, 0x000 }, + { 0xdeadbeef, 0x00204811, 0x000 }, + { 0x00000000, 0x1ae00000, 0x13e }, + { 0xa400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x0080480b, 0x000 }, + { 0x000001f3, 0x00204411, 0x000 }, + { 0xe0000000, 0xc0484a20, 0x000 }, + { 0x00000000, 0xd9000000, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0xc0200c00, 0x000 }, + { 0x8c00ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000fff, 0x00281223, 0x000 }, + { 0x0000000f, 0x00203624, 0x000 }, + { 0x00000003, 0x00381224, 0x000 }, + { 0x00005000, 0x00301224, 0x000 }, + { 0x0000000e, 0x00203624, 0x000 }, + { 0x8700ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000001, 0x00331224, 0x000 }, + { 0x8600ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x0000001d, 0x00211223, 0x000 }, + { 0x00000020, 0x00222091, 0x000 }, + { 0x00000003, 0x00381228, 0x000 }, + { 0x8800ffff, 0x00204411, 0x000 }, + { 0x00004fff, 0x00304a24, 0x000 }, + { 0x00000010, 0x00211623, 0x000 }, + { 0x00000fff, 0x00281625, 0x000 }, + { 0x00000fff, 0x00281a23, 0x000 }, + { 0x00000000, 0x00331ca6, 0x000 }, + { 0x8f00ffff, 0x00204411, 0x000 }, + { 0x00000003, 0x00384a27, 0x000 }, + { 0x00000010, 0x00211223, 0x000 }, + { 0x00000fff, 0x00281224, 0x000 }, + { 0x0000000d, 0x00203624, 0x000 }, + { 0x8b00ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000003, 0x00381224, 0x000 }, + { 0x00005000, 0x00301224, 0x000 }, + { 0x0000000c, 0x00203624, 0x000 }, + { 0x8500ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000000, 0x00331cc8, 0x000 }, + { 0x9000ffff, 0x00204411, 0x000 }, + { 0x00000003, 0x00384a27, 0x000 }, + { 0x00300000, 0x00493a2e, 0x000 }, + { 0x00000000, 0x00202c11, 0x000 }, + { 0x00000001, 0x00303e2f, 0x000 }, + { 0x00000000, 0xc0200800, 0x000 }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x172 }, + { 0x00000000, 0xd9000000, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0x00600000, 0x28c }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000002, 0x00204811, 0x000 }, + { 0x00000000, 0x002f0230, 0x000 }, + { 0x00000000, 0x0ae00000, 0x175 }, + { 0x00000000, 0xc0200800, 0x000 }, + { 0x00000009, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x17d }, + { 0x00000000, 0x00600000, 0x2b7 }, + { 0x00000000, 0x00200c11, 0x000 }, + { 0x00000016, 0x00203623, 0x000 }, + { 0x00000000, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x180 }, + { 0x00000000, 0xc0200000, 0x000 }, + { 0x00000001, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x183 }, + { 0x00000000, 0xc0200000, 0x000 }, + { 0x00000002, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x18d }, + { 0x00000004, 0xc0203620, 0x000 }, + { 0x00000005, 0xc0203620, 0x000 }, + { 0x00000006, 0xc0203620, 0x000 }, + { 0x00000007, 0xc0203620, 0x000 }, + { 0x00000008, 0xc0203620, 0x000 }, + { 0x00000009, 0xc0203620, 0x000 }, + { 0x0000000a, 0xc0203620, 0x000 }, + { 0x0000000b, 0xc0203620, 0x000 }, + { 0x00000003, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x1b5 }, + { 0x00000000, 0xc0200c00, 0x000 }, + { 0x8c00ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000fff, 0x00281223, 0x000 }, + { 0x0000000f, 0x00203624, 0x000 }, + { 0x00000003, 0x00381224, 0x000 }, + { 0x00005000, 0x00301224, 0x000 }, + { 0x0000000e, 0x00203624, 0x000 }, + { 0x8700ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000001, 0x00331224, 0x000 }, + { 0x8600ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x0000001d, 0x00211223, 0x000 }, + { 0x00000020, 0x00222091, 0x000 }, + { 0x00000003, 0x00381228, 0x000 }, + { 0x8800ffff, 0x00204411, 0x000 }, + { 0x00004fff, 0x00304a24, 0x000 }, + { 0x00000010, 0x00211623, 0x000 }, + { 0x00000fff, 0x00281625, 0x000 }, + { 0x00000fff, 0x00281a23, 0x000 }, + { 0x00000000, 0x00331ca6, 0x000 }, + { 0x8f00ffff, 0x00204411, 0x000 }, + { 0x00000003, 0x00384a27, 0x000 }, + { 0x00000010, 0x00211223, 0x000 }, + { 0x00000fff, 0x00281224, 0x000 }, + { 0x0000000d, 0x00203624, 0x000 }, + { 0x8b00ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000003, 0x00381224, 0x000 }, + { 0x00005000, 0x00301224, 0x000 }, + { 0x0000000c, 0x00203624, 0x000 }, + { 0x8500ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204804, 0x000 }, + { 0x00000000, 0x00331cc8, 0x000 }, + { 0x9000ffff, 0x00204411, 0x000 }, + { 0x00000003, 0x00384a27, 0x000 }, + { 0x00300000, 0x00293a2e, 0x000 }, + { 0x00000004, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x1bd }, + { 0xa300ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x40204800, 0x000 }, + { 0x0000000a, 0xc0220e20, 0x000 }, + { 0x00000011, 0x00203623, 0x000 }, + { 0x000021f4, 0x00204411, 0x000 }, + { 0x0000000a, 0x00614a2c, 0x2b7 }, + { 0x00000005, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x1c0 }, + { 0x00000000, 0xc0200000, 0x000 }, + { 0x00000006, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x1c6 }, + { 0x9c00ffff, 0x00204411, 0x000 }, + { 0x0000001f, 0x40214a20, 0x000 }, + { 0x9600ffff, 0x00204411, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000007, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x1d0 }, + { 0x3fffffff, 0x00283a2e, 0x000 }, + { 0xc0000000, 0x40280e20, 0x000 }, + { 0x00000000, 0x0029386e, 0x000 }, + { 0x18000000, 0x40280e20, 0x000 }, + { 0x00000016, 0x00203623, 0x000 }, + { 0xa400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0xc0202c00, 0x000 }, + { 0x00000000, 0x0020480b, 0x000 }, + { 0x00000008, 0x00210222, 0x000 }, + { 0x00000000, 0x14c00000, 0x1dc }, + { 0x00000000, 0xc0200c00, 0x000 }, + { 0x00000013, 0x00203623, 0x000 }, + { 0x00000015, 0x00203623, 0x000 }, + { 0x00000002, 0x40221220, 0x000 }, + { 0x00000000, 0x00301083, 0x000 }, + { 0x00000014, 0x00203624, 0x000 }, + { 0x00000003, 0xc0210e20, 0x000 }, + { 0x10000000, 0x00280e23, 0x000 }, + { 0xefffffff, 0x00283a2e, 0x000 }, + { 0x00000000, 0x0029386e, 0x000 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0x00600000, 0x28c }, + { 0x00000000, 0xc0200800, 0x000 }, + { 0x0000001f, 0x00210e22, 0x000 }, + { 0x00000000, 0x14e00000, 0x000 }, + { 0x000003ff, 0x00280e22, 0x000 }, + { 0x00000018, 0x00211222, 0x000 }, + { 0x00000004, 0x00301224, 0x000 }, + { 0x00000000, 0x0020108d, 0x000 }, + { 0x00002000, 0x00291224, 0x000 }, + { 0x8300ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00294984, 0x000 }, + { 0x8400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0x21000000, 0x000 }, + { 0x00000000, 0x00400000, 0x1de }, + { 0x8200ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00000000, 0xc0200800, 0x000 }, + { 0x00003fff, 0x40280e20, 0x000 }, + { 0x00000010, 0xc0211220, 0x000 }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x1fb }, + { 0x00000000, 0x2ae00000, 0x205 }, + { 0x20000080, 0x00281e2e, 0x000 }, + { 0x00000080, 0x002f0227, 0x000 }, + { 0x00000000, 0x0ce00000, 0x1f8 }, + { 0x00000000, 0x00401c0c, 0x1f9 }, + { 0x00000010, 0x00201e2d, 0x000 }, + { 0x000021f9, 0x00294627, 0x000 }, + { 0x00000000, 0x00404811, 0x205 }, + { 0x00000001, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x23a }, + { 0x00000000, 0x28e00000, 0x205 }, + { 0x00800080, 0x00281e2e, 0x000 }, + { 0x00000080, 0x002f0227, 0x000 }, + { 0x00000000, 0x0ce00000, 0x202 }, + { 0x00000000, 0x00401c0c, 0x203 }, + { 0x00000010, 0x00201e2d, 0x000 }, + { 0x000021f9, 0x00294627, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x20c }, + { 0x00000003, 0x00204811, 0x000 }, + { 0x0000000c, 0x0020162d, 0x000 }, + { 0x0000000d, 0x00201a2d, 0x000 }, + { 0xffdfffff, 0x00483a2e, 0x210 }, + { 0x00000004, 0x00204811, 0x000 }, + { 0x0000000e, 0x0020162d, 0x000 }, + { 0x0000000f, 0x00201a2d, 0x000 }, + { 0xffefffff, 0x00283a2e, 0x000 }, + { 0x00000000, 0x00201c10, 0x000 }, + { 0x00000000, 0x002f0067, 0x000 }, + { 0x00000000, 0x04e00000, 0x205 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000006, 0x00204811, 0x000 }, + { 0x8300ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204805, 0x000 }, + { 0x8900ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204806, 0x000 }, + { 0x8400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0x21000000, 0x000 }, + { 0x00000000, 0x00601010, 0x28c }, + { 0x0000000c, 0x00221e24, 0x000 }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x22d }, + { 0x20000000, 0x00293a2e, 0x000 }, + { 0x000021f7, 0x0029462c, 0x000 }, + { 0x00000000, 0x002948c7, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000005, 0x00204811, 0x000 }, + { 0x0000000c, 0x00203630, 0x000 }, + { 0x00000007, 0x00204811, 0x000 }, + { 0x0000000d, 0x00203630, 0x000 }, + { 0x9100ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0x23000000, 0x000 }, + { 0x8d00ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00404803, 0x240 }, + { 0x00800000, 0x00293a2e, 0x000 }, + { 0x000021f6, 0x0029462c, 0x000 }, + { 0x00000000, 0x002948c7, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000005, 0x00204811, 0x000 }, + { 0x0000000e, 0x00203630, 0x000 }, + { 0x00000007, 0x00204811, 0x000 }, + { 0x0000000f, 0x00203630, 0x000 }, + { 0x9200ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0x25000000, 0x000 }, + { 0x8e00ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00404803, 0x240 }, + { 0x8300ffff, 0x00204411, 0x000 }, + { 0x00000003, 0x00381224, 0x000 }, + { 0x00005000, 0x00304a24, 0x000 }, + { 0x8400ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x00000000, 0x21000000, 0x000 }, + { 0x8200ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00404811, 0x000 }, + { 0x00000003, 0x40280a20, 0x000 }, + { 0xffffffe0, 0xc0280e20, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00000001, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x24a }, + { 0x000021f6, 0x0029122c, 0x000 }, + { 0x00040000, 0x00494624, 0x24c }, + { 0x000021f7, 0x0029122c, 0x000 }, + { 0x00040000, 0x00294624, 0x000 }, + { 0x00000000, 0x00600000, 0x2ba }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x252 }, + { 0x00000001, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ce00000, 0x252 }, + { 0x00000000, 0x00481630, 0x258 }, + { 0x00000fff, 0x00281630, 0x000 }, + { 0x0000000c, 0x00211a30, 0x000 }, + { 0x00000fff, 0x00281a26, 0x000 }, + { 0x00000000, 0x002f0226, 0x000 }, + { 0x00000000, 0x0ae00000, 0x258 }, + { 0x00000000, 0xc0400000, 0x000 }, + { 0x00040d02, 0x00604411, 0x2ba }, + { 0x00000000, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x25d }, + { 0x00000010, 0x00211e30, 0x000 }, + { 0x00000fff, 0x00482630, 0x267 }, + { 0x00000001, 0x002f0222, 0x000 }, + { 0x00000000, 0x0ae00000, 0x261 }, + { 0x00000fff, 0x00281e30, 0x000 }, + { 0x00000200, 0x00402411, 0x267 }, + { 0x00000000, 0x00281e30, 0x000 }, + { 0x00000010, 0x00212630, 0x000 }, + { 0x00000010, 0x00211a30, 0x000 }, + { 0x00000000, 0x002f0226, 0x000 }, + { 0x00000000, 0x0ae00000, 0x258 }, + { 0x00000000, 0xc0400000, 0x000 }, + { 0x00000003, 0x00381625, 0x000 }, + { 0x00000003, 0x00381a26, 0x000 }, + { 0x00000003, 0x00381e27, 0x000 }, + { 0x00000003, 0x00382629, 0x000 }, + { 0x00005000, 0x00302629, 0x000 }, + { 0x0000060d, 0x00204411, 0x000 }, + { 0x00000000, 0xc0204800, 0x000 }, + { 0x00000000, 0x00204806, 0x000 }, + { 0x00005000, 0x00302225, 0x000 }, + { 0x00040000, 0x00694628, 0x2ba }, + { 0x00000001, 0x00302228, 0x000 }, + { 0x00000000, 0x00202810, 0x000 }, + { 0x00040000, 0x00694628, 0x2ba }, + { 0x00000001, 0x00302228, 0x000 }, + { 0x00000000, 0x00200810, 0x000 }, + { 0x00040000, 0x00694628, 0x2ba }, + { 0x00000001, 0x00302228, 0x000 }, + { 0x00000000, 0x00201410, 0x000 }, + { 0x0000060d, 0x00204411, 0x000 }, + { 0x00000000, 0x00204803, 0x000 }, + { 0x0000860e, 0x00204411, 0x000 }, + { 0x00000000, 0x0020480a, 0x000 }, + { 0x00000000, 0x00204802, 0x000 }, + { 0x00000000, 0x00204805, 0x000 }, + { 0x00000000, 0x002f0128, 0x000 }, + { 0x00000000, 0x0ae00000, 0x282 }, + { 0x00005000, 0x00302227, 0x000 }, + { 0x0000000c, 0x00300e23, 0x000 }, + { 0x00000003, 0x00331a26, 0x000 }, + { 0x00000000, 0x002f0226, 0x000 }, + { 0x00000000, 0x0ae00000, 0x270 }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x000001f3, 0x00204411, 0x000 }, + { 0x04000000, 0x00204811, 0x000 }, + { 0x00000000, 0x00400000, 0x289 }, + { 0x00000000, 0xc0600000, 0x28c }, + { 0x00000000, 0x00400000, 0x000 }, + { 0x00000000, 0x0ec00000, 0x28e }, + { 0x00000000, 0x00800000, 0x000 }, + { 0x000021f9, 0x0029462c, 0x000 }, + { 0x00000005, 0x00204811, 0x000 }, + { 0x00000000, 0x0020280c, 0x000 }, + { 0x00000011, 0x0020262d, 0x000 }, + { 0x00000000, 0x002f012c, 0x000 }, + { 0x00000000, 0x0ae00000, 0x295 }, + { 0x00000000, 0x00403011, 0x296 }, + { 0x00000400, 0x0030322c, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000002, 0x00204811, 0x000 }, + { 0x0000000a, 0x0021262c, 0x000 }, + { 0x00000000, 0x00210130, 0x000 }, + { 0x00000000, 0x14c00000, 0x29d }, + { 0xa500ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00404811, 0x299 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00042294, 0x00604411, 0x2ba }, + { 0x00000000, 0x00200010, 0x000 }, + { 0xa500ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204811, 0x000 }, + { 0x000021f4, 0x0029462c, 0x000 }, + { 0x0000000a, 0x00214a2a, 0x000 }, + { 0xa200ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000002, 0x00204811, 0x000 }, + { 0x00000000, 0x00210130, 0x000 }, + { 0xdf7fffff, 0x00283a2e, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000001, 0x00204811, 0x000 }, + { 0x00042294, 0x00604411, 0x2ba }, + { 0x00000000, 0x00200010, 0x000 }, + { 0x00000010, 0x0080362a, 0x000 }, + { 0x9700ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x0020480c, 0x000 }, + { 0xa200ffff, 0x00204411, 0x000 }, + { 0x00000000, 0x00204811, 0x000 }, + { 0x8100ffff, 0x00204411, 0x000 }, + { 0x00000002, 0x00204811, 0x000 }, + { 0x00000000, 0x00810130, 0x000 }, + { 0x00000000, 0x00203011, 0x000 }, + { 0x00000010, 0x0080362c, 0x000 }, + { 0x00000000, 0xc0400000, 0x000 }, + { 0x00000000, 0x1ac00000, 0x2ba }, + { 0x9f00ffff, 0x00204411, 0x000 }, + { 0xdeadbeef, 0x00204811, 0x000 }, + { 0x00000000, 0x1ae00000, 0x2bd }, + { 0x00000000, 0x00800000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00000000, 0x00000000, 0x000 }, + { 0x00020143, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x01dd0002, 0x000 }, + { 0x006301ee, 0x00280012, 0x000 }, + { 0x00020002, 0x00020026, 0x000 }, + { 0x00020002, 0x01ec0002, 0x000 }, + { 0x00790242, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00200012, 0x00020016, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x011b00c5, 0x00020125, 0x000 }, + { 0x00020141, 0x00020002, 0x000 }, + { 0x00c50002, 0x0143002e, 0x000 }, + { 0x00a2016b, 0x00020145, 0x000 }, + { 0x00020002, 0x01200002, 0x000 }, + { 0x00020002, 0x010f0103, 0x000 }, + { 0x00090002, 0x000e000e, 0x000 }, + { 0x0058003d, 0x00600002, 0x000 }, + { 0x000200c1, 0x0002028a, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x00020002, 0x00020002, 0x000 }, + { 0x000502b9, 0x00020008, 0x000 }, +}; + +#endif +static const uint32 ME_JUMP_TABLE_START = 740; +static const uint32 ME_JUMP_TABLE_END = 768; + +#endif + From 93106fa652103785d6a3373c9d082ae5267d73db Mon Sep 17 00:00:00 2001 From: Matt Sealey Date: Tue, 27 Sep 2011 16:03:48 -0500 Subject: [PATCH 18/32] gpu: port to 2.6.38 --- drivers/mxc/amd-gpu/gsl_g12.c | 1 + drivers/mxc/amd-gpu/gsl_hal.c | 2 ++ drivers/mxc/amd-gpu/gsl_kmod.c | 11 ++++++----- drivers/mxc/amd-gpu/misc.c | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/mxc/amd-gpu/gsl_g12.c b/drivers/mxc/amd-gpu/gsl_g12.c index d979cd54926..e7fb131a157 100644 --- a/drivers/mxc/amd-gpu/gsl_g12.c +++ b/drivers/mxc/amd-gpu/gsl_g12.c @@ -18,6 +18,7 @@ #include #include +#include #include "gsl.h" #include "gsl_hal.h" diff --git a/drivers/mxc/amd-gpu/gsl_hal.c b/drivers/mxc/amd-gpu/gsl_hal.c index 69908c4eb78..1aca6df25a0 100644 --- a/drivers/mxc/amd-gpu/gsl_hal.c +++ b/drivers/mxc/amd-gpu/gsl_hal.c @@ -34,6 +34,8 @@ #include #include +#include + #define GSL_HAL_MEM1 0 #define GSL_HAL_MEM2 1 //#define GSL_HAL_MEM3 2 diff --git a/drivers/mxc/amd-gpu/gsl_kmod.c b/drivers/mxc/amd-gpu/gsl_kmod.c index da39bc3ef12..bab42621d93 100644 --- a/drivers/mxc/amd-gpu/gsl_kmod.c +++ b/drivers/mxc/amd-gpu/gsl_kmod.c @@ -40,6 +40,7 @@ #include #include +#include int gpu_2d_irq, gpu_3d_irq; @@ -55,7 +56,7 @@ int enable_mmu; static ssize_t gsl_kmod_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr); static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr); -static int gsl_kmod_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, unsigned long arg); +static long gsl_kmod_ioctl(struct file *fd, unsigned int cmd, unsigned long arg); static int gsl_kmod_mmap(struct file *fd, struct vm_area_struct *vma); static int gsl_kmod_fault(struct vm_area_struct *vma, struct vm_fault *vmf); static int gsl_kmod_open(struct inode *inode, struct file *fd); @@ -72,7 +73,7 @@ static const struct file_operations gsl_kmod_fops = .owner = THIS_MODULE, .read = gsl_kmod_read, .write = gsl_kmod_write, - .ioctl = gsl_kmod_ioctl, + .unlocked_ioctl = gsl_kmod_ioctl, .mmap = gsl_kmod_mmap, .open = gsl_kmod_open, .release = gsl_kmod_release @@ -93,9 +94,9 @@ static ssize_t gsl_kmod_write(struct file *fd, const char __user *buf, size_t le return 0; } -static int gsl_kmod_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, unsigned long arg) +static long gsl_kmod_ioctl(struct file *fd, unsigned int cmd, unsigned long arg) { - int kgslStatus = GSL_FAILURE; + long kgslStatus = GSL_FAILURE; switch (cmd) { case IOCTL_KGSL_DEVICE_START: @@ -768,7 +769,7 @@ static int gpu_probe(struct platform_device *pdev) int i; struct resource *res; struct device *dev; - struct mxc_gpu_platform_data *gpu_data = NULL; + struct mxc_gpu_platform_data *gpu_data; gpu_data = (struct mxc_gpu_platform_data *)pdev->dev.platform_data; diff --git a/drivers/mxc/amd-gpu/misc.c b/drivers/mxc/amd-gpu/misc.c index 210ce79eda7..88324c1526e 100644 --- a/drivers/mxc/amd-gpu/misc.c +++ b/drivers/mxc/amd-gpu/misc.c @@ -27,7 +27,7 @@ #include typedef struct _gsl_autogate_t { - struct timer_list timer; + struct timer_list timer; spinlock_t lock; int active; /* pending indicate the timer has been fired but clock not yet disabled. */ @@ -38,7 +38,7 @@ typedef struct _gsl_autogate_t { } gsl_autogate_t; static gsl_autogate_t *g_autogate[2]; -static DECLARE_MUTEX(sem_dev); +static DEFINE_SEMAPHORE(sem_dev); #define KGSL_DEVICE_IDLE_TIMEOUT 5000 /* unit ms */ From 47387b1fa20747a60c5e9478f6fbf7b104b229d8 Mon Sep 17 00:00:00 2001 From: Steev Klimaszewski Date: Tue, 11 Oct 2011 15:54:40 -0500 Subject: [PATCH 19/32] mx53_efikasb: Remove duplicate includes There were 2 duplicate includes in the board-mx53_efikasb.c file. Signed-off-by: Steev Klimaszewski --- arch/arm/mach-mx5/board-mx53_efikasb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c index afcdbcd611d..253f58bf840 100644 --- a/arch/arm/mach-mx5/board-mx53_efikasb.c +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -30,9 +30,6 @@ #include #include #include -#include -#include -#include #include #include @@ -45,6 +42,7 @@ #include #include +#include #include #include From 45f4a9a4f6cd53a6b2306f70ecd6b9a87ce463e1 Mon Sep 17 00:00:00 2001 From: Steev Klimaszewski Date: Tue, 11 Oct 2011 16:07:44 -0500 Subject: [PATCH 20/32] sppp: Add initial header for sppp --- include/linux/sppp.h | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 include/linux/sppp.h diff --git a/include/linux/sppp.h b/include/linux/sppp.h new file mode 100644 index 00000000000..0db9d935b76 --- /dev/null +++ b/include/linux/sppp.h @@ -0,0 +1,49 @@ +#ifndef _SPPP_H_ +#define _SPPP_H_ + +#define MAX_RECV_PKG_SIZE 100 + +#define MAX_PKG_SIZE 100 +#define MAX_LOOP_COUNT MAX_RECV_PKG_SIZE + +#define SPPP_PKT_ID_MASK 0x3F +#define SPPP_PKT_START 0x80 +#define SPPP_PKT_STOP 0xC0 +#define ISBITSET(val, bit) ((val) & (1 << (bit))) + +#define SPPP_SHORT_ID 0 +#define SPPP_KEY_ID 1 +#define SPPP_PS2_ID 2 +#define SPPP_RTC_ID 3 +#define SPPP_PWR_ID 4 +#define SPPP_STRING_ID 60 +#define SPPP_BINARY_ID 61 + +#define SPPP_NOSYNC 0x00 +#define SPPP_SYNC 0xff + +typedef struct { + uint8_t input[MAX_RECV_PKG_SIZE]; + uint8_t id; + uint8_t crc; + uint8_t pos; + uint8_t num; + uint8_t carry; + uint8_t sync; +} sppp_rx_t; + +typedef struct { + uint8_t crc; + uint8_t pos; + uint8_t carry; + int comd; +} sppp_tx_t; + +int sppp_recv(int comd, sppp_rx_t *sppp_rx); +void sppp_start(sppp_tx_t *sppp_tx, uint8_t pkg_id); +void sppp_data(sppp_tx_t *sppp_tx, uint8_t data); +void sppp_stop(sppp_tx_t *sppp_tx); + +void sppp_send(sppp_tx_t *sppp_tx, unsigned char *buf, int size, int pkg_id); + +#endif /* _SPPP_H_ */ From 9d6750c2b6836df82b61df5d39c804c19c7f2d19 Mon Sep 17 00:00:00 2001 From: Steev Klimaszewski Date: Mon, 17 Oct 2011 17:32:27 -0500 Subject: [PATCH 21/32] sppp: whitespace cleanups Signed-off-by: Steev Klimaszewski --- include/linux/sppp.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/linux/sppp.h b/include/linux/sppp.h index 0db9d935b76..6995e8d0a92 100644 --- a/include/linux/sppp.h +++ b/include/linux/sppp.h @@ -23,20 +23,20 @@ #define SPPP_SYNC 0xff typedef struct { - uint8_t input[MAX_RECV_PKG_SIZE]; - uint8_t id; - uint8_t crc; - uint8_t pos; - uint8_t num; - uint8_t carry; - uint8_t sync; + uint8_t input[MAX_RECV_PKG_SIZE]; + uint8_t id; + uint8_t crc; + uint8_t pos; + uint8_t num; + uint8_t carry; + uint8_t sync; } sppp_rx_t; typedef struct { - uint8_t crc; - uint8_t pos; - uint8_t carry; - int comd; + uint8_t crc; + uint8_t pos; + uint8_t carry; + int comd; } sppp_tx_t; int sppp_recv(int comd, sppp_rx_t *sppp_rx); From 4d92dff4b22d8a272cb816fc1fe66175d437639f Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Wed, 16 Nov 2011 04:15:15 +0200 Subject: [PATCH 22/32] Step one to get the CW1200 driver to work. Important: @if (val & SDHCI_INT_CARD_INT) we enter the part which clears and then sets D3CD bit to avoid missing the card interrupt. This is a Freescale patch which in our case causes an interrupt storm and freezes the system. The original steps are: data = readl(host->ioaddr + SDHCI_HOST_CONTROL); data &= ~SDHCI_CTRL_D3CD; writel(data, host->ioaddr + SDHCI_HOST_CONTROL); data |= SDHCI_CTRL_D3CD; writel(data, host->ioaddr + SDHCI_HOST_CONTROL); We just do: data = readl(host->ioaddr + SDHCI_HOST_CONTROL); data |= SDHCI_CTRL_D3CD; writel(data, host->ioaddr + SDHCI_HOST_CONTROL); This needs to be investigated furhter. --- drivers/mmc/host/sdhci-esdhc-imx.c | 42 ++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 3ef52006046..ee3c48548f5 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -27,6 +27,7 @@ #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" +#define SDHCI_CTRL_D3CD 0x08 /* VENDOR SPEC register */ #define SDHCI_VENDOR_SPEC 0xC0 #define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 @@ -74,7 +75,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) if (boarddata && gpio_is_valid(boarddata->cd_gpio) && gpio_get_value(boarddata->cd_gpio)) /* no card, if a valid gpio says so... */ - val &= SDHCI_CARD_PRESENT; + val &= ~SDHCI_CARD_PRESENT; else /* ... in all other cases assume card is present */ val |= SDHCI_CARD_PRESENT; @@ -87,14 +88,22 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = pltfm_host->priv; - - if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE) - && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) - /* - * these interrupts won't work with a custom card_detect gpio - * (only applied to mx25/35) - */ - val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); + u32 data; + + if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { + if (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP) + /* + * these interrupts won't work with a custom card_detect gpio + * (only applied to mx25/35) + */ + val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); + + if (val & SDHCI_INT_CARD_INT) { + data = readl(host->ioaddr + SDHCI_HOST_CONTROL); + data |= SDHCI_CTRL_D3CD; + writel(data, host->ioaddr + SDHCI_HOST_CONTROL); + } + } if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT) && (reg == SDHCI_INT_STATUS) @@ -164,8 +173,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) */ return; case SDHCI_HOST_CONTROL: - /* FSL messed up here, so we can just keep those two */ - new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS); + /* FSL messed up here, so we can just keep those three */ + new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS | SDHCI_CTRL_D3CD); /* ensure the endianess */ new_val |= ESDHC_HOST_CONTROL_LE; /* DMA mode bits are shifted */ @@ -175,6 +184,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) return; } esdhc_clrset_le(host, 0xff, val, reg); + + /* + * The esdhc has a design violation to SDHC spec which tells + * that software reset should not affect card detection circuit. + * But esdhc clears its SYSCTL register bits [0..2] during the + * software reset. This will stop those clocks that card detection + * circuit relies on. To work around it, we turn the clocks on back + * to keep card detection circuit functional. + */ + if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1)) + esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL); } static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) From 47361645b0af61305e073a4e3ef4ce55767d6322 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Wed, 16 Nov 2011 04:18:17 +0200 Subject: [PATCH 23/32] Step two to get the cw1200 driver to work. This quirck takes care of SDIO devices not supporting 512 byte requests in byte mode during CMD53. http://comments.gmane.org/gmane.linux.kernel.mmc/10087 --- drivers/mmc/core/quirks.c | 10 ++++++++++ drivers/mmc/core/sdio_ops.c | 9 +++++++-- include/linux/mmc/card.h | 8 +++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index 11118b74eb2..4cb5a6966d4 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c @@ -57,6 +57,14 @@ static void add_quirk_for_sdio_devices(struct mmc_card *card, int data) #define SDIO_DEVICE_ID_TI_WL1271 0x4076 #endif +#ifndef SDIO_VENDOR_ID_STE +#define SDIO_VENDOR_ID_STE 0x0020 +#endif + +#ifndef SDIO_DEVICE_ID_STE_CW1200 +#define SDIO_DEVICE_ID_STE_CW1200 0x2280 +#endif + static const struct mmc_fixup mmc_fixup_methods[] = { /* by default sdio devices are considered CLK_GATING broken */ /* good cards will be whitelisted as they are tested */ @@ -64,6 +72,8 @@ static const struct mmc_fixup mmc_fixup_methods[] = { add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING }, { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING }, + { SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, + add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512}, { 0 } }; diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index dea36d9c22e..2aefb41d89f 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -152,8 +152,13 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, cmd.arg |= fn << 28; cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; cmd.arg |= addr << 9; - if (blocks == 1 && blksz <= 512) - cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ + //if (blocks == 1 && blksz <= 512) + // cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ + if (blocks == 1 && blksz < 512) + cmd.arg |= blksz; /* byte mode */ + else if (blocks == 1 && blksz == 512 && + !(mmc_card_broken_byte_mode_512(card))) + cmd.arg |= 0; /* byte mode, 0==512 */ else cmd.arg |= 0x08000000 | blocks; /* block mode */ cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index adb4888248b..245b641fef2 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -125,7 +125,8 @@ struct mmc_card { #define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card attached */ /* (missing CIA registers) */ #define MMC_QUIRK_BROKEN_CLK_GATING (1<<3) /* clock gating the sdio bus will make card fail */ - +#define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ + /* byte mode */ unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ @@ -180,6 +181,11 @@ static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; } +static inline int mmc_card_broken_byte_mode_512(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_BYTE_MODE_512; +} + #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) From 50f545859a13c1a5a3b4ac507bf51bb5a8e6466f Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Sun, 11 Dec 2011 07:33:44 +0200 Subject: [PATCH 24/32] Wrong mute mask, and some restructuring for clarity. --- sound/soc/codecs/cs42l52.h | 5 ++--- sound/soc/imx/imx-cs42l52.c | 41 +++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h index 4f0fe3d37de..bbe42ac1941 100644 --- a/sound/soc/codecs/cs42l52.h +++ b/sound/soc/codecs/cs42l52.h @@ -26,8 +26,7 @@ #define CS42L52_MAX_CLK 27000000 #define CS42L52_DEFAULT_FORMAT SNDRV_PCM_FMTBIT_S16_LE #define CS42L52_DEFAULT_MAX_CHANS 2 -#define CS42L52_SYSCLK 1 - +#define CS42L52_SYSCLK 0x01 #define CS42L52_CHIP_SWICTH (1 << 17) #define CS42L52_ALL_IN_ONE (1 << 16) @@ -188,7 +187,7 @@ #define PB_CTL1_INV_PCMA (1 << 2) #define PB_CTL1_MSTB_MUTE (1 << 1) #define PB_CTL1_MSTA_MUTE (1 << 0) -#define PB_CTL1_MUTE_MASK 0xFFFD +#define PB_CTL1_MUTE_MASK 0xFFFC//0xFFFD #define MISC_CTL 0x0E //0x02 #define MISC_CTL_DEEMPH (1 << 2) diff --git a/sound/soc/imx/imx-cs42l52.c b/sound/soc/imx/imx-cs42l52.c index c2effa4e34d..19c09fb9dfd 100644 --- a/sound/soc/imx/imx-cs42l52.c +++ b/sound/soc/imx/imx-cs42l52.c @@ -58,18 +58,7 @@ static int imx_efikasb_cs42l52_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; - /* TODO: The SSI driver should figure this out for us */ unsigned int channels = params_channels(params); - switch (channels) { - case 2: - snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffc, 0xfffffffc, 2, 0); - break; - case 1: - snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffe, 0xfffffffe, 1, 0); - break; - default: - return -EINVAL; - } /* Set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, @@ -82,6 +71,27 @@ static int imx_efikasb_cs42l52_hw_params(struct snd_pcm_substream *substream, return ret; } + /* Set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, CS42L52_SYSCLK, + card_priv.sysclk, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + /* TODO: The SSI driver should figure this out for us */ + switch (channels) { + case 2: + snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffc, 0xfffffffc, 2, 0); + break; + case 1: + snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffe, 0xfffffffe, 1, 0); + break; + default: + return -EINVAL; + } + /* Set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | @@ -92,15 +102,6 @@ static int imx_efikasb_cs42l52_hw_params(struct snd_pcm_substream *substream, return ret; } - /* Set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, CS42L52_SYSCLK, - card_priv.sysclk, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - return ret; } From 3cdc226dd534e6be547d233d72683aa556e05a65 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Sun, 11 Dec 2011 07:37:56 +0200 Subject: [PATCH 25/32] Don't register RTC. We have the SPPP RTC, and the srtc driver seems to conflict with audio. This is still under investigation. --- arch/arm/mach-mx5/board-mx53_efikasb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c index 253f58bf840..661dd610510 100644 --- a/arch/arm/mach-mx5/board-mx53_efikasb.c +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -109,8 +109,8 @@ static iomux_v3_cfg_t mx53_efikasb_pads[] = { MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, /* I2C1 */ -/* MX53_PAD_CSI0_DAT8__I2C1_SDA, */ -/* MX53_PAD_CSI0_DAT9__I2C1_SCL, */ +// MX53_PAD_CSI0_DAT8__I2C1_SDA, +// MX53_PAD_CSI0_DAT9__I2C1_SCL, MX53_PAD_CSI0_DAT8__GPIO5_26, MX53_PAD_CSI0_DAT9__GPIO5_27, /* UART */ @@ -172,6 +172,7 @@ static struct ipuv3_fb_platform_data efikasb_fb0_data = { .num_modes = ARRAY_SIZE(video_modes), }; + static struct ipuv3_fb_platform_data efikasb_fb1_data = { .interface_pix_fmt = IPU_PIX_FMT_BGR24, .mode_str = "WSVGA", @@ -179,6 +180,7 @@ static struct ipuv3_fb_platform_data efikasb_fb1_data = { .num_modes = ARRAY_SIZE(video_modes), }; + static struct imx_ipuv3_platform_data ipu_data = { .rev = 3, .fb_head0_platform_data = &efikasb_fb0_data, @@ -551,11 +553,10 @@ static void __init mx53_efikasb_board_init(void) imx53_add_v4l2_output(0); imx53_add_imx2_wdt(0, NULL); - imx53_add_srtc(); imx53_add_dvfs_core(&efikasb_dvfs_core_data); /* I2C */ - /* imx53_add_imx_i2c(0, &mx53_efikasb_i2c_data); */ + //imx53_add_imx_i2c(0, &mx53_efikasb_i2c_data); mxc_register_device(&i2c_gpio_device, &i2c_gpio_data); i2c_register_board_info(0, mxc_i2c0_board_info, From 8f7b7c565003138b690ca9a16f808c3a7f644c06 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Sun, 11 Dec 2011 07:38:57 +0200 Subject: [PATCH 26/32] SPPP integration for keyboard, trackpad, clock and power. Power and main driver are part of the architecture specific files. This can probably be done better with specific platform devices. Drivers for mouse, trackpad and rtc are in their respective directories. --- arch/arm/mach-mx5/Makefile | 2 +- arch/arm/mach-mx5/sppp_power.c | 55 ++++ arch/arm/mach-mx5/spppdriver.c | 406 +++++++++++++++++++++++++ arch/arm/mach-mx5/spppdriver.h | 108 +++++++ drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/sppp_keyboard.c | 247 +++++++++++++++ drivers/input/mouse/Kconfig | 9 + drivers/input/mouse/Makefile | 1 + drivers/input/mouse/sppp_trackpad.c | 139 +++++++++ drivers/rtc/Kconfig | 9 + drivers/rtc/Makefile | 1 + drivers/rtc/sppp_rtc.c | 152 +++++++++ include/linux/sppp.h | 59 ++-- 14 files changed, 1180 insertions(+), 18 deletions(-) create mode 100644 arch/arm/mach-mx5/sppp_power.c create mode 100644 arch/arm/mach-mx5/spppdriver.c create mode 100644 arch/arm/mach-mx5/spppdriver.h create mode 100644 drivers/input/keyboard/sppp_keyboard.c create mode 100644 drivers/input/mouse/sppp_trackpad.c create mode 100644 drivers/rtc/sppp_rtc.c mode change 100644 => 100755 include/linux/sppp.h diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile index 7e0f41978c0..c0f9152c285 100644 --- a/arch/arm/mach-mx5/Makefile +++ b/arch/arm/mach-mx5/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o mx53_smd_pmic_da9053.o obj-$(CONFIG_MACH_IMX_BLUETOOTH_RFKILL) += imx_bt_rfkill.o obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o mx53_loco_pmic_da9053.o -obj-$(CONFIG_MACH_MX53_EFIKASB) += board-mx53_efikasb.o +obj-$(CONFIG_MACH_MX53_EFIKASB) += board-mx53_efikasb.o spppdriver.o sppp_power.o obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o diff --git a/arch/arm/mach-mx5/sppp_power.c b/arch/arm/mach-mx5/sppp_power.c new file mode 100644 index 00000000000..11a6d19096a --- /dev/null +++ b/arch/arm/mach-mx5/sppp_power.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +#include + +#include + +static struct sppp_client sppp_pwr_client; + +/* Callback for incoming data from SPM */ +static void sppp_get_data(sppp_rx_t *packet) +{ + +} + +/* Send power suspend sequence to SPM */ +static void sppp_pwr_suspend(void) +{ + + sppp_tx_t sppp_tx_g; + + sppp_start(&sppp_tx_g, SPPP_PWR_ID); + sppp_data(&sppp_tx_g, PWR_ID_GOTO_STANDY); + sppp_stop(&sppp_tx_g); + +} + +static int __init sppp_pwr_init(void) +{ + sppp_pwr_client.id = POWER; + sppp_pwr_client.decode = sppp_get_data; + sppp_client_register(&sppp_pwr_client); + + pm_power_off = sppp_pwr_suspend; + + return 0; +} + +static void __exit sppp_pwr_exit(void) +{ + sppp_client_remove(&sppp_pwr_client); + + pm_power_off = NULL; +} + +module_init(sppp_pwr_init); +module_exit(sppp_pwr_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SPPP Power Management client"); +MODULE_AUTHOR("Johan Dams "); + diff --git a/arch/arm/mach-mx5/spppdriver.c b/arch/arm/mach-mx5/spppdriver.c new file mode 100644 index 00000000000..41e09aa5e0d --- /dev/null +++ b/arch/arm/mach-mx5/spppdriver.c @@ -0,0 +1,406 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "spppdriver.h" +#include + +/* Read and write registers */ +#define __REG(x) (*((volatile u32 *)(x))) + +/* Maximum number of SPPP clients */ +#define MAX_CLIENTS 10 + +/* Simple device structure for the SPPP driver */ +struct sppp_device { + struct uart_port port; + unsigned int baud; + struct clk *clk; +}; + +/* Array od SPPP clients */ +static struct sppp_client *array_of_clients[MAX_CLIENTS] = {NULL}; + +/* baseint contains the address as a 32 bit integer */ +static volatile u32 *base, baseint; + +/* Actual SPPP device */ +static struct sppp_device sppp __initdata; + +/* Receive structure */ +static sppp_rx_t sppp_rx_g; + +/* Registers an SPPP client with the driver */ +void sppp_client_register(struct sppp_client *client) +{ + if (client->id <= MAX_CLIENTS) + array_of_clients[client->id] = client; + else + printk(KERN_ERR "Wrong client id\n"); +} +EXPORT_SYMBOL(sppp_client_register); + +/* Removes an SPPP client from the driver */ +void sppp_client_remove(struct sppp_client *client) +{ + if (client->id <= MAX_CLIENTS) + array_of_clients[client->id] = NULL; + else + printk(KERN_ERR "Wrong client id\n"); +} +EXPORT_SYMBOL(sppp_client_remove); + +/* Process, identify and decode packet after full encapulated packet received */ +static int decode(void) +{ + int i; + + switch (sppp_rx_g.id) { + case SPPP_IDENTIFICATION_ID: + printk(KERN_ERR "IDENTIFICATION\n"); + for (i=0; idecode(&sppp_rx_g); + break; + case SPPP_KEY_ID: + //printk(KERN_ERR "KEY\n"); + //for (i=0; idecode(&sppp_rx_g); + break; + + case SPPP_RTC_ID: + //printk(KERN_ERR "RTC\n"); + //for (i=0; idecode(&sppp_rx_g); + break; + case SPPP_PWR_ID: + //printk(KERN_ERR "PWR\n"); + //for (i=0; idecode(&sppp_rx_g); + break; + case SPPP_STRING_ID: + printk(KERN_ERR "STRING\n"); + for (i=0; isync == SPPP_SYNC ) { + switch (data & ~SPPP_PKT_ID_MASK) { + case SPPP_PKT_START: + goto sppp_start; + case SPPP_PKT_STOP: + sppp_rx->sync = SPPP_NOSYNC; //mark the end of the current packet + /* check for valid CRC */ + if ( !(( sppp_rx->crc^data) & SPPP_PKT_ID_MASK) ) { + //printk(KERN_ERR "valid crc\n"); + /* More processing */ + decode(); + } else { + printk(KERN_ERR "no valid crc=0x%02x != 0x%02x\n",(sppp_rx->crc& SPPP_PKT_ID_MASK), (data& SPPP_PKT_ID_MASK) ); + } + break; + default: + /* max input size reached */ + if ( sppp_rx->pos < MAX_RECV_PKG_SIZE) { + /* add to CRC sum */ + sppp_rx->crc += data; + if (sppp_rx->num != 0) { + //printk(KERN_ERR "input=%c carry=0x%x\n",sppp_rx->input[sppp_rx->pos], sppp_rx->carry); + /* Shift current byte on right pos */ + sppp_rx->input[sppp_rx->pos] = ( (data >>(7-sppp_rx->num)) | sppp_rx->carry); + /* Input size */ + sppp_rx->pos++; + } + /* shift carry byte on right pos for next run */ + sppp_rx->carry = ( data <<(1+sppp_rx->num)); + //printk(KERN_ERR "carry=0x%x\n",sppp_rx->carry); + sppp_rx->num++; + if (sppp_rx->num>7) + sppp_rx->num=0; + } else { + /* size is to big, drop this one */ + sppp_rx->sync = SPPP_NOSYNC; + } + } + } else { + if ( (data & ~SPPP_PKT_ID_MASK) == SPPP_PKT_START ) { +sppp_start: + sppp_rx->id = data & SPPP_PKT_ID_MASK; + sppp_rx->crc = data; + sppp_rx->pos = 0; + sppp_rx->num = 0; + sppp_rx->carry = 0; + sppp_rx->sync = SPPP_SYNC; + } + } +} + + +/* Interrupt service routine for serial interface */ +static irqreturn_t sppp_int(int irq, void *dev_id) +{ + + uint8_t rx; + volatile unsigned int sr2, sr1, cr1; + + sr1 = __REG(baseint + USR1); + sr2 = __REG(baseint + USR2); + cr1 = __REG(baseint + UCR1); + + /* Clear interrupt bits */ + __REG(baseint + USR1) = sr1; + __REG(baseint + USR2) = sr2; + + /* Receive interrupt */ + if (sr2 & USR2_RDR) { + while (__REG(baseint + USR2) & USR2_RDR) { + + /* Read data from the receive data register and mask out any status bits */ + rx = (__REG(baseint + URXD) & URXD_RX_DATA); + + /* Process incoming data */ + recv(&sppp_rx_g, rx); + } + + } + + return IRQ_HANDLED; +} + +/* Polling send function */ +void serial_putc(const char c) +{ + __REG(baseint + UTXD) = c; + + /* wait for transmitter to be ready */ + while (!(__REG(baseint + USR1) & USR1_TRDY)); + + /* STM needs time for processing... */ + msleep(1); +} + +/* Writing a string, uses polled serial_putc() */ +void serial_puts(const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) +#define TXTL 2 /* reset default */ +#define RXTL 1 /* reset default */ + +static int imx_setup_ufcr(struct uart_port *port, unsigned int mode) +{ + unsigned int val; + unsigned int ufcr_rfdiv; + + /* set receiver / transmitter trigger level. + * RFDIV is set such way to satisfy requested uartclk value + * 24000000 is the value of the oscillator, see mx53_clocks_init() + */ + val = TXTL << 10 | RXTL; + ufcr_rfdiv = (clk_get_rate(clk_get_sys("imx-uart.1", NULL)) + 24000000 / 2) + / 24000000; + + if (!ufcr_rfdiv) + ufcr_rfdiv = 1; + + val |= UFCR_RFDIV_REG(ufcr_rfdiv); + + __REG(baseint + UFCR) = val; + + return 0; +} + + +/* Initialise the serial port with the baudrate. */ +static int sppp_setup(void) +{ + int retval; + struct sppp_device *device = &sppp; + struct uart_port *port = &device->port; + + port->mapbase = MX53_UART2_BASE_ADDR; /* UART 2 is connected to the STM */ + port->irq = MX53_INT_UART2; /* Our interrupt */ + + /* Currently at 115200 */ + device->baud = 115200; + + /* Get base address of our remapped uart */ + base = (u32 *)ioremap(port->mapbase, 0xD4); + + /* Make it available as an integer for use with __REG(x) macro */ + baseint = (u32)base; + + /* Enable the uart clock */ + clk_enable(clk_get_sys("imx-uart.1", NULL)); + port->uartclk = clk_get_rate(clk_get_sys("imx-uart.1", NULL)); + + /* Set clock divider */ + imx_setup_ufcr(port, 0); + + /* Initialise registers to zero, clears any possible flags that shouldn't be set */ + __REG(baseint + UCR1) = 0x0; + __REG(baseint + UCR2) = 0x0; + + /* Wait for SW reset */ + while (!(__REG(baseint + UCR2) & UCR2_SRST)); + + /* disable the DREN bit (Data Ready interrupt enable) before + * requesting IRQs + */ + __REG(baseint + UCR4) &= ~UCR4_DREN; + + /* Get the irq */ + retval = request_irq(port->irq, sppp_int, 0, "spppinterrupt", port); + if (retval != 0) { + printk(KERN_ERR "Could not get interrupt... \n"); + } + + /* Set Baudrate */ + __REG(baseint + UBIR) = 0xf; + __REG(baseint + UBMR) = port->uartclk / (2 * device->baud); + + /* And finally enable the port and interrupts in the control registers */ + __REG(baseint + UCR2) = UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; + __REG(baseint + UCR1) = UCR1_UARTEN | UCR1_RRDYEN; /* The last one enables receive ready interrupt */ + + return 0; +} + +/* SPPP send operations */ + +/* Low Level write */ +void _sppp_write(sppp_tx_t *sppp_tx, uint8_t data) +{ + sppp_tx->crc += data; + serial_putc(data); +} + +/* Send Start */ +void sppp_start(sppp_tx_t *sppp_tx, uint8_t pkg_id) +{ + sppp_tx->crc=0; + sppp_tx->pos=0; + sppp_tx->carry=0; + _sppp_write(sppp_tx, SPPP_PKT_START | (pkg_id&0x3F)) ; +} +EXPORT_SYMBOL(sppp_start); + +/* Encode data for sending */ +void sppp_data(sppp_tx_t *sppp_tx, uint8_t data) +{ + _sppp_write(sppp_tx, (data >>(1+sppp_tx->pos)) | sppp_tx->carry ); // send + sppp_tx->carry = (data <<(6-sppp_tx->pos))&0x7F; // save carry + sppp_tx->pos++; + //printk(KERN_ERR "carry=0x%02x\n",sppp_tx->carry); + if (sppp_tx->pos>=7) { + //printk(KERN_ERR "carry=0x%02x\n",sppp_tx->carry); + _sppp_write(sppp_tx, sppp_tx->carry); // send this byte + sppp_tx->carry=0; + sppp_tx->pos=0; + } +} +EXPORT_SYMBOL(sppp_data); + +/* Send Stop */ +void sppp_stop(sppp_tx_t *sppp_tx) +{ + if (sppp_tx->pos < 7) + _sppp_write(sppp_tx, sppp_tx->carry); + _sppp_write(sppp_tx, SPPP_PKT_STOP | (~SPPP_PKT_STOP & sppp_tx->crc)); // send EOP +} +EXPORT_SYMBOL(sppp_stop); + +/* General all-in-one send function */ +void sppp_send(sppp_tx_t *sppp_tx, unsigned char *buf, int size, int pkg_id) +{ + int i; + sppp_tx->crc=0; + sppp_tx->pos=0; + sppp_tx->carry=0; + + printk(KERN_ERR "send SOP\n"); + _sppp_write(sppp_tx, (SPPP_PKT_START | (pkg_id&0x3F)) ) ; //send SOP and ID + for (i=0; ipos < 7) + _sppp_write(sppp_tx, sppp_tx->carry); // send only carry if no more bytes send + _sppp_write(sppp_tx, SPPP_PKT_STOP | (~SPPP_PKT_STOP & sppp_tx->crc)); // send EOP +} +EXPORT_SYMBOL(sppp_send); + +static int __init sppp_init(void) +{ + + printk(KERN_ALERT "Inserting SPPP driver.\n"); + sppp_setup(); + sppp_rx_g.sync = SPPP_NOSYNC; + + return 0; +} + +static void __exit sppp_exit(void) +{ +// struct sppp_device *device = &sppp; +// struct uart_port *port = &device->port; + + printk(KERN_ALERT "Removing SPPP driver.\n"); + + //free_irq(port->irq, NULL); //--> needs fixing, blows up with segfault... + clk_disable(clk_get_sys("imx-uart.1", NULL)); + iounmap(base); +} + + +module_init(sppp_init); +module_exit(sppp_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SPPP device driver"); +MODULE_AUTHOR("Johan Dams "); + diff --git a/arch/arm/mach-mx5/spppdriver.h b/arch/arm/mach-mx5/spppdriver.h new file mode 100644 index 00000000000..238c9344b03 --- /dev/null +++ b/arch/arm/mach-mx5/spppdriver.h @@ -0,0 +1,108 @@ +/* Register definitions */ +#define URXD 0x0 /* Receiver Register */ +#define UTXD 0x40 /* Transmitter Register */ +#define UCR1 0x80 /* Control Register 1 */ +#define UCR2 0x84 /* Control Register 2 */ +#define UCR3 0x88 /* Control Register 3 */ +#define UCR4 0x8c /* Control Register 4 */ +#define UFCR 0x90 /* FIFO Control Register */ +#define USR1 0x94 /* Status Register 1 */ +#define USR2 0x98 /* Status Register 2 */ +#define UESC 0x9c /* Escape Character Register */ +#define UTIM 0xa0 /* Escape Timer Register */ +#define UBIR 0xa4 /* BRM Incremental Register */ +#define UBMR 0xa8 /* BRM Modulator Register */ +#define UBRC 0xac /* Baud Rate Count Register */ +#define UTS 0xb4 /* UART Test Register (mx31) */ + +/* UART Control Register Bit Fields.*/ +#define URXD_CHARRDY (1<<15) +#define URXD_ERR (1<<14) +#define URXD_OVRRUN (1<<13) +#define URXD_FRMERR (1<<12) +#define URXD_BRK (1<<11) +#define URXD_PRERR (1<<10) +#define URXD_RX_DATA (0xFF) +#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ +#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ +#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ +#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ +#define UCR1_IREN (1<<7) /* Infrared interface enable */ +#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ +#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ +#define UCR1_SNDBRK (1<<4) /* Send break */ +#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#define UCR1_DOZE (1<<1) /* Doze */ +#define UCR1_UARTEN (1<<0) /* UART enabled */ +#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ +#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ +#define UCR2_CTSC (1<<13) /* CTS pin control */ +#define UCR2_CTS (1<<12) /* Clear to send */ +#define UCR2_ESCEN (1<<11) /* Escape enable */ +#define UCR2_PREN (1<<8) /* Parity enable */ +#define UCR2_PROE (1<<7) /* Parity odd/even */ +#define UCR2_STPB (1<<6) /* Stop */ +#define UCR2_WS (1<<5) /* Word size */ +#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_TXEN (1<<2) /* Transmitter enabled */ +#define UCR2_RXEN (1<<1) /* Receiver enabled */ +#define UCR2_SRST (1<<0) /* SW reset */ +#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ +#define UCR3_PARERREN (1<<12) /* Parity enable */ +#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ +#define UCR3_DSR (1<<10) /* Data set ready */ +#define UCR3_DCD (1<<9) /* Data carrier detect */ +#define UCR3_RI (1<<8) /* Ring indicator */ +#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ +#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ +#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ +#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ +#define UCR3_BPEN (1<<0) /* Preset registers enable */ +#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ +#define UCR4_INVR (1<<9) /* Inverted infrared reception */ +#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ +#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ +#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IRSC (1<<5) /* IR special case */ +#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ +#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ +#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ +#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ +#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ +#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ +#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */ +#define USR1_RTSD (1<<12) /* RTS delta */ +#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ +#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ +#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ +#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ +#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ +#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ +#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ +#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ +#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ +#define USR2_IDLE (1<<12) /* Idle condition */ +#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ +#define USR2_WAKE (1<<7) /* Wake */ +#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ +#define USR2_TXDC (1<<3) /* Transmitter complete */ +#define USR2_BRCD (1<<2) /* Break condition */ +#define USR2_ORE (1<<1) /* Overrun error */ +#define USR2_RDR (1<<0) /* Recv data ready */ +#define UTS_FRCPERR (1<<13) /* Force parity error */ +#define UTS_LOOP (1<<12) /* Loop tx and rx */ +#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ +#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define UTS_RXFULL (1<<3) /* RxFIFO full */ +#define UTS_SOFTRST (1<<0) /* Software reset */ diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 8e73ccb411f..2c9f4899f2e 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -533,6 +533,14 @@ config KEYBOARD_MXS help This is the Keypad driver for the Freescale mxs soc +config KEYBOARD_SPPP + bool "SPPP keyboard driver" + depends on MACH_MX53_EFIKASB + help + Say Y here if you have a Genesi MX53 EfikaSB based + System. These systems use the SPPP protocol to + communicate with a housekeeper chip responsible + for keyboard and trackpad among others. config KEYBOARD_MC9S08DZ60 tristate "mc9s08dz60 keyboard" @@ -558,3 +566,4 @@ config KEYBOARD_MPR121 To compile this driver as a module, choose M here endif + diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index dac8089cc2f..fcc33762d59 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -51,5 +51,6 @@ obj-$(CONFIG_KEYBOARD_MXC) += mxc_keyb.o obj-$(CONFIG_KEYBOARD_MXC) += mxc_pwrkey.o obj-$(CONFIG_KEYBOARD_MPR084) += mpr084.o obj-$(CONFIG_KEYBOARD_MXS) += mxs-kbd.o +obj-$(CONFIG_KEYBOARD_SPPP) += sppp_keyboard.o obj-$(CONFIG_KEYBOARD_MC9S08DZ60) += mc9s08dz60_keyb.o obj-$(CONFIG_KEYBOARD_MPR121) += mpr121.o diff --git a/drivers/input/keyboard/sppp_keyboard.c b/drivers/input/keyboard/sppp_keyboard.c new file mode 100644 index 00000000000..6c47fc725fa --- /dev/null +++ b/drivers/input/keyboard/sppp_keyboard.c @@ -0,0 +1,247 @@ +#include +#include + +#include + + +#define VERBOSE 0 /* show some (not all) debug */ + +#define KBD_SYNC 0xAA /* keyboard inserts a SYNC after each full matrix scan */ + +#define MAXROW 8 +#define MAXCOL 16 + + +static struct input_dev *keyb_dev; + +static struct sppp_client sppp_keyboard_client; + +char keyboard_g[MAXCOL][MAXROW]; // raw keys from keyboard +char keypress_g[MAXCOL][MAXROW]; // current keys reported to the system +char keyvalid_g[MAXCOL][MAXROW]={ // valid key and scancodes on current keyboard + { 66,12,82,83, 0, 8, 0,52 }, // COL 0 a '0' indicates none existing==invalid + { 0, 0, 0,25, 0, 0, 0,13 }, // COL 1 + { 0, 0, 9, 0, 0, 2, 0, 0 }, + { 1,32,67,54,39,14, 0,26 }, + { 0, 0, 0, 0, 7, 0, 0, 0 }, + { 0, 0,73,61,62,34,20,47 }, + { 0, 0,74,75,63,35,21,48 }, + { 31,18,72,60,46,33,19,59 }, + { 0,24,78,79,65,37,23,50 }, + { 0, 0, 0, 0, 0, 0, 3, 0 }, + { 71,45,70,58,43,30,17,44 }, + { 0, 0,69,56,57,29,16,42 }, + { 0,11,80,81,53,38, 0,51 }, + { 4, 6, 0, 0, 0, 0, 0, 0 }, + { 5,10,76,77,64,36,22,49 }, // COL 14 + { 15, 0,68,55,40,27,28,41 } // COL 15 +}; + +int key_sync_g = 0; +int key_ghost_g = 0; + +/* Reset 'raw' and 'clean' versions of the key matix */ +static void kbd_clear(void) +{ + int i,j; + + for ( i=0 ; i>= 1; + } +} + + + +/* Take the payload of the keyboard event packet and do some meanfull things. */ +/* The data comes as 2 bytes pair with first byte=column index (0-15) and */ +/* second byte as the row read out value (note: this is active lo bitfield). */ +/* The data comes as 'endless' stream with a SYNC byte inserted after each */ +/* full scan of the key matix. The keyboard ONLY reports the key deltas */ +/* between two consecutive scans. */ + +static void kbd_decode(sppp_rx_t *packet) +{ + + unsigned char *keys = packet->input; + int keyc = packet->pos; +#if VERBOSE + int i; + + printk(KERN_ERR "decode %d bytes (",keyc); + for (i=0;i 1 ) { // two or more bytes left + if ( keys[0] == KBD_SYNC ) { // found SYNC, this also indicates next KBD event + key_sync_g++; // statistics only + kbd_handle(); // handle keys of this event +#if VERBOSE + printk(KERN_ERR "event %d\n",key_sync_g); +#endif + } else { + kbd_add_col( keys[0], keys[1] ); // insert changes into raw matrix + } + keyc -= 2; + keys += 2; + } +} + + +#define PCI_VENDOR_ID_FREESCALE 0x1957 + +static int __init sppp_kbd_init(void) +{ + + int i,j; + int error; + + keyb_dev = input_allocate_device(); + + keyb_dev->name = "Efika SB Keyboard"; + keyb_dev->phys = "efikasb/input0"; + keyb_dev->uniq = "efikasb_keyboard"; + keyb_dev->id.bustype = BUS_HOST; + keyb_dev->id.vendor = PCI_VENDOR_ID_FREESCALE; + + keyb_dev->evbit[0] = BIT_MASK(EV_KEY); + + for (i=0;ikeybit); + + error = input_register_device(keyb_dev); + if (error) { + printk(KERN_ERR "Keyboard input device registration failed.\n"); + input_free_device(keyb_dev); + return -1; + } + + kbd_clear(); + + sppp_keyboard_client.id = KEYBOARD; + sppp_keyboard_client.decode = kbd_decode; + + sppp_client_register(&sppp_keyboard_client); + + return 0; +} + +static void __exit sppp_kbd_exit(void) +{ + + sppp_client_remove(&sppp_keyboard_client); + +} + +module_init(sppp_kbd_init); +module_exit(sppp_kbd_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SPPP keyboard client"); +MODULE_AUTHOR("Johan Dams "); + diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 9c1e6ee8353..f9786b8669a 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -136,6 +136,15 @@ config MOUSE_PS2_OLPC If unsure, say N. +config MOUSE_SPPP + bool "SPPP trackpad driver" + depends on MACH_MX53_EFIKASB + help + Say Y here if you have a Genesi MX53 EfikaSB based + System. These systems use the SPPP protocol to + communicate with a housekeeper chip responsible + for keyboard and trackpad among others. + config MOUSE_SERIAL tristate "Serial mouse" select SERIO diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 570c84a4a65..9f0e64050ab 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o +obj-$(CONFIG_MOUSE_SPPP) += sppp_trackpad.o psmouse-objs := psmouse-base.o synaptics.o diff --git a/drivers/input/mouse/sppp_trackpad.c b/drivers/input/mouse/sppp_trackpad.c new file mode 100644 index 00000000000..5ea364585df --- /dev/null +++ b/drivers/input/mouse/sppp_trackpad.c @@ -0,0 +1,139 @@ +#include +#include +#include + +#include + +static struct input_dev *track_dev; + +static struct sppp_client sppp_trackpad_client; + +/* Decode trackpad data, which is encoded as PS/2. + * PS/2 data is send as a 2 byte value, first one is a sequence number + * second one is the PS/2 data. The sequence number will change for independant + * PS/2 data. A single byte value from a PS/2 device will have one sequence number, + * as well as every bytes out of a multi byte message (e.g. streaming data) will + * have the same sequence number. We use this to correctly identify the message + * start and ending of a multibyte message (streaming data from pointing device) + */ +static void trackpad_decode(sppp_rx_t *packet) +{ + static uint8_t ps2_byte[3]; + static uint8_t ps2_seq; + static int ps2_count; + int i; + + + /* note: a PS/2 packet can have incomplete and/or multiple messages */ + for (i=0; (i+1)pos; i+=2) { + if (packet->input[i] != ps2_seq) { + ps2_seq = packet->input[i]; + ps2_count=0; + } + + ps2_byte[ps2_count++] = packet->input[i+1]; + + if (ps2_count == 3) { + /* Check for overflow, and discard if so */ + if ( ! ((ps2_byte[0]&0x80) || (ps2_byte[0]&0x40)) ) { + + /* Actually send ps2_byte to input dev */ + input_report_key(track_dev, BTN_LEFT, ps2_byte[0] & 0x01); + input_report_key(track_dev, BTN_RIGHT, ps2_byte[0] & 0x02); + + input_report_rel(track_dev, REL_X, ps2_byte[1] ? (int) ps2_byte[1] - (int) ((ps2_byte[0] << 4) & 0x100) : 0); + input_report_rel(track_dev, REL_Y, ps2_byte[2] ? (int) ((ps2_byte[0] << 3) & 0x100) - (int) ps2_byte[2] : 0); + + input_sync(track_dev); + } + ps2_count=0; + } + } +} + +static int __init sppp_trackpad_init(void) +{ + + int error; + sppp_tx_t sppp_tx_g; + + track_dev = input_allocate_device(); + + track_dev->name = "Efika SB Trackpad"; + track_dev->phys = "efikasb/input1"; + track_dev->uniq = "efikasb_trackpad"; + track_dev->id.bustype = BUS_I8042; + track_dev->id.vendor = 0x0002; + track_dev->id.product = 1; + track_dev->id.version = 0; + + track_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); + track_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + track_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); + + error = input_register_device(track_dev); + if (error) { + printk(KERN_ERR "Keyboard input device registration failed.\n"); + input_free_device(track_dev); + return -1; + } + + sppp_trackpad_client.id = TRACKPAD; + sppp_trackpad_client.decode = trackpad_decode; + + /* Low Level PS/2 trackpad init */ + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xFF); //reset + sppp_stop(&sppp_tx_g); + //msleep(1000); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xF3); //going to set sample rate + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0x50); //sample rate + /* Valid sample rates are 10, 20, 40, 60, 80, 100, and 200 samples/sec */ + sppp_stop(&sppp_tx_g); + //msleep(1000); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xE6); //Scaling 2:1; 1:1 = 0xE6 + sppp_stop(&sppp_tx_g); + //msleep(1000); + + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xE8); //Going to set resolution + sppp_stop(&sppp_tx_g); + //msleep(1000); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + // 00,01,02,03 -> 1, 2, 4, 8 counts/mm + sppp_data(&sppp_tx_g, 0x03); //set resolution + sppp_stop(&sppp_tx_g); + //msleep(1000); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xF4); //enable data reporting + sppp_stop(&sppp_tx_g); + + sppp_client_register(&sppp_trackpad_client); + + return 0; +} + +static void __exit sppp_trackpad_exit(void) +{ + + sppp_client_remove(&sppp_trackpad_client); + +} + +module_init(sppp_trackpad_init); +module_exit(sppp_trackpad_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SPPP trackpad client"); +MODULE_AUTHOR("Johan Dams "); + diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9431c806119..32758260b1d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -999,4 +999,13 @@ config RTC_DRV_DA9052 Say y here to support the RTC found on Dialog Semiconductor DA9052 PMIC. +config RTC_SPPP + bool "SPPP RTC driver" + depends on MACH_MX53_EFIKASB + help + Say Y here if you have a Genesi MX53 EfikaSB based + System. These systems use the SPPP protocol to + communicate with a housekeeper chip responsible + for keyboard and trackpad among others. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index c769a034ac2..c34b0e73d48 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -103,3 +103,4 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o +obj-$(CONFIG_RTC_SPPP) += sppp_rtc.o diff --git a/drivers/rtc/sppp_rtc.c b/drivers/rtc/sppp_rtc.c new file mode 100644 index 00000000000..f7573a55d0d --- /dev/null +++ b/drivers/rtc/sppp_rtc.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +static struct sppp_client sppp_rtc_client; + +struct rtc_sppp { + struct rtc_device *rtc; +}; + +uint32_t rawtime = 0; + +/* Callback for incoming data from SPM */ +static void sppp_get_data(sppp_rx_t *packet) +{ + uint32_t time; + + time = packet->input[0]<<24; + time |= (packet->input[1]<<16); + time |= (packet->input[2]<< 8); + time |= (packet->input[3]<< 0); + + rawtime = time; +} + +/* Send read sequence to SPM and get data when it arrives */ +static int sppp_rtc_readtime(struct device *dev, struct rtc_time *tm) +{ + + sppp_tx_t sppp_tx_g; + + sppp_start(&sppp_tx_g, SPPP_RTC_ID); + sppp_data(&sppp_tx_g, RTC_ID_GET); + sppp_stop(&sppp_tx_g); + + while (rawtime == 0); + + rtc_time_to_tm(rawtime, tm); + + rawtime = 0; + + return rtc_valid_tm(tm); +} + +static int sppp_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + + sppp_tx_t sppp_tx_g; + unsigned long now; + + rtc_tm_to_time(tm, &now); + + sppp_start(&sppp_tx_g, SPPP_RTC_ID); + sppp_data(&sppp_tx_g, RTC_ID_SET); + sppp_data(&sppp_tx_g, (now&0xFF000000)>>24); + sppp_data(&sppp_tx_g, (now&0x00FF0000)>>16); + sppp_data(&sppp_tx_g, (now&0x0000FF00)>> 8); + sppp_data(&sppp_tx_g, (now&0x000000FF)>> 0); + sppp_stop(&sppp_tx_g); + + return 0; +} + +static struct rtc_class_ops sppp_rtc_ops = { + .read_time = sppp_rtc_readtime, + .set_time = sppp_rtc_settime, +}; + +static int __init sppp_rtc_probe(struct platform_device *pdev) +{ + + struct rtc_sppp *rtc; + + rtc = kzalloc(sizeof(struct rtc_sppp), GFP_KERNEL); + if (!rtc) { + dev_dbg(&pdev->dev, "out of memory\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, rtc); + + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + &sppp_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc->rtc)) { + dev_dbg(&pdev->dev, "could not register rtc device\n"); + return PTR_ERR(rtc->rtc); + } + + dev_info(&pdev->dev, "SPPP RTC for Genesi EfikaSB\n"); + + sppp_rtc_client.id = RTC; + sppp_rtc_client.decode = sppp_get_data; + sppp_client_register(&sppp_rtc_client); + + return 0; +} + + +static int __exit sppp_rtc_remove(struct platform_device *pdev) +{ + + struct rtc_sppp *rtc = platform_get_drvdata(pdev); + + rtc_device_unregister(rtc->rtc); + kfree(rtc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver sppp_rtc_driver = { + .remove = __exit_p(sppp_rtc_remove), + .driver = { + .name = "sppp_rtc", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device sppp_rtc = { + .name = "sppp_rtc", + .id = -1, +}; + +static int __init sppp_rtc_init(void) +{ + + platform_device_register(&sppp_rtc); + return platform_driver_probe(&sppp_rtc_driver, sppp_rtc_probe); +} + +static void __exit sppp_rtc_exit(void) +{ + sppp_client_remove(&sppp_rtc_client); + platform_driver_unregister(&sppp_rtc_driver); + platform_device_unregister(&sppp_rtc); +} + +module_init(sppp_rtc_init); +module_exit(sppp_rtc_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SPPP RTC client"); +MODULE_AUTHOR("Johan Dams "); + diff --git a/include/linux/sppp.h b/include/linux/sppp.h old mode 100644 new mode 100755 index 6995e8d0a92..81dbb84aa88 --- a/include/linux/sppp.h +++ b/include/linux/sppp.h @@ -1,44 +1,66 @@ #ifndef _SPPP_H_ #define _SPPP_H_ -#define MAX_RECV_PKG_SIZE 100 - -#define MAX_PKG_SIZE 100 -#define MAX_LOOP_COUNT MAX_RECV_PKG_SIZE +#define MAX_RECV_PKG_SIZE 1024 +#define MAX_PKG_SIZE MAX_RECV_PKG_SIZE #define SPPP_PKT_ID_MASK 0x3F #define SPPP_PKT_START 0x80 #define SPPP_PKT_STOP 0xC0 -#define ISBITSET(val, bit) ((val) & (1 << (bit))) +#define IsBitSet(val, bit) ((val) & (1 << (bit))) -#define SPPP_SHORT_ID 0 +#define SPPP_IDENTIFICATION_ID 0 #define SPPP_KEY_ID 1 #define SPPP_PS2_ID 2 #define SPPP_RTC_ID 3 + #define RTC_ID_SET 0x73 + #define RTC_ID_GET 0xAA #define SPPP_PWR_ID 4 + #define PWR_ID_SET_RTC_ALARM 2 + #define PWR_ID_GET_RTC_ALARM 3 + #define PWR_ID_GOTO_STANDY 4 + #define SPPP_STRING_ID 60 #define SPPP_BINARY_ID 61 #define SPPP_NOSYNC 0x00 #define SPPP_SYNC 0xff +#define FLASH_FW_START_PAGE 8 + typedef struct { - uint8_t input[MAX_RECV_PKG_SIZE]; - uint8_t id; - uint8_t crc; - uint8_t pos; - uint8_t num; - uint8_t carry; - uint8_t sync; + uint8_t input[MAX_RECV_PKG_SIZE]; + uint8_t id; + uint8_t crc; + uint8_t pos; + uint8_t num; + uint8_t carry; + uint8_t sync; + } sppp_rx_t; typedef struct { - uint8_t crc; - uint8_t pos; - uint8_t carry; - int comd; + uint8_t crc; + uint8_t pos; + uint8_t carry; + int comd; + } sppp_tx_t; +/* Possible SPPP clients */ +enum clients { + KEYBOARD = 0, + TRACKPAD, + RTC, + POWER, +}; + +/* Each SPPP client has these */ +struct sppp_client { + unsigned int id; + void (* decode)(sppp_rx_t *); +}; + int sppp_recv(int comd, sppp_rx_t *sppp_rx); void sppp_start(sppp_tx_t *sppp_tx, uint8_t pkg_id); void sppp_data(sppp_tx_t *sppp_tx, uint8_t data); @@ -46,4 +68,7 @@ void sppp_stop(sppp_tx_t *sppp_tx); void sppp_send(sppp_tx_t *sppp_tx, unsigned char *buf, int size, int pkg_id); +void sppp_client_register(struct sppp_client *client); +void sppp_client_remove(struct sppp_client *client); + #endif /* _SPPP_H_ */ From abe5e73416c561441ebd389afb045226262b8d3d Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Sun, 11 Dec 2011 07:42:30 +0200 Subject: [PATCH 27/32] Updated defconfig to reflect SPPP driver addition --- arch/arm/configs/mx53_efikasb_defconfig | 141 +++++++++++++++++++----- 1 file changed, 115 insertions(+), 26 deletions(-) diff --git a/arch/arm/configs/mx53_efikasb_defconfig b/arch/arm/configs/mx53_efikasb_defconfig index 4839f88a134..8110746a9de 100644 --- a/arch/arm/configs/mx53_efikasb_defconfig +++ b/arch/arm/configs/mx53_efikasb_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux/arm 2.6.38.3 Kernel Configuration -# Tue Sep 20 04:45:01 2011 +# Sun Dec 11 07:24:44 2011 # CONFIG_ARM=y CONFIG_HAVE_PWM=y @@ -152,7 +152,7 @@ CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y +# CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y CONFIG_LBDAF=y @@ -281,6 +281,7 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_DVFS=y CONFIG_IMX_HAVE_PLATFORM_IMX_IIM=y CONFIG_IMX_HAVE_PLATFORM_MXC_GPU=y CONFIG_IMX_HAVE_PLATFORM_LDB=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y # # Freescale MXC Implementations @@ -320,7 +321,6 @@ CONFIG_MXC_PWM=y CONFIG_ARCH_MXC_IOMUX_V3=y CONFIG_ARCH_MXC_AUDMUX_V2=y CONFIG_IRAM_ALLOC=y -CONFIG_DMA_ZONE_SIZE=24 # # System MMU @@ -590,16 +590,34 @@ CONFIG_BT_HCIVHCI=y # CONFIG_BT_ATH3K is not set # CONFIG_AF_RXRPC is not set CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# - -# -# Some wireless drivers require a rate control algorithm -# +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y CONFIG_RFKILL_INPUT=y @@ -900,8 +918,25 @@ CONFIG_NET_ETHERNET=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set # CONFIG_USB_ZD1201 is not set -# CONFIG_HOSTAP is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_ATH_COMMON is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +CONFIG_HOSTAP=m +# CONFIG_HOSTAP_FIRMWARE is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTL8192CE is not set +# CONFIG_WL1251 is not set +# CONFIG_WL12XX_MENU is not set +# CONFIG_ZD1211RW is not set # CONFIG_ATH6K_LEGACY is not set # @@ -915,27 +950,27 @@ CONFIG_WLAN=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set -CONFIG_USB_USBNET=y -CONFIG_USB_NET_AX8817X=y -CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m # CONFIG_USB_NET_CDC_EEM is not set -CONFIG_USB_NET_CDC_NCM=y +CONFIG_USB_NET_CDC_NCM=m # CONFIG_USB_NET_DM9601 is not set # CONFIG_USB_NET_SMSC75XX is not set # CONFIG_USB_NET_SMSC95XX is not set # CONFIG_USB_NET_GL620A is not set -CONFIG_USB_NET_NET1080=y +CONFIG_USB_NET_NET1080=m # CONFIG_USB_NET_PLUSB is not set # CONFIG_USB_NET_MCS7830 is not set # CONFIG_USB_NET_RNDIS_HOST is not set -CONFIG_USB_NET_CDC_SUBSET=y +CONFIG_USB_NET_CDC_SUBSET=m # CONFIG_USB_ALI_M5632 is not set # CONFIG_USB_AN2720 is not set CONFIG_USB_BELKIN=y CONFIG_USB_ARMLINUX=y # CONFIG_USB_EPSON2888 is not set # CONFIG_USB_KC2190 is not set -CONFIG_USB_NET_ZAURUS=y +CONFIG_USB_NET_ZAURUS=m # CONFIG_USB_NET_CX82310_ETH is not set # CONFIG_USB_HSO is not set # CONFIG_USB_NET_INT51X1 is not set @@ -995,8 +1030,17 @@ CONFIG_KEYBOARD_GPIO=y # CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_MXC is not set +CONFIG_KEYBOARD_SPPP=y CONFIG_KEYBOARD_MPR121=y -# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_MOUSE_SPPP=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y @@ -1693,7 +1737,9 @@ CONFIG_SND_SOC=y CONFIG_SND_SOC_AC97_BUS=y CONFIG_SND_IMX_SOC=y CONFIG_SND_MXC_SOC_MX2=y +# CONFIG_SND_SOC_IMX_SGTL5000 is not set CONFIG_SND_SOC_IMX_CS42L52=y +# CONFIG_SND_SOC_IMX_SPDIF is not set CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set CONFIG_SND_SOC_CS42L52=y @@ -2086,6 +2132,7 @@ CONFIG_RTC_DRV_MXC_V2=y # # on-CPU RTC drivers # +CONFIG_RTC_SPPP=y CONFIG_DMADEVICES=y # CONFIG_DMADEVICES_DEBUG is not set @@ -2105,7 +2152,48 @@ CONFIG_DMA_ENGINE=y # CONFIG_DMATEST is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set -# CONFIG_STAGING is not set +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IP_COMMON is not set +# CONFIG_W35UND is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_ECHO is not set +# CONFIG_BRCM80211 is not set +# CONFIG_RT2870 is not set +# CONFIG_COMEDI is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_R8712U is not set +# CONFIG_TRANZPORT is not set +# CONFIG_POHMELFS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_VT6656 is not set +# CONFIG_IIO is not set +# CONFIG_ZRAM is not set +# CONFIG_FB_SM7XX is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_ST_BT is not set +# CONFIG_SMB_FS is not set +# CONFIG_EASYCAP is not set +CONFIG_MACH_NO_WESTBRIDGE=y +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set CONFIG_CLKDEV_LOOKUP=y # @@ -2159,7 +2247,6 @@ CONFIG_MXC_DAM=y # MXC VPU(Video Processing Unit) support # CONFIG_MXC_VPU=y -CONFIG_MXC_VPU_IRAM=y # CONFIG_MXC_VPU_DEBUG is not set # @@ -2189,6 +2276,7 @@ CONFIG_MXC_VPU_IRAM=y # MXC GPU support # CONFIG_MXC_AMD_GPU=y +# CONFIG_MXC_AMD_GPU_LOGGING is not set # # File systems @@ -2525,7 +2613,7 @@ CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD128 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set @@ -2541,7 +2629,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set @@ -2595,3 +2683,4 @@ CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y From a4b6211d5877003c1f92304c91010ab85ea76204 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Sun, 11 Dec 2011 07:56:36 +0200 Subject: [PATCH 28/32] Allow SPPP drivers to be compiled as modules. --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/mouse/Kconfig | 2 +- drivers/rtc/Kconfig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2c9f4899f2e..b0c79e0a004 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -534,7 +534,7 @@ config KEYBOARD_MXS This is the Keypad driver for the Freescale mxs soc config KEYBOARD_SPPP - bool "SPPP keyboard driver" + tristate "SPPP keyboard driver" depends on MACH_MX53_EFIKASB help Say Y here if you have a Genesi MX53 EfikaSB based diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index f9786b8669a..c02b2564ce9 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -137,7 +137,7 @@ config MOUSE_PS2_OLPC If unsure, say N. config MOUSE_SPPP - bool "SPPP trackpad driver" + tristate "SPPP trackpad driver" depends on MACH_MX53_EFIKASB help Say Y here if you have a Genesi MX53 EfikaSB based diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 32758260b1d..8882b761039 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1000,7 +1000,7 @@ config RTC_DRV_DA9052 Dialog Semiconductor DA9052 PMIC. config RTC_SPPP - bool "SPPP RTC driver" + tristate "SPPP RTC driver" depends on MACH_MX53_EFIKASB help Say Y here if you have a Genesi MX53 EfikaSB based From e95c03e90b59eb167c3b60bf398812052e6b94b3 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Mon, 12 Dec 2011 01:47:21 +0200 Subject: [PATCH 29/32] Removed temporary GPIO I2C solution for earlier boards. --- arch/arm/mach-mx5/board-mx53_efikasb.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c index 661dd610510..b7a4e82c0fd 100644 --- a/arch/arm/mach-mx5/board-mx53_efikasb.c +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -109,10 +109,8 @@ static iomux_v3_cfg_t mx53_efikasb_pads[] = { MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, /* I2C1 */ -// MX53_PAD_CSI0_DAT8__I2C1_SDA, -// MX53_PAD_CSI0_DAT9__I2C1_SCL, - MX53_PAD_CSI0_DAT8__GPIO5_26, - MX53_PAD_CSI0_DAT9__GPIO5_27, + MX53_PAD_CSI0_DAT8__I2C1_SDA, + MX53_PAD_CSI0_DAT9__I2C1_SCL, /* UART */ MX53_PAD_PATA_DIOW__UART1_TXD_MUX, MX53_PAD_PATA_DMACK__UART1_RXD_MUX, @@ -259,17 +257,6 @@ static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { }, }; -/* Temporary GPIO I2C solution */ -static struct i2c_gpio_platform_data i2c_gpio_data = { - .sda_pin = GPIO_SDA, - .scl_pin = GPIO_SCL, -}; - -static struct platform_device i2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, -}; - static int nand_init(void) { u32 i, reg; @@ -556,9 +543,7 @@ static void __init mx53_efikasb_board_init(void) imx53_add_dvfs_core(&efikasb_dvfs_core_data); /* I2C */ - //imx53_add_imx_i2c(0, &mx53_efikasb_i2c_data); - mxc_register_device(&i2c_gpio_device, &i2c_gpio_data); - + imx53_add_imx_i2c(0, &mx53_efikasb_i2c_data); i2c_register_board_info(0, mxc_i2c0_board_info, ARRAY_SIZE(mxc_i2c0_board_info)); From b4299373d0b4a6b492cab88414db2b3e5b7085da Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 13 Dec 2011 03:53:00 +0200 Subject: [PATCH 30/32] Fix audio driver crash on system shutdown. --- sound/soc/codecs/cs42l52.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index e2df36fa35e..ec3a0f58792 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -91,7 +91,7 @@ static inline int cs42l52_get_revison(struct snd_soc_codec *codec) u8 addr; int ret; - struct cs42l52_private *info = snd_soc_codec_get_drvdata(codec); + //struct cs42l52_private *info = snd_soc_codec_get_drvdata(codec); if(codec->hw_write(codec->control_data, &addr, 1) == 1) @@ -382,13 +382,13 @@ SOC_SINGLE_S8_C_TLV("HP Analog Playback Volume", PB_CTL1, 5, 7, 0, hpaloa_tlv), SOC_SINGLE_S8_C_TLV("HP Digital Playback Switch", - PB_CTL2, 6, 7, 1, 1), + PB_CTL2, 6, 7, 1, NULL), /* Speaker */ SOC_DOUBLE_R_S8_C_TLV("Speaker Playback Volume", SPKA_VOL, SPKB_VOL, 0xff, 0x1, hl_tlv), SOC_SINGLE_S8_C_TLV("Speaker Playback Switch", - PB_CTL2, 4, 5, 1, 1), + PB_CTL2, 4, 5, 1, NULL), /* Passthrough */ SOC_DOUBLE_R_S8_C_TLV("Passthru Playback Volume", PASSTHRUA_VOL, @@ -915,7 +915,7 @@ static int cs42l52_suspend(struct snd_soc_codec *codec, pm_message_t state) static int cs42l52_resume(struct snd_soc_codec *codec) { - int i, reg; + int i;//, reg; u8 *cache = codec->reg_cache; /* Sync reg_cache with the hardware */ @@ -947,7 +947,7 @@ static int cs42l52_probe(struct snd_soc_codec *codec) { struct cs42l52_private *info = snd_soc_codec_get_drvdata(codec); - int i, ret = 0; + //int i, ret = 0; info->sysclk = CS42L52_DEFAULT_CLK; info->config.format = CS42L52_DEFAULT_FORMAT; From 69e9a204eea7cd3ba498b2f55f36e8a6bcce94a8 Mon Sep 17 00:00:00 2001 From: Johan Dams Date: Tue, 13 Dec 2011 04:44:13 +0200 Subject: [PATCH 31/32] GPL headers and copyright notice. --- arch/arm/mach-mx5/sppp_power.c | 21 +++++++++++++++++++++ arch/arm/mach-mx5/spppdriver.c | 21 +++++++++++++++++++++ drivers/input/keyboard/sppp_keyboard.c | 21 +++++++++++++++++++++ drivers/input/mouse/sppp_trackpad.c | 21 +++++++++++++++++++++ drivers/rtc/sppp_rtc.c | 22 ++++++++++++++++++++++ include/linux/sppp.h | 21 +++++++++++++++++++++ 6 files changed, 127 insertions(+) diff --git a/arch/arm/mach-mx5/sppp_power.c b/arch/arm/mach-mx5/sppp_power.c index 11a6d19096a..14997cb30bd 100644 --- a/arch/arm/mach-mx5/sppp_power.c +++ b/arch/arm/mach-mx5/sppp_power.c @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + #include #include #include diff --git a/arch/arm/mach-mx5/spppdriver.c b/arch/arm/mach-mx5/spppdriver.c index 41e09aa5e0d..44dcb22f984 100644 --- a/arch/arm/mach-mx5/spppdriver.c +++ b/arch/arm/mach-mx5/spppdriver.c @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + #include #include #include diff --git a/drivers/input/keyboard/sppp_keyboard.c b/drivers/input/keyboard/sppp_keyboard.c index 6c47fc725fa..642da8e65c4 100644 --- a/drivers/input/keyboard/sppp_keyboard.c +++ b/drivers/input/keyboard/sppp_keyboard.c @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + #include #include diff --git a/drivers/input/mouse/sppp_trackpad.c b/drivers/input/mouse/sppp_trackpad.c index 5ea364585df..7a384d44b20 100644 --- a/drivers/input/mouse/sppp_trackpad.c +++ b/drivers/input/mouse/sppp_trackpad.c @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + #include #include #include diff --git a/drivers/rtc/sppp_rtc.c b/drivers/rtc/sppp_rtc.c index f7573a55d0d..870d0bcc46f 100644 --- a/drivers/rtc/sppp_rtc.c +++ b/drivers/rtc/sppp_rtc.c @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + + #include #include #include diff --git a/include/linux/sppp.h b/include/linux/sppp.h index 81dbb84aa88..a8fe7a65876 100755 --- a/include/linux/sppp.h +++ b/include/linux/sppp.h @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2011 Genesi USA, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + #ifndef _SPPP_H_ #define _SPPP_H_ From 13d1a67140f37104251365284ba010a102a0e85c Mon Sep 17 00:00:00 2001 From: Steev Klimaszewski Date: Fri, 11 May 2012 16:46:46 -0500 Subject: [PATCH 32/32] efikasb: cleanups for efikasb and sppp --- arch/arm/mach-mx5/board-mx53_efikasb.c | 21 +- arch/arm/mach-mx5/sppp_power.c | 29 +- arch/arm/mach-mx5/spppdriver.c | 459 ++++++++++++------------- drivers/input/keyboard/sppp_keyboard.c | 323 +++++++++-------- drivers/input/mouse/sppp_trackpad.c | 181 +++++----- drivers/rtc/sppp_rtc.c | 138 ++++---- include/linux/sppp.h | 30 +- 7 files changed, 550 insertions(+), 631 deletions(-) diff --git a/arch/arm/mach-mx5/board-mx53_efikasb.c b/arch/arm/mach-mx5/board-mx53_efikasb.c index b7a4e82c0fd..81986f77ca9 100644 --- a/arch/arm/mach-mx5/board-mx53_efikasb.c +++ b/arch/arm/mach-mx5/board-mx53_efikasb.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -48,6 +47,7 @@ #include #include #include +#include #include #include "crm_regs.h" @@ -56,7 +56,7 @@ #include "usb.h" /* MX53 Efika SB GPIO PIN configurations */ -#define USBDR_OC IMX_GPIO_NR(4, 14) /* GPIO_4_14 */ +#define USBDR_OC IMX_GPIO_NR(4, 14) /* GPIO_4_14 */ #define USBDR_PWREN IMX_GPIO_NR(4, 15) /* GPIO_4_15 */ #define USBH1_OC IMX_GPIO_NR(3, 30) /* GPIO_3_30 */ #define USBH1_PWREN IMX_GPIO_NR(3, 31) /* GPIO_3_31 */ @@ -109,8 +109,8 @@ static iomux_v3_cfg_t mx53_efikasb_pads[] = { MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, /* I2C1 */ - MX53_PAD_CSI0_DAT8__I2C1_SDA, - MX53_PAD_CSI0_DAT9__I2C1_SCL, + MX53_PAD_CSI0_DAT8__I2C1_SDA, + MX53_PAD_CSI0_DAT9__I2C1_SCL, /* UART */ MX53_PAD_PATA_DIOW__UART1_TXD_MUX, MX53_PAD_PATA_DMACK__UART1_RXD_MUX, @@ -170,7 +170,6 @@ static struct ipuv3_fb_platform_data efikasb_fb0_data = { .num_modes = ARRAY_SIZE(video_modes), }; - static struct ipuv3_fb_platform_data efikasb_fb1_data = { .interface_pix_fmt = IPU_PIX_FMT_BGR24, .mode_str = "WSVGA", @@ -178,7 +177,6 @@ static struct ipuv3_fb_platform_data efikasb_fb1_data = { .num_modes = ARRAY_SIZE(video_modes), }; - static struct imx_ipuv3_platform_data ipu_data = { .rev = 3, .fb_head0_platform_data = &efikasb_fb0_data, @@ -214,7 +212,6 @@ static struct mxc_dvfs_platform_data efikasb_dvfs_core_data = { .delay_time = 30, }; - static const struct esdhc_platform_data mx53_efikasb_sd1_data __initconst = { .always_present = true, .wp_gpio = SD1_WP, @@ -240,7 +237,6 @@ static struct platform_device cs42l52_device = { .name = "imx-cs42l52", }; - static const struct imxi2c_platform_data mx53_efikasb_i2c_data __initconst = { .bitrate = 100000, }; @@ -264,14 +260,14 @@ static int nand_init(void) #define M4IF_GENP_WEIM_MM_MASK 0x00000001 #define WEIM_GCR2_MUX16_BYP_GRANT_MASK 0x00001000 - + base = ioremap(MX53_M4IF_BASE_ADDR, SZ_4K); reg = __raw_readl(base + 0xc); reg &= ~M4IF_GENP_WEIM_MM_MASK; __raw_writel(reg, base + 0xc); - + iounmap(base); - + base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K); for (i = 0x4; i < 0x94; i += 0x18) { reg = __raw_readl((u32)base + i); @@ -279,11 +275,10 @@ static int nand_init(void) __raw_writel(reg, (u32)base + i); } iounmap(base); - + return 0; } - /* NAND Flash Partitions */ #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition nand_flash_partitions[] = { diff --git a/arch/arm/mach-mx5/sppp_power.c b/arch/arm/mach-mx5/sppp_power.c index 14997cb30bd..1df39d5ccdb 100644 --- a/arch/arm/mach-mx5/sppp_power.c +++ b/arch/arm/mach-mx5/sppp_power.c @@ -18,15 +18,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include #include #include #include #include - #include - #include static struct sppp_client sppp_pwr_client; @@ -34,37 +31,33 @@ static struct sppp_client sppp_pwr_client; /* Callback for incoming data from SPM */ static void sppp_get_data(sppp_rx_t *packet) { - } /* Send power suspend sequence to SPM */ static void sppp_pwr_suspend(void) { + sppp_tx_t sppp_tx_g; - sppp_tx_t sppp_tx_g; - - sppp_start(&sppp_tx_g, SPPP_PWR_ID); - sppp_data(&sppp_tx_g, PWR_ID_GOTO_STANDY); - sppp_stop(&sppp_tx_g); - + sppp_start(&sppp_tx_g, SPPP_PWR_ID); + sppp_data(&sppp_tx_g, PWR_ID_GOTO_STANDY); + sppp_stop(&sppp_tx_g); } static int __init sppp_pwr_init(void) { - sppp_pwr_client.id = POWER; - sppp_pwr_client.decode = sppp_get_data; - sppp_client_register(&sppp_pwr_client); + sppp_pwr_client.id = POWER; + sppp_pwr_client.decode = sppp_get_data; + sppp_client_register(&sppp_pwr_client); - pm_power_off = sppp_pwr_suspend; + pm_power_off = sppp_pwr_suspend; - return 0; + return 0; } static void __exit sppp_pwr_exit(void) { - sppp_client_remove(&sppp_pwr_client); - - pm_power_off = NULL; + sppp_client_remove(&sppp_pwr_client); + pm_power_off = NULL; } module_init(sppp_pwr_init); diff --git a/arch/arm/mach-mx5/spppdriver.c b/arch/arm/mach-mx5/spppdriver.c index 44dcb22f984..392e485d1c7 100644 --- a/arch/arm/mach-mx5/spppdriver.c +++ b/arch/arm/mach-mx5/spppdriver.c @@ -18,7 +18,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include #include #include @@ -28,31 +27,31 @@ #include #include #include +#include #include #include #include "spppdriver.h" -#include /* Read and write registers */ -#define __REG(x) (*((volatile u32 *)(x))) +#define __REG(x) (*((u32 *)(x))) /* Maximum number of SPPP clients */ #define MAX_CLIENTS 10 /* Simple device structure for the SPPP driver */ struct sppp_device { - struct uart_port port; - unsigned int baud; - struct clk *clk; + struct uart_port port; + unsigned int baud; + struct clk *clk; }; /* Array od SPPP clients */ static struct sppp_client *array_of_clients[MAX_CLIENTS] = {NULL}; /* baseint contains the address as a 32 bit integer */ -static volatile u32 *base, baseint; +static u32 *base, baseint; /* Actual SPPP device */ static struct sppp_device sppp __initdata; @@ -63,273 +62,246 @@ static sppp_rx_t sppp_rx_g; /* Registers an SPPP client with the driver */ void sppp_client_register(struct sppp_client *client) { - if (client->id <= MAX_CLIENTS) - array_of_clients[client->id] = client; - else - printk(KERN_ERR "Wrong client id\n"); + if (client->id <= MAX_CLIENTS) + array_of_clients[client->id] = client; + else + printk(KERN_ERR "Wrong client id\n"); } EXPORT_SYMBOL(sppp_client_register); /* Removes an SPPP client from the driver */ void sppp_client_remove(struct sppp_client *client) { - if (client->id <= MAX_CLIENTS) - array_of_clients[client->id] = NULL; - else - printk(KERN_ERR "Wrong client id\n"); + if (client->id <= MAX_CLIENTS) + array_of_clients[client->id] = NULL; + else + printk(KERN_ERR "Wrong client id\n"); } EXPORT_SYMBOL(sppp_client_remove); /* Process, identify and decode packet after full encapulated packet received */ static int decode(void) { - int i; - - switch (sppp_rx_g.id) { - case SPPP_IDENTIFICATION_ID: - printk(KERN_ERR "IDENTIFICATION\n"); - for (i=0; idecode(&sppp_rx_g); - break; - case SPPP_KEY_ID: - //printk(KERN_ERR "KEY\n"); - //for (i=0; idecode(&sppp_rx_g); - break; - - case SPPP_RTC_ID: - //printk(KERN_ERR "RTC\n"); - //for (i=0; idecode(&sppp_rx_g); - break; - case SPPP_PWR_ID: - //printk(KERN_ERR "PWR\n"); - //for (i=0; idecode(&sppp_rx_g); - break; - case SPPP_STRING_ID: - printk(KERN_ERR "STRING\n"); - for (i=0; idecode(&sppp_rx_g); + break; + case SPPP_KEY_ID: + if (array_of_clients[KEYBOARD] != NULL) + array_of_clients[KEYBOARD]->decode(&sppp_rx_g); + break; + + case SPPP_RTC_ID: + if (array_of_clients[RTC] != NULL) + array_of_clients[RTC]->decode(&sppp_rx_g); + break; + case SPPP_PWR_ID: + if (array_of_clients[POWER] != NULL) + array_of_clients[POWER]->decode(&sppp_rx_g); + break; + case SPPP_STRING_ID: + printk(KERN_ERR "STRING\n"); + for (i = 0; i < sppp_rx_g.pos; i++) + printk(KERN_ERR "%c", sppp_rx_g.input[i]); + printk(KERN_ERR "\n"); + break; + case 10: + return 0; + default: + break; + } + + return 0; } /* Process incoming encapsulated data */ static void recv(sppp_rx_t *sppp_rx, uint8_t data) { - - //printk(KERN_ERR "decode byte: 0x%02x\n",data); - - if ( sppp_rx->sync == SPPP_SYNC ) { - switch (data & ~SPPP_PKT_ID_MASK) { - case SPPP_PKT_START: - goto sppp_start; - case SPPP_PKT_STOP: - sppp_rx->sync = SPPP_NOSYNC; //mark the end of the current packet - /* check for valid CRC */ - if ( !(( sppp_rx->crc^data) & SPPP_PKT_ID_MASK) ) { - //printk(KERN_ERR "valid crc\n"); - /* More processing */ - decode(); - } else { - printk(KERN_ERR "no valid crc=0x%02x != 0x%02x\n",(sppp_rx->crc& SPPP_PKT_ID_MASK), (data& SPPP_PKT_ID_MASK) ); - } - break; - default: - /* max input size reached */ - if ( sppp_rx->pos < MAX_RECV_PKG_SIZE) { - /* add to CRC sum */ - sppp_rx->crc += data; - if (sppp_rx->num != 0) { - //printk(KERN_ERR "input=%c carry=0x%x\n",sppp_rx->input[sppp_rx->pos], sppp_rx->carry); - /* Shift current byte on right pos */ - sppp_rx->input[sppp_rx->pos] = ( (data >>(7-sppp_rx->num)) | sppp_rx->carry); - /* Input size */ - sppp_rx->pos++; - } - /* shift carry byte on right pos for next run */ - sppp_rx->carry = ( data <<(1+sppp_rx->num)); - //printk(KERN_ERR "carry=0x%x\n",sppp_rx->carry); - sppp_rx->num++; - if (sppp_rx->num>7) - sppp_rx->num=0; - } else { - /* size is to big, drop this one */ - sppp_rx->sync = SPPP_NOSYNC; - } - } - } else { - if ( (data & ~SPPP_PKT_ID_MASK) == SPPP_PKT_START ) { + if (sppp_rx->sync == SPPP_SYNC) { + switch (data & ~SPPP_PKT_ID_MASK) { + case SPPP_PKT_START: + goto sppp_start; + case SPPP_PKT_STOP: + sppp_rx->sync = SPPP_NOSYNC; /* mark the end of the current packet */ + /* check for valid CRC */ + if (!((sppp_rx->crc^data) & SPPP_PKT_ID_MASK)) + decode(); + else + printk(KERN_ERR "no valid crc=0x%02x != 0x%02x\n", (sppp_rx->crc & SPPP_PKT_ID_MASK), (data & SPPP_PKT_ID_MASK)); + break; + default: + /* max input size reached */ + if (sppp_rx->pos < MAX_RECV_PKG_SIZE) { + /* add to CRC sum */ + sppp_rx->crc += data; + if (sppp_rx->num != 0) { + /* Shift current byte on right pos */ + sppp_rx->input[sppp_rx->pos] = ((data >> (7-sppp_rx->num)) | sppp_rx->carry); + /* Input size */ + sppp_rx->pos++; + } + /* shift carry byte on right pos for next run */ + sppp_rx->carry = (data << (1 + sppp_rx->num)); + sppp_rx->num++; + if (sppp_rx->num > 7) + sppp_rx->num = 0; + } else { + /* size is to big, drop this one */ + sppp_rx->sync = SPPP_NOSYNC; + } + } + } else { + if ((data & ~SPPP_PKT_ID_MASK) == SPPP_PKT_START) { sppp_start: - sppp_rx->id = data & SPPP_PKT_ID_MASK; - sppp_rx->crc = data; - sppp_rx->pos = 0; - sppp_rx->num = 0; - sppp_rx->carry = 0; - sppp_rx->sync = SPPP_SYNC; - } - } + sppp_rx->id = data & SPPP_PKT_ID_MASK; + sppp_rx->crc = data; + sppp_rx->pos = 0; + sppp_rx->num = 0; + sppp_rx->carry = 0; + sppp_rx->sync = SPPP_SYNC; + } + } } /* Interrupt service routine for serial interface */ static irqreturn_t sppp_int(int irq, void *dev_id) { + uint8_t rx; + unsigned int sr2, sr1, cr1; - uint8_t rx; - volatile unsigned int sr2, sr1, cr1; - - sr1 = __REG(baseint + USR1); - sr2 = __REG(baseint + USR2); - cr1 = __REG(baseint + UCR1); + sr1 = __REG(baseint + USR1); + sr2 = __REG(baseint + USR2); + cr1 = __REG(baseint + UCR1); - /* Clear interrupt bits */ - __REG(baseint + USR1) = sr1; - __REG(baseint + USR2) = sr2; + /* Clear interrupt bits */ + __REG(baseint + USR1) = sr1; + __REG(baseint + USR2) = sr2; - /* Receive interrupt */ - if (sr2 & USR2_RDR) { - while (__REG(baseint + USR2) & USR2_RDR) { + /* Receive interrupt */ + if (sr2 & USR2_RDR) { + while (__REG(baseint + USR2) & USR2_RDR) { - /* Read data from the receive data register and mask out any status bits */ - rx = (__REG(baseint + URXD) & URXD_RX_DATA); + /* Read data from the receive data register and mask out any status bits */ + rx = (__REG(baseint + URXD) & URXD_RX_DATA); - /* Process incoming data */ - recv(&sppp_rx_g, rx); - } + /* Process incoming data */ + recv(&sppp_rx_g, rx); + } - } + } - return IRQ_HANDLED; + return IRQ_HANDLED; } /* Polling send function */ void serial_putc(const char c) { - __REG(baseint + UTXD) = c; + __REG(baseint + UTXD) = c; - /* wait for transmitter to be ready */ - while (!(__REG(baseint + USR1) & USR1_TRDY)); - - /* STM needs time for processing... */ - msleep(1); + /* wait for transmitter to be ready */ + while + (!(__REG(baseint + USR1) & USR1_TRDY)); + /* STM needs time for processing... */ + msleep(1); } /* Writing a string, uses polled serial_putc() */ void serial_puts(const char *s) { - while (*s) { - serial_putc (*s++); - } + while (*s) + serial_putc(*s++); } -#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) +#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) #define TXTL 2 /* reset default */ #define RXTL 1 /* reset default */ static int imx_setup_ufcr(struct uart_port *port, unsigned int mode) { - unsigned int val; - unsigned int ufcr_rfdiv; + unsigned int val; + unsigned int ufcr_rfdiv; - /* set receiver / transmitter trigger level. - * RFDIV is set such way to satisfy requested uartclk value - * 24000000 is the value of the oscillator, see mx53_clocks_init() - */ - val = TXTL << 10 | RXTL; - ufcr_rfdiv = (clk_get_rate(clk_get_sys("imx-uart.1", NULL)) + 24000000 / 2) - / 24000000; + /* set receiver / transmitter trigger level. + * RFDIV is set such way to satisfy requested uartclk value + * 24000000 is the value of the oscillator, see mx53_clocks_init() + */ + val = TXTL << 10 | RXTL; + ufcr_rfdiv = (clk_get_rate(clk_get_sys("imx-uart.1", NULL)) + 24000000 / 2) + / 24000000; - if (!ufcr_rfdiv) - ufcr_rfdiv = 1; + if (!ufcr_rfdiv) + ufcr_rfdiv = 1; - val |= UFCR_RFDIV_REG(ufcr_rfdiv); + val |= UFCR_RFDIV_REG(ufcr_rfdiv); - __REG(baseint + UFCR) = val; + __REG(baseint + UFCR) = val; - return 0; + return 0; } - /* Initialise the serial port with the baudrate. */ static int sppp_setup(void) { - int retval; - struct sppp_device *device = &sppp; - struct uart_port *port = &device->port; + int retval; + struct sppp_device *device = &sppp; + struct uart_port *port = &device->port; - port->mapbase = MX53_UART2_BASE_ADDR; /* UART 2 is connected to the STM */ - port->irq = MX53_INT_UART2; /* Our interrupt */ + port->mapbase = MX53_UART2_BASE_ADDR; /* UART 2 is connected to the STM */ + port->irq = MX53_INT_UART2; /* Our interrupt */ - /* Currently at 115200 */ - device->baud = 115200; + /* Currently at 115200 */ + device->baud = 115200; - /* Get base address of our remapped uart */ - base = (u32 *)ioremap(port->mapbase, 0xD4); + /* Get base address of our remapped uart */ + base = (u32 *)ioremap(port->mapbase, 0xD4); - /* Make it available as an integer for use with __REG(x) macro */ - baseint = (u32)base; + /* Make it available as an integer for use with __REG(x) macro */ + baseint = (u32)base; - /* Enable the uart clock */ - clk_enable(clk_get_sys("imx-uart.1", NULL)); - port->uartclk = clk_get_rate(clk_get_sys("imx-uart.1", NULL)); + /* Enable the uart clock */ + clk_enable(clk_get_sys("imx-uart.1", NULL)); + port->uartclk = clk_get_rate(clk_get_sys("imx-uart.1", NULL)); - /* Set clock divider */ - imx_setup_ufcr(port, 0); + /* Set clock divider */ + imx_setup_ufcr(port, 0); - /* Initialise registers to zero, clears any possible flags that shouldn't be set */ - __REG(baseint + UCR1) = 0x0; - __REG(baseint + UCR2) = 0x0; + /* Initialise registers to zero, clears any possible flags that shouldn't be set */ + __REG(baseint + UCR1) = 0x0; + __REG(baseint + UCR2) = 0x0; - /* Wait for SW reset */ - while (!(__REG(baseint + UCR2) & UCR2_SRST)); + /* Wait for SW reset */ + while + (!(__REG(baseint + UCR2) & UCR2_SRST)); - /* disable the DREN bit (Data Ready interrupt enable) before - * requesting IRQs - */ - __REG(baseint + UCR4) &= ~UCR4_DREN; + /* disable the DREN bit (Data Ready interrupt enable) before + * requesting IRQs + */ + __REG(baseint + UCR4) &= ~UCR4_DREN; - /* Get the irq */ - retval = request_irq(port->irq, sppp_int, 0, "spppinterrupt", port); - if (retval != 0) { - printk(KERN_ERR "Could not get interrupt... \n"); - } + /* Get the irq */ + retval = request_irq(port->irq, sppp_int, 0, "spppinterrupt", port); + if (retval != 0) + printk(KERN_ERR "Could not get interrupt...\n"); - /* Set Baudrate */ - __REG(baseint + UBIR) = 0xf; - __REG(baseint + UBMR) = port->uartclk / (2 * device->baud); + /* Set Baudrate */ + __REG(baseint + UBIR) = 0xf; + __REG(baseint + UBMR) = port->uartclk / (2 * device->baud); - /* And finally enable the port and interrupts in the control registers */ - __REG(baseint + UCR2) = UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; - __REG(baseint + UCR1) = UCR1_UARTEN | UCR1_RRDYEN; /* The last one enables receive ready interrupt */ + /* And finally enable the port and interrupts in the control registers */ + __REG(baseint + UCR2) = UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; + __REG(baseint + UCR1) = UCR1_UARTEN | UCR1_RRDYEN; /* The last one enables receive ready interrupt */ - return 0; + return 0; } /* SPPP send operations */ @@ -337,87 +309,80 @@ static int sppp_setup(void) /* Low Level write */ void _sppp_write(sppp_tx_t *sppp_tx, uint8_t data) { - sppp_tx->crc += data; - serial_putc(data); + sppp_tx->crc += data; + serial_putc(data); } /* Send Start */ void sppp_start(sppp_tx_t *sppp_tx, uint8_t pkg_id) { - sppp_tx->crc=0; - sppp_tx->pos=0; - sppp_tx->carry=0; - _sppp_write(sppp_tx, SPPP_PKT_START | (pkg_id&0x3F)) ; + sppp_tx->crc = 0; + sppp_tx->pos = 0; + sppp_tx->carry = 0; + _sppp_write(sppp_tx, SPPP_PKT_START | (pkg_id&0x3F)) ; } EXPORT_SYMBOL(sppp_start); /* Encode data for sending */ void sppp_data(sppp_tx_t *sppp_tx, uint8_t data) { - _sppp_write(sppp_tx, (data >>(1+sppp_tx->pos)) | sppp_tx->carry ); // send - sppp_tx->carry = (data <<(6-sppp_tx->pos))&0x7F; // save carry - sppp_tx->pos++; - //printk(KERN_ERR "carry=0x%02x\n",sppp_tx->carry); - if (sppp_tx->pos>=7) { - //printk(KERN_ERR "carry=0x%02x\n",sppp_tx->carry); - _sppp_write(sppp_tx, sppp_tx->carry); // send this byte - sppp_tx->carry=0; - sppp_tx->pos=0; - } + _sppp_write(sppp_tx, (data >> (1 + sppp_tx->pos)) | sppp_tx->carry); /* send */ + sppp_tx->carry = (data << (6-sppp_tx->pos)) & 0x7F; /* save carry */ + sppp_tx->pos++; + if (sppp_tx->pos >= 7) { + _sppp_write(sppp_tx, sppp_tx->carry); /* send this byte */ + sppp_tx->carry = 0; + sppp_tx->pos = 0; + } } EXPORT_SYMBOL(sppp_data); /* Send Stop */ void sppp_stop(sppp_tx_t *sppp_tx) { - if (sppp_tx->pos < 7) - _sppp_write(sppp_tx, sppp_tx->carry); - _sppp_write(sppp_tx, SPPP_PKT_STOP | (~SPPP_PKT_STOP & sppp_tx->crc)); // send EOP + if (sppp_tx->pos < 7) + _sppp_write(sppp_tx, sppp_tx->carry); + _sppp_write(sppp_tx, SPPP_PKT_STOP | (~SPPP_PKT_STOP & sppp_tx->crc)); /* send EOP */ } EXPORT_SYMBOL(sppp_stop); /* General all-in-one send function */ void sppp_send(sppp_tx_t *sppp_tx, unsigned char *buf, int size, int pkg_id) { - int i; - sppp_tx->crc=0; - sppp_tx->pos=0; - sppp_tx->carry=0; - - printk(KERN_ERR "send SOP\n"); - _sppp_write(sppp_tx, (SPPP_PKT_START | (pkg_id&0x3F)) ) ; //send SOP and ID - for (i=0; ipos < 7) - _sppp_write(sppp_tx, sppp_tx->carry); // send only carry if no more bytes send - _sppp_write(sppp_tx, SPPP_PKT_STOP | (~SPPP_PKT_STOP & sppp_tx->crc)); // send EOP + int i; + sppp_tx->crc = 0; + sppp_tx->pos = 0; + sppp_tx->carry = 0; + + printk(KERN_ERR "send SOP\n"); + _sppp_write(sppp_tx, (SPPP_PKT_START | (pkg_id&0x3F))) ; /* send SOP and ID */ + for (i = 0; i < size; i++) + sppp_data(sppp_tx, buf[i]); + printk(KERN_ERR "send EOP\n"); + if (sppp_tx->pos < 7) + _sppp_write(sppp_tx, sppp_tx->carry); /* send only carry if no more bytes send */ + _sppp_write(sppp_tx, SPPP_PKT_STOP | (~SPPP_PKT_STOP & sppp_tx->crc)); /* send EOP */ } EXPORT_SYMBOL(sppp_send); static int __init sppp_init(void) { + printk(KERN_ALERT "Inserting SPPP driver.\n"); + sppp_setup(); + sppp_rx_g.sync = SPPP_NOSYNC; - printk(KERN_ALERT "Inserting SPPP driver.\n"); - sppp_setup(); - sppp_rx_g.sync = SPPP_NOSYNC; - - return 0; + return 0; } static void __exit sppp_exit(void) { -// struct sppp_device *device = &sppp; -// struct uart_port *port = &device->port; + printk(KERN_ALERT "Removing SPPP driver.\n"); - printk(KERN_ALERT "Removing SPPP driver.\n"); - - //free_irq(port->irq, NULL); //--> needs fixing, blows up with segfault... - clk_disable(clk_get_sys("imx-uart.1", NULL)); - iounmap(base); + /* free_irq(port->irq, NULL); //--> needs fixing, blows up with segfault... */ + clk_disable(clk_get_sys("imx-uart.1", NULL)); + iounmap(base); } - module_init(sppp_init); module_exit(sppp_exit); diff --git a/drivers/input/keyboard/sppp_keyboard.c b/drivers/input/keyboard/sppp_keyboard.c index 642da8e65c4..382591beb7e 100644 --- a/drivers/input/keyboard/sppp_keyboard.c +++ b/drivers/input/keyboard/sppp_keyboard.c @@ -18,91 +18,85 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include #include #include - -#define VERBOSE 0 /* show some (not all) debug */ - -#define KBD_SYNC 0xAA /* keyboard inserts a SYNC after each full matrix scan */ - -#define MAXROW 8 -#define MAXCOL 16 - +#define VERBOSE 0 /* show some (not all) debug */ +#define KBD_SYNC 0xAA /* keyboard inserts a SYNC after each full matrix scan */ +#define MAXROW 8 +#define MAXCOL 16 static struct input_dev *keyb_dev; static struct sppp_client sppp_keyboard_client; -char keyboard_g[MAXCOL][MAXROW]; // raw keys from keyboard -char keypress_g[MAXCOL][MAXROW]; // current keys reported to the system -char keyvalid_g[MAXCOL][MAXROW]={ // valid key and scancodes on current keyboard - { 66,12,82,83, 0, 8, 0,52 }, // COL 0 a '0' indicates none existing==invalid - { 0, 0, 0,25, 0, 0, 0,13 }, // COL 1 - { 0, 0, 9, 0, 0, 2, 0, 0 }, - { 1,32,67,54,39,14, 0,26 }, - { 0, 0, 0, 0, 7, 0, 0, 0 }, - { 0, 0,73,61,62,34,20,47 }, - { 0, 0,74,75,63,35,21,48 }, - { 31,18,72,60,46,33,19,59 }, - { 0,24,78,79,65,37,23,50 }, - { 0, 0, 0, 0, 0, 0, 3, 0 }, - { 71,45,70,58,43,30,17,44 }, - { 0, 0,69,56,57,29,16,42 }, - { 0,11,80,81,53,38, 0,51 }, - { 4, 6, 0, 0, 0, 0, 0, 0 }, - { 5,10,76,77,64,36,22,49 }, // COL 14 - { 15, 0,68,55,40,27,28,41 } // COL 15 +char keyboard_g[MAXCOL][MAXROW]; /* raw keys from keyboard */ +char keypress_g[MAXCOL][MAXROW]; /* current keys reported to the system */ +char keyvalid_g[MAXCOL][MAXROW] = { /* valid key and scancodes on current keyboard */ + { 66, 12, 82, 83, 0, 8, 0, 52 }, /* COL 0 a '0' indicates none existing==invalid */ + { 0, 0, 0, 25, 0, 0, 0, 13 }, /* COL 1 */ + { 0, 0, 9, 0, 0, 2, 0, 0 }, + { 1, 32, 67, 54, 39, 14, 0, 26 }, + { 0, 0, 0, 0, 7, 0, 0, 0 }, + { 0, 0, 73, 61, 62, 34, 20, 47 }, + { 0, 0, 74, 75, 63, 35, 21, 48 }, + { 31, 18, 72, 60, 46, 33, 19, 59 }, + { 0, 24, 78, 79, 65, 37, 23, 50 }, + { 0, 0, 0, 0, 0, 0, 3, 0 }, + { 71, 45, 70, 58, 43, 30, 17, 44 }, + { 0, 0, 69, 56, 57, 29, 16, 42 }, + { 0, 11, 80, 81, 53, 38, 0, 51 }, + { 4, 6, 0, 0, 0, 0, 0, 0 }, + { 5, 10, 76, 77, 64, 36, 22, 49 }, /* COL 14 */ + { 15, 0, 68, 55, 40, 27, 28, 41 } /* COL 15 */ }; -int key_sync_g = 0; -int key_ghost_g = 0; +int key_sync_g; +int key_ghost_g; /* Reset 'raw' and 'clean' versions of the key matix */ static void kbd_clear(void) { - int i,j; + int i, j; - for ( i=0 ; i>= 1; - } + for (j = 0; j < MAXROW; j++) { + keyboard_g[col][j] = key&1 ? 0 : 1; /* note: keyboard reports active lo signals */ + key >>= 1; + } } - - -/* Take the payload of the keyboard event packet and do some meanfull things. */ -/* The data comes as 2 bytes pair with first byte=column index (0-15) and */ -/* second byte as the row read out value (note: this is active lo bitfield). */ -/* The data comes as 'endless' stream with a SYNC byte inserted after each */ -/* full scan of the key matix. The keyboard ONLY reports the key deltas */ -/* between two consecutive scans. */ - +/* Take the payload of the keyboard event packet and do some meanfull things. + * The data comes as 2 bytes pair with first byte=column index (0-15) and + * second byte as the row read out value (note: this is active lo bitfield). + * The data comes as 'endless' stream with a SYNC byte inserted after each + * full scan of the key matix. The keyboard ONLY reports the key deltas + * between two consecutive scans. + */ static void kbd_decode(sppp_rx_t *packet) { - - unsigned char *keys = packet->input; - int keyc = packet->pos; + unsigned char *keys = packet->input; + int keyc = packet->pos; #if VERBOSE - int i; + int i; - printk(KERN_ERR "decode %d bytes (",keyc); - for (i=0;i 1 ) { // two or more bytes left - if ( keys[0] == KBD_SYNC ) { // found SYNC, this also indicates next KBD event - key_sync_g++; // statistics only - kbd_handle(); // handle keys of this event + while (keyc > 1) { /* two or more bytes left */ + if (keys[0] == KBD_SYNC) { /* found SYNC, this also indicates next KBD event */ + key_sync_g++; /* statistics only */ + kbd_handle(); /* handle keys of this event */ #if VERBOSE - printk(KERN_ERR "event %d\n",key_sync_g); + printk(KERN_ERR "event %d\n", key_sync_g); #endif - } else { - kbd_add_col( keys[0], keys[1] ); // insert changes into raw matrix - } - keyc -= 2; - keys += 2; - } + } else { + kbd_add_col(keys[0], keys[1]); /* insert changes into raw matrix */ + } + keyc -= 2; + keys += 2; + } } - #define PCI_VENDOR_ID_FREESCALE 0x1957 static int __init sppp_kbd_init(void) { + int i, j; + int error; - int i,j; - int error; - - keyb_dev = input_allocate_device(); + keyb_dev = input_allocate_device(); - keyb_dev->name = "Efika SB Keyboard"; - keyb_dev->phys = "efikasb/input0"; - keyb_dev->uniq = "efikasb_keyboard"; - keyb_dev->id.bustype = BUS_HOST; - keyb_dev->id.vendor = PCI_VENDOR_ID_FREESCALE; + keyb_dev->name = "Efika SB Keyboard"; + keyb_dev->phys = "efikasb/input0"; + keyb_dev->uniq = "efikasb_keyboard"; + keyb_dev->id.bustype = BUS_HOST; + keyb_dev->id.vendor = PCI_VENDOR_ID_FREESCALE; - keyb_dev->evbit[0] = BIT_MASK(EV_KEY); + keyb_dev->evbit[0] = BIT_MASK(EV_KEY); - for (i=0;ikeybit); + for (i = 0; i < MAXCOL; i++) + for (j = 0; j < MAXROW; j++) + set_bit(keyvalid_g[i][j], keyb_dev->keybit); - error = input_register_device(keyb_dev); - if (error) { - printk(KERN_ERR "Keyboard input device registration failed.\n"); - input_free_device(keyb_dev); - return -1; - } + error = input_register_device(keyb_dev); + if (error) { + printk(KERN_ERR "Keyboard input device registration failed.\n"); + input_free_device(keyb_dev); + return -1; + } - kbd_clear(); + kbd_clear(); - sppp_keyboard_client.id = KEYBOARD; - sppp_keyboard_client.decode = kbd_decode; + sppp_keyboard_client.id = KEYBOARD; + sppp_keyboard_client.decode = kbd_decode; - sppp_client_register(&sppp_keyboard_client); + sppp_client_register(&sppp_keyboard_client); - return 0; + return 0; } static void __exit sppp_kbd_exit(void) { - - sppp_client_remove(&sppp_keyboard_client); - + sppp_client_remove(&sppp_keyboard_client); } module_init(sppp_kbd_init); diff --git a/drivers/input/mouse/sppp_trackpad.c b/drivers/input/mouse/sppp_trackpad.c index 7a384d44b20..8274e70f279 100644 --- a/drivers/input/mouse/sppp_trackpad.c +++ b/drivers/input/mouse/sppp_trackpad.c @@ -39,116 +39,107 @@ static struct sppp_client sppp_trackpad_client; */ static void trackpad_decode(sppp_rx_t *packet) { - static uint8_t ps2_byte[3]; - static uint8_t ps2_seq; - static int ps2_count; - int i; + static uint8_t ps2_byte[3]; + static uint8_t ps2_seq; + static int ps2_count; + int i; - /* note: a PS/2 packet can have incomplete and/or multiple messages */ - for (i=0; (i+1)pos; i+=2) { - if (packet->input[i] != ps2_seq) { - ps2_seq = packet->input[i]; - ps2_count=0; - } + /* note: a PS/2 packet can have incomplete and/or multiple messages */ + for (i = 0; (i+1) < packet->pos; i += 2) { + if (packet->input[i] != ps2_seq) { + ps2_seq = packet->input[i]; + ps2_count = 0; + } - ps2_byte[ps2_count++] = packet->input[i+1]; + ps2_byte[ps2_count++] = packet->input[i+1]; - if (ps2_count == 3) { - /* Check for overflow, and discard if so */ - if ( ! ((ps2_byte[0]&0x80) || (ps2_byte[0]&0x40)) ) { + if (ps2_count == 3) { + /* Check for overflow, and discard if so */ + if (!((ps2_byte[0]&0x80) || (ps2_byte[0]&0x40))) { - /* Actually send ps2_byte to input dev */ - input_report_key(track_dev, BTN_LEFT, ps2_byte[0] & 0x01); - input_report_key(track_dev, BTN_RIGHT, ps2_byte[0] & 0x02); + /* Actually send ps2_byte to input dev */ + input_report_key(track_dev, BTN_LEFT, ps2_byte[0] & 0x01); + input_report_key(track_dev, BTN_RIGHT, ps2_byte[0] & 0x02); - input_report_rel(track_dev, REL_X, ps2_byte[1] ? (int) ps2_byte[1] - (int) ((ps2_byte[0] << 4) & 0x100) : 0); - input_report_rel(track_dev, REL_Y, ps2_byte[2] ? (int) ((ps2_byte[0] << 3) & 0x100) - (int) ps2_byte[2] : 0); + input_report_rel(track_dev, REL_X, ps2_byte[1] ? (int) ps2_byte[1] - (int) ((ps2_byte[0] << 4) & 0x100) : 0); + input_report_rel(track_dev, REL_Y, ps2_byte[2] ? (int) ((ps2_byte[0] << 3) & 0x100) - (int) ps2_byte[2] : 0); - input_sync(track_dev); - } - ps2_count=0; - } - } + input_sync(track_dev); + } + ps2_count = 0; + } + } } static int __init sppp_trackpad_init(void) { - - int error; - sppp_tx_t sppp_tx_g; - - track_dev = input_allocate_device(); - - track_dev->name = "Efika SB Trackpad"; - track_dev->phys = "efikasb/input1"; - track_dev->uniq = "efikasb_trackpad"; - track_dev->id.bustype = BUS_I8042; - track_dev->id.vendor = 0x0002; - track_dev->id.product = 1; - track_dev->id.version = 0; - - track_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - track_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - track_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - - error = input_register_device(track_dev); - if (error) { - printk(KERN_ERR "Keyboard input device registration failed.\n"); - input_free_device(track_dev); - return -1; - } - - sppp_trackpad_client.id = TRACKPAD; - sppp_trackpad_client.decode = trackpad_decode; - - /* Low Level PS/2 trackpad init */ - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - sppp_data(&sppp_tx_g, 0xFF); //reset - sppp_stop(&sppp_tx_g); - //msleep(1000); - - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - sppp_data(&sppp_tx_g, 0xF3); //going to set sample rate - sppp_stop(&sppp_tx_g); - - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - sppp_data(&sppp_tx_g, 0x50); //sample rate - /* Valid sample rates are 10, 20, 40, 60, 80, 100, and 200 samples/sec */ - sppp_stop(&sppp_tx_g); - //msleep(1000); - - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - sppp_data(&sppp_tx_g, 0xE6); //Scaling 2:1; 1:1 = 0xE6 - sppp_stop(&sppp_tx_g); - //msleep(1000); - - - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - sppp_data(&sppp_tx_g, 0xE8); //Going to set resolution - sppp_stop(&sppp_tx_g); - //msleep(1000); - - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - // 00,01,02,03 -> 1, 2, 4, 8 counts/mm - sppp_data(&sppp_tx_g, 0x03); //set resolution - sppp_stop(&sppp_tx_g); - //msleep(1000); - - sppp_start(&sppp_tx_g, SPPP_PS2_ID); - sppp_data(&sppp_tx_g, 0xF4); //enable data reporting - sppp_stop(&sppp_tx_g); - - sppp_client_register(&sppp_trackpad_client); - - return 0; + int error; + sppp_tx_t sppp_tx_g; + + track_dev = input_allocate_device(); + + track_dev->name = "Efika SB Trackpad"; + track_dev->phys = "efikasb/input1"; + track_dev->uniq = "efikasb_trackpad"; + track_dev->id.bustype = BUS_I8042; + track_dev->id.vendor = 0x0002; + track_dev->id.product = 1; + track_dev->id.version = 0; + + track_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); + track_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + track_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); + + error = input_register_device(track_dev); + if (error) { + printk(KERN_ERR "Keyboard input device registration failed.\n"); + input_free_device(track_dev); + return -1; + } + + sppp_trackpad_client.id = TRACKPAD; + sppp_trackpad_client.decode = trackpad_decode; + + /* Low Level PS/2 trackpad init */ + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xFF); /* reset */ + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xF3); /* going to set sample rate */ + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0x50); /* sample rate */ + /* Valid sample rates are 10, 20, 40, 60, 80, 100, and 200 samples/sec */ + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xE6); /* Scaling 2:1; 1:1 = 0xE6 */ + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xE8); /* Going to set resolution */ + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + /* 00,01,02,03 -> 1, 2, 4, 8 counts/mm */ + sppp_data(&sppp_tx_g, 0x03); /* set resolution */ + sppp_stop(&sppp_tx_g); + + sppp_start(&sppp_tx_g, SPPP_PS2_ID); + sppp_data(&sppp_tx_g, 0xF4); /* enable data reporting */ + sppp_stop(&sppp_tx_g); + + sppp_client_register(&sppp_trackpad_client); + + return 0; } static void __exit sppp_trackpad_exit(void) { - - sppp_client_remove(&sppp_trackpad_client); - + sppp_client_remove(&sppp_trackpad_client); } module_init(sppp_trackpad_init); diff --git a/drivers/rtc/sppp_rtc.c b/drivers/rtc/sppp_rtc.c index 870d0bcc46f..9aa9edb2954 100644 --- a/drivers/rtc/sppp_rtc.c +++ b/drivers/rtc/sppp_rtc.c @@ -18,151 +18,143 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - - #include #include #include #include #include #include - #include - #include static struct sppp_client sppp_rtc_client; struct rtc_sppp { - struct rtc_device *rtc; + struct rtc_device *rtc; }; -uint32_t rawtime = 0; +uint32_t rawtime; /* Callback for incoming data from SPM */ static void sppp_get_data(sppp_rx_t *packet) { - uint32_t time; + uint32_t time; - time = packet->input[0]<<24; - time |= (packet->input[1]<<16); - time |= (packet->input[2]<< 8); - time |= (packet->input[3]<< 0); + time = packet->input[0] << 24; + time |= (packet->input[1] << 16); + time |= (packet->input[2] << 8); + time |= (packet->input[3] << 0); - rawtime = time; + rawtime = time; } /* Send read sequence to SPM and get data when it arrives */ static int sppp_rtc_readtime(struct device *dev, struct rtc_time *tm) { + sppp_tx_t sppp_tx_g; - sppp_tx_t sppp_tx_g; - - sppp_start(&sppp_tx_g, SPPP_RTC_ID); - sppp_data(&sppp_tx_g, RTC_ID_GET); - sppp_stop(&sppp_tx_g); + sppp_start(&sppp_tx_g, SPPP_RTC_ID); + sppp_data(&sppp_tx_g, RTC_ID_GET); + sppp_stop(&sppp_tx_g); - while (rawtime == 0); + while + (rawtime == 0); - rtc_time_to_tm(rawtime, tm); + rtc_time_to_tm(rawtime, tm); - rawtime = 0; + rawtime = 0; - return rtc_valid_tm(tm); + return rtc_valid_tm(tm); } static int sppp_rtc_settime(struct device *dev, struct rtc_time *tm) { + sppp_tx_t sppp_tx_g; + unsigned long now; - sppp_tx_t sppp_tx_g; - unsigned long now; + rtc_tm_to_time(tm, &now); - rtc_tm_to_time(tm, &now); + sppp_start(&sppp_tx_g, SPPP_RTC_ID); + sppp_data(&sppp_tx_g, RTC_ID_SET); + sppp_data(&sppp_tx_g, (now&0xFF000000) >> 24); + sppp_data(&sppp_tx_g, (now&0x00FF0000) >> 16); + sppp_data(&sppp_tx_g, (now&0x0000FF00) >> 8); + sppp_data(&sppp_tx_g, (now&0x000000FF) >> 0); + sppp_stop(&sppp_tx_g); - sppp_start(&sppp_tx_g, SPPP_RTC_ID); - sppp_data(&sppp_tx_g, RTC_ID_SET); - sppp_data(&sppp_tx_g, (now&0xFF000000)>>24); - sppp_data(&sppp_tx_g, (now&0x00FF0000)>>16); - sppp_data(&sppp_tx_g, (now&0x0000FF00)>> 8); - sppp_data(&sppp_tx_g, (now&0x000000FF)>> 0); - sppp_stop(&sppp_tx_g); - - return 0; + return 0; } static struct rtc_class_ops sppp_rtc_ops = { - .read_time = sppp_rtc_readtime, - .set_time = sppp_rtc_settime, + .read_time = sppp_rtc_readtime, + .set_time = sppp_rtc_settime, }; static int __init sppp_rtc_probe(struct platform_device *pdev) { + struct rtc_sppp *rtc; - struct rtc_sppp *rtc; - - rtc = kzalloc(sizeof(struct rtc_sppp), GFP_KERNEL); - if (!rtc) { - dev_dbg(&pdev->dev, "out of memory\n"); - return -ENOMEM; - } + rtc = kzalloc(sizeof(struct rtc_sppp), GFP_KERNEL); + if (!rtc) { + dev_dbg(&pdev->dev, "out of memory\n"); + return -ENOMEM; + } - platform_set_drvdata(pdev, rtc); + platform_set_drvdata(pdev, rtc); - rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, - &sppp_rtc_ops, THIS_MODULE); + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + &sppp_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc->rtc)) { - dev_dbg(&pdev->dev, "could not register rtc device\n"); - return PTR_ERR(rtc->rtc); - } + if (IS_ERR(rtc->rtc)) { + dev_dbg(&pdev->dev, "could not register rtc device\n"); + return PTR_ERR(rtc->rtc); + } - dev_info(&pdev->dev, "SPPP RTC for Genesi EfikaSB\n"); + dev_info(&pdev->dev, "SPPP RTC for Genesi EfikaSB\n"); - sppp_rtc_client.id = RTC; - sppp_rtc_client.decode = sppp_get_data; - sppp_client_register(&sppp_rtc_client); + sppp_rtc_client.id = RTC; + sppp_rtc_client.decode = sppp_get_data; + sppp_client_register(&sppp_rtc_client); - return 0; + return 0; } static int __exit sppp_rtc_remove(struct platform_device *pdev) { + struct rtc_sppp *rtc = platform_get_drvdata(pdev); - struct rtc_sppp *rtc = platform_get_drvdata(pdev); + rtc_device_unregister(rtc->rtc); + kfree(rtc); + platform_set_drvdata(pdev, NULL); - rtc_device_unregister(rtc->rtc); - kfree(rtc); - platform_set_drvdata(pdev, NULL); - - return 0; + return 0; } static struct platform_driver sppp_rtc_driver = { - .remove = __exit_p(sppp_rtc_remove), - .driver = { - .name = "sppp_rtc", - .owner = THIS_MODULE, - }, + .remove = __exit_p(sppp_rtc_remove), + .driver = { + .name = "sppp_rtc", + .owner = THIS_MODULE, + }, }; static struct platform_device sppp_rtc = { - .name = "sppp_rtc", - .id = -1, + .name = "sppp_rtc", + .id = -1, }; static int __init sppp_rtc_init(void) { - - platform_device_register(&sppp_rtc); - return platform_driver_probe(&sppp_rtc_driver, sppp_rtc_probe); + platform_device_register(&sppp_rtc); + return platform_driver_probe(&sppp_rtc_driver, sppp_rtc_probe); } static void __exit sppp_rtc_exit(void) { - sppp_client_remove(&sppp_rtc_client); - platform_driver_unregister(&sppp_rtc_driver); - platform_device_unregister(&sppp_rtc); + sppp_client_remove(&sppp_rtc_client); + platform_driver_unregister(&sppp_rtc_driver); + platform_device_unregister(&sppp_rtc); } module_init(sppp_rtc_init); diff --git a/include/linux/sppp.h b/include/linux/sppp.h index a8fe7a65876..c530385a059 100755 --- a/include/linux/sppp.h +++ b/include/linux/sppp.h @@ -30,7 +30,7 @@ #define SPPP_PKT_STOP 0xC0 #define IsBitSet(val, bit) ((val) & (1 << (bit))) -#define SPPP_IDENTIFICATION_ID 0 +#define SPPP_IDENTIFICATION_ID 0 #define SPPP_KEY_ID 1 #define SPPP_PS2_ID 2 #define SPPP_RTC_ID 3 @@ -50,22 +50,20 @@ #define FLASH_FW_START_PAGE 8 typedef struct { - uint8_t input[MAX_RECV_PKG_SIZE]; - uint8_t id; - uint8_t crc; - uint8_t pos; - uint8_t num; - uint8_t carry; - uint8_t sync; - + uint8_t input[MAX_RECV_PKG_SIZE]; + uint8_t id; + uint8_t crc; + uint8_t pos; + uint8_t num; + uint8_t carry; + uint8_t sync; } sppp_rx_t; typedef struct { - uint8_t crc; - uint8_t pos; - uint8_t carry; - int comd; - + uint8_t crc; + uint8_t pos; + uint8_t carry; + int comd; } sppp_tx_t; /* Possible SPPP clients */ @@ -77,9 +75,9 @@ enum clients { }; /* Each SPPP client has these */ -struct sppp_client { +struct sppp_client { unsigned int id; - void (* decode)(sppp_rx_t *); + void (*decode)(sppp_rx_t *); }; int sppp_recv(int comd, sppp_rx_t *sppp_rx);